xref: /reactos/base/applications/notepad/dialog.c (revision 22f0c3a8)
1 /*
2  *  Notepad (dialog.c)
3  *
4  *  Copyright 1998,99 Marcel Baur <mbaur@g26.ethz.ch>
5  *  Copyright 2002 Sylvain Petreolle <spetreolle@yahoo.fr>
6  *  Copyright 2002 Andriy Palamarchuk
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22 
23 #include "notepad.h"
24 
25 #include <assert.h>
26 #include <commctrl.h>
27 #include <strsafe.h>
28 
29 LRESULT CALLBACK EDIT_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
30 
31 static const TCHAR helpfile[] = _T("notepad.hlp");
32 static const TCHAR empty_str[] = _T("");
33 static const TCHAR szDefaultExt[] = _T("txt");
34 static const TCHAR txt_files[] = _T("*.txt");
35 
36 static UINT_PTR CALLBACK DIALOG_PAGESETUP_Hook(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
37 
38 VOID ShowLastError(VOID)
39 {
40     DWORD error = GetLastError();
41     if (error != NO_ERROR)
42     {
43         LPTSTR lpMsgBuf = NULL;
44         TCHAR szTitle[MAX_STRING_LEN];
45 
46         LoadString(Globals.hInstance, STRING_ERROR, szTitle, ARRAY_SIZE(szTitle));
47 
48         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
49                       NULL,
50                       error,
51                       0,
52                       (LPTSTR) &lpMsgBuf,
53                       0,
54                       NULL);
55 
56         MessageBox(NULL, lpMsgBuf, szTitle, MB_OK | MB_ICONERROR);
57         LocalFree(lpMsgBuf);
58     }
59 }
60 
61 /**
62  * Sets the caption of the main window according to Globals.szFileTitle:
63  *    (untitled) - Notepad      if no file is open
64  *    [filename] - Notepad      if a file is given
65  */
66 void UpdateWindowCaption(BOOL clearModifyAlert)
67 {
68     TCHAR szCaption[MAX_STRING_LEN];
69     TCHAR szNotepad[MAX_STRING_LEN];
70     TCHAR szFilename[MAX_STRING_LEN];
71     BOOL isModified;
72 
73     if (clearModifyAlert)
74     {
75         /* When a file is being opened or created, there is no need to have
76          * the edited flag shown when the file has not been edited yet. */
77         isModified = FALSE;
78     }
79     else
80     {
81         /* Check whether the user has modified the file or not. If we are
82          * in the same state as before, don't change the caption. */
83         isModified = !!SendMessage(Globals.hEdit, EM_GETMODIFY, 0, 0);
84         if (isModified == Globals.bWasModified)
85             return;
86     }
87 
88     /* Remember the state for later calls */
89     Globals.bWasModified = isModified;
90 
91     /* Load the name of the application */
92     LoadString(Globals.hInstance, STRING_NOTEPAD, szNotepad, ARRAY_SIZE(szNotepad));
93 
94     /* Determine if the file has been saved or if this is a new file */
95     if (Globals.szFileTitle[0] != 0)
96         StringCchCopy(szFilename, ARRAY_SIZE(szFilename), Globals.szFileTitle);
97     else
98         LoadString(Globals.hInstance, STRING_UNTITLED, szFilename, ARRAY_SIZE(szFilename));
99 
100     /* Update the window caption based upon whether the user has modified the file or not */
101     StringCbPrintf(szCaption, sizeof(szCaption), _T("%s%s - %s"),
102                    (isModified ? _T("*") : _T("")), szFilename, szNotepad);
103 
104     SetWindowText(Globals.hMainWnd, szCaption);
105 }
106 
107 int DIALOG_StringMsgBox(HWND hParent, int formatId, LPCTSTR szString, DWORD dwFlags)
108 {
109     TCHAR szMessage[MAX_STRING_LEN];
110     TCHAR szResource[MAX_STRING_LEN];
111 
112     /* Load and format szMessage */
113     LoadString(Globals.hInstance, formatId, szResource, ARRAY_SIZE(szResource));
114     _sntprintf(szMessage, ARRAY_SIZE(szMessage), szResource, szString);
115 
116     /* Load szCaption */
117     if ((dwFlags & MB_ICONMASK) == MB_ICONEXCLAMATION)
118         LoadString(Globals.hInstance, STRING_ERROR, szResource, ARRAY_SIZE(szResource));
119     else
120         LoadString(Globals.hInstance, STRING_NOTEPAD, szResource, ARRAY_SIZE(szResource));
121 
122     /* Display Modal Dialog */
123     // if (hParent == NULL)
124         // hParent = Globals.hMainWnd;
125     return MessageBox(hParent, szMessage, szResource, dwFlags);
126 }
127 
128 static void AlertFileNotFound(LPCTSTR szFileName)
129 {
130     DIALOG_StringMsgBox(Globals.hMainWnd, STRING_NOTFOUND, szFileName, MB_ICONEXCLAMATION | MB_OK);
131 }
132 
133 static int AlertFileNotSaved(LPCTSTR szFileName)
134 {
135     TCHAR szUntitled[MAX_STRING_LEN];
136 
137     LoadString(Globals.hInstance, STRING_UNTITLED, szUntitled, ARRAY_SIZE(szUntitled));
138 
139     return DIALOG_StringMsgBox(Globals.hMainWnd, STRING_NOTSAVED,
140                                szFileName[0] ? szFileName : szUntitled,
141                                MB_ICONQUESTION | MB_YESNOCANCEL);
142 }
143 
144 static void AlertPrintError(void)
145 {
146     TCHAR szUntitled[MAX_STRING_LEN];
147 
148     LoadString(Globals.hInstance, STRING_UNTITLED, szUntitled, ARRAY_SIZE(szUntitled));
149 
150     DIALOG_StringMsgBox(Globals.hMainWnd, STRING_PRINTERROR,
151                         Globals.szFileName[0] ? Globals.szFileName : szUntitled,
152                         MB_ICONEXCLAMATION | MB_OK);
153 }
154 
155 /**
156  * Returns:
157  *   TRUE  - if file exists
158  *   FALSE - if file does not exist
159  */
160 BOOL FileExists(LPCTSTR szFilename)
161 {
162     WIN32_FIND_DATA entry;
163     HANDLE hFile;
164 
165     hFile = FindFirstFile(szFilename, &entry);
166     FindClose(hFile);
167 
168     return (hFile != INVALID_HANDLE_VALUE);
169 }
170 
171 BOOL HasFileExtension(LPCTSTR szFilename)
172 {
173     LPCTSTR s;
174 
175     s = _tcsrchr(szFilename, _T('\\'));
176     if (s)
177         szFilename = s;
178     return _tcsrchr(szFilename, _T('.')) != NULL;
179 }
180 
181 int GetSelectionTextLength(HWND hWnd)
182 {
183     DWORD dwStart = 0;
184     DWORD dwEnd = 0;
185 
186     SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
187 
188     return dwEnd - dwStart;
189 }
190 
191 int GetSelectionText(HWND hWnd, LPTSTR lpString, int nMaxCount)
192 {
193     DWORD dwStart = 0;
194     DWORD dwEnd = 0;
195     DWORD dwSize;
196     HRESULT hResult;
197     LPTSTR lpTemp;
198 
199     if (!lpString)
200     {
201         return 0;
202     }
203 
204     SendMessage(hWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
205 
206     if (dwStart == dwEnd)
207     {
208         return 0;
209     }
210 
211     dwSize = GetWindowTextLength(hWnd) + 1;
212     lpTemp = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(TCHAR));
213     if (!lpTemp)
214     {
215         return 0;
216     }
217 
218     dwSize = GetWindowText(hWnd, lpTemp, dwSize);
219 
220     if (!dwSize)
221     {
222         HeapFree(GetProcessHeap(), 0, lpTemp);
223         return 0;
224     }
225 
226     hResult = StringCchCopyN(lpString, nMaxCount, lpTemp + dwStart, dwEnd - dwStart);
227     HeapFree(GetProcessHeap(), 0, lpTemp);
228 
229     switch (hResult)
230     {
231         case S_OK:
232         {
233             return dwEnd - dwStart;
234         }
235 
236         case STRSAFE_E_INSUFFICIENT_BUFFER:
237         {
238             return nMaxCount - 1;
239         }
240 
241         default:
242         {
243             return 0;
244         }
245     }
246 }
247 
248 static RECT
249 GetPrintingRect(HDC hdc, RECT margins)
250 {
251     int iLogPixelsX, iLogPixelsY;
252     int iHorzRes, iVertRes;
253     int iPhysPageX, iPhysPageY, iPhysPageW, iPhysPageH;
254     RECT rcPrintRect;
255 
256     iPhysPageX = GetDeviceCaps(hdc, PHYSICALOFFSETX);
257     iPhysPageY = GetDeviceCaps(hdc, PHYSICALOFFSETY);
258     iPhysPageW = GetDeviceCaps(hdc, PHYSICALWIDTH);
259     iPhysPageH = GetDeviceCaps(hdc, PHYSICALHEIGHT);
260     iLogPixelsX = GetDeviceCaps(hdc, LOGPIXELSX);
261     iLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
262     iHorzRes = GetDeviceCaps(hdc, HORZRES);
263     iVertRes = GetDeviceCaps(hdc, VERTRES);
264 
265     rcPrintRect.left = (margins.left * iLogPixelsX / 2540) - iPhysPageX;
266     rcPrintRect.top = (margins.top * iLogPixelsY / 2540) - iPhysPageY;
267     rcPrintRect.right = iHorzRes - (((margins.left * iLogPixelsX / 2540) - iPhysPageX) + ((margins.right * iLogPixelsX / 2540) - (iPhysPageW - iPhysPageX - iHorzRes)));
268     rcPrintRect.bottom = iVertRes - (((margins.top * iLogPixelsY / 2540) - iPhysPageY) + ((margins.bottom * iLogPixelsY / 2540) - (iPhysPageH - iPhysPageY - iVertRes)));
269 
270     return rcPrintRect;
271 }
272 
273 static BOOL DoSaveFile(VOID)
274 {
275     BOOL bRet = TRUE;
276     HANDLE hFile;
277     LPTSTR pTemp;
278     DWORD size;
279 
280     hFile = CreateFile(Globals.szFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
281                        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
282     if(hFile == INVALID_HANDLE_VALUE)
283     {
284         ShowLastError();
285         return FALSE;
286     }
287 
288     size = GetWindowTextLength(Globals.hEdit) + 1;
289     pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*pTemp));
290     if (!pTemp)
291     {
292         CloseHandle(hFile);
293         ShowLastError();
294         return FALSE;
295     }
296     size = GetWindowText(Globals.hEdit, pTemp, size);
297 
298     if (size)
299     {
300         if (!WriteText(hFile, (LPWSTR)pTemp, size, Globals.encFile, Globals.iEoln))
301         {
302             ShowLastError();
303             bRet = FALSE;
304         }
305         else
306         {
307             SendMessage(Globals.hEdit, EM_SETMODIFY, FALSE, 0);
308             bRet = TRUE;
309         }
310     }
311 
312     CloseHandle(hFile);
313     HeapFree(GetProcessHeap(), 0, pTemp);
314 
315     if (bRet)
316     {
317         SetFileName(Globals.szFileName);
318     }
319 
320     return bRet;
321 }
322 
323 /**
324  * Returns:
325  *   TRUE  - User agreed to close (both save/don't save)
326  *   FALSE - User cancelled close by selecting "Cancel"
327  */
328 BOOL DoCloseFile(VOID)
329 {
330     int nResult;
331 
332     if (SendMessage(Globals.hEdit, EM_GETMODIFY, 0, 0))
333     {
334         /* prompt user to save changes */
335         nResult = AlertFileNotSaved(Globals.szFileName);
336         switch (nResult)
337         {
338             case IDYES:
339                 if(!DIALOG_FileSave())
340                     return FALSE;
341                 break;
342 
343             case IDNO:
344                 break;
345 
346             case IDCANCEL:
347                 return FALSE;
348 
349             default:
350                 return FALSE;
351         }
352     }
353 
354     SetFileName(empty_str);
355     UpdateWindowCaption(TRUE);
356 
357     return TRUE;
358 }
359 
360 VOID DoOpenFile(LPCTSTR szFileName)
361 {
362     static const TCHAR dotlog[] = _T(".LOG");
363     HANDLE hFile;
364     LPTSTR pszText = NULL;
365     DWORD dwTextLen;
366     TCHAR log[5];
367 
368     /* Close any files and prompt to save changes */
369     if (!DoCloseFile())
370         return;
371 
372     hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
373                        OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
374     if (hFile == INVALID_HANDLE_VALUE)
375     {
376         ShowLastError();
377         goto done;
378     }
379 
380     if (!ReadText(hFile, (LPWSTR *)&pszText, &dwTextLen, &Globals.encFile, &Globals.iEoln))
381     {
382         ShowLastError();
383         goto done;
384     }
385     SetWindowText(Globals.hEdit, pszText);
386 
387     SendMessage(Globals.hEdit, EM_SETMODIFY, FALSE, 0);
388     SendMessage(Globals.hEdit, EM_EMPTYUNDOBUFFER, 0, 0);
389     SetFocus(Globals.hEdit);
390 
391     /*  If the file starts with .LOG, add a time/date at the end and set cursor after
392      *  See http://support.microsoft.com/?kbid=260563
393      */
394     if (GetWindowText(Globals.hEdit, log, ARRAY_SIZE(log)) && !_tcscmp(log, dotlog))
395     {
396         static const TCHAR lf[] = _T("\r\n");
397         SendMessage(Globals.hEdit, EM_SETSEL, GetWindowTextLength(Globals.hEdit), -1);
398         SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)lf);
399         DIALOG_EditTimeDate();
400         SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)lf);
401     }
402 
403     SetFileName(szFileName);
404     UpdateWindowCaption(TRUE);
405     NOTEPAD_EnableSearchMenu();
406 done:
407     if (hFile != INVALID_HANDLE_VALUE)
408         CloseHandle(hFile);
409     if (pszText)
410         HeapFree(GetProcessHeap(), 0, pszText);
411 }
412 
413 VOID DIALOG_FileNew(VOID)
414 {
415     /* Close any files and prompt to save changes */
416     if (DoCloseFile()) {
417         SetWindowText(Globals.hEdit, empty_str);
418         SendMessage(Globals.hEdit, EM_EMPTYUNDOBUFFER, 0, 0);
419         SetFocus(Globals.hEdit);
420         NOTEPAD_EnableSearchMenu();
421     }
422 }
423 
424 VOID DIALOG_FileNewWindow(VOID)
425 {
426     TCHAR pszNotepadExe[MAX_PATH];
427     GetModuleFileName(NULL, pszNotepadExe, ARRAYSIZE(pszNotepadExe));
428     ShellExecute(NULL, NULL, pszNotepadExe, NULL, NULL, SW_SHOWNORMAL);
429 }
430 
431 VOID DIALOG_FileOpen(VOID)
432 {
433     OPENFILENAME openfilename;
434     TCHAR szPath[MAX_PATH];
435 
436     ZeroMemory(&openfilename, sizeof(openfilename));
437 
438     if (Globals.szFileName[0] == 0)
439         _tcscpy(szPath, txt_files);
440     else
441         _tcscpy(szPath, Globals.szFileName);
442 
443     openfilename.lStructSize = sizeof(openfilename);
444     openfilename.hwndOwner = Globals.hMainWnd;
445     openfilename.hInstance = Globals.hInstance;
446     openfilename.lpstrFilter = Globals.szFilter;
447     openfilename.lpstrFile = szPath;
448     openfilename.nMaxFile = ARRAY_SIZE(szPath);
449     openfilename.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
450     openfilename.lpstrDefExt = szDefaultExt;
451 
452     if (GetOpenFileName(&openfilename)) {
453         if (FileExists(openfilename.lpstrFile))
454             DoOpenFile(openfilename.lpstrFile);
455         else
456             AlertFileNotFound(openfilename.lpstrFile);
457     }
458 }
459 
460 BOOL DIALOG_FileSave(VOID)
461 {
462     if (Globals.szFileName[0] == 0)
463     {
464         return DIALOG_FileSaveAs();
465     }
466     else if (DoSaveFile())
467     {
468         UpdateWindowCaption(TRUE);
469         return TRUE;
470     }
471     return FALSE;
472 }
473 
474 static UINT_PTR
475 CALLBACK
476 DIALOG_FileSaveAs_Hook(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
477 {
478     TCHAR szText[128];
479     HWND hCombo;
480 
481     UNREFERENCED_PARAMETER(wParam);
482 
483     switch(msg)
484     {
485         case WM_INITDIALOG:
486             hCombo = GetDlgItem(hDlg, ID_ENCODING);
487 
488             LoadString(Globals.hInstance, STRING_ANSI, szText, ARRAY_SIZE(szText));
489             SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
490 
491             LoadString(Globals.hInstance, STRING_UNICODE, szText, ARRAY_SIZE(szText));
492             SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
493 
494             LoadString(Globals.hInstance, STRING_UNICODE_BE, szText, ARRAY_SIZE(szText));
495             SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
496 
497             LoadString(Globals.hInstance, STRING_UTF8, szText, ARRAY_SIZE(szText));
498             SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
499 
500             SendMessage(hCombo, CB_SETCURSEL, Globals.encFile, 0);
501 
502             hCombo = GetDlgItem(hDlg, ID_EOLN);
503 
504             LoadString(Globals.hInstance, STRING_CRLF, szText, ARRAY_SIZE(szText));
505             SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
506 
507             LoadString(Globals.hInstance, STRING_LF, szText, ARRAY_SIZE(szText));
508             SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
509 
510             LoadString(Globals.hInstance, STRING_CR, szText, ARRAY_SIZE(szText));
511             SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
512 
513             SendMessage(hCombo, CB_SETCURSEL, Globals.iEoln, 0);
514             break;
515 
516         case WM_NOTIFY:
517             if (((NMHDR *) lParam)->code == CDN_FILEOK)
518             {
519                 hCombo = GetDlgItem(hDlg, ID_ENCODING);
520                 if (hCombo)
521                     Globals.encFile = (ENCODING) SendMessage(hCombo, CB_GETCURSEL, 0, 0);
522 
523                 hCombo = GetDlgItem(hDlg, ID_EOLN);
524                 if (hCombo)
525                     Globals.iEoln = (int) SendMessage(hCombo, CB_GETCURSEL, 0, 0);
526             }
527             break;
528     }
529     return 0;
530 }
531 
532 BOOL DIALOG_FileSaveAs(VOID)
533 {
534     OPENFILENAME saveas;
535     TCHAR szPath[MAX_PATH];
536 
537     ZeroMemory(&saveas, sizeof(saveas));
538 
539     if (Globals.szFileName[0] == 0)
540         _tcscpy(szPath, txt_files);
541     else
542         _tcscpy(szPath, Globals.szFileName);
543 
544     saveas.lStructSize = sizeof(OPENFILENAME);
545     saveas.hwndOwner = Globals.hMainWnd;
546     saveas.hInstance = Globals.hInstance;
547     saveas.lpstrFilter = Globals.szFilter;
548     saveas.lpstrFile = szPath;
549     saveas.nMaxFile = ARRAY_SIZE(szPath);
550     saveas.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
551                    OFN_EXPLORER | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
552     saveas.lpstrDefExt = szDefaultExt;
553     saveas.lpTemplateName = MAKEINTRESOURCE(DIALOG_ENCODING);
554     saveas.lpfnHook = DIALOG_FileSaveAs_Hook;
555 
556     if (GetSaveFileName(&saveas))
557     {
558         /* HACK: Because in ROS, Save-As boxes don't check the validity
559          * of file names and thus, here, szPath can be invalid !! We only
560          * see its validity when we call DoSaveFile()... */
561         SetFileName(szPath);
562         if (DoSaveFile())
563         {
564             UpdateWindowCaption(TRUE);
565             return TRUE;
566         }
567         else
568         {
569             SetFileName(_T(""));
570             return FALSE;
571         }
572     }
573     else
574     {
575         return FALSE;
576     }
577 }
578 
579 VOID DIALOG_FilePrint(VOID)
580 {
581     DOCINFO di;
582     TEXTMETRIC tm;
583     PRINTDLG printer;
584     SIZE szMetric;
585     int border;
586     int xLeft, yTop, pagecount, dopage, copycount;
587     unsigned int i;
588     LOGFONT hdrFont;
589     HFONT font, old_font=0;
590     DWORD size;
591     LPTSTR pTemp;
592     static const TCHAR times_new_roman[] = _T("Times New Roman");
593     RECT rcPrintRect;
594 
595     /* Get a small font and print some header info on each page */
596     ZeroMemory(&hdrFont, sizeof(hdrFont));
597     hdrFont.lfHeight = 100;
598     hdrFont.lfWeight = FW_BOLD;
599     hdrFont.lfCharSet = ANSI_CHARSET;
600     hdrFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
601     hdrFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
602     hdrFont.lfQuality = PROOF_QUALITY;
603     hdrFont.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
604     _tcscpy(hdrFont.lfFaceName, times_new_roman);
605 
606     font = CreateFontIndirect(&hdrFont);
607 
608     /* Get Current Settings */
609     ZeroMemory(&printer, sizeof(printer));
610     printer.lStructSize = sizeof(printer);
611     printer.hwndOwner = Globals.hMainWnd;
612     printer.hInstance = Globals.hInstance;
613 
614     /* Set some default flags */
615     printer.Flags = PD_RETURNDC | PD_SELECTION;
616 
617     /* Disable the selection radio button if there is no text selected */
618     if (!GetSelectionTextLength(Globals.hEdit))
619     {
620         printer.Flags = printer.Flags | PD_NOSELECTION;
621     }
622 
623     printer.nFromPage = 0;
624     printer.nMinPage = 1;
625     /* we really need to calculate number of pages to set nMaxPage and nToPage */
626     printer.nToPage = (WORD)-1;
627     printer.nMaxPage = (WORD)-1;
628 
629     /* Let commdlg manage copy settings */
630     printer.nCopies = (WORD)PD_USEDEVMODECOPIES;
631 
632     printer.hDevMode = Globals.hDevMode;
633     printer.hDevNames = Globals.hDevNames;
634 
635     if (!PrintDlg(&printer))
636     {
637         DeleteObject(font);
638         return;
639     }
640 
641     Globals.hDevMode = printer.hDevMode;
642     Globals.hDevNames = printer.hDevNames;
643 
644     assert(printer.hDC != 0);
645 
646     /* initialize DOCINFO */
647     di.cbSize = sizeof(DOCINFO);
648     di.lpszDocName = Globals.szFileTitle;
649     di.lpszOutput = NULL;
650     di.lpszDatatype = NULL;
651     di.fwType = 0;
652 
653     if (StartDoc(printer.hDC, &di) <= 0)
654     {
655         DeleteObject(font);
656         return;
657     }
658 
659 
660     /* Get the file text */
661     if (printer.Flags & PD_SELECTION)
662     {
663         size = GetSelectionTextLength(Globals.hEdit) + 1;
664     }
665     else
666     {
667         size = GetWindowTextLength(Globals.hEdit) + 1;
668     }
669 
670     pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(TCHAR));
671     if (!pTemp)
672     {
673         EndDoc(printer.hDC);
674         DeleteObject(font);
675         ShowLastError();
676         return;
677     }
678 
679     if (printer.Flags & PD_SELECTION)
680     {
681         size = GetSelectionText(Globals.hEdit, pTemp, size);
682     }
683     else
684     {
685         size = GetWindowText(Globals.hEdit, pTemp, size);
686     }
687 
688     /* Get the current printing area */
689     rcPrintRect = GetPrintingRect(printer.hDC, Globals.lMargins);
690 
691     /* Ensure that each logical unit maps to one pixel */
692     SetMapMode(printer.hDC, MM_TEXT);
693 
694     /* Needed to get the correct height of a text line */
695     GetTextMetrics(printer.hDC, &tm);
696 
697     border = 15;
698     for (copycount=1; copycount <= printer.nCopies; copycount++) {
699         i = 0;
700         pagecount = 1;
701         do {
702             /* Don't start a page if none of the conditions below are true */
703             dopage = 0;
704 
705             /* The user wants to print the current selection */
706             if (printer.Flags & PD_SELECTION)
707             {
708                 dopage = 1;
709             }
710 
711             /* The user wants to print the entire document */
712             if (!(printer.Flags & PD_PAGENUMS) && !(printer.Flags & PD_SELECTION))
713             {
714                 dopage = 1;
715             }
716 
717             /* The user wants to print a specified range of pages */
718             if ((pagecount >= printer.nFromPage && pagecount <= printer.nToPage))
719             {
720                 dopage = 1;
721             }
722 
723             old_font = SelectObject(printer.hDC, font);
724 
725             if (dopage) {
726                 if (StartPage(printer.hDC) <= 0) {
727                     SelectObject(printer.hDC, old_font);
728                     EndDoc(printer.hDC);
729                     DeleteDC(printer.hDC);
730                     HeapFree(GetProcessHeap(), 0, pTemp);
731                     DeleteObject(font);
732                     AlertPrintError();
733                     return;
734                 }
735 
736                 SetViewportOrgEx(printer.hDC, rcPrintRect.left, rcPrintRect.top, NULL);
737 
738                 /* Write a rectangle and header at the top of each page */
739                 Rectangle(printer.hDC, border, border, rcPrintRect.right - border, border + tm.tmHeight * 2);
740                 /* I don't know what's up with this TextOut command. This comes out
741                 kind of mangled.
742                 */
743                 TextOut(printer.hDC,
744                         border * 2,
745                         border + tm.tmHeight / 2,
746                         Globals.szFileTitle,
747                         lstrlen(Globals.szFileTitle));
748             }
749 
750             /* The starting point for the main text */
751             xLeft = 0;
752             yTop = border + tm.tmHeight * 4;
753 
754             SelectObject(printer.hDC, old_font);
755 
756             /* Since outputting strings is giving me problems, output the main
757              * text one character at a time. */
758             do {
759                 if (pTemp[i] == '\n') {
760                     xLeft = 0;
761                     yTop += tm.tmHeight;
762                 }
763                 else if (pTemp[i] != '\r') {
764                     if (dopage)
765                         TextOut(printer.hDC, xLeft, yTop, &pTemp[i], 1);
766 
767                     /* We need to get the width for each individual char, since a proportional font may be used */
768                     GetTextExtentPoint32(printer.hDC, &pTemp[i], 1, &szMetric);
769                     xLeft += szMetric.cx;
770 
771                     /* Insert a line break if the current line does not fit into the printing area */
772                     if (xLeft > rcPrintRect.right)
773                     {
774                         xLeft = 0;
775                         yTop = yTop + tm.tmHeight;
776                     }
777                 }
778             } while (i++ < size && yTop < rcPrintRect.bottom);
779 
780             if (dopage)
781                 EndPage(printer.hDC);
782             pagecount++;
783         } while (i < size);
784     }
785 
786     if (old_font != 0)
787         SelectObject(printer.hDC, old_font);
788     EndDoc(printer.hDC);
789     DeleteDC(printer.hDC);
790     HeapFree(GetProcessHeap(), 0, pTemp);
791     DeleteObject(font);
792 }
793 
794 VOID DIALOG_FileExit(VOID)
795 {
796     PostMessage(Globals.hMainWnd, WM_CLOSE, 0, 0l);
797 }
798 
799 VOID DIALOG_EditUndo(VOID)
800 {
801     SendMessage(Globals.hEdit, EM_UNDO, 0, 0);
802 }
803 
804 VOID DIALOG_EditCut(VOID)
805 {
806     SendMessage(Globals.hEdit, WM_CUT, 0, 0);
807 }
808 
809 VOID DIALOG_EditCopy(VOID)
810 {
811     SendMessage(Globals.hEdit, WM_COPY, 0, 0);
812 }
813 
814 VOID DIALOG_EditPaste(VOID)
815 {
816     SendMessage(Globals.hEdit, WM_PASTE, 0, 0);
817 }
818 
819 VOID DIALOG_EditDelete(VOID)
820 {
821     SendMessage(Globals.hEdit, WM_CLEAR, 0, 0);
822 }
823 
824 VOID DIALOG_EditSelectAll(VOID)
825 {
826     SendMessage(Globals.hEdit, EM_SETSEL, 0, (LPARAM)-1);
827 }
828 
829 VOID DIALOG_EditTimeDate(VOID)
830 {
831     SYSTEMTIME st;
832     TCHAR szDate[MAX_STRING_LEN];
833     TCHAR szText[MAX_STRING_LEN * 2 + 2];
834 
835     GetLocalTime(&st);
836 
837     GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, szDate, MAX_STRING_LEN);
838     _tcscpy(szText, szDate);
839     _tcscat(szText, _T(" "));
840     GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szDate, MAX_STRING_LEN);
841     _tcscat(szText, szDate);
842     SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)szText);
843 }
844 
845 VOID DoCreateStatusBar(VOID)
846 {
847     RECT rc;
848     RECT rcstatus;
849     BOOL bStatusBarVisible;
850 
851     /* Check if status bar object already exists. */
852     if (Globals.hStatusBar == NULL)
853     {
854         /* Try to create the status bar */
855         Globals.hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE | WS_EX_STATICEDGE,
856                                                 NULL,
857                                                 Globals.hMainWnd,
858                                                 CMD_STATUSBAR_WND_ID);
859 
860         if (Globals.hStatusBar == NULL)
861         {
862             ShowLastError();
863             return;
864         }
865 
866         /* Load the string for formatting column/row text output */
867         LoadString(Globals.hInstance, STRING_LINE_COLUMN, Globals.szStatusBarLineCol, MAX_PATH - 1);
868 
869         /* Set the status bar for single-text output */
870         SendMessage(Globals.hStatusBar, SB_SIMPLE, (WPARAM)TRUE, (LPARAM)0);
871     }
872 
873     /* Set status bar visiblity according to the settings. */
874     if ((Globals.bWrapLongLines != FALSE) || (Globals.bShowStatusBar == FALSE))
875     {
876         bStatusBarVisible = FALSE;
877         ShowWindow(Globals.hStatusBar, SW_HIDE);
878     }
879     else
880     {
881         bStatusBarVisible = TRUE;
882         ShowWindow(Globals.hStatusBar, SW_SHOW);
883         SendMessage(Globals.hStatusBar, WM_SIZE, 0, 0);
884     }
885 
886     /* Set check state in show status bar item. */
887     if (bStatusBarVisible)
888     {
889         CheckMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_CHECKED);
890     }
891     else
892     {
893         CheckMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_UNCHECKED);
894     }
895 
896     /* Update menu mar with the previous changes */
897     DrawMenuBar(Globals.hMainWnd);
898 
899     /* Sefety test is edit control exists */
900     if (Globals.hEdit != NULL)
901     {
902         /* Retrieve the sizes of the controls */
903         GetClientRect(Globals.hMainWnd, &rc);
904         GetClientRect(Globals.hStatusBar, &rcstatus);
905 
906         /* If status bar is currently visible, update dimensions of edit control */
907         if (bStatusBarVisible)
908             rc.bottom -= (rcstatus.bottom - rcstatus.top);
909 
910         /* Resize edit control to right size. */
911         MoveWindow(Globals.hEdit,
912                    rc.left,
913                    rc.top,
914                    rc.right - rc.left,
915                    rc.bottom - rc.top,
916                    TRUE);
917     }
918 
919     /* Update content with current row/column text */
920     DIALOG_StatusBarUpdateCaretPos();
921 }
922 
923 VOID DoCreateEditWindow(VOID)
924 {
925     DWORD dwStyle;
926     int iSize;
927     LPTSTR pTemp = NULL;
928     BOOL bModified = FALSE;
929 
930     iSize = 0;
931 
932     /* If the edit control already exists, try to save its content */
933     if (Globals.hEdit != NULL)
934     {
935         /* number of chars currently written into the editor. */
936         iSize = GetWindowTextLength(Globals.hEdit);
937         if (iSize)
938         {
939             /* Allocates temporary buffer. */
940             pTemp = HeapAlloc(GetProcessHeap(), 0, (iSize + 1) * sizeof(TCHAR));
941             if (!pTemp)
942             {
943                 ShowLastError();
944                 return;
945             }
946 
947             /* Recover the text into the control. */
948             GetWindowText(Globals.hEdit, pTemp, iSize + 1);
949 
950             if (SendMessage(Globals.hEdit, EM_GETMODIFY, 0, 0))
951                 bModified = TRUE;
952         }
953 
954         /* Restore original window procedure */
955         SetWindowLongPtr(Globals.hEdit, GWLP_WNDPROC, (LONG_PTR)Globals.EditProc);
956 
957         /* Destroy the edit control */
958         DestroyWindow(Globals.hEdit);
959     }
960 
961     /* Update wrap status into the main menu and recover style flags */
962     if (Globals.bWrapLongLines)
963     {
964         dwStyle = EDIT_STYLE_WRAP;
965         EnableMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
966     } else {
967         dwStyle = EDIT_STYLE;
968         EnableMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_ENABLED);
969     }
970 
971     /* Update previous changes */
972     DrawMenuBar(Globals.hMainWnd);
973 
974     /* Create the new edit control */
975     Globals.hEdit = CreateWindowEx(WS_EX_CLIENTEDGE,
976                                    EDIT_CLASS,
977                                    NULL,
978                                    dwStyle,
979                                    CW_USEDEFAULT,
980                                    CW_USEDEFAULT,
981                                    CW_USEDEFAULT,
982                                    CW_USEDEFAULT,
983                                    Globals.hMainWnd,
984                                    NULL,
985                                    Globals.hInstance,
986                                    NULL);
987 
988     if (Globals.hEdit == NULL)
989     {
990         if (pTemp)
991         {
992             HeapFree(GetProcessHeap(), 0, pTemp);
993         }
994 
995         ShowLastError();
996         return;
997     }
998 
999     SendMessage(Globals.hEdit, WM_SETFONT, (WPARAM)Globals.hFont, FALSE);
1000     SendMessage(Globals.hEdit, EM_LIMITTEXT, 0, 0);
1001 
1002     /* If some text was previously saved, restore it. */
1003     if (iSize != 0)
1004     {
1005         SetWindowText(Globals.hEdit, pTemp);
1006         HeapFree(GetProcessHeap(), 0, pTemp);
1007 
1008         if (bModified)
1009             SendMessage(Globals.hEdit, EM_SETMODIFY, TRUE, 0);
1010     }
1011 
1012     /* Sub-class a new window callback for row/column detection. */
1013     Globals.EditProc = (WNDPROC)SetWindowLongPtr(Globals.hEdit,
1014                                                  GWLP_WNDPROC,
1015                                                  (LONG_PTR)EDIT_WndProc);
1016 
1017     /* Create/update status bar */
1018     DoCreateStatusBar();
1019 
1020     /* Finally shows new edit control and set focus into it. */
1021     ShowWindow(Globals.hEdit, SW_SHOW);
1022     SetFocus(Globals.hEdit);
1023 }
1024 
1025 VOID DIALOG_EditWrap(VOID)
1026 {
1027     Globals.bWrapLongLines = !Globals.bWrapLongLines;
1028 
1029     if (Globals.bWrapLongLines)
1030     {
1031         EnableMenuItem(Globals.hMenu, CMD_GOTO, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1032     }
1033     else
1034     {
1035         EnableMenuItem(Globals.hMenu, CMD_GOTO, MF_BYCOMMAND | MF_ENABLED);
1036     }
1037 
1038     DoCreateEditWindow();
1039 }
1040 
1041 VOID DIALOG_SelectFont(VOID)
1042 {
1043     CHOOSEFONT cf;
1044     LOGFONT lf = Globals.lfFont;
1045 
1046     ZeroMemory( &cf, sizeof(cf) );
1047     cf.lStructSize = sizeof(cf);
1048     cf.hwndOwner = Globals.hMainWnd;
1049     cf.lpLogFont = &lf;
1050     cf.Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT | CF_NOVERTFONTS;
1051 
1052     if (ChooseFont(&cf))
1053     {
1054         HFONT currfont = Globals.hFont;
1055 
1056         Globals.hFont = CreateFontIndirect(&lf);
1057         Globals.lfFont = lf;
1058         SendMessage(Globals.hEdit, WM_SETFONT, (WPARAM)Globals.hFont, (LPARAM)TRUE);
1059         if (currfont != NULL)
1060             DeleteObject(currfont);
1061     }
1062 }
1063 
1064 typedef HWND (WINAPI *FINDPROC)(LPFINDREPLACE lpfr);
1065 
1066 static VOID DIALOG_SearchDialog(FINDPROC pfnProc)
1067 {
1068     if (Globals.hFindReplaceDlg != NULL)
1069     {
1070         SetFocus(Globals.hFindReplaceDlg);
1071         return;
1072     }
1073 
1074     ZeroMemory(&Globals.find, sizeof(Globals.find));
1075     Globals.find.lStructSize = sizeof(Globals.find);
1076     Globals.find.hwndOwner = Globals.hMainWnd;
1077     Globals.find.hInstance = Globals.hInstance;
1078     Globals.find.lpstrFindWhat = Globals.szFindText;
1079     Globals.find.wFindWhatLen = ARRAY_SIZE(Globals.szFindText);
1080     Globals.find.lpstrReplaceWith = Globals.szReplaceText;
1081     Globals.find.wReplaceWithLen = ARRAY_SIZE(Globals.szReplaceText);
1082     Globals.find.Flags = FR_DOWN;
1083 
1084     /* We only need to create the modal FindReplace dialog which will */
1085     /* notify us of incoming events using hMainWnd Window Messages    */
1086 
1087     Globals.hFindReplaceDlg = pfnProc(&Globals.find);
1088     assert(Globals.hFindReplaceDlg != NULL);
1089 }
1090 
1091 VOID DIALOG_Search(VOID)
1092 {
1093     DIALOG_SearchDialog(FindText);
1094 }
1095 
1096 VOID DIALOG_SearchNext(VOID)
1097 {
1098     if (Globals.find.lpstrFindWhat != NULL)
1099         NOTEPAD_FindNext(&Globals.find, FALSE, TRUE);
1100     else
1101         DIALOG_Search();
1102 }
1103 
1104 VOID DIALOG_Replace(VOID)
1105 {
1106     DIALOG_SearchDialog(ReplaceText);
1107 }
1108 
1109 static INT_PTR
1110 CALLBACK
1111 DIALOG_GoTo_DialogProc(HWND hwndDialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
1112 {
1113     BOOL bResult = FALSE;
1114     HWND hTextBox;
1115     TCHAR szText[32];
1116 
1117     switch(uMsg) {
1118     case WM_INITDIALOG:
1119         hTextBox = GetDlgItem(hwndDialog, ID_LINENUMBER);
1120         _sntprintf(szText, ARRAY_SIZE(szText), _T("%Id"), lParam);
1121         SetWindowText(hTextBox, szText);
1122         break;
1123     case WM_COMMAND:
1124         if (HIWORD(wParam) == BN_CLICKED)
1125         {
1126             if (LOWORD(wParam) == IDOK)
1127             {
1128                 hTextBox = GetDlgItem(hwndDialog, ID_LINENUMBER);
1129                 GetWindowText(hTextBox, szText, ARRAY_SIZE(szText));
1130                 EndDialog(hwndDialog, _ttoi(szText));
1131                 bResult = TRUE;
1132             }
1133             else if (LOWORD(wParam) == IDCANCEL)
1134             {
1135                 EndDialog(hwndDialog, 0);
1136                 bResult = TRUE;
1137             }
1138         }
1139         break;
1140     }
1141 
1142     return bResult;
1143 }
1144 
1145 VOID DIALOG_GoTo(VOID)
1146 {
1147     INT_PTR nLine;
1148     LPTSTR pszText;
1149     int nLength, i;
1150     DWORD dwStart, dwEnd;
1151 
1152     nLength = GetWindowTextLength(Globals.hEdit);
1153     pszText = (LPTSTR) HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(*pszText));
1154     if (!pszText)
1155         return;
1156 
1157     /* Retrieve current text */
1158     GetWindowText(Globals.hEdit, pszText, nLength + 1);
1159     SendMessage(Globals.hEdit, EM_GETSEL, (WPARAM) &dwStart, (LPARAM) &dwEnd);
1160 
1161     nLine = 1;
1162     for (i = 0; (i < (int) dwStart) && pszText[i]; i++)
1163     {
1164         if (pszText[i] == '\n')
1165             nLine++;
1166     }
1167 
1168     nLine = DialogBoxParam(Globals.hInstance,
1169                            MAKEINTRESOURCE(DIALOG_GOTO),
1170                            Globals.hMainWnd,
1171                            DIALOG_GoTo_DialogProc,
1172                            nLine);
1173 
1174     if (nLine >= 1)
1175     {
1176         for (i = 0; pszText[i] && (nLine > 1) && (i < nLength - 1); i++)
1177         {
1178             if (pszText[i] == '\n')
1179                 nLine--;
1180         }
1181         SendMessage(Globals.hEdit, EM_SETSEL, i, i);
1182         SendMessage(Globals.hEdit, EM_SCROLLCARET, 0, 0);
1183     }
1184     HeapFree(GetProcessHeap(), 0, pszText);
1185 }
1186 
1187 VOID DIALOG_StatusBarUpdateCaretPos(VOID)
1188 {
1189     int line, col;
1190     TCHAR buff[MAX_PATH];
1191     DWORD dwStart, dwSize;
1192 
1193     SendMessage(Globals.hEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwSize);
1194     line = SendMessage(Globals.hEdit, EM_LINEFROMCHAR, (WPARAM)dwStart, 0);
1195     col = dwStart - SendMessage(Globals.hEdit, EM_LINEINDEX, (WPARAM)line, 0);
1196 
1197     _stprintf(buff, Globals.szStatusBarLineCol, line + 1, col + 1);
1198     SendMessage(Globals.hStatusBar, SB_SETTEXT, SB_SIMPLEID, (LPARAM)buff);
1199 }
1200 
1201 VOID DIALOG_ViewStatusBar(VOID)
1202 {
1203     Globals.bShowStatusBar = !Globals.bShowStatusBar;
1204 
1205     DoCreateStatusBar();
1206 }
1207 
1208 VOID DIALOG_HelpContents(VOID)
1209 {
1210     WinHelp(Globals.hMainWnd, helpfile, HELP_INDEX, 0);
1211 }
1212 
1213 VOID DIALOG_HelpAboutNotepad(VOID)
1214 {
1215     TCHAR szNotepad[MAX_STRING_LEN];
1216     TCHAR szNotepadAuthors[MAX_STRING_LEN];
1217 
1218     HICON notepadIcon = LoadIcon(Globals.hInstance, MAKEINTRESOURCE(IDI_NPICON));
1219 
1220     LoadString(Globals.hInstance, STRING_NOTEPAD, szNotepad, ARRAY_SIZE(szNotepad));
1221     LoadString(Globals.hInstance, STRING_NOTEPAD_AUTHORS, szNotepadAuthors, ARRAY_SIZE(szNotepadAuthors));
1222 
1223     ShellAbout(Globals.hMainWnd, szNotepad, szNotepadAuthors, notepadIcon);
1224     DeleteObject(notepadIcon);
1225 }
1226 
1227 /***********************************************************************
1228  *
1229  *           DIALOG_FilePageSetup
1230  */
1231 VOID DIALOG_FilePageSetup(void)
1232 {
1233     PAGESETUPDLG page;
1234 
1235     ZeroMemory(&page, sizeof(page));
1236     page.lStructSize = sizeof(page);
1237     page.hwndOwner = Globals.hMainWnd;
1238     page.Flags = PSD_ENABLEPAGESETUPTEMPLATE | PSD_ENABLEPAGESETUPHOOK | PSD_MARGINS;
1239     page.hInstance = Globals.hInstance;
1240     page.rtMargin = Globals.lMargins;
1241     page.hDevMode = Globals.hDevMode;
1242     page.hDevNames = Globals.hDevNames;
1243     page.lpPageSetupTemplateName = MAKEINTRESOURCE(DIALOG_PAGESETUP);
1244     page.lpfnPageSetupHook = DIALOG_PAGESETUP_Hook;
1245 
1246     PageSetupDlg(&page);
1247 
1248     Globals.hDevMode = page.hDevMode;
1249     Globals.hDevNames = page.hDevNames;
1250     Globals.lMargins = page.rtMargin;
1251 }
1252 
1253 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
1254  *
1255  *           DIALOG_PAGESETUP_Hook
1256  */
1257 
1258 static UINT_PTR CALLBACK DIALOG_PAGESETUP_Hook(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
1259 {
1260     switch (msg)
1261     {
1262     case WM_COMMAND:
1263         if (HIWORD(wParam) == BN_CLICKED)
1264         {
1265             switch (LOWORD(wParam))
1266             {
1267             case IDOK:
1268                 /* save user input and close dialog */
1269                 GetDlgItemText(hDlg, 0x141, Globals.szHeader, ARRAY_SIZE(Globals.szHeader));
1270                 GetDlgItemText(hDlg, 0x143, Globals.szFooter, ARRAY_SIZE(Globals.szFooter));
1271                 return FALSE;
1272 
1273             case IDCANCEL:
1274                 /* discard user input and close dialog */
1275                 return FALSE;
1276 
1277             case IDHELP:
1278                 {
1279                     /* FIXME: Bring this to work */
1280                     static const TCHAR sorry[] = _T("Sorry, no help available");
1281                     static const TCHAR help[] = _T("Help");
1282                     MessageBox(Globals.hMainWnd, sorry, help, MB_ICONEXCLAMATION);
1283                     return TRUE;
1284                 }
1285 
1286             default:
1287                 break;
1288             }
1289         }
1290         break;
1291 
1292     case WM_INITDIALOG:
1293         /* fetch last user input prior to display dialog */
1294         SetDlgItemText(hDlg, 0x141, Globals.szHeader);
1295         SetDlgItemText(hDlg, 0x143, Globals.szFooter);
1296         break;
1297     }
1298 
1299     return FALSE;
1300 }
1301