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