RWDLG.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:44k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples. 
  3. *       Copyright (C) 1993-1997 Microsoft Corporation.
  4. *       All rights reserved. 
  5. *       This source code is only intended as a supplement to 
  6. *       Microsoft Development Tools and/or WinHelp documentation.
  7. *       See these sources for detailed information regarding the 
  8. *       Microsoft samples programs.
  9. ******************************************************************************/
  10. /****************************** Module Header *******************************
  11. * Module Name: rwdlg.c
  12. *
  13. * Does the writing of .DLG files.
  14. *
  15. * Functions:
  16. *    WriteDlg()
  17. *    WriteDlgInclude()
  18. *    WriteDialogHeader()
  19. *    WriteDialogHeaderLanguage()
  20. *    WriteControl()
  21. *    WriteNameOrd()
  22. *    WriteText()
  23. *    WriteIDDlg()
  24. *    GetControlKeyword()
  25. *    WriteClass()
  26. *    WriteStyles()
  27. *    WriteClassStyle()
  28. *    WriteCustomStyle()
  29. *    WriteCoords()
  30. *    WriteValue()
  31. *    WriteHexWord()
  32. *    WriteHexDWord()
  33. *    WriteString()
  34. *    WriteQuotedString()
  35. *    WriteEscapedString()
  36. *    WriteDlgChar()
  37. *    WriteDlgFlush()
  38. *    Tab()
  39. *    NewLine()
  40. *    Quote()
  41. *    Comma()
  42. *    Space()
  43. *    ORSymbol()
  44. *
  45. * Comments:
  46. *
  47. ****************************************************************************/
  48. #include "dlgedit.h"
  49. #include "dlgfuncs.h"
  50. #include "dlgextrn.h"
  51. /*
  52.  * Wrap lines before they go over this right margin.
  53.  */
  54. #define CCHRIGHTMARGIN      76
  55. /*
  56.  * Defines for the tabs and tab indent levels.
  57.  */
  58. #define CCHTABWIDTH         4           // Tabs are four spaces wide.
  59. #define TABLEVELNONE        0           // No indent (at left margin).
  60. #define TABLEVELCONTROL     1           // Indent to start of controls.
  61. #define TABLEVELCONTROLDESC 5           // Indent to control description.
  62. /*
  63.  * Macro to set the current tab level.  The level is multiplied
  64.  * by the tab width.
  65.  */
  66. #define SetTab(t)           (cTabStop = ((t)*CCHTABWIDTH))
  67. /*
  68.  * Macro that determines if the current position is the first
  69.  * column for the current tab setting.
  70.  */
  71. #define AtFirstTabColumn()  ((cColumn == cTabStop) ? TRUE : FALSE)
  72. STATICFN VOID WriteDlgInclude(LPTSTR pszFullDlgFile);
  73. STATICFN PCONTROLDATA WriteDialogHeader(PRES pRes, PDIALOGBOXHEADER pdbh);
  74. STATICFN VOID WriteDialogHeaderLanguage(WORD wLanguage);
  75. STATICFN PCONTROLDATA WriteControl(PCONTROLDATA pcd);
  76. STATICFN VOID WriteNameOrd(LPTSTR pszNameOrd);
  77. STATICFN VOID WriteText(LPTSTR pszText);
  78. STATICFN VOID WriteIDDlg(INT id, BOOL fHexOK);
  79. STATICFN LPTSTR GetControlKeyword(INT iClass, DWORD flStyle,
  80.     DWORD *pflStylePredef, DWORD *pflStyleDefault, BOOL *pfWriteText,
  81.     BOOL *pfNotFound);
  82. STATICFN VOID WriteClass(LPTSTR pszClass);
  83. STATICFN BOOL WriteStyles(INT iClass, LPTSTR pszClass, DWORD flStyle,
  84.     DWORD flStylePredef, DWORD flStyleDefault, PDWORD pflStyleLeft,
  85.     BOOL fNullStyles, BOOL fCommaPrefix);
  86. STATICFN BOOL WriteClassStyle(INT iClass, DWORD flStyle,
  87.     DWORD flStylePredef, DWORD flStyleDefault, PDWORD pflStyleLeft,
  88.     BOOL fPrevWritten, BOOL fNullStyles, BOOL fCommaPrefix);
  89. STATICFN BOOL WriteCustomStyle(LPTSTR pszClass, DWORD flStyle,
  90.     PDWORD pflStyleLeft);
  91. STATICFN VOID WriteCoords(INT x, INT y, INT cx, INT cy);
  92. STATICFN VOID WriteValue(INT n);
  93. STATICFN VOID WriteHexWord(WORD w);
  94. STATICFN VOID WriteHexDWord(DWORD dw);
  95. STATICFN VOID WriteString(LPTSTR psz);
  96. STATICFN VOID WriteQuotedString(LPTSTR psz);
  97. STATICFN VOID WriteEscapedString(LPTSTR psz);
  98. STATICFN VOID WriteDlgChar(TCHAR ch);
  99. STATICFN VOID WriteDlgFlush(VOID);
  100. STATICFN VOID Tab(VOID);
  101. STATICFN VOID NewLine(VOID);
  102. STATICFN VOID Quote(VOID);
  103. STATICFN VOID Comma(VOID);
  104. STATICFN VOID Space(VOID);
  105. STATICFN VOID ORSymbol(VOID);
  106. static INT cColumn;                 /* Current column in the line.      */
  107. static INT cTabStop;                /* Current tabstop column.          */
  108. static HANDLE hfDlg;                /* All workers write to this file.  */
  109. static jmp_buf jbWriteDlg;          /* Capture the state for longjmp.   */
  110. /************************************************************************
  111. * WriteDlg
  112. *
  113. * This function writes the dialog boxes in the given resource to the
  114. * hfWrite file in the .DLG file RC format.
  115. *
  116. * Arguments:
  117. *    HANDLE - handle to the file
  118. *    LPTSTR - pointer to the resource file name
  119. *
  120. ************************************************************************/
  121. BOOL WriteDlg(
  122.     HANDLE hfWrite,
  123.     LPTSTR pszFullDlgFile)
  124. {
  125.     HANDLE hResLocked = NULL;
  126.     PRES pRes = NULL;
  127.     PRESLINK prl;
  128.     PDIALOGBOXHEADER pdbh;
  129.     PCONTROLDATA pcd;
  130.     INT cItems;
  131.     /*
  132.      * Set our error trap up.  The api setjmp will return a zero at first,
  133.      * then if a write error occurs later and longjmp is called, it
  134.      * will return non-zero and we will return the failure up to the
  135.      * caller.  After this point, there must be no calls to allocate
  136.      * memory, open files, etc., unless this trap has a way to detect
  137.      * what happened and clean it up.  See the c-runtime help file for more
  138.      * information about setjump/longjmp.
  139.      */
  140.     if (_setjmp(jbWriteDlg)) {
  141.         /*
  142.          * If the resource is locked, unlock it.
  143.          */
  144.         if (hResLocked)
  145.             GlobalUnlock(hResLocked);
  146.         return FALSE;
  147.     }
  148.     /*
  149.      * Initialize our globals.  The hfDlg global is used so that hfWrite
  150.      * doesn't have to be passed on the stack over and over.
  151.      */
  152.     hfDlg = hfWrite;
  153.     cColumn = 0;
  154.     SetTab(TABLEVELNONE);
  155.     WriteDlgInclude(pszFullDlgFile);
  156.     /*
  157.      * Process each resource in the list.
  158.      */
  159.     for (prl = gprlHead; prl; prl = prl->prlNext) {
  160.         /*
  161.          * Skip if it is not a dialog resource.
  162.          */
  163.         if (!prl->fDlgResource)
  164.             continue;
  165.         /*
  166.          * Set up pointers to this dialog resource.
  167.          */
  168.         pRes = (PRES)GlobalLock(prl->hRes);
  169.         hResLocked = prl->hRes;
  170.         pdbh = (PDIALOGBOXHEADER)SkipResHeader(pRes);
  171.         NewLine();
  172.         pcd = WriteDialogHeader(pRes, pdbh);
  173.         WriteString(ids(IDS_BEGIN));
  174.         NewLine();
  175.         /*
  176.          * Write the controls.
  177.          */
  178.         cItems = (INT)pdbh->NumberOfItems;
  179.         while (cItems--)
  180.             pcd = WriteControl(pcd);
  181.         /*
  182.          * Finish up dialog template.
  183.          */
  184.         WriteString(ids(IDS_END));
  185.         NewLine();
  186.         GlobalUnlock(prl->hRes);
  187.         hResLocked = NULL;
  188.     }
  189.     /*
  190.      * Flush any remaining characters in the write buffer.
  191.      */
  192.     WriteDlgFlush();
  193.     return TRUE;
  194. }
  195. /************************************************************************
  196. * WriteDlgInclude
  197. *
  198. * This routine writes out the "DLGINCLUDE" lines to the .DLG file.
  199. *
  200. * Arguments:
  201. *    LPTSTR - dialog file name
  202. *
  203. ************************************************************************/
  204. STATICFN VOID WriteDlgInclude(
  205.     LPTSTR pszFullDlgFile)
  206. {
  207.     if (pszIncludeFile) {
  208.         WriteValue(ORDID_DLGINCLUDE_NAME);
  209.         Space();
  210.         WriteString(ids(IDS_DLGINCLUDE));
  211.         Space();
  212.         Quote();
  213.         /*
  214.          * If the include file is in a different directory than the resource
  215.          * file, write the full path to it.  Otherwise, we just write the
  216.          * include file name.
  217.          */
  218.         if (DifferentDirs(pszFullDlgFile, szFullIncludeFile))
  219.             WriteEscapedString(szFullIncludeFile);
  220.         else
  221.             WriteEscapedString(pszIncludeFile);
  222.         Quote();
  223.         NewLine();
  224.     }
  225. }
  226. /************************************************************************
  227. * WriteDialogHeader
  228. *
  229. * Writes out the dialog header lines.
  230. *
  231. * Arguments:
  232. *    PRES - pointer to the resource
  233. *    PDIALOGBOXHEADER - pointer to the dialog box header
  234. *
  235. ************************************************************************/
  236. STATICFN PCONTROLDATA WriteDialogHeader(
  237.     PRES pRes,
  238.     PDIALOGBOXHEADER pdbh)
  239. {
  240.     DWORD flStyle;
  241.     DWORD flExtStyle;
  242.     DWORD flStyleLeft;
  243.     INT cdit;
  244.     INT x;
  245.     INT y;
  246.     INT cx;
  247.     INT cy;
  248.     LPTSTR pszMenuName;
  249.     LPTSTR pszClass;
  250.     LPTSTR pszCaption;
  251.     INT nPointSize;
  252.     LPTSTR pszFontName;
  253.     PCONTROLDATA pcd;
  254.     PRES2 pRes2;
  255.     BOOL fWritten;
  256.     pRes2 = ResourcePart2(pRes);
  257.     WriteNameOrd(ResourceName(pRes));
  258.     Space();
  259.     WriteString(ids(IDS_DIALOG));
  260.     if (pRes2->MemoryFlags & MMF_PRELOAD) {
  261.         Space();
  262.         WriteString(ids(IDS_PRELOAD));
  263.     }
  264.     if (!(pRes2->MemoryFlags & MMF_MOVEABLE)) {
  265.         Space();
  266.         WriteString(ids(IDS_FIXED));
  267.     }
  268.     if (!(pRes2->MemoryFlags & MMF_PURE)) {
  269.         Space();
  270.         WriteString(ids(IDS_IMPURE));
  271.     }
  272.     /*
  273.      * Parse out the dialog template.
  274.      */
  275.     pcd = ParseDialogBoxHeader(pdbh, &flStyle, &flExtStyle, &cdit, &x, &y,
  276.             &cx, &cy, &pszMenuName, &pszClass, &pszCaption,
  277.             &nPointSize, &pszFontName);
  278.     Space();
  279.     WriteCoords(x, y, cx, cy);
  280.     NewLine();
  281.     /*
  282.      * Write the language.
  283.      */
  284.     WriteDialogHeaderLanguage(pRes2->LanguageId);
  285.     /*
  286.      * Print out the "STYLE" line for the dialog.
  287.      */
  288.     WriteString(ids(IDS_STYLE));
  289.     Space();
  290.     SetTab(TABLEVELCONTROL);
  291.     WriteStyles(IC_DIALOG, NULL, flStyle, 0L, 0L, &flStyleLeft, TRUE, FALSE);
  292.     SetTab(TABLEVELNONE);
  293.     NewLine();
  294.     /*
  295.      * Print out the "EXSTYLE" line for the dialog, if necessary.
  296.      */
  297.     if (flExtStyle) {
  298.         WriteString(ids(IDS_EXSTYLE));
  299.         Space();
  300.         SetTab(TABLEVELCONTROL);
  301.         fWritten = WriteClassStyle(IC_EXSTYLE, flExtStyle, 0L, 0L,
  302.                 &flStyleLeft, FALSE, TRUE, FALSE);
  303.         /*
  304.          * If there is anything left (styles that the dialog editor
  305.          * does not know about) write it out as a hex constant.
  306.          */
  307.         if (flStyleLeft) {
  308.             if (fWritten)
  309.                 ORSymbol();
  310.             WriteHexDWord(flStyleLeft);
  311.         }
  312.         SetTab(TABLEVELNONE);
  313.         NewLine();
  314.     }
  315.     /*
  316.      * If it has a caption, print it out.
  317.      */
  318.     if (*pszCaption) {
  319.         WriteString(ids(IDS_CAPTION));
  320.         Space();
  321.         WriteText(pszCaption);
  322.         NewLine();
  323.     }
  324.     /*
  325.      * If it has a font specified, print it out.
  326.      */
  327.     if (flStyle & DS_SETFONT) {
  328.         WriteString(ids(IDS_FONT));
  329.         Space();
  330.         WriteValue(nPointSize);
  331.         Comma();
  332.         WriteQuotedString(pszFontName);
  333.         NewLine();
  334.     }
  335.     /*
  336.      * If it has a class specified, print it out.
  337.      */
  338.     if (*pszClass) {
  339.         WriteString(ids(IDS_CLASS));
  340.         Space();
  341.         WriteText(pszClass);
  342.         NewLine();
  343.     }
  344.     /*
  345.      * If it has a menu specified, print it out.
  346.      */
  347.     if (*pszMenuName) {
  348.         WriteString(ids(IDS_MENU));
  349.         Space();
  350.         WriteNameOrd(pszMenuName);
  351.         NewLine();
  352.     }
  353.     if (pRes2->Version) {
  354.         WriteString(ids(IDS_VERSION));
  355.         Space();
  356.         WriteValue(pRes2->Version);
  357.         NewLine();
  358.     }
  359.     if (pRes2->Characteristics) {
  360.         WriteString(ids(IDS_CHARACTERISTICS));
  361.         Space();
  362.         WriteValue(pRes2->Characteristics);
  363.         NewLine();
  364.     }
  365.     return pcd;
  366. }
  367. /************************************************************************
  368. * WriteDialogHeaderLanguage
  369. *
  370. * Writes out the dialog header "LANGUAGE" line.
  371. *
  372. * Arguments:
  373. *    WORD - language to write out
  374. *
  375. ************************************************************************/
  376. STATICFN VOID WriteDialogHeaderLanguage(
  377.     WORD wLanguage)
  378. {
  379.     WORD wPrimary;
  380.     WORD wSubLang;
  381.     INT i;
  382.     INT j;
  383.     INT idsLang;
  384.     INT idsSubLang;
  385.     WriteString(ids(IDS_LANGUAGE));
  386.     Space();
  387.     idsLang = 0;
  388.     idsSubLang = 0;
  389.     wPrimary = (WORD)PRIMARYLANGID(wLanguage);
  390.     wSubLang = SUBLANGID(wLanguage);
  391.     for (i = 0; i < gcLanguages; i++) {
  392.         if (gaLangTable[i].wPrimary == wPrimary) {
  393.             idsLang = gaLangTable[i].idsLang;
  394.             for (j = 0; j < gaLangTable[i].cSubLangs; j++) {
  395.                 if (gaLangTable[i].asl[j].wSubLang == wSubLang) {
  396.                     idsSubLang = gaLangTable[i].asl[j].idsSubLang;
  397.                     break;
  398.                 }
  399.             }
  400.             break;
  401.         }
  402.     }
  403.     if (idsLang)
  404.         WriteString(ids(idsLang));
  405.     else
  406.         WriteHexWord(wPrimary);
  407.     Comma();
  408.     if (idsSubLang)
  409.         WriteString(ids(idsSubLang));
  410.     else
  411.         WriteHexWord(wSubLang);
  412.     NewLine();
  413. }
  414. /************************************************************************
  415. * WriteControl
  416. *
  417. * Writes out a control line.
  418. *
  419. * Arguments:
  420. *    PCONTROLDATA - pointer to the control data
  421. *
  422. ************************************************************************/
  423. STATICFN PCONTROLDATA WriteControl(
  424.     PCONTROLDATA pcd)
  425. {
  426.     INT x;
  427.     INT y;
  428.     INT cx;
  429.     INT cy;
  430.     INT id;
  431.     DWORD flStyle;
  432.     DWORD flExtStyle;
  433.     LPTSTR pszClass;
  434.     LPTSTR pszText;
  435.     INT iClass;
  436.     LPTSTR pszKeyword;
  437.     BOOL fWriteText;
  438.     BOOL fNotFound;
  439.     DWORD flStylePredef;
  440.     DWORD flStyleDefault;
  441.     DWORD flStyleLeft;
  442.     BOOL fWritten;
  443.     pcd = ParseControlData(pcd, &flStyle, &flExtStyle, &x, &y, &cx, &cy,
  444.             &id, &pszClass, &pszText);
  445.     /*
  446.      * Determine the class of the control.
  447.      */
  448.     iClass = GetiClass(pszClass);
  449.     /*
  450.      * Determine if there are any predefined RC keywords that we
  451.      * can use instead of the generic "CONTROL" keyword for this
  452.      * style of control.
  453.      */
  454.     pszKeyword = GetControlKeyword(iClass, flStyle, &flStylePredef,
  455.             &flStyleDefault, &fWriteText, &fNotFound);
  456.     SetTab(TABLEVELCONTROL);
  457.     Tab();
  458.     WriteString(pszKeyword);
  459.     SetTab(TABLEVELCONTROLDESC);
  460.     Tab();
  461.     /*
  462.      * Write out the text field, if this type of control has one.
  463.      */
  464.     if (fWriteText) {
  465. #ifdef JAPAN
  466.         TCHAR   szTmp[CCHTEXTMAX];
  467.         KDExpandCopy(szTmp, pszText, CCHTEXTMAX);
  468.         WriteText(szTmp);
  469. #else
  470.         WriteText(pszText);
  471. #endif
  472.         Comma();
  473.     }
  474.     /*
  475.      * Write out the id for the control.
  476.      */
  477.     WriteIDDlg(id, TRUE);
  478.     /*
  479.      * If we did not find a predefined keyword to use instead of "CONTROL",
  480.      * we have to write out the fields in a different order, and specify
  481.      * the class as well.
  482.      */
  483.     if (fNotFound) {
  484.         WriteClass(pszClass);
  485.         Comma();
  486.         fWritten = WriteStyles(iClass, pszClass, flStyle, flStylePredef,
  487.                 flStyleDefault, &flStyleLeft, fNotFound, FALSE);
  488.         if (!fWritten || flStyleLeft) {
  489.             if (fWritten)
  490.                 ORSymbol();
  491.             WriteHexWord(LOWORD(flStyleLeft));
  492.         }
  493.         Comma();
  494.         WriteCoords(x, y, cx, cy);
  495.     }
  496.     else {
  497.         Comma();
  498.         WriteCoords(x, y, cx, cy);
  499.         fWritten = WriteStyles(iClass, pszClass, flStyle, flStylePredef,
  500.                 flStyleDefault, &flStyleLeft, fNotFound, TRUE);
  501.         if (flStyleLeft) {
  502.             if (fWritten)
  503.                 ORSymbol();
  504.             else
  505.                 Comma();
  506.             WriteHexWord(LOWORD(flStyleLeft));
  507.             fWritten = TRUE;
  508.         }
  509.     }
  510.     /*
  511.      * Write out the extended styles for the control, if necessary.
  512.      */
  513.     if (flExtStyle) {
  514.         /*
  515.          * If writing a predefined keyword (not CONTROL), and there
  516.          * were no styles written out at the end of the line, write
  517.          * a style of zero.  RC doesn't like consecutive comma's,
  518.          * and we need to skip the styles field to get to the
  519.          * extended styles field.
  520.          */
  521.         if (!fNotFound && !fWritten) {
  522.             Comma();
  523.             WriteValue(0);
  524.         }
  525.         Comma();
  526.         fWritten = WriteClassStyle(IC_EXSTYLE, flExtStyle, 0L, 0L,
  527.                 &flStyleLeft, FALSE, TRUE, FALSE);
  528.         /*
  529.          * If there is anything left (styles that the dialog editor
  530.          * does not know about) write it out as a hex constant.
  531.          */
  532.         if (flStyleLeft) {
  533.             if (fWritten)
  534.                 ORSymbol();
  535.             WriteHexDWord(flStyleLeft);
  536.         }
  537.     }
  538.     SetTab(TABLEVELNONE);
  539.     NewLine();
  540.     return pcd;
  541. }
  542. /************************************************************************
  543. * WriteNameOrd
  544. *
  545. * Writes out the name/ordinal.  Handles the case where the name
  546. * is really an ordinal instead of a string.  When it is a string,
  547. * it will not be quoted.
  548. *
  549. * This routine never writes the ordinal out in hex, because the
  550. * items that it is intended to write are not parsed properly by
  551. * the Windows RC.EXE if they are written in hex notation.
  552. *
  553. * Arguments:
  554. *   LPTSTR pszNameOrd - The name/ordinal to write.
  555. *
  556. ************************************************************************/
  557. STATICFN VOID WriteNameOrd(
  558.     LPTSTR pszNameOrd)
  559. {
  560.     if (IsOrd(pszNameOrd))
  561.         /*
  562.          * Write the name as a numeric ordinal.
  563.          */
  564.         WriteIDDlg(OrdID(pszNameOrd), FALSE);
  565.     else
  566.         WriteString(pszNameOrd);
  567. }
  568. /************************************************************************
  569. * WriteText
  570. *
  571. * Writes out the text for a control or dialog.  This will either be
  572. * an ordinal (icon's text field) or a quoted string.
  573. *
  574. * Arguments:
  575. *    LPTSTR pszText - text to write out
  576. *
  577. ************************************************************************/
  578. STATICFN VOID WriteText(
  579.     LPTSTR pszText)
  580. {
  581.     if (IsOrd(pszText))
  582.         /*
  583.          * Write the text as an ID.  Hex notation is allowed.
  584.          */
  585.         WriteIDDlg(OrdID(pszText), TRUE);
  586.     else
  587.         WriteQuotedString(pszText);
  588. }
  589. /************************************************************************
  590. * WriteIDDlg
  591. *
  592. * Writes out the ID.  This may be written out as either a symbol
  593. * or a numeric.
  594. *
  595. * Arguments:
  596. *    INT id - id to write out
  597. *    BOOL fHexOK - flag specifies whether the id is a hex numeric.
  598. *
  599. ************************************************************************/
  600. STATICFN VOID WriteIDDlg(
  601.     INT id,
  602.     BOOL fHexOK)
  603. {
  604.     TCHAR szID[CCHTEXTMAX];
  605.     IDToLabel(szID, id, fHexOK);
  606.     WriteString(szID);
  607. }
  608. /************************************************************************
  609. * GetControlKeyword
  610. *
  611. * This routine does a lookup in the predefined RC keyword table
  612. * associated with the given class for a keyword that can be used
  613. * instead of "CONTROL".  The match is based on the style of the control
  614. * that is passed in.  If a match is not found, it defaults all the
  615. * returned values to use the "CONTROL" keyword.
  616. *
  617. * Arguments:
  618. *   INT iClass              - The class of the control.
  619. *   DWORD flStyle           - The style of the control.
  620. *   DWORD *pflStylePredef   - Return for the bits of the predefined control
  621. *                             (if found).  These can be removed later from
  622. *                             the style flag.
  623. *   DWORD *pflStyleDefault  - Return for the default styles.
  624. *   BOOL *pfWriteText       - Return for the "Write Text" flag.  This will
  625. *                             be TRUE if this control has a text field.
  626. *   BOOL *pfNotFound        - Return for the "Not Found" flag.  This will
  627. *                             be TRUE if no match was found and the "CONTROL"
  628. *                             keyword was defaulted to.
  629. *
  630. * Returns:
  631. *   A pointer to the control keyword to use.
  632. *   If a match was found, *pflStylePredef is set to the bits for the match.
  633. *       If not found, this is set to zero.
  634. *   The default style bits for this keyword will be returned.
  635. *   The "Write Text" flag will be set.
  636. *   The "Not Found" flag will be set.
  637. *
  638. ************************************************************************/
  639. STATICFN LPTSTR GetControlKeyword(
  640.     INT iClass,
  641.     DWORD flStyle,
  642.     DWORD *pflStylePredef,
  643.     DWORD *pflStyleDefault,
  644.     BOOL *pfWriteText,
  645.     BOOL *pfNotFound)
  646. {
  647.     register INT i;
  648.     INT iMax;
  649.     PRCKEYWORD prckwd;
  650.     if (gfUseNewKeywords && iClass != IC_UNKNOWN) {
  651.         iMax = acsd[iClass].cKeywords;
  652.         prckwd = acsd[iClass].parckwd;
  653.         /*
  654.          * Loop through all the keywords for this class.
  655.          */
  656.         for (i = 0; i < iMax; i++, prckwd++) {
  657.             /*
  658.              * Does the style (masked) exactly match the keywords style?
  659.              */
  660.             if ((flStyle & prckwd->flStyleMask) == prckwd->flStyle) {
  661.                 /*
  662.                  * Yes.  Set the "Has Text" flag, we did find a match,
  663.                  * put the found bits in the predefined style flag,
  664.                  * set the default styles flag and return the found
  665.                  * keyword.
  666.                  */
  667.                 *pfWriteText = prckwd->fHasText;
  668.                 *pfNotFound = FALSE;
  669.                 *pflStylePredef = prckwd->flStyle;
  670.                 *pflStyleDefault = prckwd->flStyleDefault;
  671.                 return ids(prckwd->idsKeyword);
  672.             }
  673.         }
  674.     }
  675.     /*
  676.      * A match was not found.  We must write text, we didn't find a
  677.      * match, we will be using the "CONTROL" keyword and the default
  678.      * styles that this keyword implies is the "child" and "visible"
  679.      * bits (rc.exe OR's these styles in implicitly).
  680.      */
  681.     *pfWriteText = TRUE;
  682.     *pfNotFound = TRUE;
  683.     *pflStylePredef = 0L;
  684.     *pflStyleDefault = WS_VISIBLE | WS_CHILD;
  685.     return ids(IDS_CONTROL);
  686. }
  687. /************************************************************************
  688. * WriteClass
  689. *
  690. * Writes out the class for a control.
  691. *
  692. * Arguments:
  693. *    LPTSTR pszClass - pointer to the class string
  694. *
  695. ************************************************************************/
  696. STATICFN VOID WriteClass(
  697.     LPTSTR pszClass)
  698. {
  699.     INT i;
  700.     WORD idOrd;
  701.     Comma();
  702.     /*
  703.      * Is this class a predefined type instead of a string?
  704.      */
  705.     if (IsOrd(pszClass)) {
  706.         /*
  707.          * Figure out which type it is and get the class string to
  708.          * write.
  709.          */
  710.         idOrd = OrdID(pszClass);
  711.         for (i = 0; i < IC_DIALOG; i++) {
  712.             if (acsd[i].idOrd == idOrd) {
  713.                 pszClass = ids(acsd[i].idsClass);
  714.                 break;
  715.             }
  716.         }
  717.     }
  718.     WriteQuotedString(pszClass);
  719. }
  720. /************************************************************************
  721. * WriteStyles
  722. *
  723. * This function writes the class and style info to the file
  724. * for the control or dialog box in the RC format.
  725. *
  726. * Arguments:
  727. *     INT iClass           = The class of the item.
  728. *     LPTSTR pszClass      = Class name of the control.
  729. *     DWORD flStyle        = The style of the item.
  730. *     DWORD flStylePredef  = The styles bits implicit in the predefined
  731. *                            keyword for this control.  This should be
  732. *                            zero if this control doesn't have a predefined
  733. *                            keyword for it.
  734. *     DWORD flStyleDefault = The default styles implicit in the item.
  735. *     PDWORD pflStyleLeft  = Where to  return any style bits that do not
  736. *                            get written out.
  737. *     BOOL fNullStyles     = TRUE if we should still write the style word
  738. *                            even if the style flag is zero.
  739. *     BOOL fCommaPrefix    = TRUE means that a comma will be written out
  740. *                            before writing any styles.  If no styles
  741. *                            are written, no comma will be written either.
  742. *
  743. * Returns:
  744. *     TRUE => Something was written out.
  745. *     FALSE => Nothing was written out.
  746. *
  747. ************************************************************************/
  748. STATICFN BOOL WriteStyles(
  749.     INT iClass,
  750.     LPTSTR pszClass,
  751.     DWORD flStyle,
  752.     DWORD flStylePredef,
  753.     DWORD flStyleDefault,
  754.     PDWORD pflStyleLeft,
  755.     BOOL fNullStyles,
  756.     BOOL fCommaPrefix)
  757. {
  758.     DWORD flStyleLeft;
  759.     BOOL fWritten = FALSE;
  760.     /*
  761.      * Write the control specific styles.
  762.      */
  763.     if (iClass == IC_CUSTOM) {
  764.         fWritten = WriteCustomStyle(pszClass, flStyle, &flStyleLeft);
  765.     }
  766.     else {
  767.         fWritten = WriteClassStyle(iClass, flStyle, flStylePredef,
  768.                 flStyleDefault, &flStyleLeft, FALSE, fNullStyles,
  769.                 fCommaPrefix);
  770.     }
  771.     /*
  772.      * If we are writing styles for the dialog, remove the WS_GROUP
  773.      * and WS_TABSTOP bits from the style before proceeding.  This is
  774.      * because the WS_MINIMIZEBOX and WS_MAXIMIZEBOX styles use the
  775.      * same bits, and these keywords will have already been written
  776.      * out by the preceding WriteClassStyle call if those bits are
  777.      * present.
  778.      */
  779.     if (iClass == IC_DIALOG)
  780.         flStyle &= ~(WS_GROUP | WS_TABSTOP);
  781.     /*
  782.      * Write the window styles that are common to the different
  783.      * controls (the high word).
  784.      */
  785.     fWritten |= WriteClassStyle(IC_WINDOW, flStyleLeft, flStylePredef,
  786.             flStyleDefault, &flStyleLeft, fWritten, fNullStyles, fCommaPrefix);
  787.     /*
  788.      * Pass back any styles that were not written.
  789.      */
  790.     *pflStyleLeft = flStyleLeft;
  791.     return fWritten;
  792. }
  793. /************************************************************************
  794. * WriteClassStyle
  795. *
  796. * This function writes the class style symbols to the file.  The styles
  797. * to write out are passed in flStyle, and the styles that are implicitly
  798. * set by this type of control already are passed in flStyleDefault.  The
  799. * style keywords corresponding to the bits in flStyle are written out,
  800. * separated by " | ", and any bits in flStyleDefault that are NOT set
  801. * are written out preceded by a "NOT" to explicitly turn them off.  This
  802. * is used in the case of the predefined RC keywords, which often have
  803. * styles like WS_TABSTOP or WS_VISIBLE already implicit in them.  There
  804. * is no need to explicitly specify them, but if they are not present, we
  805. * must NOT them out.  The parameter flStylePredef contains the style bits
  806. * that identified the predefined control keyword itself (if any) and
  807. * thus are removed from the style before writing anything out.
  808. *
  809. * Arguments:
  810. *     INT iClass           = The class of the control. See the
  811. *                            IC_ constants defined in dlgedit.h.
  812. *     DWORD flStyle        = The style of control.  This nails
  813. *                            down the exact type of control.
  814. *     DWORD flStylePredef  = The styles bits implicit in the predefined
  815. *                            keyword for this control.  This should be
  816. *                            zero if this control doesn't have a predefined
  817. *                            keyword for it.
  818. *     DWORD flStyleDefault = The default styles that are implicit with
  819. *                            this control.  This will only be set if this
  820. *                            control is using a predefined RC keyword. A
  821. *                            value of zero means that there are no default
  822. *                            styles implicitly specified.
  823. *     PDWORD pflStyleLeft  = Where to  return any style bits that do not
  824. *                            get written out.
  825. *     BOOL fPrevWritten    = TRUE means a previous style symbol has
  826. *                            been written and to put " | " before
  827. *                            the next symbol.
  828. *     BOOL fNullStyles     = TRUE if we should still write the style word
  829. *                            even if the style flag is zero.  This is used
  830. *                            to handle the case where a predefined keyword
  831. *                            has been written out that implies a style that
  832. *                            also happens to be zero.  Without this flag
  833. *                            being FALSE the style flag implicit in the
  834. *                            keyword would be redundantly written out again.
  835. *                            In general, if we have written out a predefined
  836. *                            keyword this flag should be FALSE.
  837. *     BOOL fCommaPrefix    = TRUE means that a comma will be written out
  838. *                            before writing any styles.  This will only
  839. *                            happen if fPrevWritten is FALSE.  If no styles
  840. *                            are written, no comma will be written either.
  841. *
  842. * Returns:
  843. *     TRUE => Something was written out.
  844. *     FALSE => Nothing was written out.
  845. *
  846. ************************************************************************/
  847. STATICFN BOOL WriteClassStyle(
  848.     INT iClass,
  849.     DWORD flStyle,
  850.     DWORD flStylePredef,
  851.     DWORD flStyleDefault,
  852.     PDWORD pflStyleLeft,
  853.     BOOL fPrevWritten,
  854.     BOOL fNullStyles,
  855.     BOOL fCommaPrefix)
  856. {
  857.     register WORD i;
  858.     WORD iMax;
  859.     DWORD flStyleMask;
  860.     PCLASSSTYLE pcs;
  861.     iMax = (WORD)acsd[iClass].cClassStyles;
  862.     pcs = acsd[iClass].pacs;
  863.     /*
  864.      * Remove the bits that identified the predefined control keyword
  865.      * from the style flag before proceeding.  For instance, if I already
  866.      * am going to be writing out a "PUSHBUTTON", there is no reason
  867.      * to write out the "BS_PUSHBUTTON" style.  If there is no predefined
  868.      * control keyword, flStylePredef will be zero and this will do
  869.      * nothing.
  870.      */
  871.     flStyle &= ~flStylePredef;
  872.     /*
  873.      * Go through all possible flags for this style.
  874.      */
  875.     for (i = 0; i < iMax; i++, pcs++) {
  876.         flStyleMask = pcs->flStyleMask ? pcs->flStyleMask : pcs->flStyle;
  877.         /*
  878.          * Is this styles bits set?
  879.          */
  880.         if ((flStyle & flStyleMask) == pcs->flStyle) {
  881.             /*
  882.              * Remove these bits from the styles left.  Even if
  883.              * we do not write them out, they are still accounted
  884.              * for and can be removed from the styles remaining.
  885.              */
  886.             flStyle &= ~pcs->flStyle;
  887.             /*
  888.              * Skip this style if we don't want to write styles that are
  889.              * zero, or if the style is already implicitly specified for
  890.              * this control (a non-zero default style mask must be specified).
  891.              */
  892.             if ((!pcs->flStyle && !fNullStyles) ||
  893.                     (flStyleDefault &&
  894.                     (flStyleDefault & flStyleMask) == pcs->flStyle))
  895.                 continue;
  896.             /*
  897.              * If there is a string for this style, write it out, preceded
  898.              * by an "|" symbol if necessary.
  899.              */
  900.             if (*ids(acsd[iClass].idsStylesStart + i)) {
  901.                 if (fPrevWritten) {
  902.                     ORSymbol();
  903.                 }
  904.                 else {
  905.                     if (fCommaPrefix)
  906.                         Comma();
  907.                     fPrevWritten = TRUE;
  908.                 }
  909.                 /*
  910.                  * Write the string.
  911.                  */
  912.                 WriteString(ids(acsd[iClass].idsStylesStart + i));
  913.             }
  914.         }
  915.         /*
  916.          * No the styles bit is not set.  Is it implicit in the keyword
  917.          * being used?  If so, we need to explicitly NOT it
  918.          * out in the dialog template.
  919.          * Note that this should not be done in the case where the style
  920.          * is zero.
  921.          */
  922.         else if (flStyleDefault &&
  923.                 (flStyleDefault & flStyleMask) == pcs->flStyle &&
  924.                 pcs->flStyle) {
  925.             if (fPrevWritten) {
  926.                 ORSymbol();
  927.             }
  928.             else {
  929.                 if (fCommaPrefix)
  930.                     Comma();
  931.                 fPrevWritten = TRUE;
  932.             }
  933.             WriteString(ids(IDS_NOT));
  934.             Space();
  935.             WriteString(ids(acsd[iClass].idsStylesStart + i));
  936.         }
  937.     }
  938.     /*
  939.      * Pass back the style bits that were not written out.
  940.      */
  941.     *pflStyleLeft = flStyle;
  942.     return fPrevWritten;
  943. }
  944. /************************************************************************
  945. * WriteCustomStyle
  946. *
  947. * Writes our the custom control information
  948. *
  949. * Arguments:
  950. *    LPTSTR - class name of the control
  951. *    DWORD - style of the control
  952. *    PDWORD - styles left to be written
  953. *
  954. * Returns:
  955. *    TRUE if custom styles were written out; otherwise, FALSE.
  956. *
  957. ************************************************************************/
  958. STATICFN BOOL WriteCustomStyle(
  959.     LPTSTR pszClass,
  960.     DWORD flStyle,
  961.     PDWORD pflStyleLeft)
  962. {
  963.     PCUSTLINK pcl;
  964.     LPCCSTYLEFLAG pStyleFlags;
  965.     DWORD flStyleMask;
  966.     INT i;
  967.     BOOL fWritten = FALSE;
  968.     /*
  969.      * Search the list of installed custom controls for one
  970.      * that matches the class.
  971.      */
  972.     for (pcl = gpclHead;
  973.             pcl && lstrcmpi(pcl->pwcd->pszClass, pszClass) != 0;
  974.             pcl = pcl->pclNext)
  975.         ;
  976.     /*
  977.      * Was a match found and is this control from a DLL (not emulated)?
  978.      */
  979.     if (pcl && !pcl->pwcd->fEmulated) {
  980.         for (i = 0, pStyleFlags = pcl->pwcd->aStyleFlags;
  981.                 i < pcl->pwcd->cStyleFlags;
  982.                 i++, pStyleFlags++) {
  983.             flStyleMask = pStyleFlags->flStyleMask ?
  984.                     pStyleFlags->flStyleMask : pStyleFlags->flStyle;
  985.             /*
  986.              * Is this styles bits set?
  987.              */
  988.             if ((flStyle & flStyleMask) == pStyleFlags->flStyle) {
  989.                 /*
  990.                  * Remove these bits from the styles left.
  991.                  */
  992.                 flStyle &= ~pStyleFlags->flStyle;
  993.                 if (fWritten)
  994.                     ORSymbol();
  995.                 else
  996.                     fWritten = TRUE;
  997.                 /*
  998.                  * Write the string.
  999.                  */
  1000.                 WriteString(pStyleFlags->pszStyle);
  1001.             }
  1002.         }
  1003.     }
  1004.     /*
  1005.      * Return the styles that remain to be written.
  1006.      */
  1007.     *pflStyleLeft = flStyle;
  1008.     return fWritten;
  1009. }
  1010. /************************************************************************
  1011. * WriteCoords
  1012. *
  1013. * This function writes the coordinates out to the file as decimal
  1014. * ascii numbers separated by ", ".
  1015. *
  1016. * Arguments:
  1017. *     INT x, y, cx, cy = The coordinates.
  1018. *
  1019. ************************************************************************/
  1020. STATICFN VOID WriteCoords(
  1021.     INT x,
  1022.     INT y,
  1023.     INT cx,
  1024.     INT cy)
  1025. {
  1026.     WriteValue(x);
  1027.     Comma();
  1028.     WriteValue(y);
  1029.     Comma();
  1030.     WriteValue(cx);
  1031.     Comma();
  1032.     WriteValue(cy);
  1033. }
  1034. /************************************************************************
  1035. * WriteValue
  1036. *
  1037. * This function writes the value of 'n' as a decimal ascii string to
  1038. * the file.
  1039. *
  1040. * Arguments:
  1041. *     INT n = The number to write.
  1042. *
  1043. ************************************************************************/
  1044. STATICFN VOID WriteValue(
  1045.     INT n)
  1046. {
  1047.     TCHAR szNum[32];
  1048.     itoaw(n, szNum, 10);
  1049.     WriteString(szNum);
  1050. }
  1051. /************************************************************************
  1052. * WriteHexWord
  1053. *
  1054. * This function writes the value of 'w' as a hex constant to the file.
  1055. *
  1056. * Arguments:
  1057. *     WORD w - The word to write.
  1058. *
  1059. ************************************************************************/
  1060. STATICFN VOID WriteHexWord(
  1061.     WORD w)
  1062. {
  1063.     TCHAR szNum[17];
  1064.     itoax(w, szNum);
  1065.     WriteString(szNum);
  1066. }
  1067. /************************************************************************
  1068. * WriteHexDWord
  1069. *
  1070. * This function writes the value of 'dw' as a hex constant to the file.
  1071. *
  1072. * Arguments:
  1073. *     DWORD dw - The dword to write.
  1074. *
  1075. ************************************************************************/
  1076. STATICFN VOID WriteHexDWord(
  1077.     DWORD dw)
  1078. {
  1079.     TCHAR szNum[32];
  1080.     wsprintf(szNum, L"0x%8.8X", dw);
  1081.     WriteString(szNum);
  1082. }
  1083. /************************************************************************
  1084. * WriteString
  1085. *
  1086. * This function writes the given string to the file.  If the string
  1087. * would cause it to overflow the margin, a new line, with indenting
  1088. * to the current tab level, is forced before writing the string.
  1089. *
  1090. * Arguments:
  1091. *   LPTSTR psz = The string to write out.
  1092. *
  1093. ************************************************************************/
  1094. STATICFN VOID WriteString(
  1095.     LPTSTR psz)
  1096. {
  1097.     register INT nLen;
  1098.     nLen = lstrlen(psz);
  1099.     if (!AtFirstTabColumn() && cColumn + nLen > CCHRIGHTMARGIN)
  1100.         NewLine();
  1101.     while (nLen--)
  1102.         WriteDlgChar(*psz++);
  1103. }
  1104. /************************************************************************
  1105. * WriteQuotedString
  1106. *
  1107. * This function writes the given string to the file.  If the string
  1108. * would cause it to overflow the margin, a new line, with indenting
  1109. * to the current tab level, is forced before writing the string.
  1110. * This function will also enclose the given string in double-quotes,
  1111. * and ensures that the string will not be broken when it is written.
  1112. * If there are any escape characters (backslashes or quotes) in the
  1113. * string, they will be escaped properly so that rc.exe can read them
  1114. * properly.
  1115. *
  1116. * Arguments:
  1117. *   LPTSTR psz = The string to write out.
  1118. *
  1119. ************************************************************************/
  1120. STATICFN VOID WriteQuotedString(
  1121.     LPTSTR psz)
  1122. {
  1123.     register INT nLen;
  1124.     LPTSTR pszT;
  1125.     /*
  1126.      * Find the actual length of the string.  To do this, we must scan
  1127.      * for the characters that will be escaped later.
  1128.      */
  1129.     nLen = lstrlen(psz);
  1130.     pszT = psz;
  1131.     while (*pszT) {
  1132.         if (*pszT == CHAR_DBLQUOTE || *pszT == CHAR_BACKSLASH)
  1133.             nLen++;
  1134.         pszT = CharNext(pszT);
  1135.     }
  1136.     /*
  1137.      * Start a new line if necessary.  Add 2 for the quotes.
  1138.      */
  1139.     if (!AtFirstTabColumn() && cColumn + nLen + 2 > CCHRIGHTMARGIN)
  1140.         NewLine();
  1141.     Quote();
  1142.     WriteEscapedString(psz);
  1143.     Quote();
  1144. }
  1145. /************************************************************************
  1146. * WriteEscapedString
  1147. *
  1148. * This function writes the given string to the file.  It is different
  1149. * from WriteString in that it will add a '' in front of other
  1150. * backslashes and a second double quote in front of double quotes.
  1151. * This is necessary when writing out a string which will be surrounded
  1152. * by quotes, such as the Text fields in the .DLG file.
  1153. *
  1154. * Arguments:
  1155. *   LPTSTR psz = The string to write out.
  1156. *
  1157. ************************************************************************/
  1158. STATICFN VOID WriteEscapedString(
  1159.     LPTSTR psz)
  1160. {
  1161.     while (*psz) {
  1162.         if (*psz == CHAR_DBLQUOTE)
  1163.             WriteDlgChar(CHAR_DBLQUOTE);
  1164.         else if (*psz == CHAR_BACKSLASH)
  1165. #ifdef JAPAN
  1166. #ifndef UNICODE
  1167. #define wcsncmp     strncmp
  1168. #endif
  1169.             if ((wcsncmp(psz+1, TEXT("036"), 3)) &&
  1170.                 (wcsncmp(psz+1, TEXT("037"), 3)))
  1171. #endif
  1172.             WriteDlgChar(CHAR_BACKSLASH);
  1173.         if(IsDBCSLeadByte((BYTE)*psz))
  1174.             WriteDlgChar(*psz++);
  1175.         WriteDlgChar(*psz++);
  1176.     }
  1177. }
  1178. /************************************************************************
  1179. * WriteDlgChar
  1180. *
  1181. * Low level function to do an actual character write to the file.
  1182. * Some buffering is done then _lwrite is called.
  1183. *
  1184. * Because it is buffered, before closing the file any remaining
  1185. * characters in the buffer must be flushed to disk using WriteDlgFlush.
  1186. *
  1187. * If an error occurs on the write, Throw will be called to jump back
  1188. * up to WriteDlg and return the failure to the caller.
  1189. *
  1190. * The globals gachWriteBuffer and cbWritePos are updated by this routine.
  1191. *
  1192. * Arguments:
  1193. *     TCHAR ch - The character to write.
  1194. *
  1195. * Returns:
  1196. *   If an error occurs on the _lwrite, the execution will be thrown
  1197. *   back to the WriteDlg function.  Otherwise, nothing is returned.
  1198. *
  1199. ************************************************************************/
  1200. STATICFN VOID WriteDlgChar(
  1201.     TCHAR ch)
  1202. {
  1203.     INT cbWritten;
  1204.     gachWriteBuffer[cbWritePos++] = ch;
  1205.     /*
  1206.      * Is the buffer full?
  1207.      */
  1208.     if (cbWritePos == CCHFILEBUFFER) {
  1209. // The abWriteBuffer[] is too small for Japanese language.
  1210.         // Please don't assume WideChar_length/2 == MultiByte_length.
  1211.         // July 12, 1992 by ShigeO
  1212.         CHAR abWriteBuffer[CCHFILEBUFFER*2];
  1213.         BOOL fDefCharUsed;
  1214.         int  iRequired =
  1215.         WideCharToMultiByte(CP_ACP, 0, gachWriteBuffer, CCHFILEBUFFER,
  1216.                 abWriteBuffer, CCHFILEBUFFER*2, NULL, &fDefCharUsed);
  1217.         cbWritten = (INT)_lwrite((HFILE)hfDlg, abWriteBuffer, iRequired);
  1218.         if (cbWritten != iRequired)
  1219.             longjmp(jbWriteDlg, 1);
  1220.         cbWritePos = 0;
  1221.     }
  1222.     /*
  1223.      * Update the current column counter.
  1224.      */
  1225.     if (ch == CHAR_RETURN || ch == CHAR_NEWLINE) {
  1226.         /*
  1227.          * Carriage return or newline resets column position to 0.
  1228.          */
  1229.         cColumn = 0;
  1230.     }
  1231.     else {
  1232.         cColumn++;
  1233.     }
  1234. }
  1235. /************************************************************************
  1236. * WriteDlgFlush
  1237. *
  1238. * This routine flushes the write buffer.  This must be done before
  1239. * the file is closed or data can be lost.
  1240. *
  1241. * The global cbWritePos is updated by this routine.
  1242. *
  1243. * Returns:
  1244. *   If an error occurs on the _lwrite, the execution will be thrown
  1245. *   back to the WriteDlg function.  Otherwise, nothing is returned.
  1246. *
  1247. ************************************************************************/
  1248. STATICFN VOID WriteDlgFlush(VOID)
  1249. {
  1250.     INT cbWritten;
  1251.     /*
  1252.      * Are any bytes remaining in the buffer?
  1253.      */
  1254.     if (cbWritePos) {
  1255. // The abWriteBuffer[] is too small for Japanese language.
  1256.         // Please don't assume WideChar_length/2 == MultiByte_length.
  1257.         // July 12, 1992 by ShigeO
  1258.         CHAR abWriteBuffer[CCHFILEBUFFER*2];
  1259.         BOOL fDefCharUsed;
  1260.         int  iRequired =
  1261.         WideCharToMultiByte(CP_ACP, 0, gachWriteBuffer, cbWritePos,
  1262.                 abWriteBuffer, CCHFILEBUFFER*2, NULL, &fDefCharUsed);
  1263.         cbWritten = (INT)_lwrite((HFILE)hfDlg, abWriteBuffer, iRequired);
  1264.         if (cbWritten != iRequired)
  1265.             longjmp(jbWriteDlg, 1);
  1266.         cbWritePos = 0;
  1267.     }
  1268. }
  1269. /****************************************************************************
  1270. * Tab
  1271. *
  1272. * Writes spaces up to the current tab level setting.
  1273. *
  1274. ****************************************************************************/
  1275. STATICFN VOID Tab(VOID)
  1276. {
  1277.     while (cColumn < cTabStop)
  1278.         WriteDlgChar(CHAR_SPACE);
  1279. }
  1280. /****************************************************************************
  1281. * NewLine
  1282. *
  1283. * Begins a new line by writing a carriage return and linefeed.  Also
  1284. * indents the following line up to the current tab level.
  1285. *
  1286. ****************************************************************************/
  1287. STATICFN VOID NewLine(VOID)
  1288. {
  1289.     WriteDlgChar(CHAR_RETURN);
  1290.     WriteDlgChar(CHAR_NEWLINE);
  1291.     Tab();
  1292. }
  1293. /****************************************************************************
  1294. * Quote
  1295. *
  1296. * Writes a double quote.
  1297. *
  1298. ****************************************************************************/
  1299. STATICFN VOID Quote(VOID)
  1300. {
  1301.     WriteDlgChar(CHAR_DBLQUOTE);
  1302. }
  1303. /****************************************************************************
  1304. * Comma
  1305. *
  1306. * Writes a comma then a space.
  1307. *
  1308. ****************************************************************************/
  1309. STATICFN VOID Comma(VOID)
  1310. {
  1311.     WriteDlgChar(CHAR_COMMA);
  1312.     WriteDlgChar(CHAR_SPACE);
  1313. }
  1314. /****************************************************************************
  1315. * Space
  1316. *
  1317. * Writes a space.
  1318. *
  1319. ****************************************************************************/
  1320. STATICFN VOID Space(VOID)
  1321. {
  1322.     WriteDlgChar(CHAR_SPACE);
  1323. }
  1324. /****************************************************************************
  1325. * ORSymbol
  1326. *
  1327. * Writes " | ".
  1328. *
  1329. ****************************************************************************/
  1330. STATICFN VOID ORSymbol(VOID)
  1331. {
  1332.     WriteDlgChar(CHAR_SPACE);
  1333.     WriteDlgChar(CHAR_ORSYMBOL);
  1334.     WriteDlgChar(CHAR_SPACE);
  1335. }