home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / WRITEPAD.PAK / RTF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  20.3 KB  |  687 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1995  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   rtf.c
  9. //
  10. //  PURPOSE:  Provide an interface to the RichEdit control
  11. //
  12. //  FUNCTIONS:
  13. //    RTF_ChangeCharAttribute -  To set the selected text to 
  14. //                               have the supplied attributes.
  15. //    RTF_GetCharAttribute -     To determine if the selected 
  16. //                               text has the requested attributes
  17. //    RTF_ChangeSizeAttribute -  Change the point size of the selected text
  18. //    RTF_ChangeFont -           Change the attributes of the selected text 
  19. //                               with the Common Font Dialog.
  20. //    SaveCallback -             Callback routine for the 
  21. //                               EM_STREAMOUT Message from 
  22. //                               the RichEdit control.
  23. //    RTF_Save -                 Save the contents of the Richedit 
  24. //                               control to a file       
  25. //    OpenCallback -             Callback routine for the EM_STREAMIN 
  26. //                               Message from the RichEdit control.
  27. //    RTF_Open -                 Load the contents of a file ito the 
  28. //                               Richedit control
  29. //    RTF_GetCurrentFont -       Get the facename of the selected text's font
  30. //    RTF_SetCurrentFont -       Set the facename of the selected text's font
  31. //    RTF_ChangeMargins -        Set the margins of the current paragraph.
  32. //    RTF_ShowMargins -          Get the margins of the current paragraph 
  33. //                               and reflect them on the ruler.
  34. //    SetToolbarButtonToReflectCharacterAttribute - Show the status of an 
  35. //                                                  attribute on a toolbar button
  36. //    RTF_ShowCharAttributes -   Show the status of the bold, itailc, 
  37. //                               and underline attributes on the toolbar
  38. //
  39. //  COMMENTS:
  40. //
  41.  
  42.  
  43. #include <windows.h>     // required for all Windows applications
  44. #include <windowsx.h>
  45. #include <malloc.h>
  46. #include <commctrl.h>
  47. #include <richedit.h>
  48. #include "globals.h"     // prototypes specific to this application
  49. #include "resource.h"
  50. #include "rtf.h"         // prototypes specific to this application
  51. #include "ruler.h"
  52. #include "toolbar.h"
  53.  
  54. //
  55. //  FUNCTION: RTF_ChangeCharAttribute(HWND, DWORD, DWORD)
  56. //
  57. //  PURPOSE: To set the selected text to have the supplied
  58. //           attributes.
  59. //
  60. //  PARAMETERS:
  61. //    hRTFWnd - Handle to RichEdit control
  62. //    dwMask - Mask of which attributes to change
  63. //    dwEffects - State of each attribute
  64. //
  65. //  RETURN VALUE:
  66. //    None
  67. //
  68. //  COMMENTS:
  69. //
  70. //
  71.  
  72. void RTF_ChangeCharAttribute(HWND hRTFWnd, DWORD dwMask, DWORD dwEffects)
  73. {
  74.     CHARFORMAT cf; // This is defined in RICHEDIT.H
  75.  
  76.     cf.cbSize = sizeof(cf);
  77.  
  78.     // Get the current status of the text into the CHARFORMAT structure,
  79.     // use the selected text. wParam is TRUE to indicate the
  80.     // selected textt, FALSE for the first character in the
  81.     // RTF Edit control.
  82.     SendMessage(hRTFWnd, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf);
  83.  
  84.     // Set the mask to tell the RTF Edit control to pay attention to
  85.     // the appropriate bit of the dwEffects field.
  86.     cf.dwMask      = dwMask;
  87.     // Twiddle de bits, captain!
  88.     cf.dwEffects  ^= dwEffects;
  89.  
  90.     // Set the new underline status to the selected text
  91.     SendMessage(hRTFWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
  92. }
  93.  
  94. //
  95. //  FUNCTION: RTF_GetCharAttribute(HWND, DWORD, DWORD)
  96. //
  97. //  PURPOSE: To determine if the selected text has the requested
  98. //           attributes
  99. //
  100. //  PARAMETERS:
  101. //    hRTFWnd - Handle to RichEdit control
  102. //    dwMask - Mask of which attributes to check
  103. //    dwEffects - State of each attribute
  104. //
  105. //  RETURN VALUE:
  106. //    One of three constants:
  107. //
  108. //      CHAR_ATTRIB_YES - All of the selected text has the attribute
  109. //      CHAR_ATTRIB_NO  - None of the selected text has the attribute
  110. //      CHAR_ATTRIB_WAFFLE - Some, but not all of the selected text 
  111. //                           has the attribute
  112. //
  113. //  COMMENTS:
  114. //
  115. //
  116.  
  117. int RTF_GetCharAttribute(HWND hRTFWnd, DWORD dwMask, DWORD dwEffects)
  118. {
  119.     CHARFORMAT cf; // This is defined in RICHEDIT.H
  120.  
  121.     cf.cbSize = sizeof(cf);
  122.  
  123.     // Get the current status of the text into the CHARFORMAT structure,
  124.     // use the selected text. wParam is TRUE to indicate the
  125.     // selected textt, FALSE for the first character in the
  126.     // RTF Edit control.
  127.     SendMessage(hRTFWnd, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf);
  128.  
  129.     if (cf.dwMask & dwMask)
  130.     {
  131.         if (cf.dwEffects & dwEffects)
  132.             return CHAR_ATTRIB_YES;
  133.         else
  134.             return CHAR_ATTRIB_NO;
  135.     }
  136.     else
  137.     {
  138.         return CHAR_ATTRIB_WAFFLE;
  139.     }
  140. }
  141.  
  142. //
  143. //  FUNCTION: RTF_ChangeSizeAttribute(HWND, int)
  144. //
  145. //  PURPOSE: Change the point size of the selected text
  146. //
  147. //  PARAMETERS:
  148. //    hRTFWnd - Handle to RichEdit control
  149. //    iPointChange - Number of points, positive or neagtive to
  150. //                   change text
  151. //
  152. //  RETURN VALUE:
  153. //    none
  154. //
  155. //  COMMENTS:
  156. //
  157. //
  158.  
  159. void RTF_ChangeSizeAttribute(HWND hRTFWnd, int iPointChange)
  160. {
  161.     CHARFORMAT cf; // This is defined in RICHEDIT.H
  162.  
  163.     cf.cbSize = sizeof(cf);
  164.  
  165.     // Get the current status of the text into the CHARFORMAT structure,
  166.     // use the selected text. wParam is TRUE to indicate the
  167.     // selected textt, FALSE for the first character in the
  168.     // RTF Edit control.
  169.     SendMessage(hRTFWnd, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf);
  170.  
  171.     // Set the mask to tell the RTF Edit control to pay attention to
  172.     // the size bit of the dwEffects field.
  173.     cf.dwMask      = CFM_SIZE;
  174.     // Increase or decrease the font size, keeping it between 6 and 128 points
  175.     if ( 
  176.          ((cf.yHeight + 20*iPointChange) <= (128*20))
  177.          &&
  178.          ((cf.yHeight + 20*iPointChange) >= (6*20))
  179.        )
  180.         cf.yHeight += 20*iPointChange;
  181.  
  182.     // Set the new underline status to the selected text
  183.     SendMessage(hRTFWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
  184. }
  185.  
  186. //
  187. //  FUNCTION: RTF_ChangeFont(HWND hWnd, HWND hRTFWnd)
  188. //
  189. //  PURPOSE: Change the attributes of the selected text with the
  190. //           Common Font Dialog.
  191. //
  192. //  PARAMETERS:
  193. //    hWnd - Handle to a frame suitable as a parent to the Common
  194. //           font dialog.
  195. //    hRTFWnd - Handle to RichEdit control
  196. //
  197. //  RETURN VALUE:
  198. //    none
  199. //
  200. //  COMMENTS:
  201. //
  202. //
  203.  
  204. void RTF_ChangeFont(HWND hWnd, HWND hRTFWnd)
  205. {
  206.     CHARFORMAT cf;                // This is defined in RICHEDIT.H
  207.     CHOOSEFONT ChooseFontStruct;  // Common Dialog fun
  208.     LOGFONT    lf;                // Log font information
  209.     HDC        hDC;
  210.  
  211.     cf.cbSize = sizeof(cf);
  212.  
  213.     // Get the font formatting status into the CHARFORMAT strucuture,
  214.     // use the selected text. wParam is TRUE to indicate the
  215.     // selected text, FALSE for the first character in the
  216.     // RTF Edit control.
  217.     SendMessage(hRTFWnd, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf);
  218.  
  219.     // Fill in the font info for the font common fialog
  220.  
  221.     ZeroMemory(&ChooseFontStruct, sizeof(CHOOSEFONT));
  222.     ZeroMemory(&lf, sizeof(LOGFONT));
  223.  
  224.     hDC = GetDC(hWnd); // Need a screen DC, use the parent's DC
  225.  
  226.     // The RTF Edit control measures in twips, but LOGFONT measures
  227.     // in logical units (here, pixels) so we must convert.
  228.     //   1 point == 20 twips
  229.     //   1 inch  == 72 points
  230.     //     ==> 1 inch  == 1440 twips
  231.  
  232.     lf.lfHeight = MulDiv(cf.yHeight,
  233.                          GetDeviceCaps(hDC, LOGPIXELSY),
  234.                          -1440);
  235.  
  236.     // Done with this
  237.     ReleaseDC(hWnd, hDC);
  238.  
  239.     // Set up the rest of the logfont structure according to the 
  240.     // information retrieved from the EM_GETCHARFORMAT message
  241.  
  242.     if (cf.dwEffects & CFE_BOLD)
  243.         lf.lfWeight = FW_BOLD;
  244.     else
  245.         lf.lfWeight = FW_NORMAL;
  246.      lf.lfItalic = (BYTE)(cf.dwEffects & CFE_ITALIC);
  247.      lf.lfUnderline = (BYTE)(cf.dwEffects & CFE_UNDERLINE);
  248.     lf.lfCharSet = ANSI_CHARSET;
  249.     lf.lfQuality = DEFAULT_QUALITY;
  250.     lf.lfPitchAndFamily = cf.bPitchAndFamily;
  251.     lstrcpy(lf.lfFaceName, cf.szFaceName);
  252.  
  253.     // Fire up the common dialog.
  254.  
  255.     ChooseFontStruct.lStructSize = sizeof(ChooseFontStruct);
  256.     ChooseFontStruct.hwndOwner = hWnd;
  257.     ChooseFontStruct.hDC = GetCurrentPrinterDC();
  258.     ChooseFontStruct.lpLogFont = &lf;
  259.     ChooseFontStruct.Flags = CF_BOTH | CF_SCALABLEONLY | CF_WYSIWYG
  260.                              | CF_NOVECTORFONTS | CF_INITTOLOGFONTSTRUCT;
  261.     ChooseFontStruct.rgbColors = RGB(0,0,0);
  262.     ChooseFontStruct.nFontType = 0;
  263.  
  264.     if (ChooseFont(&ChooseFontStruct))
  265.     {
  266.         // Set the mask to tell the RTF Edit control to pay attention to
  267.         // the font formatting bits.
  268.         cf.dwMask = CFM_BOLD | CFM_FACE | CFM_ITALIC | 
  269.                     CFM_OFFSET | CFM_SIZE | CFM_UNDERLINE;
  270.  
  271.         // ChooseFont returns the new point size in tenths of a point so
  272.         // so we can multiply by 2 to get twips for the richedit control.
  273.  
  274.         cf.yHeight = 2 * ChooseFontStruct.iPointSize;
  275.  
  276.         // Fill in the rest of the character formatting
  277.          
  278.         cf.dwEffects = 0;
  279.         if (lf.lfWeight >= FW_BOLD)
  280.             cf.dwEffects |= CFE_BOLD;
  281.         if (lf.lfItalic)
  282.             cf.dwEffects |= CFE_ITALIC;
  283.  
  284.         if (lf.lfUnderline)
  285.             cf.dwEffects |= CFE_UNDERLINE;
  286.  
  287.         cf.bPitchAndFamily = lf.lfPitchAndFamily;
  288.  
  289.         lstrcpy(cf.szFaceName, lf.lfFaceName);
  290.  
  291.         // Set the new formatting to the selected text
  292.         SendMessage(hRTFWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
  293.     }
  294.  
  295.     if (ChooseFontStruct.hDC)
  296.         DeleteDC(ChooseFontStruct.hDC);
  297. }
  298.  
  299. //
  300. //  FUNCTION: SaveCallback(DWORD, LPBYTE, LONG, LONG *)
  301. //
  302. //  PURPOSE: Callback routine for the EM_STREAMOUT Message from
  303. //           the RichEdit control.
  304. //
  305. //  PARAMETERS:
  306. //    dwCookie - App supplied value (a file handle for this example)
  307. //    pbBuff - Pointer to data to write
  308. //    cb - size of data to write
  309. //    pcb - Number of bytes written to the file
  310. //
  311. //  RETURN VALUE:
  312. //    Always 0
  313. //
  314. //  COMMENTS:
  315. //
  316. //
  317.  
  318. DWORD CALLBACK SaveCallback(DWORD    dwCookie, // App supplied value
  319.                             LPBYTE   pbBuff,   // Pointer to data
  320.                             LONG     cb,       // size of data
  321.                             LONG     *pcb)     // Not used in streamout
  322. {
  323.     // Write the data to the disk for our example. dwCookie is used as a file
  324.     // handle for our example.
  325.     cb = _lwrite((HFILE)dwCookie, (LPCSTR) pbBuff, cb);
  326.     *pcb = cb; // Indicate the number of bytes written to the file
  327.     return 0;
  328. }
  329.  
  330. //
  331. //  FUNCTION: RTF_Save(LPSTR, HWND)
  332. //
  333. //  PURPOSE: Save the contents of the Richedit control to a file
  334. //
  335. //  PARAMETERS:
  336. //    hRTFWnd - Handle to RichEdit control
  337. //    szFileName - Name of file to save to
  338. //
  339. //  RETURN VALUE:
  340. //    TRUE if successful, FALSE otherwise
  341. //
  342. //  COMMENTS:
  343. //    This function utilizes the SaveCallback function above
  344. //
  345.  
  346. BOOL RTF_Save(LPSTR szFileName, HWND hRTFWnd)
  347. {
  348.     HFILE         hFile; // File handle
  349.     OFSTRUCT      of;    // open file strucuture
  350.     EDITSTREAM    es;    // The EDITSTREAM structure
  351.  
  352.     // Call the file save as dialog only if the szFileName is empty,
  353.     // otherwise szFileName already has a valid filename in it.
  354.  
  355.     if (*szFileName)
  356.     {
  357.         // Open the file, erasing previous contents
  358.         hFile = OpenFile(szFileName, &of, OF_CREATE);
  359.  
  360.         // Set up the EDITSTREAM structure
  361.         es.dwCookie    = (DWORD)hFile;   // our file handle
  362.         es.dwError     = 0;              // No error
  363.         es.pfnCallback = SaveCallback;   // Use above callback
  364.  
  365.         // Engage!
  366.         SendMessage(hRTFWnd, EM_STREAMOUT, SF_RTF, (LPARAM)&es);
  367.  
  368.         // Close the file
  369.         _lclose ( hFile );
  370.  
  371.         // Clear the dirty bit
  372.         SendMessage(hRTFWnd, EM_SETMODIFY, FALSE, 0L);
  373.         return TRUE;
  374.     }
  375.  
  376.     return FALSE;
  377. }
  378.  
  379. //
  380. //  FUNCTION: OpenCallback(DWORD, LPBYTE, LONG, LONG *)
  381. //
  382. //  PURPOSE: Callback routine for the EM_STREAMIN Message from
  383. //           the RichEdit control.
  384. //
  385. //  PARAMETERS:
  386. //    dwCookie - App supplied value (a file handle for this example)
  387. //    pbBuff - Pointer to data to read from disk
  388. //    cb - size of data to read
  389. //    pcb - Number of bytes read from the file
  390. //
  391. //  RETURN VALUE:
  392. //    Always 0
  393. //
  394. //  COMMENTS:
  395. //
  396. //
  397.  
  398. DWORD CALLBACK OpenCallback(DWORD    dwCookie,
  399.                             LPBYTE   pbBuff,
  400.                             LONG     cb,
  401.                             LONG     *pcb)
  402. {
  403.   // Read as much data as allowed in the cb variable
  404.   *pcb = _lread((HFILE)dwCookie, pbBuff, cb);
  405.   if (*pcb <= 0) // EOF?
  406.       *pcb = 0;    // Indicate the read is complete
  407.   return 0;
  408. }
  409.  
  410. //
  411. //  FUNCTION: RTF_Open(LPSTR, HWND)
  412. //
  413. //  PURPOSE: Load the contents of a file ito the Richedit control
  414. //
  415. //  PARAMETERS:
  416. //    hRTFWnd - Handle to RichEdit control
  417. //    szFileName - Name of file to save to
  418. //
  419. //  RETURN VALUE:
  420. //    TRUE if successful, FALSE otherwise
  421. //
  422. //  COMMENTS:
  423. //    This function utilizes the OpenCallback function above
  424. //
  425.  
  426. BOOL RTF_Open(LPSTR szFileName, HWND hRTFWnd)
  427. {
  428.     HFILE         hFile;  // File handle
  429.     OFSTRUCT      of;     // open file strucuture
  430.     EDITSTREAM    es;     // The EDITSTREAM structure
  431.  
  432.     // Get a filename to load from
  433.  
  434.     if (*szFileName)
  435.     {
  436.         // Open the file for reading
  437.         hFile = OpenFile(szFileName, &of, OF_READ);
  438.  
  439.         if (hFile)
  440.         {
  441.             es.dwCookie    = (DWORD)hFile; // our file handle
  442.             es.dwError     = 0;            // No error
  443.             es.pfnCallback = OpenCallback; // Use above callback
  444.  
  445.             // Make it so!
  446.             SendMessage(hRTFWnd, EM_STREAMIN, SF_RTF, (LPARAM)&es);
  447.  
  448.             // Clear the dirty bit
  449.             SendMessage(hRTFWnd, EM_SETMODIFY, 0, 0L);
  450.  
  451.             // Close the file
  452.             _lclose(hFile);
  453.         }
  454.  
  455.         // Update the toolbar
  456.         RTF_ShowCharAttributes();
  457.  
  458.         return TRUE;
  459.     }
  460.  
  461.     return FALSE;
  462. }
  463.  
  464. //
  465. //  FUNCTION: RTF_GetCurrentFont(HWND, LPSTR)
  466. //
  467. //  PURPOSE: Get the facename of the selected text's font
  468. //
  469. //  PARAMETERS:
  470. //    hRTFWnd - Handle to RichEdit control
  471. //    szFont - String to contain facename
  472. //
  473. //  RETURN VALUE:
  474. //    None
  475. //
  476. //  COMMENTS:
  477. //    The string is a null string if the selection has more than
  478. //    one facename of font
  479. //
  480.  
  481. void RTF_GetCurrentFont(HWND hRTFWnd, LPSTR szFont)
  482. {
  483.     CHARFORMAT cf;                // This is defined in RICHEDIT.H
  484.  
  485.     cf.cbSize = sizeof(cf);
  486.         
  487.     // Get the font formatting status into the CHARFORMAT strucuture,
  488.     // use the selected text. wParam is TRUE to indicate the
  489.     // selected text, FALSE for the first character in the
  490.     // RTF Edit control.
  491.     SendMessage(hRTFWnd, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf);
  492.  
  493.     if (cf.dwMask & CFM_FACE)
  494.         lstrcpy(szFont, cf.szFaceName);
  495.     else
  496.         *szFont = 0;
  497.  
  498. }
  499.  
  500. //
  501. //  FUNCTION: RTF_SetCurrentFont(HWND, LPSTR)
  502. //
  503. //  PURPOSE: Set the facename of the selected text's font
  504. //
  505. //  PARAMETERS:
  506. //    hRTFWnd - Handle to RichEdit control
  507. //    szFont - String that contains facename
  508. //
  509. //  RETURN VALUE:
  510. //    None
  511. //
  512. //  COMMENTS:
  513. //
  514.  
  515. void RTF_SetCurrentFont(HWND hRTFWnd, LPSTR szFont)
  516. {
  517.     CHARFORMAT cf;                // This is defined in RICHEDIT.H
  518.  
  519.     cf.cbSize = sizeof(cf);
  520.  
  521.     // Get the font formatting status into the CHARFORMAT strucuture,
  522.     // use the selected text. wParam is TRUE to indicate the
  523.     // selected text, FALSE for the first character in the
  524.     // RTF Edit control.
  525.     SendMessage(hRTFWnd, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf);
  526.  
  527.     cf.dwMask = CFM_FACE;
  528.  
  529.     lstrcpy(cf.szFaceName, szFont);
  530.  
  531.     SendMessage(hRTFWnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
  532. }
  533.  
  534. //
  535. //  FUNCTION: RTF_ChangeMargins(HWND, UINT, UINT, UINT)
  536. //
  537. //  PURPOSE: Set the margins of the current paragraph.
  538. //
  539. //  PARAMETERS:
  540. //    hRTFWnd - Handle to RichEdit control
  541. //    dxStartIndent - Indent in twips of first line's left margin
  542. //    dxRightIndent - Indent in twips from right edge of printable area
  543. //                    of right margin.
  544. //    dxOffset - Distance in twips of second, third, etc line's left
  545. //               margin
  546. //
  547. //  RETURN VALUE:
  548. //    None
  549. //
  550. //  COMMENTS:
  551. //    This function uses the RM_GETTABS (RULER.H) message to set the
  552. //    tabs.
  553. //
  554.  
  555. void RTF_ChangeMargins(HWND hwndRuler,
  556.                        UINT dxStartIndent,
  557.                        UINT dxRightIndent,
  558.                        UINT dxOffset)
  559. {
  560.     PARAFORMAT pf;
  561.  
  562.     pf.cbSize = sizeof(pf);
  563.     pf.dwMask = PFM_STARTINDENT | PFM_RIGHTINDENT | PFM_OFFSET | PFM_TABSTOPS;
  564.     pf.dxStartIndent = dxStartIndent;
  565.     pf.dxRightIndent = dxRightIndent;
  566.     pf.dxOffset = dxOffset;
  567.  
  568.     pf.cTabCount = (short)SendMessage(hwndRuler, 
  569.                                       RM_GETTABS, 
  570.                                       (WPARAM)25,
  571.                                       (LPARAM)(pf.rgxTabs));
  572.  
  573.     SendMessage(GetEditWindow(NULL), EM_SETPARAFORMAT, 0, (LPARAM)&pf);
  574. }
  575.  
  576. //
  577. //  FUNCTION: RTF_ShowMargins(HWND)
  578. //
  579. //  PURPOSE: Get the margins of the current paragraph and reflect them
  580. //           on the ruler.
  581. //
  582. //  PARAMETERS:
  583. //    hwndRuler - Handle to Ruler control (RULER.H)
  584. //
  585. //  RETURN VALUE:
  586. //    None
  587. //
  588. //  COMMENTS:
  589. //
  590.  
  591. void RTF_ShowMargins(HWND hwndRuler)
  592. {
  593.      PARAFORMAT pf;
  594.      
  595.      pf.cbSize = sizeof(pf);
  596.      SendMessage (GetEditWindow(NULL), EM_GETPARAFORMAT, 0, (LPARAM)&pf);
  597.  
  598.      if (
  599.           (pf.dwMask & (PFM_STARTINDENT|PFM_RIGHTINDENT|PFM_OFFSET)) ==
  600.           (PFM_STARTINDENT|PFM_RIGHTINDENT|PFM_OFFSET)
  601.         )
  602.      {
  603.          int iMargins[5];
  604.          iMargins[0] = pf.dxStartIndent + pf.dxOffset;
  605.          iMargins[1] = pf.dxRightIndent;
  606.          iMargins[2] = pf.dxStartIndent;
  607.          iMargins[3] = 0;
  608.          iMargins[4] = 7*1440;
  609.          SendMessage(hwndRuler, RM_SETMARGINS, 0, (LPARAM)iMargins);
  610.      }
  611.      SendMessage (hwndRuler, 
  612.                   RM_SETTABS, 
  613.                   (WPARAM)(pf.cTabCount), 
  614.                   (LPARAM)(pf.rgxTabs));
  615.  
  616. }
  617.  
  618. //
  619. //  FUNCTION: SetToolbarButtonToReflectCharacterAttribute(UINT,DWORD,DWORD)
  620. //
  621. //  PURPOSE: Show the status of an attribute on a toolbar button
  622. //
  623. //  PARAMETERS:
  624. //    uID - ID of the toolbar button
  625. //    dwMask - Attribute mask to check for
  626. //    dwEffects - Attribute to check for
  627. //
  628. //  RETURN VALUE:
  629. //    None
  630. //
  631. //  COMMENTS:
  632. //
  633.  
  634. void SetToolbarButtonToReflectCharacterAttribute(UINT uID, 
  635.                                                  DWORD dwMask, 
  636.                                                  DWORD dwEffects)
  637. {
  638.     int iState = RTF_GetCharAttribute(GetEditWindow(NULL), 
  639.                                       dwMask, 
  640.                                       dwEffects);
  641.     switch (iState)
  642.     {
  643.         case CHAR_ATTRIB_YES:    
  644.  
  645.             UpdateButton (uID, TBSTATE_ENABLED | TBSTATE_CHECKED); 
  646.             break;
  647.  
  648.         case CHAR_ATTRIB_NO :    
  649.  
  650.             UpdateButton (uID, TBSTATE_ENABLED); 
  651.             break;
  652.  
  653.         case CHAR_ATTRIB_WAFFLE: 
  654.  
  655.             UpdateButton (uID, TBSTATE_ENABLED | TBSTATE_INDETERMINATE); 
  656.             break;
  657.     }
  658. }
  659.  
  660. //
  661. //  FUNCTION: RTF_ShowCharAttributes()
  662. //
  663. //  PURPOSE: Show the status of the bold, itailc, and underline
  664. //           attributes on the toolbar
  665. //
  666. //  PARAMETERS:
  667. //    none
  668. //
  669. //  RETURN VALUE:
  670. //    None
  671. //
  672. //  COMMENTS:
  673. //
  674.  
  675. void RTF_ShowCharAttributes(void)
  676. {
  677.   SetToolbarButtonToReflectCharacterAttribute(IDM_EDITBOLD, 
  678.                                               CFM_BOLD, 
  679.                                               CFE_BOLD);
  680.   SetToolbarButtonToReflectCharacterAttribute(IDM_EDITITALIC, 
  681.                                               CFM_ITALIC, 
  682.                                               CFE_ITALIC);
  683.   SetToolbarButtonToReflectCharacterAttribute(IDM_EDITUNDERLINE, 
  684.                                               CFM_UNDERLINE, 
  685.                                               CFE_UNDERLINE);
  686. }
  687.