Added a few more Unicode digits from Unicode version 4.1.
[wine] / programs / cmdlgtst / cmdlgtst.c
1 /*
2  * Copyright (c) 1999-2000 Eric Williams.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 /*
20  * One might call this a Commdlg test jig.  Its sole function in life
21  * is to call the Commdlg Common Dialogs.  The results of a call to
22  * File Open or File Save are printed in the upper left corner;
23  * Font adjusts the font of the printout, and Color adjusts the color
24  * of the background.
25  */
26
27 /*
28  * Ideally it would also do event logging and be a bit less stupid
29  * about displaying the results of the various requesters.  But hey,
30  * it's only a first step. :-)
31  */
32
33 #define NONAMELESSUNION
34 #define NONAMELESSSTRUCT
35
36 #include <windows.h>
37 #include <commdlg.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include "cmdlgtst.h"
41
42 /*
43  * This structure is to set up flag / control associations for the custom
44  * requesters.  The ft_id is the id for the control (usually generated
45  * by the system) and the ft_bit is the flag bit which goes into the
46  * settings longword for the various Commdlg structures.  It is assumed
47  * that all flags fit in an unsigned long and that all bits are in fact
48  * one bit.
49  */
50
51 /*
52  * The array of entries is terminated by {IDOK, 0}; the assumption is that
53  * IDOK would never be associated with a dialogbox control (since it's
54  * usually the ID of the OK button}.
55  */
56
57 struct FlagTableEntry {
58         int ft_id;
59         unsigned long ft_bit;
60 };
61
62 #define EXPORT
63
64 static const char menuName[]   = "CmdlgtstMenu";
65 static const char className[]  = "CmdlgtstClass";
66 static const char windowName[] = "Cmdlgtst Window";
67
68 /*
69  * global hInstance variable.  This makes the code non-threadable,
70  * but wotthehell; this is Win32 anyway!  (Though it does work
71  * under Win16, if one doesn't run more than one copy at a time.)
72  */
73
74 static HINSTANCE g_hInstance;
75
76 /*
77  * global CommDlg data structures for modals.  These are placed here
78  * so that the custom dialog boxes can get at them.
79  */
80
81 static PAGESETUPDLG psd;
82 static PRINTDLG pd;
83 static COLORREF cc_cr[16];
84 static CHOOSECOLOR cc;
85 static LOGFONT cf_lf;
86 static CHOOSEFONT cf;
87 static const char ofn_filepat[] = "All Files (*.*)\0*.*\0Only Text Files (*.txt)\0*.txt\0";
88 static char ofn_result[1024];
89 static char ofn_titleresult[128];
90 static OPENFILENAME ofn;
91
92 /* Stuff for find and replace.  These are modeless, so I have to put them here. */
93
94 static HWND findDialogBox = 0;
95 static UINT findMessageId = 0;
96
97 static FINDREPLACE frS;
98 static char fromstring[1024], tostring[1024];
99
100 /* Stuff for the drawing of the window(s).  I put them here for convenience. */
101
102 static COLORREF fgColor = RGB(0, 0, 0); /* not settable */
103 static COLORREF bgColor = RGB(255, 255, 255); /* COLOR dialog */
104 static COLORREF txtColor = RGB(0, 0, 0); /* settable if one enables CF_EFFECTS */
105
106 /* Utility routines. */
107
108 static void nyi(HWND hWnd)
109 {
110         /* "Hi there!  I'm not yet implemented!" */
111         MessageBox(hWnd, "Not yet implemented!", "NYI", MB_ICONEXCLAMATION | MB_OK);
112 }
113
114 #if 0
115 static UINT CALLBACK dummyfnHook(HWND hWnd, UINT msg, UINT wParam, UINT lParam)
116 {
117         /*
118          * If the user specifies something that needs an awfully stupid hook function,
119          * this is the one to use.  It's a no-op, and says "I didn't do anything."
120          */
121
122         (void) hWnd;
123         (void) msg;
124         (void) wParam;
125         (void) lParam;
126
127         printf("dummyfnhook\n"); /* visible under Wine, but Windows probably won't see it! */
128
129         return 0;
130 }
131 #endif
132
133 /*
134  * Initialization code.  This code simply shoves in predefined
135  * data into the COMMDLG data structures; in the future, I might use
136  * a series of loadable resources, or static initializers; of course,
137  * if Microsoft decides to change the field ordering, I'd be screwed.
138  */
139
140 static void mwi_Print(HWND hWnd)
141 {
142         pd.lStructSize = sizeof(PRINTDLG);
143         pd.hwndOwner = hWnd;
144         pd.hDevMode = 0;
145         pd.hDevNames = 0;
146         pd.hDC = 0;
147         pd.Flags = 0;
148         pd.nMinPage = 1;
149         pd.nMaxPage = 100;
150         pd.hInstance = g_hInstance;
151         pd.lCustData = 0;
152         pd.lpfnPrintHook = 0;
153         pd.lpfnSetupHook = 0;
154         pd.lpPrintTemplateName = 0;
155         pd.lpSetupTemplateName = 0;
156         pd.hPrintTemplate = 0;
157         pd.hSetupTemplate = 0;
158 }
159
160 static void mwi_PageSetup(HWND hWnd)
161 {
162         ZeroMemory(&psd, sizeof(PAGESETUPDLG));
163         psd.lStructSize = sizeof(PAGESETUPDLG);
164         psd.hwndOwner = hWnd;
165         
166 }
167
168 static void mwi_Color(HWND hWnd)
169 {
170         int i;
171
172         /* there's probably an init call for this, somewhere. */
173
174         for(i=0;i<16;i++)
175                 cc_cr[i] = RGB(0,0,0);
176
177         cc.lStructSize = sizeof(CHOOSECOLOR);
178         cc.hwndOwner = hWnd;
179         cc.hInstance = (HWND)g_hInstance; /* Should be an HINSTANCE but MS made a typo */
180         cc.rgbResult = RGB(0,0,0);
181         cc.lpCustColors = cc_cr;
182         cc.Flags = 0;
183         cc.lCustData = 0;
184         cc.lpfnHook = 0;
185         cc.lpTemplateName = 0;
186 }
187
188 static void mwi_Font(HWND hWnd)
189 {
190         cf.lStructSize = sizeof(CHOOSEFONT);
191         cf.hwndOwner = hWnd;
192         cf.hDC = 0;
193         cf.lpLogFont = &cf_lf;
194         cf.Flags = CF_SCREENFONTS; /* something's needed for display; otherwise it craps out with an error */
195         cf.rgbColors = RGB(0,0,0);  /* what is *this* doing here?? */
196         cf.lCustData = 0;
197         cf.lpfnHook = 0;
198         cf.lpTemplateName = 0;
199         cf.hInstance = g_hInstance;
200         cf.lpszStyle = 0;
201         cf.nFontType = 0;
202         cf.nSizeMin = 8;
203         cf.nSizeMax = 72;
204
205         cf_lf.lfHeight = -18; /* this can be positive or negative, but negative is usually used. */
206 }
207
208 static void mwi_File(HWND hWnd)
209 {
210         ofn.lStructSize = sizeof(OPENFILENAME);
211         ofn.hwndOwner = hWnd;
212         ofn.hInstance = g_hInstance;
213         ofn.lpstrFilter = ofn_filepat;
214         ofn.lpstrCustomFilter = 0;
215         ofn.nMaxCustFilter = 0;
216         ofn.nFilterIndex = 0;
217         ofn.lpstrFile = ofn_result;
218         ofn.nMaxFile = sizeof(ofn_result);
219         ofn.lpstrFileTitle = ofn_titleresult;
220         ofn.nMaxFileTitle = sizeof(ofn_titleresult);
221         ofn.lpstrInitialDir = 0;
222         ofn.lpstrTitle = "Open File";
223         ofn.Flags = 0;
224         ofn.nFileOffset = 0;
225         ofn.nFileExtension = 0;
226         ofn.lpstrDefExt = "*";
227         ofn.lCustData = 0;
228         ofn.lpfnHook = 0;
229         ofn.lpTemplateName = 0;
230
231         ofn_result[0] = '\0';
232 }
233
234 static void mwi_FindReplace(HWND hWnd)
235 {
236         frS.lStructSize = sizeof(FINDREPLACE);
237         frS.hwndOwner = hWnd;
238         frS.hInstance = g_hInstance;
239         frS.Flags = FR_DOWN;
240         frS.lpstrFindWhat = fromstring;
241         frS.lpstrReplaceWith = tostring;
242         frS.wFindWhatLen = sizeof(fromstring);
243         frS.wReplaceWithLen = sizeof(tostring);
244         frS.lCustData = 0;
245         frS.lpfnHook = 0;
246         frS.lpTemplateName = 0;
247
248         fromstring[0] = '\0';
249         tostring[0] = '\0';
250         findMessageId = RegisterWindowMessage(FINDMSGSTRING);
251 }
252
253 static void mwi_InitAll(HWND hWnd)
254 {
255         mwi_Print(hWnd);
256         mwi_Font(hWnd);
257         mwi_Color(hWnd);
258         mwi_File(hWnd);
259         mwi_FindReplace(hWnd);
260         mwi_PageSetup(hWnd);
261 }
262
263 /*
264  * Various configurations for the window.  Ideally, this
265  * would be stored with the window itself, but then, this
266  * isn't the brightest of apps.  Wouldn't be hard to set up,
267  * though -- one of the neater functions of Windows, but if
268  * someone decides to load the windows themselves from resources,
269  * there might be a problem.
270  */
271
272 static void paintMainWindow(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
273 {
274         PAINTSTRUCT ps;
275         RECT rect;
276         HPEN pen;
277         HFONT font;
278         HBRUSH brush;
279
280         (void) iMessage;
281         (void) wParam;
282         (void) lParam;
283
284         /* Commence painting! */
285
286         BeginPaint(hWnd, &ps);
287         GetClientRect(hWnd, (LPRECT) &rect);
288
289         pen = (HPEN) SelectObject(ps.hdc, CreatePen(0, 0, fgColor));
290         brush = (HBRUSH) SelectObject(ps.hdc, CreateSolidBrush(bgColor));
291         font = (HFONT) SelectObject(ps.hdc, CreateFontIndirect(&cf_lf));
292
293         /*
294          * Ideally, we'd only need to draw the exposed bit.
295          * But something in BeginPaint is screwing up the rectangle.
296          * Either that, or Windows is drawing it wrong.  AARGH!
297          * Rectangle(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
298          */
299         Rectangle(ps.hdc, rect.left, rect.top, rect.right, rect.bottom);
300
301         /* now draw a couple of lines, just for giggles. */
302
303         MoveToEx(ps.hdc, rect.left, rect.top, (POINT *) 0);
304         LineTo(ps.hdc, rect.right, rect.bottom);
305         MoveToEx(ps.hdc, rect.left, rect.bottom, (POINT *) 0);
306         LineTo(ps.hdc, rect.right, rect.top);
307
308         /* draw some text */
309
310         SetTextAlign(ps.hdc, TA_CENTER|TA_BASELINE);
311         SetTextColor(ps.hdc, txtColor);
312         TextOut(ps.hdc, (rect.left+rect.right)/2, (rect.top+rect.bottom)/2, "Common Dialog Test Page", 23);
313
314         SetTextAlign(ps.hdc, TA_LEFT|TA_TOP);
315         TextOut(ps.hdc, rect.left+10, rect.top+10, ofn_result, strlen(ofn_result));
316         TextOut(ps.hdc, rect.left+10, rect.top-cf_lf.lfHeight+10, ofn_titleresult, strlen(ofn_titleresult));
317
318         /*
319          * set the HDC back to the old pen and brush,
320          * and delete the newly created objects.
321          */
322
323         pen = (HPEN) SelectObject(ps.hdc, pen);
324         DeleteObject(pen);
325         brush = (HBRUSH) SelectObject(ps.hdc, brush);
326         DeleteObject(brush);
327         font = (HFONT) SelectObject(ps.hdc, font);
328         DeleteObject(font);
329
330         EndPaint(hWnd, &ps);
331 }
332
333 /*
334  * This function simply returns an error indication.  Naturally,
335  * I do not (yet) see an elegant method by which one can convert
336  * the CDERR_xxx return values into something resembling usable text;
337  * consult cderr.h to see what was returned.
338  */
339
340 static void mw_checkError(HWND hWnd, BOOL explicitcancel)
341 {
342         DWORD errval = CommDlgExtendedError();
343         if(errval) {
344                 char errbuf[80];
345
346                 sprintf(errbuf, "CommDlgExtendedError(): error code %ld (0x%lx)", errval, errval);
347                 MessageBox(hWnd, errbuf, "Error", MB_ICONEXCLAMATION | MB_OK);
348         }
349         else {
350                 if(explicitcancel) MessageBox(hWnd, "Nope, user canceled it.", "No", MB_OK);
351         }
352 }
353
354 /*
355  * The actual dialog function calls.  These merely wrap the Commdlg
356  * calls, and do something (not so) intelligent with the result.
357  * Ideally, the main window would refresh and take into account the
358  * various values specified in the dialog.
359  */
360
361 static void mw_ColorSetup(HWND hWnd)
362 {
363         if(ChooseColor(&cc)) {
364                 RECT rect;
365
366                 GetClientRect(hWnd, (LPRECT) &rect);
367                 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
368                 bgColor = cc.rgbResult;
369         }
370         else mw_checkError(hWnd, FALSE);
371 }
372
373 static void mw_FontSetup(HWND hWnd)
374 {
375         if(ChooseFont(&cf)) {
376                 RECT rect;
377                 GetClientRect(hWnd, (LPRECT) &rect);
378                 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
379                 txtColor = cf.rgbColors;
380         }
381         else mw_checkError(hWnd, FALSE);
382 }
383
384 static void mw_FindSetup(HWND hWnd)
385 {
386         if(findDialogBox == 0) {
387                 findDialogBox = FindText(&frS);
388                 if(findDialogBox==0) mw_checkError(hWnd,TRUE);
389         }
390 }
391
392 static void mw_ReplaceSetup(HWND hWnd)
393 {
394         if(findDialogBox == 0) {
395                 findDialogBox = ReplaceText(&frS);
396                 if(findDialogBox==0) mw_checkError(hWnd,TRUE);
397         }
398 }
399
400 static void mw_OpenSetup(HWND hWnd)
401 {
402         if(GetOpenFileName(&ofn)) {
403                 RECT rect;
404                 GetClientRect(hWnd, (LPRECT) &rect);
405                 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
406         }
407         else mw_checkError(hWnd,FALSE);
408 }
409
410 static void mw_SaveSetup(HWND hWnd)
411 {
412         if(GetSaveFileName(&ofn)) {
413                 RECT rect;
414                 GetClientRect(hWnd, (LPRECT) &rect);
415                 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
416         }
417         else mw_checkError(hWnd,FALSE);
418 }
419
420 /*
421  * Can't find documentation in Borland for this one.  Does it
422  * exist at all, or is it merely a subdialog of Print?
423  */
424
425 static void mw_PSetupSetup(HWND hWnd)
426 {
427         nyi(hWnd);
428 }
429
430 static void mw_PrintSetup(HWND hWnd)
431 {
432         if(PrintDlg(&pd)) {
433                 /*
434                  * the following are suggested in the Borland documentation,
435                  * but aren't that useful until WinE starts to actually
436                  * function with respect to printing.
437                  */
438
439 #if 0
440                 Escape(tmp.hDC, STARTDOC, 8, "Test-Doc", NULL);
441 #endif
442
443          /* Print text and rectangle */
444
445 #if 0
446                 TextOut(tmp.hDC, 50, 50, "Common Dialog Test Page", 23);
447
448                 Rectangle(tmp.hDC, 50, 90, 625, 105);
449                 Escape(tmp.hDC, NEWFRAME, 0, NULL, NULL);
450                 Escape(tmp.hDC, ENDDOC, 0, NULL, NULL);
451                 DeleteDC(tmp.hDC);
452 #endif
453                  if (pd.hDevMode != 0)
454                          GlobalFree(pd.hDevMode);
455                  if (pd.hDevNames != 0)
456                          GlobalFree(pd.hDevNames);
457
458                  pd.hDevMode = 0;
459                  pd.hDevNames = 0;
460
461                  MessageBox(hWnd, "Success.", "Yes", MB_OK);
462         }
463         else mw_checkError(hWnd,TRUE);
464 }
465
466 #define OF(fn, fi, fl)  \
467                 if(dm->dmFields & fl){ \
468                         printf("        %s  =%hd \n", (fn), dm->fi); \
469                 } else \
470                         printf("        %s NOT SET!\n", fn);
471
472
473 static void mw_PageSetup(HWND hWnd)
474 {
475         DEVMODEA *dm;
476         DEVNAMES *dn;
477         CHAR      tmplnm[30] = "PAGESETUPDLGORD_CSTM";
478         
479         if(psd.Flags & PSD_ENABLEPAGESETUPTEMPLATE)
480                 psd.lpPageSetupTemplateName = tmplnm;
481         psd.hInstance = g_hInstance;
482         
483         if(PageSetupDlg(&psd)){
484                 dm = GlobalLock(psd.hDevMode);
485                 if(dm) {
486                         printf("dm != NULL\nDEVMODEA struct:\n");
487                         printf("    dmDeviceName    ='%s'  \n",         dm->dmDeviceName);
488                         printf("    dmSpecVersion   =%#x \n",   dm->dmSpecVersion);
489                         printf("    dmDriverVersion =%#x \n",   dm->dmDriverVersion);
490                         printf("    dmSize          =%#x \n",   dm->dmSize);    
491                         printf("    dmDriverExtra   =%#x \n",   dm->dmDriverExtra);
492                         printf("    dmFields        =%#lx\n",   dm->dmFields);
493                         OF("dmOrientation",     u1.s1.dmOrientation,    DM_ORIENTATION)
494                         OF("dmPaperSize",       u1.s1.dmPaperSize,      DM_PAPERSIZE);
495                         OF("dmPaperLength",     u1.s1.dmPaperLength,    DM_PAPERLENGTH);
496                         OF("dmPaperWidth",      u1.s1.dmPaperWidth,     DM_PAPERWIDTH);
497                         OF("dmScale",           dmScale,        DM_SCALE);
498                         OF("dmCopies",          dmCopies,       DM_COPIES);
499                         OF("dmDefaultSource",   dmDefaultSource,DM_DEFAULTSOURCE);
500                         OF("dmPrintQuality",    dmPrintQuality, DM_PRINTQUALITY);
501                         if(dm->dmFields &       DM_POSITION)
502                                 printf("        dmPosition(%ld, %ld)\n", dm->u1.dmPosition.x, dm->u1.dmPosition.y);
503                         else
504                                 printf("        dmPosition NOT SET!\n");
505                         OF("dmColor",           dmColor,        DM_COLOR);
506                         OF("dmDuplex",          dmDuplex,       DM_DUPLEX);
507                         OF("dmYResolution",     dmYResolution,  DM_YRESOLUTION);
508                         OF("dmTTOption",        dmTTOption,     DM_TTOPTION);
509                         OF("dmCollate",         dmCollate,      DM_COLLATE);
510                         if(dm->dmFields & DM_FORMNAME)
511                                 printf("        dmFormName = '%s'\n", dm->dmFormName);
512                         else 
513                                 printf("        dmFormName NOT SET!\n");
514                         if(dm->dmFields & DM_ICMMETHOD)
515                                 printf("        dmICMMethod = %#lx\n", dm->dmICMMethod);
516                         else
517                                 printf("        dmICMMethod NOT SET!");
518                         
519                         GlobalUnlock(psd.hDevMode);
520                 }
521                 else
522                         printf("dm == NULL\n");
523         
524                 printf("\nPAGESETUPDLG struct\n");
525                 printf("    ptPaperSize(%ld, %ld)\n", psd.ptPaperSize.x, psd.ptPaperSize.y);
526                 printf("    rtMargin(%ld, %ld, %ld, %ld)\n", 
527                         psd.rtMargin.left, psd.rtMargin.top, psd.rtMargin.right, psd.rtMargin.bottom);
528         
529                 printf("\nDEVNAMES struct\n");
530                 dn = GlobalLock(psd.hDevNames);
531                 if(dn){
532                         printf("    wDriverOffset='%s'\n", ((char*)dn+dn->wDriverOffset));
533                         printf("    wDeviceOffset='%s'\n", ((char*)dn+dn->wDeviceOffset));
534                         printf("    wOutputOffset='%s'\n", ((char*)dn+dn->wOutputOffset));
535                         printf("    wDefault     ='%s'\n", ((char*)dn+dn->wDefault));
536                         GlobalUnlock(psd.hDevNames);
537                 }else
538                         printf(" dn == NULL!\n");               
539                 printf("End.\n");
540
541                 if (psd.hDevMode != NULL)
542                         GlobalFree(psd.hDevMode);
543                 if (psd.hDevNames != NULL)
544                         GlobalFree(psd.hDevNames);
545                 if (psd.hPageSetupTemplate != NULL)
546                         GlobalFree(psd.hPageSetupTemplate);
547
548                 psd.hDevMode  = NULL;
549                 psd.hDevNames = NULL;
550                 psd.hPageSetupTemplate = NULL;
551
552                 MessageBox(hWnd, "Success.", "Yes", MB_OK);
553         } mw_checkError(hWnd, FALSE);
554 }
555
556 /********************************************************************************************************/
557 /*
558  * Some support functions for the custom dialog box handlers.
559  * In particular, we have to set things properly, and get the flags back.
560  */
561
562 static void mwcd_SetFlags(HWND hWnd, struct FlagTableEntry *table, unsigned long flags)
563 {
564         int i;
565
566         for(i=0; table[i].ft_id != IDOK; i++)
567         {
568                 CheckDlgButton(hWnd, table[i].ft_id,(table[i].ft_bit & flags) ? 1 : 0);
569         }
570 }
571
572 static unsigned long mwcd_GetFlags(HWND hWnd, struct FlagTableEntry * table)
573 {
574         int i;
575         unsigned long l = 0;
576
577         for(i=0; table[i].ft_id != IDOK; i++)
578         {
579                 if(IsDlgButtonChecked(hWnd, table[i].ft_id) == 1)
580                         l |= table[i].ft_bit;
581         }
582
583         return l;
584 }
585
586 /*
587  * These functions are the custom dialog box handlers.
588  * The division of labor may be a tad peculiar; in particular,
589  * the flag tables should probably be in the main functions,
590  * not the handlers.  I'll fix that later; this works as of right now.
591  */
592
593 static BOOL mwcd_Setup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
594                                          struct FlagTableEntry * table, unsigned long * flags)
595 {
596         (void) lParam;
597
598         switch(uMsg)
599         {
600                 case WM_INITDIALOG:
601                         /* Set the controls properly. */
602
603                         mwcd_SetFlags(hWnd, table, *flags);
604
605                         return TRUE; /* I would return FALSE if I explicitly called SetFocus(). */
606                                      /* As usual, Windows is weird. */
607
608                 case WM_COMMAND:
609                         switch(wParam) {
610                                 case IDOK:
611                                         *flags = mwcd_GetFlags(hWnd, table);
612                                         EndDialog(hWnd,1);
613                                         break;
614
615                                 case IDCANCEL:
616                                         EndDialog(hWnd,0);
617                                         break;
618
619                                 case CM_R_HELP:
620                                         break; /* help?  We don't need no steenkin help! */
621
622                                 default:
623                                         break; /* eat the message */
624                         }
625                         return TRUE;
626
627                 default:
628                         return FALSE; /* since I don't process this particular message */
629         }
630 }
631
632 static BOOL CALLBACK mwcd_ColorSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
633 {
634         static struct FlagTableEntry flagTable[] = {
635                 {I_CC_RGBINIT, CC_RGBINIT},
636                 {I_CC_SHOWHELP, CC_SHOWHELP},
637                 {I_CC_PREVENTFULLOPEN, CC_PREVENTFULLOPEN},
638                 {I_CC_FULLOPEN, CC_FULLOPEN},
639                 {I_CC_ENABLETEMPLATEHANDLE, CC_ENABLETEMPLATEHANDLE},
640                 {I_CC_ENABLETEMPLATE, CC_ENABLETEMPLATE},
641                 {I_CC_ENABLEHOOK, CC_ENABLEHOOK},
642                 {IDOK, 0},
643         };
644
645         return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &cc.Flags);
646 }
647
648 static BOOL CALLBACK mwcd_FontSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
649 {
650         static struct FlagTableEntry flagTable[] = {
651                 {I_CF_APPLY, CF_APPLY},
652                 {I_CF_ANSIONLY, CF_ANSIONLY},
653                 {I_CF_BOTH, CF_BOTH},
654                 {I_CF_TTONLY, CF_TTONLY},
655                 {I_CF_EFFECTS, CF_EFFECTS},
656                 {I_CF_ENABLEHOOK, CF_ENABLEHOOK},
657                 {I_CF_ENABLETEMPLATE, CF_ENABLETEMPLATE},
658                 {I_CF_ENABLETEMPLATEHANDLE, CF_ENABLETEMPLATEHANDLE},
659                 {I_CF_FIXEDPITCHONLY, CF_FIXEDPITCHONLY},
660                 {I_CF_INITTOLOGFONTSTRUCT, CF_INITTOLOGFONTSTRUCT},
661                 {I_CF_LIMITSIZE, CF_LIMITSIZE},
662                 {I_CF_NOFACESEL, CF_NOFACESEL},
663                 {I_CF_USESTYLE, CF_USESTYLE},
664                 {I_CF_WYSIWYG, CF_WYSIWYG},
665                 {I_CF_SHOWHELP, CF_SHOWHELP},
666                 {I_CF_SCREENFONTS, CF_SCREENFONTS},
667                 {I_CF_SCALABLEONLY, CF_SCALABLEONLY},
668                 {I_CF_PRINTERFONTS, CF_PRINTERFONTS},
669                 {I_CF_NOVECTORFONTS, CF_NOVECTORFONTS},
670                 {I_CF_NOSTYLESEL, CF_NOSTYLESEL},
671                 {I_CF_NOSIZESEL, CF_NOSIZESEL},
672                 {I_CF_NOOEMFONTS, CF_NOOEMFONTS},
673                 {IDOK, 0},
674         };
675
676         return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &cf.Flags);
677 }
678
679 static BOOL CALLBACK mwcd_FindSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
680 {
681
682         static struct FlagTableEntry flagTable[] = {
683                 {I_FR_DIALOGTERM, FR_DIALOGTERM},
684                 {I_FR_DOWN, FR_DOWN},
685                 {I_FR_ENABLEHOOK, FR_ENABLEHOOK},
686                 {I_FR_ENABLETEMPLATE, FR_ENABLETEMPLATE},
687                 {I_FR_ENABLETEMPLATEHANDLE, FR_ENABLETEMPLATEHANDLE},
688                 {I_FR_FINDNEXT, FR_FINDNEXT},
689                 {I_FR_HIDEMATCHCASE, FR_HIDEMATCHCASE},
690                 {I_FR_HIDEWHOLEWORD, FR_HIDEWHOLEWORD},
691                 {I_FR_HIDEUPDOWN, FR_HIDEUPDOWN},
692                 {I_FR_MATCHCASE, FR_MATCHCASE},
693                 {I_FR_NOMATCHCASE, FR_NOMATCHCASE},
694                 {I_FR_NOUPDOWN, FR_NOUPDOWN},
695                 {I_FR_NOWHOLEWORD, FR_NOWHOLEWORD},
696                 {I_FR_REPLACE, FR_REPLACE},
697                 {I_FR_REPLACEALL, FR_REPLACEALL},
698                 {I_FR_SHOWHELP, FR_SHOWHELP},
699                 {I_FR_WHOLEWORD, FR_WHOLEWORD},
700                 {IDOK, 0},
701         };
702
703         return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &frS.Flags);
704 }
705
706 static BOOL CALLBACK mwcd_PrintSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
707 {
708         static struct FlagTableEntry flagTable[] = {
709                 {I_PD_ALLPAGES, PD_ALLPAGES},
710                 {I_PD_COLLATE, PD_COLLATE},
711                 {I_PD_DISABLEPRINTTOFILE, PD_DISABLEPRINTTOFILE},
712                 {I_PD_ENABLEPRINTHOOK, PD_ENABLEPRINTHOOK},
713                 {I_PD_ENABLEPRINTTEMPLATE, PD_ENABLEPRINTTEMPLATE},
714                 {I_PD_ENABLEPRINTTEMPLATEHANDLE, PD_ENABLEPRINTTEMPLATEHANDLE},
715                 {I_PD_ENABLESETUPHOOK, PD_ENABLESETUPHOOK},
716                 {I_PD_ENABLESETUPTEMPLATE, PD_ENABLESETUPTEMPLATE},
717                 {I_PD_ENABLESETUPTEMPLATEHANDLE, PD_ENABLESETUPTEMPLATEHANDLE},
718                 {I_PD_HIDEPRINTTOFILE, PD_HIDEPRINTTOFILE},
719                 {I_PD_NOPAGENUMS, PD_NOPAGENUMS},
720                 {I_PD_NOSELECTION, PD_NOSELECTION},
721                 {I_PD_NOWARNING, PD_NOWARNING},
722                 {I_PD_PAGENUMS, PD_PAGENUMS},
723                 {I_PD_PRINTSETUP, PD_PRINTSETUP},
724                 {I_PD_PRINTTOFILE, PD_PRINTTOFILE},
725                 {I_PD_RETURNDC, PD_RETURNDC},
726                 {I_PD_RETURNDEFAULT, PD_RETURNDEFAULT},
727                 {I_PD_RETURNIC, PD_RETURNIC},
728                 {I_PD_SELECTION, PD_SELECTION},
729                 {I_PD_SHOWHELP, PD_SHOWHELP},
730                 {I_PD_USEDEVMODECOPIES, PD_USEDEVMODECOPIES},
731                 {IDOK, 0},
732         };
733
734         return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &pd.Flags);
735 }
736
737 static BOOL CALLBACK mwcd_PageSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
738 {
739         static struct FlagTableEntry flagTable[] = {
740                 {I_PSD_DEFAULTMINMARGINS,       PSD_DEFAULTMINMARGINS},
741                 {I_PSD_DISABLEMARGINS,          PSD_DISABLEMARGINS},
742                 {I_PSD_DISABLEORIENTATION,      PSD_DISABLEORIENTATION},
743                 {I_PSD_DISABLEPAGEPAINTING,     PSD_DISABLEPAGEPAINTING},
744                 {I_PSD_DISABLEPAPER,            PSD_DISABLEPAPER},
745                 {I_PSD_DISABLEPRINTER,          PSD_DISABLEPRINTER},
746                 {I_PSD_ENABLEPAGEPAINTHOOK,     PSD_ENABLEPAGEPAINTHOOK},
747                 {I_PSD_ENABLEPAGESETUPHOOK,     PSD_ENABLEPAGESETUPHOOK},
748                 {I_PSD_ENABLEPAGESETUPTEMPLATE, PSD_ENABLEPAGESETUPTEMPLATE},
749                 {I_PSD_ENABLEPAGESETUPTEMPLATEHANDLE, PSD_ENABLEPAGESETUPTEMPLATEHANDLE},
750                 {I_PSD_INHUNDREDTHSOFMILLIMETERS, PSD_INHUNDREDTHSOFMILLIMETERS},
751                 {I_PSD_INTHOUSANDTHSOFINCHES,   PSD_INTHOUSANDTHSOFINCHES},
752                 {I_PSD_INWININIINTLMEASURE,     PSD_INWININIINTLMEASURE},
753                 {I_PSD_MARGINS,                 PSD_MARGINS},
754                 {I_PSD_MINMARGINS,              PSD_MINMARGINS},
755                 {I_PSD_NONETWORKBUTTON,         PSD_NONETWORKBUTTON},
756                 {I_PSD_NOWARNING,               PSD_NOWARNING},
757                 {I_PSD_RETURNDEFAULT,           PSD_RETURNDEFAULT},
758                 {I_PSD_SHOWHELP,                PSD_SHOWHELP},
759                 {IDOK, 0}
760         };
761
762         return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &psd.Flags);
763 }
764
765 static BOOL CALLBACK mwcd_FileSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
766 {
767         static struct FlagTableEntry flagTable[] = {
768                 {I_OFN_ALLOWMULTISELECT, OFN_ALLOWMULTISELECT},
769                 {I_OFN_CREATEPROMPT, OFN_CREATEPROMPT},
770                 {I_OFN_ENABLEHOOK, OFN_ENABLEHOOK},
771                 {I_OFN_ENABLETEMPLATE, OFN_ENABLETEMPLATE},
772                 {I_OFN_ENABLETEMPLATEHANDLE, OFN_ENABLETEMPLATEHANDLE},
773                 {I_OFN_EXTENSIONDIFFERENT, OFN_EXTENSIONDIFFERENT},
774                 {I_OFN_FILEMUSTEXIST, OFN_FILEMUSTEXIST},
775                 {I_OFN_HIDEREADONLY, OFN_HIDEREADONLY},
776                 {I_OFN_NOCHANGEDIR, OFN_NOCHANGEDIR},
777                 {I_OFN_NOREADONLYRETURN, OFN_NOREADONLYRETURN},
778                 {I_OFN_NOTESTFILECREATE, OFN_NOTESTFILECREATE},
779                 {I_OFN_NOVALIDATE, OFN_NOVALIDATE},
780                 {I_OFN_OVERWRITEPROMPT, OFN_OVERWRITEPROMPT},
781                 {I_OFN_PATHMUSTEXIST, OFN_PATHMUSTEXIST},
782                 {I_OFN_READONLY, OFN_READONLY},
783                 {I_OFN_SHAREAWARE, OFN_SHAREAWARE},
784                 {I_OFN_SHOWHELP, OFN_SHOWHELP},
785                 {IDOK, 0},
786         };
787
788         return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &ofn.Flags);
789 }
790
791 static BOOL CALLBACK mwcd_About(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
792 {
793         (void) wParam;
794         (void) lParam;
795
796         switch(uMsg) {
797                 case WM_INITDIALOG: return TRUE; /* let WINDOWS set the focus. */
798                 case WM_COMMAND: EndDialog(hWnd, 0); return TRUE; /* it's our OK button. */
799                 default: return FALSE; /* it's something else, let Windows worry about it */
800         }
801 }
802
803 /*
804  * These functions call custom dialog boxes (resource-loaded, if I do this right).
805  * Right now they don't do a heck of a lot, but at some future time
806  * they will muck about with the flags (and be loaded from the flags) of
807  * the CommDlg structures initialized by the mwi_xxx() routines.
808  */
809
810 static void mwc_ColorSetup(HWND hWnd)
811 {
812         int r = DialogBox(g_hInstance, "Color_Flags_Dialog", hWnd, (DLGPROC) mwcd_ColorSetup);
813         if(r < 0) { MessageBox(hWnd, "Failure opening Color_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
814 }
815
816 static void mwc_FontSetup(HWND hWnd)
817 {
818         int r = DialogBox(g_hInstance, "Font_Flags_Dialog", hWnd, (DLGPROC) mwcd_FontSetup);
819         if(r < 0) { MessageBox(hWnd, "Failure opening Font_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
820 }
821
822 static void mwc_FindReplaceSetup(HWND hWnd)
823 {
824         int r = DialogBox(g_hInstance, "Find_Flags_Dialog", hWnd, (DLGPROC) mwcd_FindSetup);
825         if(r < 0) { MessageBox(hWnd, "Failure opening Find_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
826 }
827
828 static void mwc_PrintSetup(HWND hWnd)
829 {
830         int r = DialogBox(g_hInstance, "Print_Flags_Dialog", hWnd, (DLGPROC) mwcd_PrintSetup);
831         if(r < 0) { MessageBox(hWnd, "Failure opening Print_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
832 }
833
834 static void mwc_PageSetup(HWND hWnd)
835 {
836         int r = DialogBox(g_hInstance, "PageSetup_Flags_Dialog", hWnd, (DLGPROC) mwcd_PageSetup);
837         if(r < 0) { MessageBox(hWnd, "Failure opening PageSetup_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
838 }
839
840 static void mwc_FileSetup(HWND hWnd)
841 {
842         int r = DialogBox(g_hInstance, "File_Flags_Dialog", hWnd, (DLGPROC) mwcd_FileSetup);
843         if(r < 0) { MessageBox(hWnd, "Failure opening File_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
844 }
845
846 /*
847  * Main window message dispatcher.  Here the messages get chewed up
848  * and spit out.  Note the ugly hack for the modeless Find/Replace box;
849  * this looks like it was bolted on with hexhead screws and is now
850  * dangling from Windows like a loose muffler.  Sigh.
851  */
852
853 static LRESULT CALLBACK EXPORT mainWindowDispatcher(
854         HWND hWnd,
855         UINT uMsg,
856         WPARAM wParam,
857         LPARAM lParam
858 )
859 {
860
861         if(uMsg == findMessageId) {
862                 FINDREPLACE * lpfr = (FINDREPLACE *) lParam;
863                 if(lpfr->Flags & FR_DIALOGTERM) {
864                         MessageBox(hWnd, "User closing us down.", "Down", MB_OK);
865                         findDialogBox = 0;
866                 }
867                 else if (lpfr->Flags & FR_FINDNEXT) {
868                         MessageBox(hWnd, "Finding next occurrence.", "Findnext", MB_OK);
869                 }
870                 else if (lpfr->Flags & FR_REPLACE) {
871                         MessageBox(hWnd, "Replacing next occurrence.", "Replace", MB_OK);
872                 }
873                 else if (lpfr->Flags & FR_REPLACEALL) {
874                         MessageBox(hWnd, "Replacing all occurrences.", "Replace All", MB_OK);
875                 }
876                 else {
877                         MessageBox(hWnd, "Eh?", "Eh?", MB_OK);
878                 }
879                 return 1;
880         }
881         else switch(uMsg) {
882         case WM_CREATE:
883                         /*
884                          * this is always the first message...at least as far as
885                          * we are concerned.
886                          */
887                 mwi_InitAll(hWnd);
888                 break;
889
890         case WM_PAINT:
891                         /* Well, draw something! */
892                 paintMainWindow(hWnd, uMsg, wParam, lParam);
893                 break;
894
895         case WM_DESTROY:
896                         /* Uh oh.  Eject!  Eject!  Eject! */
897                 PostQuitMessage(0);
898                 break;
899
900         case WM_COMMAND:
901                         /* menu or accelerator pressed; do something. */
902
903                 switch(wParam) {
904                 case CM_U_EXIT:
905                                 /* Uh oh.  Eject!  Eject!  Eject! */
906                         PostQuitMessage(0);
907                         break;
908
909                 /* these actually call the Common Dialogs. */
910
911                 case CM_U_COLOR:
912                         mw_ColorSetup(hWnd); return 1;
913
914                 case CM_U_FONT:
915                         mw_FontSetup(hWnd); return 1;
916
917                 case CM_U_FIND:
918                         mw_FindSetup(hWnd); return 1;
919
920                 case CM_U_REPLACE:
921                         mw_ReplaceSetup(hWnd); return 1;
922
923                 case CM_U_OPEN:
924                         mw_OpenSetup(hWnd); return 1;
925
926                 case CM_U_SAVE:
927                         mw_SaveSetup(hWnd); return 1;
928
929                 case CM_U_PSETUP:
930                         mw_PSetupSetup(hWnd); return 1;
931
932                 case CM_U_PRINT:
933                         mw_PrintSetup(hWnd); return 1;
934                         
935                 case CM_U_PAGESETUP:
936                         mw_PageSetup(hWnd); return 1;
937                         
938                 /*
939                  * these set up various flags and values in the Common Dialog
940                  * data structures, which are currently stored in static memory.
941                  * The control dialogs themselves are resources as well.
942                  */
943
944                 case CM_F_FILE:
945                         mwc_FileSetup(hWnd); return 1;
946
947                 case CM_F_COLOR:
948                         mwc_ColorSetup(hWnd); return 1;
949
950                 case CM_F_FONT:
951                         mwc_FontSetup(hWnd); return 1;
952
953                 case CM_F_FINDREPLACE:
954                         mwc_FindReplaceSetup(hWnd); return 1;
955
956                 case CM_F_PRINT:
957                         mwc_PrintSetup(hWnd); return 1;
958
959                 case CM_F_PAGESETUP: 
960                         mwc_PageSetup(hWnd); return 1;
961
962                 case CM_H_ABOUT:
963                         DialogBox(g_hInstance, "AboutDialog", hWnd, (DLGPROC) mwcd_About);
964                         return 1;
965                 case CM_H_USAGE:
966                         DialogBox(g_hInstance, "UsageDialog", hWnd, (DLGPROC) mwcd_About);
967                 /* return value?  *What* return value? */
968                         return 1;
969
970                 default:
971                         nyi(hWnd); return 1;
972                 }
973                 break;
974
975         default:
976                 return DefWindowProc(hWnd, uMsg, wParam, lParam);
977         }
978         return 0;
979 }
980
981 /* Class registration.  One might call this a Windowsism. */
982
983 static int registerMainWindowClass(HINSTANCE hInstance)
984 {
985         WNDCLASS wndClass;
986
987         wndClass.style         = CS_HREDRAW|CS_VREDRAW;
988         wndClass.lpfnWndProc   = mainWindowDispatcher;
989         wndClass.cbClsExtra    = 0;
990         wndClass.cbWndExtra    = 0;
991         wndClass.hInstance     = hInstance;
992 #if 0
993         wndClass.hIcon         = LoadIcon(hInstance, "whello");
994         wndClass.hCursor       = LoadCursor(hInstance, IDC_ARROW);
995 #endif
996         wndClass.hIcon         = 0;
997         wndClass.hCursor       = 0;
998         wndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
999         wndClass.lpszMenuName  = menuName;
1000         wndClass.lpszClassName = className;
1001
1002         return RegisterClass(&wndClass);
1003 }
1004
1005 /*
1006  * Another Windowsism; this one's not too bad, as it compares
1007  * favorably with CreateWindow() in X (mucking about with X Visuals
1008  * can get messy; at least here we don't have to worry about that).
1009  */
1010
1011 static HWND createMainWindow(HINSTANCE hInstance, int show)
1012 {
1013         HWND hWnd;
1014
1015         hWnd = CreateWindow(
1016                 className,  /* classname */
1017                 windowName,  /* windowname/title */
1018                 WS_OVERLAPPEDWINDOW, /* dwStyle */
1019                 0, /* x */
1020                 0, /* y */
1021                 CW_USEDEFAULT, /* width */
1022                 CW_USEDEFAULT, /* height */
1023                 0, /* parent window */
1024                 0, /* menu */
1025                 hInstance, /* instance */
1026                 0          /* passthrough for MDI */
1027         );
1028
1029         if(hWnd==0) return 0;
1030
1031         ShowWindow(hWnd, show);
1032         UpdateWindow(hWnd);
1033
1034         return hWnd;
1035 }
1036
1037 static int messageLoop(HINSTANCE hInstance, HWND hWnd)
1038 {
1039         MSG msg;
1040
1041         (void) hInstance;
1042         (void) hWnd;
1043
1044         while(GetMessage(&msg, 0, 0, 0)) {
1045                 TranslateMessage(&msg);
1046                 DispatchMessage(&msg);
1047         }
1048
1049         return msg.wParam;
1050 }
1051
1052 /*
1053  * Oh, did we tell you that main() isn't the name of the
1054  * thing called in a Win16/Win32 app?  And then there are
1055  * the lack of argument lists, the necessity (at least in Win16)
1056  * of having to deal with class registration exactly once (as the
1057  * app may be run again), and some other bizarre holdovers from
1058  * Windows 3.x days.  But hey, Solitaire still works.
1059  */
1060
1061 int PASCAL WinMain(
1062         HINSTANCE hInstance, HINSTANCE hPrevInstance,
1063         LPSTR lpszCmdLine, int nCmdShow
1064 )
1065 {
1066         HWND hWnd;
1067
1068         (void) lpszCmdLine;
1069
1070         strcpy(ofn_result, "--- not yet set ---");
1071
1072         if(hPrevInstance==0) {
1073                 if(!registerMainWindowClass(hInstance))
1074                         return -1;
1075         }
1076
1077         g_hInstance = hInstance;
1078
1079         hWnd = createMainWindow(hInstance,nCmdShow);
1080         if(hWnd == 0)
1081                 return -1;
1082
1083         return messageLoop(hInstance, hWnd);
1084 }
1085
1086 /* And now the end of the program.  Enjoy. */
1087
1088 /*
1089  * (c) 1999-2000 Eric Williams.  Rights as specified under the WINE
1090  * License.  Don't hoard code; share it!
1091  */