xref: /reactos/base/applications/notepad/main.c (revision 136f2357)
1 /*
2  * PROJECT:    ReactOS Notepad
3  * LICENSE:    LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:    Providing a Windows-compatible simple text editor for ReactOS
5  * COPYRIGHT:  Copyright 2000 Mike McCormack <Mike_McCormack@looksmart.com.au>
6  *             Copyright 1997,98 Marcel Baur <mbaur@g26.ethz.ch>
7  *             Copyright 2002 Sylvain Petreolle <spetreolle@yahoo.fr>
8  *             Copyright 2002 Andriy Palamarchuk
9  *             Copyright 2020-2023 Katayama Hirofumi MZ
10  */
11 
12 #include "notepad.h"
13 
14 #include <shlobj.h>
15 #include <strsafe.h>
16 
17 #ifdef _DEBUG
18 #include <crtdbg.h>
19 #endif
20 
21 NOTEPAD_GLOBALS Globals;
22 static ATOM aFINDMSGSTRING;
23 
24 VOID NOTEPAD_EnableSearchMenu()
25 {
26     BOOL bEmpty = (GetWindowTextLengthW(Globals.hEdit) == 0);
27     UINT uEnable = MF_BYCOMMAND | (bEmpty ? MF_GRAYED : MF_ENABLED);
28     EnableMenuItem(Globals.hMenu, CMD_SEARCH, uEnable);
29     EnableMenuItem(Globals.hMenu, CMD_SEARCH_NEXT, uEnable);
30     EnableMenuItem(Globals.hMenu, CMD_SEARCH_PREV, uEnable);
31 }
32 
33 /***********************************************************************
34  *           SetFileName
35  *
36  *  Sets Global File Name.
37  */
38 VOID SetFileName(LPCTSTR szFileName)
39 {
40     StringCchCopy(Globals.szFileName, ARRAY_SIZE(Globals.szFileName), szFileName);
41     Globals.szFileTitle[0] = 0;
42     GetFileTitle(szFileName, Globals.szFileTitle, ARRAY_SIZE(Globals.szFileTitle));
43 
44     if (szFileName && szFileName[0])
45         SHAddToRecentDocs(SHARD_PATHW, szFileName);
46 }
47 
48 /***********************************************************************
49  *           NOTEPAD_MenuCommand
50  *
51  *  All handling of main menu events
52  */
53 static int NOTEPAD_MenuCommand(WPARAM wParam)
54 {
55     switch (wParam)
56     {
57     case CMD_NEW:        DIALOG_FileNew(); break;
58     case CMD_NEW_WINDOW: DIALOG_FileNewWindow(); break;
59     case CMD_OPEN:       DIALOG_FileOpen(); break;
60     case CMD_SAVE:       DIALOG_FileSave(); break;
61     case CMD_SAVE_AS:    DIALOG_FileSaveAs(); break;
62     case CMD_PRINT:      DIALOG_FilePrint(); break;
63     case CMD_PAGE_SETUP: DIALOG_FilePageSetup(); break;
64     case CMD_EXIT:       DIALOG_FileExit(); break;
65 
66     case CMD_UNDO:       DIALOG_EditUndo(); break;
67     case CMD_CUT:        DIALOG_EditCut(); break;
68     case CMD_COPY:       DIALOG_EditCopy(); break;
69     case CMD_PASTE:      DIALOG_EditPaste(); break;
70     case CMD_DELETE:     DIALOG_EditDelete(); break;
71     case CMD_SELECT_ALL: DIALOG_EditSelectAll(); break;
72     case CMD_TIME_DATE:  DIALOG_EditTimeDate(); break;
73 
74     case CMD_SEARCH:      DIALOG_Search(); break;
75     case CMD_SEARCH_NEXT: DIALOG_SearchNext(TRUE); break;
76     case CMD_REPLACE:     DIALOG_Replace(); break;
77     case CMD_GOTO:        DIALOG_GoTo(); break;
78     case CMD_SEARCH_PREV: DIALOG_SearchNext(FALSE); break;
79 
80     case CMD_WRAP: DIALOG_EditWrap(); break;
81     case CMD_FONT: DIALOG_SelectFont(); break;
82 
83     case CMD_STATUSBAR: DIALOG_ViewStatusBar(); break;
84 
85     case CMD_HELP_CONTENTS: DIALOG_HelpContents(); break;
86     case CMD_HELP_ABOUT_NOTEPAD: DIALOG_HelpAboutNotepad(); break;
87 
88     default:
89         break;
90     }
91     return 0;
92 }
93 
94 /***********************************************************************
95  *           NOTEPAD_FindTextAt
96  */
97 static BOOL
98 NOTEPAD_FindTextAt(FINDREPLACE *pFindReplace, LPCTSTR pszText, INT iTextLength, DWORD dwPosition)
99 {
100     BOOL bMatches;
101     size_t iTargetLength;
102     LPCTSTR pchPosition;
103 
104     if (!pFindReplace || !pszText)
105         return FALSE;
106 
107     iTargetLength = _tcslen(pFindReplace->lpstrFindWhat);
108     pchPosition = &pszText[dwPosition];
109 
110     /* Make proper comparison */
111     if (pFindReplace->Flags & FR_MATCHCASE)
112         bMatches = !_tcsncmp(pchPosition, pFindReplace->lpstrFindWhat, iTargetLength);
113     else
114         bMatches = !_tcsnicmp(pchPosition, pFindReplace->lpstrFindWhat, iTargetLength);
115 
116     if (bMatches && (pFindReplace->Flags & FR_WHOLEWORD))
117     {
118         if (dwPosition > 0)
119         {
120             if (_istalnum(*(pchPosition - 1)) || *(pchPosition - 1) == _T('_'))
121                 bMatches = FALSE;
122         }
123         if ((INT)dwPosition + iTargetLength < iTextLength)
124         {
125             if (_istalnum(pchPosition[iTargetLength]) || pchPosition[iTargetLength] == _T('_'))
126                 bMatches = FALSE;
127         }
128     }
129 
130     return bMatches;
131 }
132 
133 /***********************************************************************
134  *           NOTEPAD_FindNext
135  */
136 BOOL NOTEPAD_FindNext(FINDREPLACE *pFindReplace, BOOL bReplace, BOOL bShowAlert)
137 {
138     int iTextLength, iTargetLength;
139     size_t iAdjustment = 0;
140     LPTSTR pszText = NULL;
141     DWORD dwPosition, dwBegin, dwEnd;
142     BOOL bMatches = FALSE;
143     TCHAR szResource[128], szText[128];
144     BOOL bSuccess;
145 
146     iTargetLength = (int) _tcslen(pFindReplace->lpstrFindWhat);
147 
148     /* Retrieve the window text */
149     iTextLength = GetWindowTextLength(Globals.hEdit);
150     if (iTextLength > 0)
151     {
152         pszText = (LPTSTR) HeapAlloc(GetProcessHeap(), 0, (iTextLength + 1) * sizeof(TCHAR));
153         if (!pszText)
154             return FALSE;
155 
156         GetWindowText(Globals.hEdit, pszText, iTextLength + 1);
157     }
158 
159     SendMessage(Globals.hEdit, EM_GETSEL, (WPARAM) &dwBegin, (LPARAM) &dwEnd);
160     if (bReplace && ((dwEnd - dwBegin) == (DWORD) iTargetLength))
161     {
162         if (NOTEPAD_FindTextAt(pFindReplace, pszText, iTextLength, dwBegin))
163         {
164             SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM) pFindReplace->lpstrReplaceWith);
165             iAdjustment = _tcslen(pFindReplace->lpstrReplaceWith) - (dwEnd - dwBegin);
166         }
167     }
168 
169     if (pFindReplace->Flags & FR_DOWN)
170     {
171         /* Find Down */
172         dwPosition = dwEnd;
173         while(dwPosition < (DWORD) iTextLength)
174         {
175             bMatches = NOTEPAD_FindTextAt(pFindReplace, pszText, iTextLength, dwPosition);
176             if (bMatches)
177                 break;
178             dwPosition++;
179         }
180     }
181     else
182     {
183         /* Find Up */
184         dwPosition = dwBegin;
185         while(dwPosition > 0)
186         {
187             dwPosition--;
188             bMatches = NOTEPAD_FindTextAt(pFindReplace, pszText, iTextLength, dwPosition);
189             if (bMatches)
190                 break;
191         }
192     }
193 
194     if (bMatches)
195     {
196         /* Found target */
197         if (dwPosition > dwBegin)
198             dwPosition += (DWORD) iAdjustment;
199         SendMessage(Globals.hEdit, EM_SETSEL, dwPosition, dwPosition + iTargetLength);
200         SendMessage(Globals.hEdit, EM_SCROLLCARET, 0, 0);
201         bSuccess = TRUE;
202     }
203     else
204     {
205         /* Can't find target */
206         if (bShowAlert)
207         {
208             LoadString(Globals.hInstance, STRING_CANNOTFIND, szResource, ARRAY_SIZE(szResource));
209             _sntprintf(szText, ARRAY_SIZE(szText), szResource, pFindReplace->lpstrFindWhat);
210             LoadString(Globals.hInstance, STRING_NOTEPAD, szResource, ARRAY_SIZE(szResource));
211             MessageBox(Globals.hFindReplaceDlg, szText, szResource, MB_OK);
212         }
213         bSuccess = FALSE;
214     }
215 
216     if (pszText)
217         HeapFree(GetProcessHeap(), 0, pszText);
218     return bSuccess;
219 }
220 
221 /***********************************************************************
222  *           NOTEPAD_ReplaceAll
223  */
224 static VOID NOTEPAD_ReplaceAll(FINDREPLACE *pFindReplace)
225 {
226     BOOL bShowAlert = TRUE;
227 
228     SendMessage(Globals.hEdit, EM_SETSEL, 0, 0);
229 
230     while (NOTEPAD_FindNext(pFindReplace, TRUE, bShowAlert))
231     {
232         bShowAlert = FALSE;
233     }
234 }
235 
236 /***********************************************************************
237  *           NOTEPAD_FindTerm
238  */
239 static VOID NOTEPAD_FindTerm(VOID)
240 {
241     Globals.hFindReplaceDlg = NULL;
242 }
243 
244 /***********************************************************************
245  * Data Initialization
246  */
247 static VOID NOTEPAD_InitData(HINSTANCE hInstance)
248 {
249     LPTSTR p;
250     static const TCHAR txt_files[] = _T("*.txt");
251     static const TCHAR all_files[] = _T("*.*");
252 
253     ZeroMemory(&Globals, sizeof(Globals));
254     Globals.hInstance = hInstance;
255     Globals.encFile = ENCODING_DEFAULT;
256 
257     p = Globals.szFilter;
258     p += LoadString(Globals.hInstance, STRING_TEXT_FILES_TXT, p, MAX_STRING_LEN) + 1;
259     _tcscpy(p, txt_files);
260     p += ARRAY_SIZE(txt_files);
261 
262     p += LoadString(Globals.hInstance, STRING_ALL_FILES, p, MAX_STRING_LEN) + 1;
263     _tcscpy(p, all_files);
264     p += ARRAY_SIZE(all_files);
265     *p = '\0';
266     Globals.find.lpstrFindWhat = NULL;
267 
268     Globals.hDevMode = NULL;
269     Globals.hDevNames = NULL;
270 }
271 
272 /***********************************************************************
273  * Enable/disable items on the menu based on control state
274  */
275 static VOID NOTEPAD_InitMenuPopup(HMENU menu, LPARAM index)
276 {
277     int enable;
278 
279     UNREFERENCED_PARAMETER(index);
280 
281     CheckMenuItem(menu, CMD_WRAP, (Globals.bWrapLongLines ? MF_CHECKED : MF_UNCHECKED));
282     CheckMenuItem(menu, CMD_STATUSBAR, (Globals.bShowStatusBar ? MF_CHECKED : MF_UNCHECKED));
283     EnableMenuItem(menu, CMD_UNDO,
284         SendMessage(Globals.hEdit, EM_CANUNDO, 0, 0) ? MF_ENABLED : MF_GRAYED);
285     EnableMenuItem(menu, CMD_PASTE,
286         IsClipboardFormatAvailable(CF_TEXT) ? MF_ENABLED : MF_GRAYED);
287     enable = (int) SendMessage(Globals.hEdit, EM_GETSEL, 0, 0);
288     enable = (HIWORD(enable) == LOWORD(enable)) ? MF_GRAYED : MF_ENABLED;
289     EnableMenuItem(menu, CMD_CUT, enable);
290     EnableMenuItem(menu, CMD_COPY, enable);
291     EnableMenuItem(menu, CMD_DELETE, enable);
292 
293     EnableMenuItem(menu, CMD_SELECT_ALL,
294         GetWindowTextLength(Globals.hEdit) ? MF_ENABLED : MF_GRAYED);
295 }
296 
297 LRESULT CALLBACK EDIT_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
298 {
299     switch (msg)
300     {
301         case WM_KEYDOWN:
302         case WM_KEYUP:
303         {
304             switch (wParam)
305             {
306                 case VK_UP:
307                 case VK_DOWN:
308                 case VK_LEFT:
309                 case VK_RIGHT:
310                     DIALOG_StatusBarUpdateCaretPos();
311                     break;
312                 default:
313                 {
314                     UpdateWindowCaption(FALSE);
315                     break;
316                 }
317             }
318         }
319         case WM_LBUTTONUP:
320         {
321             DIALOG_StatusBarUpdateCaretPos();
322             break;
323         }
324     }
325     return CallWindowProc( Globals.EditProc, hWnd, msg, wParam, lParam);
326 }
327 
328 /***********************************************************************
329  *           NOTEPAD_WndProc
330  */
331 static LRESULT
332 WINAPI
333 NOTEPAD_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
334 {
335     switch (msg)
336     {
337 
338     case WM_CREATE:
339         Globals.hMainWnd = hWnd;
340         Globals.hMenu = GetMenu(hWnd);
341 
342         DragAcceptFiles(hWnd, TRUE); /* Accept Drag & Drop */
343 
344         /* Create controls */
345         DoCreateEditWindow();
346         DoShowHideStatusBar();
347 
348         DIALOG_FileNew(); /* Initialize file info */
349 
350         // For now, the "Help" dialog is disabled due to the lack of HTML Help support
351         EnableMenuItem(Globals.hMenu, CMD_HELP_CONTENTS, MF_BYCOMMAND | MF_GRAYED);
352         break;
353 
354     case WM_COMMAND:
355         if (HIWORD(wParam) == EN_CHANGE || HIWORD(wParam) == EN_HSCROLL || HIWORD(wParam) == EN_VSCROLL)
356             DIALOG_StatusBarUpdateCaretPos();
357         if ((HIWORD(wParam) == EN_CHANGE))
358             NOTEPAD_EnableSearchMenu();
359         NOTEPAD_MenuCommand(LOWORD(wParam));
360         break;
361 
362     case WM_CLOSE:
363         if (DoCloseFile())
364             DestroyWindow(hWnd);
365         break;
366 
367     case WM_QUERYENDSESSION:
368         if (DoCloseFile()) {
369             return 1;
370         }
371         break;
372 
373     case WM_DESTROY:
374         if (Globals.hFont)
375             DeleteObject(Globals.hFont);
376         if (Globals.hDevMode)
377             GlobalFree(Globals.hDevMode);
378         if (Globals.hDevNames)
379             GlobalFree(Globals.hDevNames);
380         SetWindowLongPtr(Globals.hEdit, GWLP_WNDPROC, (LONG_PTR)Globals.EditProc);
381         NOTEPAD_SaveSettingsToRegistry();
382         PostQuitMessage(0);
383         break;
384 
385     case WM_SIZE:
386     {
387         RECT rc;
388         GetClientRect(hWnd, &rc);
389 
390         if (Globals.bShowStatusBar)
391         {
392             RECT rcStatus;
393             SendMessageW(Globals.hStatusBar, WM_SIZE, 0, 0);
394             GetWindowRect(Globals.hStatusBar, &rcStatus);
395             rc.bottom -= rcStatus.bottom - rcStatus.top;
396         }
397 
398         MoveWindow(Globals.hEdit, 0, 0, rc.right, rc.bottom, TRUE);
399 
400         if (Globals.bShowStatusBar)
401         {
402             /* Align status bar parts, only if the status bar resize operation succeeds */
403             DIALOG_StatusBarAlignParts();
404         }
405         break;
406     }
407 
408     /* The entire client area is covered by edit control and by
409      * the status bar. So there is no need to erase main background.
410      * This resolves the horrible flicker effect during windows resizes. */
411     case WM_ERASEBKGND:
412         return 1;
413 
414     case WM_SETFOCUS:
415         SetFocus(Globals.hEdit);
416         break;
417 
418     case WM_DROPFILES:
419     {
420         TCHAR szFileName[MAX_PATH];
421         HDROP hDrop = (HDROP) wParam;
422 
423         DragQueryFile(hDrop, 0, szFileName, ARRAY_SIZE(szFileName));
424         DragFinish(hDrop);
425         DoOpenFile(szFileName);
426         break;
427     }
428 
429     case WM_INITMENUPOPUP:
430         NOTEPAD_InitMenuPopup((HMENU)wParam, lParam);
431         break;
432 
433     default:
434         if (msg == aFINDMSGSTRING)
435         {
436             FINDREPLACE *pFindReplace = (FINDREPLACE *) lParam;
437             Globals.find = *(FINDREPLACE *) lParam;
438 
439             if (pFindReplace->Flags & FR_FINDNEXT)
440                 NOTEPAD_FindNext(pFindReplace, FALSE, TRUE);
441             else if (pFindReplace->Flags & FR_REPLACE)
442                 NOTEPAD_FindNext(pFindReplace, TRUE, TRUE);
443             else if (pFindReplace->Flags & FR_REPLACEALL)
444                 NOTEPAD_ReplaceAll(pFindReplace);
445             else if (pFindReplace->Flags & FR_DIALOGTERM)
446                 NOTEPAD_FindTerm();
447             break;
448         }
449 
450         return DefWindowProc(hWnd, msg, wParam, lParam);
451     }
452     return 0;
453 }
454 
455 static int AlertFileDoesNotExist(LPCTSTR szFileName)
456 {
457     return DIALOG_StringMsgBox(Globals.hMainWnd, STRING_DOESNOTEXIST,
458                                szFileName,
459                                MB_ICONEXCLAMATION | MB_YESNO);
460 }
461 
462 static BOOL HandleCommandLine(LPTSTR cmdline)
463 {
464     BOOL opt_print = FALSE;
465     TCHAR szPath[MAX_PATH];
466 
467     while (*cmdline == _T(' ') || *cmdline == _T('-') || *cmdline == _T('/'))
468     {
469         TCHAR option;
470 
471         if (*cmdline++ == _T(' ')) continue;
472 
473         option = *cmdline;
474         if (option) cmdline++;
475         while (*cmdline == _T(' ')) cmdline++;
476 
477         switch(option)
478         {
479             case 'p':
480             case 'P':
481                 opt_print = TRUE;
482                 break;
483         }
484     }
485 
486     if (*cmdline)
487     {
488         /* file name is passed in the command line */
489         LPCTSTR file_name = NULL;
490         BOOL file_exists = FALSE;
491         TCHAR buf[MAX_PATH];
492 
493         if (cmdline[0] == _T('"'))
494         {
495             cmdline++;
496             cmdline[lstrlen(cmdline) - 1] = 0;
497         }
498 
499         file_name = cmdline;
500         if (FileExists(file_name))
501         {
502             file_exists = TRUE;
503         }
504         else if (!HasFileExtension(cmdline))
505         {
506             static const TCHAR txt[] = _T(".txt");
507 
508             /* try to find file with ".txt" extension */
509             if (!_tcscmp(txt, cmdline + _tcslen(cmdline) - _tcslen(txt)))
510             {
511                 file_exists = FALSE;
512             }
513             else
514             {
515                 _tcsncpy(buf, cmdline, MAX_PATH - _tcslen(txt) - 1);
516                 _tcscat(buf, txt);
517                 file_name = buf;
518                 file_exists = FileExists(file_name);
519             }
520         }
521 
522         GetFullPathName(file_name, ARRAY_SIZE(szPath), szPath, NULL);
523 
524         if (file_exists)
525         {
526             DoOpenFile(szPath);
527             InvalidateRect(Globals.hMainWnd, NULL, FALSE);
528             if (opt_print)
529             {
530                 DIALOG_FilePrint();
531                 return FALSE;
532             }
533         }
534         else
535         {
536             switch (AlertFileDoesNotExist(file_name))
537             {
538             case IDYES:
539                 DoOpenFile(szPath);
540                 break;
541 
542             case IDNO:
543                 break;
544             }
545         }
546     }
547 
548     return TRUE;
549 }
550 
551 /***********************************************************************
552  *           WinMain
553  */
554 int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE prev, LPTSTR cmdline, int show)
555 {
556     MSG msg;
557     HACCEL hAccel;
558     WNDCLASSEX wndclass;
559     HMONITOR monitor;
560     MONITORINFO info;
561     INT x, y;
562     RECT rcIntersect;
563     static const TCHAR className[] = _T("Notepad");
564     static const TCHAR winName[] = _T("Notepad");
565 
566 #ifdef _DEBUG
567     /* Report any memory leaks on exit */
568     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
569 #endif
570 
571     switch (GetUserDefaultUILanguage())
572     {
573     case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT):
574         SetProcessDefaultLayout(LAYOUT_RTL);
575         break;
576 
577     default:
578         break;
579     }
580 
581     UNREFERENCED_PARAMETER(prev);
582 
583     aFINDMSGSTRING = (ATOM)RegisterWindowMessage(FINDMSGSTRING);
584 
585     NOTEPAD_InitData(hInstance);
586     NOTEPAD_LoadSettingsFromRegistry();
587 
588     ZeroMemory(&wndclass, sizeof(wndclass));
589     wndclass.cbSize = sizeof(wndclass);
590     wndclass.lpfnWndProc = NOTEPAD_WndProc;
591     wndclass.hInstance = Globals.hInstance;
592     wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_NPICON));
593     wndclass.hCursor = LoadCursor(0, IDC_ARROW);
594     wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
595     wndclass.lpszMenuName = MAKEINTRESOURCE(MAIN_MENU);
596     wndclass.lpszClassName = className;
597     wndclass.hIconSm = (HICON)LoadImage(hInstance,
598                                         MAKEINTRESOURCE(IDI_NPICON),
599                                         IMAGE_ICON,
600                                         GetSystemMetrics(SM_CXSMICON),
601                                         GetSystemMetrics(SM_CYSMICON),
602                                         0);
603     if (!RegisterClassEx(&wndclass))
604     {
605         ShowLastError();
606         return 1;
607     }
608 
609     /* Setup windows */
610 
611     monitor = MonitorFromRect(&Globals.main_rect, MONITOR_DEFAULTTOPRIMARY);
612     info.cbSize = sizeof(info);
613     GetMonitorInfoW(monitor, &info);
614 
615     x = Globals.main_rect.left;
616     y = Globals.main_rect.top;
617     if (!IntersectRect(&rcIntersect, &Globals.main_rect, &info.rcWork))
618         x = y = CW_USEDEFAULT;
619 
620     /* Globals.hMainWnd will be set in WM_CREATE handling */
621     CreateWindow(className,
622                  winName,
623                  WS_OVERLAPPEDWINDOW,
624                  x,
625                  y,
626                  Globals.main_rect.right - Globals.main_rect.left,
627                  Globals.main_rect.bottom - Globals.main_rect.top,
628                  NULL,
629                  NULL,
630                  Globals.hInstance,
631                  NULL);
632     if (!Globals.hMainWnd)
633     {
634         ShowLastError();
635         return 1;
636     }
637 
638     ShowWindow(Globals.hMainWnd, show);
639     UpdateWindow(Globals.hMainWnd);
640 
641     if (!HandleCommandLine(cmdline))
642         return 0;
643 
644     hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(ID_ACCEL));
645 
646     while (GetMessage(&msg, NULL, 0, 0))
647     {
648         if (!TranslateAccelerator(Globals.hMainWnd, hAccel, &msg) &&
649             !IsDialogMessage(Globals.hFindReplaceDlg, &msg))
650         {
651             TranslateMessage(&msg);
652             DispatchMessage(&msg);
653         }
654     }
655 
656     DestroyAcceleratorTable(hAccel);
657 
658     return (int) msg.wParam;
659 }
660