Fixed invalid buffer size by rounding up to next multiple of
[wine/wine-kai.git] / programs / cmdlgtst / cmdlgtst.c
blob6309512d4bb936ad72632faac7cf166c5b944d91
1 /*
2 * Copyright (c) 1999-2000 Eric Williams.
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.
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.
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
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.
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. :-)
33 #include <windows.h>
34 #include <commdlg.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include "cmdlgtst.h"
40 * This structure is to set up flag / control associations for the custom
41 * requesters. The ft_id is the id for the control (usually generated
42 * by the system) and the ft_bit is the flag bit which goes into the
43 * settings longword for the various Commdlg structures. It is assumed
44 * that all flags fit in an unsigned long and that all bits are in fact
45 * one bit.
49 * The array of entries is terminated by {IDOK, 0}; the assumption is that
50 * IDOK would never be associated with a dialogbox control (since it's
51 * usually the ID of the OK button}.
54 struct FlagTableEntry {
55 int ft_id;
56 unsigned long ft_bit;
59 #define EXPORT
61 static const char menuName[] = "CmdlgtstMenu";
62 static const char className[] = "CmdlgtstClass";
63 static const char windowName[] = "Cmdlgtst Window";
66 * global hInstance variable. This makes the code non-threadable,
67 * but wotthehell; this is Win32 anyway! (Though it does work
68 * under Win16, if one doesn't run more than one copy at a time.)
71 static HINSTANCE g_hInstance;
74 * global CommDlg data structures for modals. These are placed here
75 * so that the custom dialog boxes can get at them.
78 static PRINTDLG pd;
79 static COLORREF cc_cr[16];
80 static CHOOSECOLOR cc;
81 static LOGFONT cf_lf;
82 static CHOOSEFONT cf;
83 static const char ofn_filepat[] = "All Files (*.*)\0*.*\0Only Text Files (*.txt)\0*.txt\0";
84 static char ofn_result[1024];
85 static char ofn_titleresult[128];
86 static OPENFILENAME ofn;
88 /* Stuff for find and replace. These are modeless, so I have to put them here. */
90 static HWND findDialogBox = 0;
91 static UINT findMessageId = 0;
93 static FINDREPLACE frS;
94 static char fromstring[1024], tostring[1024];
96 /* Stuff for the drawing of the window(s). I put them here for convenience. */
98 static COLORREF fgColor = RGB(0, 0, 0); /* not settable */
99 static COLORREF bgColor = RGB(255, 255, 255); /* COLOR dialog */
100 static COLORREF txtColor = RGB(0, 0, 0); /* settable if one enables CF_EFFECTS */
102 /* Utility routines. */
104 void nyi(HWND hWnd)
106 /* "Hi there! I'm not yet implemented!" */
107 MessageBox(hWnd, "Not yet implemented!", "NYI", MB_ICONEXCLAMATION | MB_OK);
110 UINT CALLBACK dummyfnHook(HWND hWnd, UINT msg, UINT wParam, UINT lParam)
113 * If the user specifies something that needs an awfully stupid hook function,
114 * this is the one to use. It's a no-op, and says "I didn't do anything."
117 (void) hWnd;
118 (void) msg;
119 (void) wParam;
120 (void) lParam;
122 printf("dummyfnhook\n"); /* visible under Wine, but Windows probably won't see it! */
124 return 0;
128 * Initialization code. This code simply shoves in predefined
129 * data into the COMMDLG data structures; in the future, I might use
130 * a series of loadable resources, or static initializers; of course,
131 * if Microsoft decides to change the field ordering, I'd be screwed.
134 void mwi_Print(HWND hWnd)
136 pd.lStructSize = sizeof(PRINTDLG);
137 pd.hwndOwner = hWnd;
138 pd.hDevMode = 0;
139 pd.hDevNames = 0;
140 pd.hDC = 0;
141 pd.Flags = 0;
142 pd.nMinPage = 1;
143 pd.nMaxPage = 100;
144 pd.hInstance = g_hInstance;
145 pd.lCustData = 0;
146 pd.lpfnPrintHook = 0;
147 pd.lpfnSetupHook = 0;
148 pd.lpPrintTemplateName = 0;
149 pd.lpSetupTemplateName = 0;
150 pd.hPrintTemplate = 0;
151 pd.hSetupTemplate = 0;
154 void mwi_Color(HWND hWnd)
156 int i;
158 /* there's probably an init call for this, somewhere. */
160 for(i=0;i<16;i++)
161 cc_cr[i] = RGB(0,0,0);
163 cc.lStructSize = sizeof(CHOOSECOLOR);
164 cc.hwndOwner = hWnd;
165 cc.hInstance = (HWND)g_hInstance; /* Should be an HINSTANCE but MS made a typo */
166 cc.rgbResult = RGB(0,0,0);
167 cc.lpCustColors = cc_cr;
168 cc.Flags = 0;
169 cc.lCustData = 0;
170 cc.lpfnHook = 0;
171 cc.lpTemplateName = 0;
174 void mwi_Font(HWND hWnd)
176 cf.lStructSize = sizeof(CHOOSEFONT);
177 cf.hwndOwner = hWnd;
178 cf.hDC = 0;
179 cf.lpLogFont = &cf_lf;
180 cf.Flags = CF_SCREENFONTS; /* something's needed for display; otherwise it craps out with an error */
181 cf.rgbColors = RGB(0,0,0); /* what is *this* doing here?? */
182 cf.lCustData = 0;
183 cf.lpfnHook = 0;
184 cf.lpTemplateName = 0;
185 cf.hInstance = g_hInstance;
186 cf.lpszStyle = 0;
187 cf.nFontType = 0;
188 cf.nSizeMin = 8;
189 cf.nSizeMax = 72;
191 cf_lf.lfHeight = -18; /* this can be positive or negative, but negative is usually used. */
194 void mwi_File(HWND hWnd)
196 ofn.lStructSize = sizeof(OPENFILENAME);
197 ofn.hwndOwner = hWnd;
198 ofn.hInstance = g_hInstance;
199 ofn.lpstrFilter = ofn_filepat;
200 ofn.lpstrCustomFilter = 0;
201 ofn.nMaxCustFilter = 0;
202 ofn.nFilterIndex = 0;
203 ofn.lpstrFile = ofn_result;
204 ofn.nMaxFile = sizeof(ofn_result);
205 ofn.lpstrFileTitle = ofn_titleresult;
206 ofn.nMaxFileTitle = sizeof(ofn_titleresult);
207 ofn.lpstrInitialDir = 0;
208 ofn.lpstrTitle = "Open File";
209 ofn.Flags = 0;
210 ofn.nFileOffset = 0;
211 ofn.nFileExtension = 0;
212 ofn.lpstrDefExt = "*";
213 ofn.lCustData = 0;
214 ofn.lpfnHook = 0;
215 ofn.lpTemplateName = 0;
217 ofn_result[0] = '\0';
220 void mwi_FindReplace(HWND hWnd)
222 frS.lStructSize = sizeof(FINDREPLACE);
223 frS.hwndOwner = hWnd;
224 frS.hInstance = g_hInstance;
225 frS.Flags = FR_DOWN;
226 frS.lpstrFindWhat = fromstring;
227 frS.lpstrReplaceWith = tostring;
228 frS.wFindWhatLen = sizeof(fromstring);
229 frS.wReplaceWithLen = sizeof(tostring);
230 frS.lCustData = 0;
231 frS.lpfnHook = 0;
232 frS.lpTemplateName = 0;
234 fromstring[0] = '\0';
235 tostring[0] = '\0';
236 findMessageId = RegisterWindowMessage(FINDMSGSTRING);
239 void mwi_InitAll(HWND hWnd)
241 mwi_Print(hWnd);
242 mwi_Font(hWnd);
243 mwi_Color(hWnd);
244 mwi_File(hWnd);
245 mwi_FindReplace(hWnd);
249 * Various configurations for the window. Ideally, this
250 * would be stored with the window itself, but then, this
251 * isn't the brightest of apps. Wouldn't be hard to set up,
252 * though -- one of the neater functions of Windows, but if
253 * someone decides to load the windows themselves from resources,
254 * there might be a problem.
257 void paintMainWindow(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
259 PAINTSTRUCT ps;
260 RECT rect;
261 HPEN pen;
262 HFONT font;
263 HBRUSH brush;
265 (void) iMessage;
266 (void) wParam;
267 (void) lParam;
269 /* Commence painting! */
271 BeginPaint(hWnd, &ps);
272 GetClientRect(hWnd, (LPRECT) &rect);
274 pen = (HPEN) SelectObject(ps.hdc, CreatePen(0, 0, fgColor));
275 brush = (HBRUSH) SelectObject(ps.hdc, CreateSolidBrush(bgColor));
276 font = (HFONT) SelectObject(ps.hdc, CreateFontIndirect(&cf_lf));
279 * Ideally, we'd only need to draw the exposed bit.
280 * But something in BeginPaint is screwing up the rectangle.
281 * Either that, or Windows is drawing it wrong. AARGH!
282 * Rectangle(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
284 Rectangle(ps.hdc, rect.left, rect.top, rect.right, rect.bottom);
286 /* now draw a couple of lines, just for giggles. */
288 MoveToEx(ps.hdc, rect.left, rect.top, (POINT *) 0);
289 LineTo(ps.hdc, rect.right, rect.bottom);
290 MoveToEx(ps.hdc, rect.left, rect.bottom, (POINT *) 0);
291 LineTo(ps.hdc, rect.right, rect.top);
293 /* draw some text */
295 SetTextAlign(ps.hdc, TA_CENTER|TA_BASELINE);
296 SetTextColor(ps.hdc, txtColor);
297 TextOut(ps.hdc, (rect.left+rect.right)/2, (rect.top+rect.bottom)/2, "Common Dialog Test Page", 23);
299 SetTextAlign(ps.hdc, TA_LEFT|TA_TOP);
300 TextOut(ps.hdc, rect.left+10, rect.top+10, ofn_result, strlen(ofn_result));
301 TextOut(ps.hdc, rect.left+10, rect.top-cf_lf.lfHeight+10, ofn_titleresult, strlen(ofn_titleresult));
304 * set the HDC back to the old pen and brush,
305 * and delete the newly created objects.
308 pen = (HPEN) SelectObject(ps.hdc, pen);
309 DeleteObject(pen);
310 brush = (HBRUSH) SelectObject(ps.hdc, brush);
311 DeleteObject(brush);
312 font = (HFONT) SelectObject(ps.hdc, font);
313 DeleteObject(font);
315 EndPaint(hWnd, &ps);
319 * This function simply returns an error indication. Naturally,
320 * I do not (yet) see an elegant method by which one can convert
321 * the CDERR_xxx return values into something resembling usable text;
322 * consult cderr.h to see what was returned.
325 void mw_checkError(HWND hWnd, BOOL explicitcancel)
327 DWORD errval = CommDlgExtendedError();
328 if(errval) {
329 char errbuf[80];
331 sprintf(errbuf, "CommDlgExtendedError(): error code %ld (0x%lx)", errval, errval);
332 MessageBox(hWnd, errbuf, "Error", MB_ICONEXCLAMATION | MB_OK);
334 else {
335 if(explicitcancel) MessageBox(hWnd, "Nope, user canceled it.", "No", MB_OK);
340 * The actual dialog function calls. These merely wrap the Commdlg
341 * calls, and do something (not so) intelligent with the result.
342 * Ideally, the main window would refresh and take into account the
343 * various values specified in the dialog.
346 void mw_ColorSetup(HWND hWnd)
348 if(ChooseColor(&cc)) {
349 RECT rect;
351 GetClientRect(hWnd, (LPRECT) &rect);
352 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
353 bgColor = cc.rgbResult;
355 else mw_checkError(hWnd, FALSE);
358 void mw_FontSetup(HWND hWnd)
360 if(ChooseFont(&cf)) {
361 RECT rect;
362 GetClientRect(hWnd, (LPRECT) &rect);
363 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
364 txtColor = cf.rgbColors;
366 else mw_checkError(hWnd, FALSE);
369 void mw_FindSetup(HWND hWnd)
371 if(findDialogBox == 0) {
372 findDialogBox = FindText(&frS);
373 if(findDialogBox==0) mw_checkError(hWnd,TRUE);
377 void mw_ReplaceSetup(HWND hWnd)
379 if(findDialogBox == 0) {
380 findDialogBox = ReplaceText(&frS);
381 if(findDialogBox==0) mw_checkError(hWnd,TRUE);
385 void mw_OpenSetup(HWND hWnd)
387 if(GetOpenFileName(&ofn)) {
388 RECT rect;
389 GetClientRect(hWnd, (LPRECT) &rect);
390 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
392 else mw_checkError(hWnd,FALSE);
395 void mw_SaveSetup(HWND hWnd)
397 if(GetSaveFileName(&ofn)) {
398 RECT rect;
399 GetClientRect(hWnd, (LPRECT) &rect);
400 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
402 else mw_checkError(hWnd,FALSE);
406 * Can't find documentation in Borland for this one. Does it
407 * exist at all, or is it merely a subdialog of Print?
410 void mw_PSetupSetup(HWND hWnd)
412 nyi(hWnd);
415 void mw_PrintSetup(HWND hWnd)
417 if(PrintDlg(&pd)) {
419 * the following are suggested in the Borland documentation,
420 * but aren't that useful until WinE starts to actually
421 * function with respect to printing.
424 #if 0
425 Escape(tmp.hDC, STARTDOC, 8, "Test-Doc", NULL);
426 #endif
428 /* Print text and rectangle */
430 #if 0
431 TextOut(tmp.hDC, 50, 50, "Common Dialog Test Page", 23);
433 Rectangle(tmp.hDC, 50, 90, 625, 105);
434 Escape(tmp.hDC, NEWFRAME, 0, NULL, NULL);
435 Escape(tmp.hDC, ENDDOC, 0, NULL, NULL);
436 DeleteDC(tmp.hDC);
437 #endif
438 if (pd.hDevMode != 0)
439 GlobalFree(pd.hDevMode);
440 if (pd.hDevNames != 0)
441 GlobalFree(pd.hDevNames);
443 pd.hDevMode = 0;
444 pd.hDevNames = 0;
446 MessageBox(hWnd, "Success.", "Yes", MB_OK);
448 else mw_checkError(hWnd,TRUE);
452 * Some support functions for the custom dialog box handlers.
453 * In particular, we have to set things properly, and get the flags back.
456 void mwcd_SetFlags(HWND hWnd, struct FlagTableEntry *table, unsigned long flags)
458 int i;
460 for(i=0; table[i].ft_id != IDOK; i++)
462 CheckDlgButton(hWnd, table[i].ft_id,(table[i].ft_bit & flags) ? 1 : 0);
466 unsigned long mwcd_GetFlags(HWND hWnd, struct FlagTableEntry * table)
468 int i;
469 unsigned long l = 0;
471 for(i=0; table[i].ft_id != IDOK; i++)
473 if(IsDlgButtonChecked(hWnd, table[i].ft_id) == 1)
474 l |= table[i].ft_bit;
477 return l;
481 * These functions are the custom dialog box handlers.
482 * The division of labor may be a tad peculiar; in particular,
483 * the flag tables should probably be in the main functions,
484 * not the handlers. I'll fix that later; this works as of right now.
487 BOOL mwcd_Setup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
488 struct FlagTableEntry * table, unsigned long * flags)
490 (void) lParam;
492 switch(uMsg)
494 case WM_INITDIALOG:
495 /* Set the controls properly. */
497 mwcd_SetFlags(hWnd, table, *flags);
499 return TRUE; /* I would return FALSE if I explicitly called SetFocus(). */
500 /* As usual, Windows is weird. */
502 case WM_COMMAND:
503 switch(wParam) {
504 case IDOK:
505 *flags = mwcd_GetFlags(hWnd, table);
506 EndDialog(hWnd,1);
507 break;
509 case IDCANCEL:
510 EndDialog(hWnd,0);
511 break;
513 case CM_R_HELP:
514 break; /* help? We don't need no steenkin help! */
516 default:
517 break; /* eat the message */
519 return TRUE;
521 default:
522 return FALSE; /* since I don't process this particular message */
526 BOOL CALLBACK mwcd_ColorSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
528 static struct FlagTableEntry flagTable[] = {
529 {I_CC_RGBINIT, CC_RGBINIT},
530 {I_CC_SHOWHELP, CC_SHOWHELP},
531 {I_CC_PREVENTFULLOPEN, CC_PREVENTFULLOPEN},
532 {I_CC_FULLOPEN, CC_FULLOPEN},
533 {I_CC_ENABLETEMPLATEHANDLE, CC_ENABLETEMPLATEHANDLE},
534 {I_CC_ENABLETEMPLATE, CC_ENABLETEMPLATE},
535 {I_CC_ENABLEHOOK, CC_ENABLEHOOK},
536 {IDOK, 0},
539 return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &cc.Flags);
542 BOOL CALLBACK mwcd_FontSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
544 static struct FlagTableEntry flagTable[] = {
545 {I_CF_APPLY, CF_APPLY},
546 {I_CF_ANSIONLY, CF_ANSIONLY},
547 {I_CF_BOTH, CF_BOTH},
548 {I_CF_TTONLY, CF_TTONLY},
549 {I_CF_EFFECTS, CF_EFFECTS},
550 {I_CF_ENABLEHOOK, CF_ENABLEHOOK},
551 {I_CF_ENABLETEMPLATE, CF_ENABLETEMPLATE},
552 {I_CF_ENABLETEMPLATEHANDLE, CF_ENABLETEMPLATEHANDLE},
553 {I_CF_FIXEDPITCHONLY, CF_FIXEDPITCHONLY},
554 {I_CF_INITTOLOGFONTSTRUCT, CF_INITTOLOGFONTSTRUCT},
555 {I_CF_LIMITSIZE, CF_LIMITSIZE},
556 {I_CF_NOFACESEL, CF_NOFACESEL},
557 {I_CF_USESTYLE, CF_USESTYLE},
558 {I_CF_WYSIWYG, CF_WYSIWYG},
559 {I_CF_SHOWHELP, CF_SHOWHELP},
560 {I_CF_SCREENFONTS, CF_SCREENFONTS},
561 {I_CF_SCALABLEONLY, CF_SCALABLEONLY},
562 {I_CF_PRINTERFONTS, CF_PRINTERFONTS},
563 {I_CF_NOVECTORFONTS, CF_NOVECTORFONTS},
564 {I_CF_NOSTYLESEL, CF_NOSTYLESEL},
565 {I_CF_NOSIZESEL, CF_NOSIZESEL},
566 {I_CF_NOOEMFONTS, CF_NOOEMFONTS},
567 {IDOK, 0},
570 return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &cf.Flags);
573 BOOL CALLBACK mwcd_FindSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
576 static struct FlagTableEntry flagTable[] = {
577 {I_FR_DIALOGTERM, FR_DIALOGTERM},
578 {I_FR_DOWN, FR_DOWN},
579 {I_FR_ENABLEHOOK, FR_ENABLEHOOK},
580 {I_FR_ENABLETEMPLATE, FR_ENABLETEMPLATE},
581 {I_FR_ENABLETEMPLATEHANDLE, FR_ENABLETEMPLATEHANDLE},
582 {I_FR_FINDNEXT, FR_FINDNEXT},
583 {I_FR_HIDEMATCHCASE, FR_HIDEMATCHCASE},
584 {I_FR_HIDEWHOLEWORD, FR_HIDEWHOLEWORD},
585 {I_FR_HIDEUPDOWN, FR_HIDEUPDOWN},
586 {I_FR_MATCHCASE, FR_MATCHCASE},
587 {I_FR_NOMATCHCASE, FR_NOMATCHCASE},
588 {I_FR_NOUPDOWN, FR_NOUPDOWN},
589 {I_FR_NOWHOLEWORD, FR_NOWHOLEWORD},
590 {I_FR_REPLACE, FR_REPLACE},
591 {I_FR_REPLACEALL, FR_REPLACEALL},
592 {I_FR_SHOWHELP, FR_SHOWHELP},
593 {I_FR_WHOLEWORD, FR_WHOLEWORD},
594 {IDOK, 0},
597 return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &frS.Flags);
600 BOOL CALLBACK mwcd_PrintSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
602 static struct FlagTableEntry flagTable[] = {
603 {I_PD_ALLPAGES, PD_ALLPAGES},
604 {I_PD_COLLATE, PD_COLLATE},
605 {I_PD_DISABLEPRINTTOFILE, PD_DISABLEPRINTTOFILE},
606 {I_PD_ENABLEPRINTHOOK, PD_ENABLEPRINTHOOK},
607 {I_PD_ENABLEPRINTTEMPLATE, PD_ENABLEPRINTTEMPLATE},
608 {I_PD_ENABLEPRINTTEMPLATEHANDLE, PD_ENABLEPRINTTEMPLATEHANDLE},
609 {I_PD_ENABLESETUPHOOK, PD_ENABLESETUPHOOK},
610 {I_PD_ENABLESETUPTEMPLATE, PD_ENABLESETUPTEMPLATE},
611 {I_PD_ENABLESETUPTEMPLATEHANDLE, PD_ENABLESETUPTEMPLATEHANDLE},
612 {I_PD_HIDEPRINTTOFILE, PD_HIDEPRINTTOFILE},
613 {I_PD_NOPAGENUMS, PD_NOPAGENUMS},
614 {I_PD_NOSELECTION, PD_NOSELECTION},
615 {I_PD_NOWARNING, PD_NOWARNING},
616 {I_PD_PAGENUMS, PD_PAGENUMS},
617 {I_PD_PRINTSETUP, PD_PRINTSETUP},
618 {I_PD_PRINTTOFILE, PD_PRINTTOFILE},
619 {I_PD_RETURNDC, PD_RETURNDC},
620 {I_PD_RETURNDEFAULT, PD_RETURNDEFAULT},
621 {I_PD_RETURNIC, PD_RETURNIC},
622 {I_PD_SELECTION, PD_SELECTION},
623 {I_PD_SHOWHELP, PD_SHOWHELP},
624 {I_PD_USEDEVMODECOPIES, PD_USEDEVMODECOPIES},
625 {IDOK, 0},
628 return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &pd.Flags);
631 BOOL CALLBACK mwcd_FileSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
633 static struct FlagTableEntry flagTable[] = {
634 {I_OFN_ALLOWMULTISELECT, OFN_ALLOWMULTISELECT},
635 {I_OFN_CREATEPROMPT, OFN_CREATEPROMPT},
636 {I_OFN_ENABLEHOOK, OFN_ENABLEHOOK},
637 {I_OFN_ENABLETEMPLATE, OFN_ENABLETEMPLATE},
638 {I_OFN_ENABLETEMPLATEHANDLE, OFN_ENABLETEMPLATEHANDLE},
639 {I_OFN_EXTENSIONDIFFERENT, OFN_EXTENSIONDIFFERENT},
640 {I_OFN_FILEMUSTEXIST, OFN_FILEMUSTEXIST},
641 {I_OFN_HIDEREADONLY, OFN_HIDEREADONLY},
642 {I_OFN_NOCHANGEDIR, OFN_NOCHANGEDIR},
643 {I_OFN_NOREADONLYRETURN, OFN_NOREADONLYRETURN},
644 {I_OFN_NOTESTFILECREATE, OFN_NOTESTFILECREATE},
645 {I_OFN_NOVALIDATE, OFN_NOVALIDATE},
646 {I_OFN_OVERWRITEPROMPT, OFN_OVERWRITEPROMPT},
647 {I_OFN_PATHMUSTEXIST, OFN_PATHMUSTEXIST},
648 {I_OFN_READONLY, OFN_READONLY},
649 {I_OFN_SHAREAWARE, OFN_SHAREAWARE},
650 {I_OFN_SHOWHELP, OFN_SHOWHELP},
651 {IDOK, 0},
654 return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &ofn.Flags);
657 BOOL CALLBACK mwcd_About(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
659 (void) wParam;
660 (void) lParam;
662 switch(uMsg) {
663 case WM_INITDIALOG: return TRUE; /* let WINDOWS set the focus. */
664 case WM_COMMAND: EndDialog(hWnd, 0); return TRUE; /* it's our OK button. */
665 default: return FALSE; /* it's something else, let Windows worry about it */
670 * These functions call custom dialog boxes (resource-loaded, if I do this right).
671 * Right now they don't do a heck of a lot, but at some future time
672 * they will muck about with the flags (and be loaded from the flags) of
673 * the CommDlg structures initialized by the mwi_xxx() routines.
676 void mwc_ColorSetup(HWND hWnd)
678 int r = DialogBox(g_hInstance, "Color_Flags_Dialog", hWnd, (DLGPROC) mwcd_ColorSetup);
679 if(r < 0) { MessageBox(hWnd, "Failure opening Color_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
682 void mwc_FontSetup(HWND hWnd)
684 int r = DialogBox(g_hInstance, "Font_Flags_Dialog", hWnd, (DLGPROC) mwcd_FontSetup);
685 if(r < 0) { MessageBox(hWnd, "Failure opening Font_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
688 void mwc_FindReplaceSetup(HWND hWnd)
690 int r = DialogBox(g_hInstance, "Find_Flags_Dialog", hWnd, (DLGPROC) mwcd_FindSetup);
691 if(r < 0) { MessageBox(hWnd, "Failure opening Find_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
694 void mwc_PrintSetup(HWND hWnd)
696 int r = DialogBox(g_hInstance, "Print_Flags_Dialog", hWnd, (DLGPROC) mwcd_PrintSetup);
697 if(r < 0) { MessageBox(hWnd, "Failure opening Print_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
700 void mwc_FileSetup(HWND hWnd)
702 int r = DialogBox(g_hInstance, "File_Flags_Dialog", hWnd, (DLGPROC) mwcd_FileSetup);
703 if(r < 0) { MessageBox(hWnd, "Failure opening File_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
707 * Main window message dispatcher. Here the messages get chewed up
708 * and spit out. Note the ugly hack for the modeless Find/Replace box;
709 * this looks like it was bolted on with hexhead screws and is now
710 * dangling from Windows like a loose muffler. Sigh.
713 LRESULT CALLBACK EXPORT mainWindowDispatcher(
714 HWND hWnd,
715 UINT uMsg,
716 WPARAM wParam,
717 LPARAM lParam
721 if(uMsg == findMessageId) {
722 FINDREPLACE * lpfr = (FINDREPLACE *) lParam;
723 if(lpfr->Flags & FR_DIALOGTERM) {
724 MessageBox(hWnd, "User closing us down.", "Down", MB_OK);
725 findDialogBox = 0;
727 else if (lpfr->Flags & FR_FINDNEXT) {
728 MessageBox(hWnd, "Finding next occurrence.", "Findnext", MB_OK);
730 else if (lpfr->Flags & FR_REPLACE) {
731 MessageBox(hWnd, "Replacing next occurence.", "Replace", MB_OK);
733 else if (lpfr->Flags & FR_REPLACEALL) {
734 MessageBox(hWnd, "Replacing all occurrences.", "Replace All", MB_OK);
736 else {
737 MessageBox(hWnd, "Eh?", "Eh?", MB_OK);
739 return 1;
741 else switch(uMsg) {
742 case WM_CREATE:
744 * this is always the first message...at least as far as
745 * we are concerned.
747 mwi_InitAll(hWnd);
748 break;
750 case WM_PAINT:
751 /* Well, draw something! */
752 paintMainWindow(hWnd, uMsg, wParam, lParam);
753 break;
755 case WM_DESTROY:
756 /* Uh oh. Eject! Eject! Eject! */
757 PostQuitMessage(0);
758 break;
760 case WM_COMMAND:
761 /* menu or accelerator pressed; do something. */
763 switch(wParam) {
764 case CM_U_EXIT:
765 /* Uh oh. Eject! Eject! Eject! */
766 PostQuitMessage(0);
767 break;
769 /* these actually call the Common Dialogs. */
771 case CM_U_COLOR:
772 mw_ColorSetup(hWnd); return 1;
774 case CM_U_FONT:
775 mw_FontSetup(hWnd); return 1;
777 case CM_U_FIND:
778 mw_FindSetup(hWnd); return 1;
780 case CM_U_REPLACE:
781 mw_ReplaceSetup(hWnd); return 1;
783 case CM_U_OPEN:
784 mw_OpenSetup(hWnd); return 1;
786 case CM_U_SAVE:
787 mw_SaveSetup(hWnd); return 1;
789 case CM_U_PSETUP:
790 mw_PSetupSetup(hWnd); return 1;
792 case CM_U_PRINT:
793 mw_PrintSetup(hWnd); return 1;
796 * these set up various flags and values in the Common Dialog
797 * data structures, which are currently stored in static memory.
798 * The control dialogs themselves are resources as well.
801 case CM_F_FILE:
802 mwc_FileSetup(hWnd); return 1;
804 case CM_F_COLOR:
805 mwc_ColorSetup(hWnd); return 1;
807 case CM_F_FONT:
808 mwc_FontSetup(hWnd); return 1;
810 case CM_F_FINDREPLACE:
811 mwc_FindReplaceSetup(hWnd); return 1;
813 case CM_F_PRINT:
814 mwc_PrintSetup(hWnd); return 1;
816 case CM_H_ABOUT:
817 DialogBox(g_hInstance, "AboutDialog", hWnd, (DLGPROC) mwcd_About);
818 return 1;
819 case CM_H_USAGE:
820 DialogBox(g_hInstance, "UsageDialog", hWnd, (DLGPROC) mwcd_About);
821 /* return value? *What* return value? */
822 return 1;
824 default:
825 nyi(hWnd); return 1;
827 break;
829 default:
830 return DefWindowProc(hWnd, uMsg, wParam, lParam);
832 return 0;
835 /* Class registration. One might call this a Windowsism. */
837 int registerMainWindowClass(HINSTANCE hInstance)
839 WNDCLASS wndClass;
841 wndClass.style = CS_HREDRAW|CS_VREDRAW;
842 wndClass.lpfnWndProc = mainWindowDispatcher;
843 wndClass.cbClsExtra = 0;
844 wndClass.cbWndExtra = 0;
845 wndClass.hInstance = hInstance;
846 #if 0
847 wndClass.hIcon = LoadIcon(hInstance, "whello");
848 wndClass.hCursor = LoadCursor(hInstance, IDC_ARROW);
849 #endif
850 wndClass.hIcon = 0;
851 wndClass.hCursor = 0;
852 wndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
853 wndClass.lpszMenuName = menuName;
854 wndClass.lpszClassName = className;
856 return RegisterClass(&wndClass);
860 * Another Windowsism; this one's not too bad, as it compares
861 * favorably with CreateWindow() in X (mucking about with X Visuals
862 * can get messy; at least here we don't have to worry about that).
865 HWND createMainWindow(HINSTANCE hInstance, int show)
867 HWND hWnd;
869 hWnd = CreateWindow(
870 className, /* classname */
871 windowName, /* windowname/title */
872 WS_OVERLAPPEDWINDOW, /* dwStyle */
873 0, /* x */
874 0, /* y */
875 CW_USEDEFAULT, /* width */
876 CW_USEDEFAULT, /* height */
877 0, /* parent window */
878 0, /* menu */
879 hInstance, /* instance */
880 0 /* passthrough for MDI */
883 if(hWnd==0) return 0;
885 ShowWindow(hWnd, show);
886 UpdateWindow(hWnd);
888 return hWnd;
891 int messageLoop(HINSTANCE hInstance, HWND hWnd)
893 MSG msg;
895 (void) hInstance;
896 (void) hWnd;
898 while(GetMessage(&msg, 0, 0, 0)) {
899 TranslateMessage(&msg);
900 DispatchMessage(&msg);
903 return msg.wParam;
907 * Oh, did we tell you that main() isn't the name of the
908 * thing called in a Win16/Win32 app? And then there are
909 * the lack of argument lists, the necessity (at least in Win16)
910 * of having to deal with class registration exactly once (as the
911 * app may be run again), and some other bizarre holdovers from
912 * Windows 3.x days. But hey, Solitaire still works.
915 int PASCAL WinMain(
916 HINSTANCE hInstance, HINSTANCE hPrevInstance,
917 LPSTR lpszCmdLine, int nCmdShow
920 HWND hWnd;
922 (void) lpszCmdLine;
924 strcpy(ofn_result, "--- not yet set ---");
926 if(hPrevInstance==0) {
927 if(!registerMainWindowClass(hInstance))
928 return -1;
931 g_hInstance = hInstance;
933 hWnd = createMainWindow(hInstance,nCmdShow);
934 if(hWnd == 0)
935 return -1;
937 return messageLoop(hInstance, hWnd);
940 /* And now the end of the program. Enjoy. */
943 * (c) 1999-2000 Eric Williams. Rights as specified under the WINE
944 * License. Don't hoard code; share it!