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