1 #include "precomp.h"
2 
3 static const TCHAR szMainWndClass[] = TEXT("WordPadMainWndClass");
4 
5 #define ID_MDI_FIRSTCHILD   50000
6 #define ID_MDI_WINDOWMENU   5
7 
8 /* menu hints */
9 static const MENU_HINT MainMenuHintTable[] = {
10     /* File Menu */
11     {ID_BLANK,     IDS_HINT_BLANK},
12     {ID_NEW,       IDS_HINT_NEW},
13     {ID_OPEN,      IDS_HINT_OPEN},
14     {ID_CLOSE,     IDS_HINT_CLOSE},
15     {ID_CLOSEALL,  IDS_HINT_CLOSEALL},
16     {ID_SAVE,      IDS_HINT_SAVE},
17     {ID_SAVEAS,    IDS_HINT_SAVEAS},
18     {ID_PRINT,     IDS_HINT_PRINT},
19     {ID_PRINTPRE,  IDS_HINT_PRINTPRE},
20     {ID_PAGESETUP, IDS_HINT_PAGESETUP},
21     {ID_EXIT,      IDS_HINT_EXIT},
22 
23     /* Window Menu */
24     {ID_WINDOW_NEXT,      IDS_HINT_NEXT},
25     {ID_WINDOW_CASCADE,   IDS_HINT_CASCADE},
26     {ID_WINDOW_TILE_HORZ, IDS_HINT_TILE_HORZ},
27     {ID_WINDOW_TILE_VERT, IDS_HINT_TILE_VERT},
28     {ID_WINDOW_ARRANGE,   IDS_HINT_ARRANGE}
29 };
30 
31 static const MENU_HINT SystemMenuHintTable[] = {
32     {SC_RESTORE,    IDS_HINT_SYS_RESTORE},
33     {SC_MOVE,       IDS_HINT_SYS_MOVE},
34     {SC_SIZE,       IDS_HINT_SYS_SIZE},
35     {SC_MINIMIZE,   IDS_HINT_SYS_MINIMIZE},
36     {SC_MAXIMIZE,   IDS_HINT_SYS_MAXIMIZE},
37     {SC_CLOSE,      IDS_HINT_CLOSE},
38     {SC_NEXTWINDOW, IDS_HINT_NEXT},
39 };
40 
41 
42 static VOID
CreateToolbars(PMAIN_WND_INFO Info)43 CreateToolbars(PMAIN_WND_INFO Info)
44 {
45 
46 }
47 
48 static VOID CALLBACK
MainWndResize(PVOID Context,WORD cx,WORD cy)49 MainWndResize(PVOID Context,
50               WORD cx,
51               WORD cy)
52 {
53     RECT rcClient = {0};
54     RECT rcStatus = {0};
55     HDWP dwp;
56     PMAIN_WND_INFO Info = (PMAIN_WND_INFO)Context;
57 
58     /* Calculate the MDI client rectangle */
59     rcClient.right = cx;
60     rcClient.bottom = cy;
61 
62     if (Info->hStatus != NULL)
63     {
64         GetWindowRect(Info->hStatus,
65                       &rcStatus);
66         rcClient.bottom -= (rcStatus.bottom - rcStatus.top);
67     }
68 
69 
70     dwp = BeginDeferWindowPos(2);
71     if (dwp != NULL)
72     {
73         /* Update the MDI client */
74         if (Info->hMdiClient != NULL)
75         {
76             dwp = DeferWindowPos(dwp,
77                                  Info->hMdiClient,
78                                  NULL,
79                                  rcClient.left,
80                                  rcClient.top,
81                                  rcClient.right - rcClient.left,
82                                  rcClient.bottom - rcClient.top,
83                                  SWP_NOZORDER);
84             if (dwp == NULL)
85                 return;
86         }
87 
88         /* Update the status bar */
89         if (Info->hStatus != NULL)
90         {
91             dwp = DeferWindowPos(dwp,
92                                  Info->hStatus,
93                                  NULL,
94                                  0,
95                                  cy - (rcStatus.bottom - rcStatus.top),
96                                  cx,
97                                  rcStatus.bottom - rcStatus.top,
98                                  SWP_NOZORDER);
99             if (dwp == NULL)
100                 return;
101         }
102 
103         EndDeferWindowPos(dwp);
104     }
105 }
106 
107 static VOID
InitMainWnd(PMAIN_WND_INFO Info)108 InitMainWnd(PMAIN_WND_INFO Info)
109 {
110     CLIENTCREATESTRUCT ccs;
111     INT statwidths[] = {110, -1};
112 
113     /* FIXME - create controls and initialize the application */
114 
115     /* create the status bar */
116     Info->hStatus = CreateWindowEx(0,
117                                    STATUSCLASSNAME,
118                                    NULL,
119                                    WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | CCS_NOPARENTALIGN | SBARS_SIZEGRIP,
120                                    0,
121                                    0,
122                                    0,
123                                    0,
124                                    Info->hSelf,
125                                    (HMENU)IDC_STATUSBAR,
126                                    hInstance,
127                                    NULL);
128 
129     if (Info->hStatus != NULL)
130         SendMessage(Info->hStatus,
131                     SB_SETPARTS,
132                     sizeof(statwidths)/sizeof(int),
133                     (LPARAM)statwidths);
134 
135     /* create the MDI client window */
136     ccs.hWindowMenu = GetSubMenu(GetMenu(Info->hSelf),
137                                  ID_MDI_WINDOWMENU);
138     ccs.idFirstChild = ID_MDI_FIRSTCHILD;
139     Info->hMdiClient = CreateWindowEx(WS_EX_ACCEPTFILES | WS_EX_CLIENTEDGE,
140                                       TEXT("MDICLIENT"),
141                                       NULL,
142                                       WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL,
143                                       0,
144                                       0,
145                                       0,
146                                       0,
147                                       Info->hSelf,
148                                       NULL,
149                                       hInstance,
150                                       &ccs);
151 
152     CreateToolbars(Info);
153 
154     /* initialize file open/save structure */
155     FileInitialize(Info->hSelf);
156 }
157 
158 static VOID
MainWndCommand(PMAIN_WND_INFO Info,WORD CmdId,HWND hControl)159 MainWndCommand(PMAIN_WND_INFO Info,
160                WORD CmdId,
161                HWND hControl)
162 {
163     static TCHAR szFileName[MAX_PATH];
164     static TCHAR szDocumentName[MAX_PATH];
165 
166     UNREFERENCED_PARAMETER(hControl);
167 
168     switch (CmdId)
169     {
170         case ID_NEW:
171         {
172             OPEN_EDIT_INFO OpenInfo;
173             INT Ret;
174 
175             OpenInfo.CreateNew = TRUE;
176 
177             LoadAndFormatString(hInstance,
178                                 IDS_DEFAULT_NAME,
179                                 &OpenInfo.lpDocumentName,
180                                 ++Info->ImagesCreated);
181 
182             Ret = DialogBox(hInstance,
183                             MAKEINTRESOURCE(IDD_NEWDOCSEL),
184                             Info->hSelf,
185                             NewDocSelDlgProc);
186             if (Ret != -1)
187             {
188                 OpenInfo.DocType = Ret;
189 
190                 CreateEditWindow(Info,
191                                  &OpenInfo);
192             }
193 
194         }
195         break;
196 
197         case ID_BOLD:
198             MessageBox(NULL, _T("Bingo"), NULL, 0);
199         break;
200 
201         case ID_OPEN:
202         {
203             OPEN_EDIT_INFO OpenInfo;
204 
205             if (DoOpenFile(Info->hSelf,
206                            szFileName,   /* full file path */
207                            szDocumentName)) /* file name */
208             {
209                 OpenInfo.CreateNew = FALSE;
210 
211                 OpenInfo.lpDocumentPath = szFileName;
212                 OpenInfo.lpDocumentName = szDocumentName;
213 
214                 CreateEditWindow(Info,
215                                  &OpenInfo);
216             }
217 
218         }
219         break;
220 
221         case ID_EXIT:
222             SendMessage(Info->hSelf,
223                         WM_CLOSE,
224                         0,
225                         0);
226             break;
227 
228         /* Window Menu */
229         case ID_WINDOW_TILE_HORZ:
230             SendMessage(Info->hMdiClient,
231                         WM_MDITILE,
232                         MDITILE_HORIZONTAL,
233                         0);
234             break;
235 
236         case ID_WINDOW_TILE_VERT:
237             SendMessage(Info->hMdiClient,
238                         WM_MDITILE,
239                         MDITILE_VERTICAL,
240                         0);
241             break;
242 
243         case ID_WINDOW_CASCADE:
244             SendMessage(Info->hMdiClient,
245                         WM_MDICASCADE,
246                         0,
247                         0);
248             break;
249 
250         case ID_WINDOW_ARRANGE:
251             SendMessage(Info->hMdiClient,
252                         WM_MDIICONARRANGE,
253                         0,
254                         0);
255             break;
256 
257         case ID_WINDOW_NEXT:
258             SendMessage(Info->hMdiClient,
259                         WM_MDINEXT,
260                         0,
261                         0);
262             break;
263 
264         /* Help Menu */
265         case ID_ABOUT:
266             DialogBox(hInstance,
267                       MAKEINTRESOURCE(IDD_ABOUTBOX),
268                       Info->hSelf,
269                       AboutDialogProc);
270             break;
271     }
272 }
273 
274 static VOID
DestroyMainWnd(PMAIN_WND_INFO Info)275 DestroyMainWnd(PMAIN_WND_INFO Info)
276 {
277     /* FIXME - cleanup allocated resources */
278 }
279 
280 
281 static VOID
UpdateMainStatusBar(PMAIN_WND_INFO Info)282 UpdateMainStatusBar(PMAIN_WND_INFO Info)
283 {
284     if (Info->hStatus != NULL)
285     {
286         SendMessage(Info->hStatus,
287                     SB_SIMPLE,
288                     (WPARAM)Info->InMenuLoop,
289                     0);
290     }
291 }
292 
293 static BOOL
MainWndMenuHint(PMAIN_WND_INFO Info,WORD CmdId,const MENU_HINT * HintArray,DWORD HintsCount,UINT DefHintId)294 MainWndMenuHint(PMAIN_WND_INFO Info,
295                 WORD CmdId,
296                 const MENU_HINT *HintArray,
297                 DWORD HintsCount,
298                 UINT DefHintId)
299 {
300     BOOL Found = FALSE;
301     const MENU_HINT *LastHint;
302     UINT HintId = DefHintId;
303 
304     LastHint = HintArray + HintsCount;
305     while (HintArray != LastHint)
306     {
307         if (HintArray->CmdId == CmdId)
308         {
309             HintId = HintArray->HintId;
310             Found = TRUE;
311             break;
312         }
313         HintArray++;
314     }
315 
316     StatusBarLoadString(Info->hStatus,
317                         SB_SIMPLEID,
318                         hInstance,
319                         HintId);
320 
321     return Found;
322 }
323 
324 static LRESULT CALLBACK
MainWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)325 MainWndProc(HWND hwnd,
326             UINT uMsg,
327             WPARAM wParam,
328             LPARAM lParam)
329 {
330     PMAIN_WND_INFO Info;
331     LRESULT Ret = 0;
332     static RECT wndOldPos;
333 
334     /* Get the window context */
335     Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd,
336                                             GWLP_USERDATA);
337     if (Info == NULL && uMsg != WM_CREATE)
338     {
339         goto HandleDefaultMessage;
340     }
341 
342     switch (uMsg)
343     {
344         case WM_CREATE:
345         {
346             Info = (PMAIN_WND_INFO)(((LPCREATESTRUCT)lParam)->lpCreateParams);
347 
348             /* Initialize the main window context */
349             Info->hSelf = hwnd;
350 
351             SetWindowLongPtr(hwnd,
352                              GWLP_USERDATA,
353                              (LONG_PTR)Info);
354 
355             InitMainWnd(Info);
356 
357             /* Show the window */
358             ShowWindow(hwnd,
359                        Info->nCmdShow);
360             /* get the windows position */
361             GetWindowRect(hwnd,
362                           &wndOldPos);
363 
364             break;
365         }
366 
367         case WM_SIZE:
368         {
369             MainWndResize(Info,
370                           LOWORD(lParam),
371                           HIWORD(lParam));
372             /* NOTE - do *not* forward this message to DefFrameProc! Otherwise the MDI client
373                       will attempt to resize itself */
374 
375             break;
376         }
377 
378         case WM_MOVE:
379         {
380 
381         }
382         break;
383 
384         case WM_NOTIFY:
385         {
386 
387                 /* FIXME - handle other notifications */
388             break;
389         }
390 
391         case WM_COMMAND:
392         {
393             MainWndCommand(Info,
394                            LOWORD(wParam),
395                            (HWND)lParam);
396             goto HandleDefaultMessage;
397         }
398 
399         case WM_MENUSELECT:
400         {
401             if (Info->hStatus != NULL)
402             {
403                 if (!MainWndMenuHint(Info,
404                                      LOWORD(wParam),
405                                      MainMenuHintTable,
406                                      sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
407                                      IDS_HINT_BLANK))
408                 {
409                     MainWndMenuHint(Info,
410                                     LOWORD(wParam),
411                                     SystemMenuHintTable,
412                                     sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
413                                     IDS_HINT_BLANK);
414                 }
415             }
416             break;
417         }
418 
419         case WM_ENTERMENULOOP:
420         {
421             Info->InMenuLoop = TRUE;
422             UpdateMainStatusBar(Info);
423             break;
424         }
425 
426         case WM_EXITMENULOOP:
427         {
428             Info->InMenuLoop = FALSE;
429             UpdateMainStatusBar(Info);
430             break;
431         }
432 
433         case WM_CLOSE:
434         {
435             DestroyWindow(hwnd);
436             break;
437         }
438 
439         case WM_ENABLE:
440         {
441 
442             goto HandleDefaultMessage;
443         }
444 
445         case WM_NCACTIVATE:
446         {
447 
448             goto HandleDefaultMessage;
449         }
450 
451         case WM_ACTIVATEAPP:
452         {
453 
454             goto HandleDefaultMessage;
455         }
456 
457         case WM_DESTROY:
458         {
459             DestroyMainWnd(Info);
460 
461             /* FIXME: set the windows position in registry*/
462             //wndOldPos
463 
464             HeapFree(ProcessHeap,
465                      0,
466                      Info);
467             SetWindowLongPtr(hwnd,
468                              GWLP_USERDATA,
469                              0);
470 
471             /* Break the message queue loop */
472             PostQuitMessage(0);
473             break;
474         }
475 
476         default:
477         {
478 HandleDefaultMessage:
479             if (Info != NULL && Info->hMdiClient != NULL)
480             {
481                 Ret = DefFrameProc(hwnd,
482                                    Info->hMdiClient,
483                                    uMsg,
484                                    wParam,
485                                    lParam);
486             }
487             else
488             {
489                 Ret = DefWindowProc(hwnd,
490                                     uMsg,
491                                     wParam,
492                                     lParam);
493             }
494             break;
495         }
496     }
497 
498     return Ret;
499 }
500 
501 MDI_EDITOR_TYPE
MainWndGetCurrentEditor(PMAIN_WND_INFO MainWnd,PVOID * Info)502 MainWndGetCurrentEditor(PMAIN_WND_INFO MainWnd,
503                         PVOID *Info)
504 {
505     MDI_EDITOR_TYPE EditorType;
506 
507     if (MainWnd->ActiveEditor != NULL)
508     {
509         EditorType = *((PMDI_EDITOR_TYPE)MainWnd->ActiveEditor);
510         *Info = MainWnd->ActiveEditor;
511     }
512     else
513     {
514         EditorType = metUnknown;
515         *Info = NULL;
516     }
517 
518     return EditorType;
519 }
520 
521 VOID
MainWndSwitchEditorContext(PMAIN_WND_INFO Info,HWND hDeactivate,HWND hActivate)522 MainWndSwitchEditorContext(PMAIN_WND_INFO Info,
523                            HWND hDeactivate,
524                            HWND hActivate)
525 {
526     PMDI_EDITOR_TYPE EditorType;
527 
528     /* FIXME - optimize light weight switching
529                when switching from and to an editor of same type */
530 
531     if (hDeactivate != NULL)
532     {
533         EditorType = (PMDI_EDITOR_TYPE)GetWindowLongPtr(hDeactivate,
534                                                         GWLP_USERDATA);
535         if (EditorType != NULL)
536         {
537             switch (*EditorType)
538             {
539                 case metImageEditor:
540                     SetEditorEnvironment((PEDIT_WND_INFO)EditorType,
541                                               FALSE);
542                     break;
543 
544                 default:
545                     break;
546             }
547 
548             Info->ActiveEditor = NULL;
549         }
550     }
551 
552     if (hActivate != NULL)
553     {
554         EditorType = (PMDI_EDITOR_TYPE)GetWindowLongPtr(hActivate,
555                                                         GWLP_USERDATA);
556         if (EditorType != NULL)
557         {
558             Info->ActiveEditor = EditorType;
559 
560             switch (*EditorType)
561             {
562                 case metImageEditor:
563                     SetEditorEnvironment((PEDIT_WND_INFO)EditorType,
564                                               TRUE);
565                     break;
566 
567                 default:
568                     break;
569             }
570         }
571     }
572 }
573 
574 HWND
CreateMainWindow(LPCTSTR lpCaption,int nCmdShow)575 CreateMainWindow(LPCTSTR lpCaption,
576                  int nCmdShow)
577 {
578     PMAIN_WND_INFO Info;
579     HWND hMainWnd = NULL;
580 
581     Info = (MAIN_WND_INFO*) HeapAlloc(ProcessHeap,
582                      0,
583                      sizeof(MAIN_WND_INFO));
584     if (Info != NULL)
585     {
586         ZeroMemory(Info,
587                    sizeof(MAIN_WND_INFO));
588         Info->nCmdShow = nCmdShow;
589 
590         /* FIXME - load the window position from the registry */
591 
592         hMainWnd = CreateWindowEx(WS_EX_WINDOWEDGE,
593                                   szMainWndClass,
594                                   lpCaption,
595                                   WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
596                                   CW_USEDEFAULT,
597                                   CW_USEDEFAULT,
598                                   CW_USEDEFAULT,
599                                   CW_USEDEFAULT,
600                                   NULL,
601                                   NULL,
602                                   hInstance,
603                                   Info);
604         if (hMainWnd == NULL)
605         {
606             HeapFree(ProcessHeap,
607                      0,
608                      Info);
609         }
610     }
611 
612     return hMainWnd;
613 }
614 
615 BOOL
MainWndTranslateMDISysAccel(HWND hwnd,LPMSG lpMsg)616 MainWndTranslateMDISysAccel(HWND hwnd,
617                             LPMSG lpMsg)
618 {
619     PMAIN_WND_INFO Info;
620 
621     /* Get the window context */
622     Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd,
623                                             GWLP_USERDATA);
624     if (Info != NULL && Info->hMdiClient != NULL)
625     {
626         return TranslateMDISysAccel(Info->hMdiClient,
627                                     lpMsg);
628     }
629 
630     return FALSE;
631 }
632 
633 BOOL
InitMainWindowImpl(VOID)634 InitMainWindowImpl(VOID)
635 {
636     WNDCLASSEX wc = {0};
637 
638     wc.cbSize = sizeof(WNDCLASSEX);
639     wc.lpfnWndProc = MainWndProc;
640     wc.hInstance = hInstance;
641     wc.hIcon = LoadIcon(hInstance,
642                         MAKEINTRESOURCE(IDI_ICON));
643     wc.hCursor = LoadCursor(NULL,
644                             IDC_ARROW);
645     wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
646     wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
647     wc.lpszClassName = szMainWndClass;
648     wc.hIconSm = (HICON)LoadImage(hInstance,
649                                   MAKEINTRESOURCE(IDI_ICON),
650                                   IMAGE_ICON,
651                                   16,
652                                   16,
653                                   LR_SHARED);
654 
655     return RegisterClassEx(&wc) != (ATOM)0;
656 }
657 
658 VOID
UninitMainWindowImpl(VOID)659 UninitMainWindowImpl(VOID)
660 {
661     UnregisterClass(szMainWndClass,
662                     hInstance);
663 }
664