home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / dlgedit / rwdlg.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  45KB  |  1,576 lines

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