· 5 years ago · Mar 07, 2020, 12:34 PM
1/*
2 * Notepad application
3 * Copyright (C) 1984-1995 Microsoft Inc.
4 */
5
6
7#include "precomp.h"
8#include <htmlhelp.h>
9
10#define DeepTrouble() MessageBox(hwndNP, szErrSpace, szNN, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);
11
12UINT lGotoLine; /* line number to goto to */
13
14TCHAR chMerge;
15HWND hwndNP = 0; /* handle to notepad parent window */
16HWND hwndEdit = 0; /* handle to main text control item */
17HANDLE hEdit; /* Handle to storage for edit item */
18HWND hDlgFind = NULL; /* handle to modeless FindText window */
19HANDLE hStdCursor; /* handle to arrow or beam cursor */
20HANDLE hWaitCursor; /* handle to hour glass cursor */
21HANDLE hInstanceNP; /* Module instance handle */
22HANDLE hFont; /* handle to Unicode font */
23LOGFONT FontStruct; /* font dialog structure */
24INT iPointSize=120; /* current point size unit=1/10 pts */
25TCHAR szFileName[MAX_PATH+1]; /* Current notepad filename */
26TCHAR szSearch[CCHKEYMAX]; /* Search string */
27TCHAR szReplace[CCHKEYMAX]; /* replace string */
28
29BOOL fUntitled = TRUE; /* TRUE iff notepad has no title */
30
31HMENU hSysMenuSetup; /* Save Away for disabled Minimize */
32
33DWORD dwEmSetHandle = 0; /* Is EM_SETHANDLE in process? */
34HANDLE hAccel; /* Handle to accelerator table */
35BOOL fRunBySetup = FALSE; /* Did SlipUp WinExec us?? */
36BOOL fWrap = 0; /* Flag for word wrap */
37TCHAR szNotepad[] = TEXT("Notepad");/* Name of notepad window class */
38
39BOOL fInSaveAsDlg = FALSE;
40
41/* variables for the new File/Open, File/Saveas,Find Text and Print dialogs */
42OPENFILENAME OFN; /* passed to the File Open/save APIs */
43TCHAR szOpenFilterSpec[CCHFILTERMAX]; /* default open filter spec */
44TCHAR szSaveFilterSpec[CCHFILTERMAX]; /* default save filter spec */
45NP_FILETYPE g_ftOpenedAs=FT_UNKNOWN; /* current file was opened */
46NP_FILETYPE g_ftSaveAs; /* current file was opened */
47
48FINDREPLACE FR; /* Passed to FindText() */
49PAGESETUPDLG g_PageSetupDlg;
50UINT wFRMsg; /* message used in communicating */
51 /* with Find/Replace dialog */
52
53DWORD dwCurrentSelectionStart = 0L; /* WM_ACTIVATEAPP selection pos */
54DWORD dwCurrentSelectionEnd = 0L; /* WM_ACTIVATEAPP selection pos */
55UINT wHlpMsg; /* message used in invoking help */
56
57/* Strings loaded from resource file passed to LoadString at initialization time */
58/* To add resource string:
59 * 1) create IDS_ macro definition in notepad.h
60 * 2) create string in resource file
61 * 3) create 'TCHAR*' variable directly below and in notepad.h file
62 * 4) add &variable to rgsz
63 * 5) increment CSTRINGS
64 */
65TCHAR *szDiskError =(TCHAR *)IDS_DISKERROR; /* Can't open File, check disk */
66TCHAR *szFNF =(TCHAR *)IDS_FNF; /* File not found */
67TCHAR *szFAE =(TCHAR *)IDS_FAE; /* File already exists */
68TCHAR *szSCBC =(TCHAR *)IDS_SCBC; /* Save changes before closing? */
69TCHAR *szUntitled =(TCHAR *)IDS_UNTITLED; /* untitled */
70TCHAR *szCFS =(TCHAR *)IDS_CFS; /* Can't find string */
71TCHAR *szErrSpace =(TCHAR *)IDS_ERRSPACE; /* Memory space exhausted */
72TCHAR *szNpTitle =(TCHAR *)IDS_NOTEPAD; /* Notepad - */
73TCHAR *szFTL =(TCHAR *)IDS_FTL; /* File too large for notepad */
74TCHAR *szNN =(TCHAR *)IDS_NN; /* Notepad Note! */
75TCHAR *szPDIE =(TCHAR *)IDS_PRINTDLGINIT; /* Print dialog init error */
76TCHAR *szCP =(TCHAR *)IDS_CANTPRINT; /* Can't print */
77TCHAR *szNVF =(TCHAR *)IDS_NVF; /* Not a valid filename. */
78TCHAR *szCREATEERR =(TCHAR *)IDS_CREATEERR; /* cannot create file */
79TCHAR *szNoWW =(TCHAR *)IDS_NOWW; /* Too much text to word wrap */
80TCHAR *szMerge =(TCHAR *)IDS_MERGE1; /* search string for merge */
81
82TCHAR *szHelpFile =(TCHAR *)IDS_HELPFILE; /* Name of helpfile. */
83TCHAR *szBadMarg =(TCHAR *)IDS_BADMARG; /* Bad margins. */
84TCHAR *szFileOpenFail =(TCHAR *)IDS_FILEOPENFAIL; /* Can't open File */
85TCHAR *szAnsiText =(TCHAR *)IDS_ANSITEXT; /* File/Open ANSI filter spec. string */
86TCHAR *szAllFiles =(TCHAR *)IDS_ALLFILES; /* File/Open Filter spec. string */
87TCHAR *szOpenCaption = (TCHAR *)IDS_OPENCAPTION; /* caption for File/Open dlg */
88TCHAR *szSaveCaption = (TCHAR *)IDS_SAVECAPTION; /* caption for File/Save dlg */
89TCHAR *szCannotQuit = (TCHAR *)IDS_CANNOTQUIT; /* cannot quit during a WM_QUERYENDSESSION */
90TCHAR *szLoadDrvFail = (TCHAR *)IDS_LOADDRVFAIL; /* LOADDRVFAIL from PrintDlg */
91TCHAR *szErrUnicode =(TCHAR *)IDS_ERRUNICODE; /* Unicode character existence error */
92TCHAR *szACCESSDENY = (TCHAR *)IDS_ACCESSDENY; /* Access denied on Open */
93TCHAR *szFontTooBig = (TCHAR *)IDS_FONTTOOBIG; /* font too big or page too small */
94TCHAR *szCommDlgErr = (TCHAR *)IDS_COMMDLGERR; /* common dialog error %x */
95TCHAR *szCommDlgInitErr = (TCHAR *)IDS_COMMDLGINIT; /* common dialog error %x */
96
97
98TCHAR *szLineError = (TCHAR*)IDS_LINEERROR; /* line number error */
99TCHAR *szLineTooLarge = (TCHAR*)IDS_LINETOOLARGE;/* line number out of range */
100
101TCHAR *szFtAnsi = (TCHAR*) IDS_FT_ANSI;
102TCHAR *szFtUnicode = (TCHAR*) IDS_FT_UNICODE;
103TCHAR *szFtUnicodeBe = (TCHAR*) IDS_FT_UNICODEBE;
104TCHAR *szFtUtf8 = (TCHAR*) IDS_FT_UTF8;
105
106
107TCHAR **rgsz[CSTRINGS-6] = {
108 &szDiskError,
109 &szFNF,
110 &szFAE,
111 &szSCBC,
112 &szUntitled,
113 &szErrSpace,
114 &szCFS,
115 &szNpTitle,
116 &szFTL,
117 &szNN,
118 &szCommDlgInitErr,
119 &szPDIE,
120 &szCP,
121 &szNVF,
122 &szCREATEERR,
123 &szNoWW,
124 &szMerge,
125 &szHelpFile,
126 &szBadMarg,
127 &szFileOpenFail,
128 &szAnsiText,
129 &szAllFiles,
130 &szOpenCaption,
131 &szSaveCaption,
132 &szCannotQuit,
133 &szLoadDrvFail,
134 &szACCESSDENY,
135 &szErrUnicode,
136 &szCommDlgErr,
137 &szFontTooBig,
138 &szLineError,
139 &szLineTooLarge,
140 &szFtAnsi,
141 &szFtUnicode,
142 &szFtUnicodeBe,
143 &szFtUtf8,
144};
145
146
147HANDLE fp; /* file pointer */
148
149
150#if 0
151VOID DisplayFont( LOGFONT* pf )
152{
153 TCHAR dbuf[100];
154
155 ODS(TEXT("-----------------------\n"));
156 wsprintf(dbuf,TEXT("lfHeight %d\n"),pf->lfHeight); ODS(dbuf);
157 wsprintf(dbuf,TEXT("lfWidth %d\n"),pf->lfWidth ); ODS(dbuf);
158 wsprintf(dbuf,TEXT("lfEscapement %d\n"),pf->lfEscapement); ODS(dbuf);
159 wsprintf(dbuf,TEXT("lfOrientation %d\n"),pf->lfOrientation); ODS(dbuf);
160 wsprintf(dbuf,TEXT("lfWeight %d\n"),pf->lfWeight); ODS(dbuf);
161 wsprintf(dbuf,TEXT("lfItalic %d\n"),pf->lfItalic); ODS(dbuf);
162 wsprintf(dbuf,TEXT("lfUnderLine %d\n"),pf->lfUnderline); ODS(dbuf);
163 wsprintf(dbuf,TEXT("lfStrikeOut %d\n"),pf->lfStrikeOut); ODS(dbuf);
164 wsprintf(dbuf,TEXT("lfCharSet %d\n"),pf->lfCharSet); ODS(dbuf);
165 wsprintf(dbuf,TEXT("lfOutPrecision %d\n"),pf->lfOutPrecision); ODS(dbuf);
166 wsprintf(dbuf,TEXT("lfClipPrecision %d\n"),pf->lfClipPrecision); ODS(dbuf);
167 wsprintf(dbuf,TEXT("lfQuality %d\n"),pf->lfQuality); ODS(dbuf);
168 wsprintf(dbuf,TEXT("lfPitchAndFamily %d\n"),pf->lfPitchAndFamily); ODS(dbuf);
169 wsprintf(dbuf,TEXT("lfFaceName %s\n"),pf->lfFaceName); ODS(dbuf);
170
171}
172#endif
173
174static TCHAR szPath[MAX_PATH];
175
176void FileDragOpen(void);
177VOID NpResetMenu(HWND hWnd);
178BOOL SignalCommDlgError(VOID);
179VOID ReplaceSel( BOOL bView );
180
181/* FreeGlobal, frees all global memory allocated. */
182
183void NEAR PASCAL FreeGlobal()
184{
185 if(g_PageSetupDlg.hDevMode)
186 {
187 GlobalFree(g_PageSetupDlg.hDevMode);
188 }
189
190 if(g_PageSetupDlg.hDevNames)
191 {
192 GlobalFree(g_PageSetupDlg.hDevNames);
193 }
194
195 g_PageSetupDlg.hDevMode= NULL; // make sure they are zero for PrintDlg
196 g_PageSetupDlg.hDevNames= NULL;
197}
198
199VOID PASCAL SetPageSetupDefaults( VOID )
200{
201 TCHAR szIMeasure[ 2 ];
202
203 g_PageSetupDlg.lpfnPageSetupHook= PageSetupHookProc;
204 g_PageSetupDlg.lpPageSetupTemplateName= MAKEINTRESOURCE(IDD_PAGESETUP);
205
206 GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_IMEASURE, szIMeasure, 2 );
207
208 g_PageSetupDlg.Flags= PSD_MARGINS |
209 PSD_ENABLEPAGESETUPHOOK | PSD_ENABLEPAGESETUPTEMPLATE;
210
211 if (szIMeasure[ 0 ] == TEXT( '1' ))
212 {
213 // English measure (in thousandths of inches).
214 g_PageSetupDlg.Flags |= PSD_INTHOUSANDTHSOFINCHES;
215 g_PageSetupDlg.rtMargin.top = 1000;
216 g_PageSetupDlg.rtMargin.bottom = 1000;
217 g_PageSetupDlg.rtMargin.left = 750;
218 g_PageSetupDlg.rtMargin.right = 750;
219 }
220 else
221 {
222 // Metric measure (in hundreths of millimeters).
223 g_PageSetupDlg.Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
224 g_PageSetupDlg.rtMargin.top = 2500;
225 g_PageSetupDlg.rtMargin.bottom = 2500;
226 g_PageSetupDlg.rtMargin.left = 2000;
227 g_PageSetupDlg.rtMargin.right = 2000;
228 }
229
230}
231
232/* Standard window size proc */
233void NPSize (int cxNew, int cyNew)
234{
235 /* Invalidate the edit control window so that it is redrawn with the new
236 * margins. Needed when comming up from iconic and when doing word wrap so
237 * the new margins are accounted for.
238 */
239 InvalidateRect(hwndEdit, (LPRECT)NULL, TRUE);
240 MoveWindow( hwndEdit, 0, 0, cxNew, cyNew, TRUE );
241}
242
243// NpSaveDialogHookProc
244//
245// Common dialog hook procedure for handling
246// the file type while saving.
247//
248
249const DWORD s_SaveAsHelpIDs[]=
250 {
251 IDC_FILETYPE, IDH_FILETYPE,
252 IDC_ENCODING, IDH_FILETYPE,
253 0, 0
254 };
255
256UINT_PTR APIENTRY NpSaveDialogHookProc(
257 HWND hWnd,
258 UINT msg,
259 WPARAM wParam,
260 LPARAM lParam)
261{
262 INT id;
263 POINT pt;
264 TCHAR* szSelect; // selected type
265
266 switch( msg )
267 {
268 case WM_INITDIALOG:
269 // Warning: the order here must be the same as NP_FILETYPE
270
271 SendDlgItemMessage(hWnd, IDC_FILETYPE,CB_ADDSTRING, 0, (LPARAM) szFtAnsi );
272 SendDlgItemMessage(hWnd, IDC_FILETYPE,CB_ADDSTRING, 0, (LPARAM) szFtUnicode );
273 SendDlgItemMessage(hWnd, IDC_FILETYPE,CB_ADDSTRING, 0, (LPARAM) szFtUnicodeBe );
274 SendDlgItemMessage(hWnd, IDC_FILETYPE,CB_ADDSTRING, 0, (LPARAM) szFtUtf8 );
275
276 szSelect= szFtAnsi; // default
277 g_ftSaveAs= g_ftOpenedAs; // default: save as same type as opened
278 switch( g_ftSaveAs )
279 {
280 case FT_UNICODE: szSelect= szFtUnicode; break;
281 case FT_UNICODEBE: szSelect= szFtUnicodeBe; break;
282 case FT_UTF8: szSelect= szFtUtf8; break;
283 default: break;
284 }
285
286 SendDlgItemMessage( hWnd, IDC_FILETYPE, CB_SELECTSTRING, (WPARAM) -1, (LPARAM)szSelect );
287 break;
288
289 case WM_COMMAND:
290 g_ftSaveAs= (NP_FILETYPE) SendDlgItemMessage( hWnd, IDC_FILETYPE, CB_GETCURSEL, 0, 0 );
291 break;
292
293 case WM_HELP:
294 //
295 // We only want to intercept help messages for controls that we are
296 // responsible for.
297 //
298
299 id = GetDlgCtrlID(((LPHELPINFO) lParam)-> hItemHandle);
300
301 if ( id != IDC_FILETYPE && id != IDC_ENCODING)
302 break;
303
304 WinHelp(((LPHELPINFO) lParam)-> hItemHandle,
305 szHelpFile,
306 HELP_WM_HELP,
307 (ULONG_PTR) s_SaveAsHelpIDs);
308 return TRUE;
309
310 case WM_CONTEXTMENU:
311 //
312 // If the user clicks on any of our labels, then the wParam will
313 // be the hwnd of the dialog, not the static control. WinHelp()
314 // handles this, but because we hook the dialog, we must catch it
315 // first.
316 //
317 if( hWnd == (HWND) wParam )
318 {
319 GetCursorPos(&pt);
320 ScreenToClient(hWnd, &pt);
321 wParam = (WPARAM) ChildWindowFromPoint(hWnd, pt);
322 }
323
324 //
325 // We only want to intercept help messages for controls that we are
326 // responsible for.
327 //
328
329 id = GetDlgCtrlID((HWND) wParam);
330
331 if ( id != IDC_FILETYPE && id != IDC_ENCODING)
332 break;
333
334 WinHelp( (HWND) wParam,
335 szHelpFile,
336 HELP_CONTEXTMENU,
337 (ULONG_PTR) s_SaveAsHelpIDs);
338 return TRUE;
339 }
340 return( FALSE );
341}
342/* ** Notepad command proc - called whenever notepad gets WM_COMMAND
343 message. wParam passed as cmd */
344INT NPCommand(
345 HWND hwnd,
346 WPARAM wParam,
347 LPARAM lParam )
348{
349 HWND hwndFocus;
350 LONG lSel;
351 TCHAR szNewName[MAX_PATH] = TEXT(""); /* New file name */
352 FARPROC lpfn;
353 LONG style;
354 DWORD rc;
355
356 switch (LOWORD(wParam))
357 {
358 case M_EXIT:
359 PostMessage(hwnd, WM_CLOSE, 0, 0L);
360 break;
361
362 case M_NEW:
363 New(TRUE);
364 break;
365
366 case M_OPEN:
367 if (CheckSave(FALSE))
368 {
369 /* set up the variable fields of the OPENFILENAME struct.
370 * (the constant fields have been set in NPInit()
371 */
372 OFN.lpstrFile = szNewName;
373 lstrcpy(szNewName, TEXT("*.txt") ); /* set default selection */
374 OFN.lpstrTitle = szOpenCaption;
375
376 /* ALL non-zero long pointers must be defined immediately
377 * before the call, as the DS might move otherwise.
378 * 12 February 1991 clarkc
379 */
380 OFN.lpstrFilter = szOpenFilterSpec;
381 OFN.lpstrDefExt = TEXT("txt");
382 /* Added OFN_FILEMUSTEXIST to eliminate problems in LoadFile.
383 * 12 February 1991 clarkc
384 */
385 OFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
386 OFN.nFilterIndex = FILE_TEXT;
387 OFN.lpTemplateName = NULL;
388 OFN.lpfnHook = NULL;
389
390 if( GetOpenFileName( (LPOPENFILENAME)&OFN ) )
391 {
392 HANDLE oldfp= fp;
393
394 fp= CreateFile( szNewName, // filename
395 GENERIC_READ, // access mode
396 FILE_SHARE_READ|FILE_SHARE_WRITE,
397 NULL, // security descriptor
398 OPEN_EXISTING, // how to create
399 FILE_ATTRIBUTE_NORMAL,// file attributes
400 NULL); // hnd to file attrs
401 /* Try to load the file and reset fp if failed */
402 if( !LoadFile( szNewName, FT_UNKNOWN ) )
403 {
404 fp= oldfp;
405 }
406 }
407 else
408 {
409 SignalCommDlgError();
410 }
411 }
412 break;
413
414 case M_SAVE:
415 /* set up the variable fields of the OPENFILENAME struct.
416 * (the constant fields have been sel in NPInit()
417 */
418 g_ftSaveAs = g_ftOpenedAs;
419 if( !fUntitled && SaveFile( hwndNP, szFileName, FALSE ) )
420 break;
421
422 /* fall through */
423
424 case M_SAVEAS:
425
426 OFN.lpstrFile = szNewName;
427 OFN.lpstrTitle = szSaveCaption;
428 /* Added OFN_PATHMUSTEXIST to eliminate problems in SaveFile.
429 * 12 February 1991 clarkc
430 */
431 OFN.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT |
432 OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST |
433 OFN_EXPLORER |
434 OFN_ENABLESIZING |
435 OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
436
437 OFN.lpTemplateName= TEXT("NpSaveDialog");
438 OFN.lpfnHook= NpSaveDialogHookProc;
439
440 /* ALL non-zero long pointers must be defined immediately
441 * before the call, as the DS might move otherwise.
442 * 12 February 1991 clarkc
443 */
444 OFN.lpstrFilter = szSaveFilterSpec;
445 OFN.lpstrDefExt = TEXT("txt");
446
447 if (!fUntitled)
448 {
449 lstrcpyn(szNewName, szFileName, MAX_PATH); /* set default selection */
450 szNewName[MAX_PATH]= TEXT('\0');
451 }
452 else
453 {
454 lstrcpy (szNewName, TEXT("*.txt") );
455 }
456
457 fInSaveAsDlg = TRUE;
458
459 OFN.nFilterIndex= FILE_TEXT;
460
461 //
462 // Do common dialog to save file
463 //
464
465
466 if (GetSaveFileName(&OFN))
467 {
468
469 if( SaveFile(hwnd, szNewName, TRUE) )
470 {
471 lstrcpyn( szFileName, szNewName, MAX_PATH);
472 szFileName[MAX_PATH]= TEXT('\0');
473 g_ftOpenedAs= g_ftSaveAs;
474 }
475 }
476 else
477 {
478 SignalCommDlgError();
479 }
480
481 fInSaveAsDlg = FALSE;
482 break;
483
484 case M_SELECTALL:
485 {
486 HMENU hMenu;
487
488 hMenu = GetMenu(hwndNP);
489 lSel = (LONG) SendMessage (hwndEdit, WM_GETTEXTLENGTH, 0, 0L);
490 SendMessage (hwndEdit, EM_SETSEL, 0, lSel );
491 SendMessage(hwndEdit, EM_SCROLLCARET, 0, 0);
492 EnableMenuItem(GetSubMenu(hMenu, 1), M_SELECTALL, MF_GRAYED);
493 break;
494 }
495
496 case M_REPLACE:
497 if( hDlgFind )
498 {
499 SetFocus( hDlgFind );
500 }
501 else
502 {
503 FR.Flags= FR_HIDEWHOLEWORD | FR_REPLACE;
504 FR.lpstrReplaceWith= szReplace;
505 FR.wReplaceWithLen= CCHKEYMAX;
506 FR.lpstrFindWhat = szSearch;
507 FR.wFindWhatLen = CCHKEYMAX;
508 hDlgFind = ReplaceText( &FR );
509 }
510 break;
511
512 case M_FINDNEXT:
513 if (szSearch[0])
514 {
515 Search(szSearch);
516 break;
517 }
518 /* else fall thro' a,d bring up "find" dialog */
519
520 case M_FIND:
521 if (hDlgFind)
522 {
523 SetFocus(hDlgFind);
524 }
525 else
526 {
527 FR.Flags= FR_DOWN | FR_HIDEWHOLEWORD;
528 FR.lpstrReplaceWith= NULL;
529 FR.wReplaceWithLen= 0;
530 FR.lpstrFindWhat = szSearch;
531 FR.wFindWhatLen = CCHKEYMAX;
532 hDlgFind = FindText((LPFINDREPLACE)&FR);
533 }
534 break;
535
536 case M_GOTO:
537 {
538 INT Result;
539
540 Result= (INT)DialogBox( hInstanceNP,
541 MAKEINTRESOURCE(IDD_GOTODIALOG),
542 hwndNP,
543 GotoDlgProc );
544
545 //
546 // move cursor only if ok pressed and line number ok
547 //
548
549 if( Result == 0 )
550 {
551 UINT CharIndex;
552 CharIndex= (UINT) SendMessage( hwndEdit,
553 EM_LINEINDEX,
554 lGotoLine-1,
555 0 );
556 if( CharIndex != (UINT) -1 )
557 {
558 SendMessage( hwndEdit, EM_SETSEL, CharIndex, CharIndex);
559 SendMessage( hwndEdit, EM_SCROLLCARET, 0, 0 );
560 }
561 }
562 }
563 break;
564
565 case M_ABOUT:
566 ShellAbout(hwndNP,
567 szNN,
568 TEXT(""),
569 LoadIcon(hInstanceNP,
570 (LPTSTR)MAKEINTRESOURCE(ID_ICON)));
571
572 break;
573
574 case M_HELP:
575 HtmlHelpA(GetDesktopWindow(), "notepad.chm", HH_DISPLAY_TOPIC, 0L);
576 break;
577
578 case M_CUT:
579 case M_COPY:
580 case M_CLEAR:
581 lSel = (LONG)SendMessage (hwndEdit, EM_GETSEL, 0, 0L);
582 if (LOWORD(lSel) == HIWORD(lSel))
583 break;
584
585 case M_PASTE:
586 /* If notepad parent or edit window has the focus,
587 pass command to edit window.
588 make sure line resulting from paste will not be too long. */
589 hwndFocus = GetFocus();
590 if (hwndFocus == hwndEdit || hwndFocus == hwndNP)
591 {
592 PostMessage(hwndEdit, LOWORD(wParam), 0, 0);
593 }
594 break;
595
596 case M_DATETIME:
597 InsertDateTime(FALSE);
598 break;
599
600 case M_UNDO:
601 SendMessage (hwndEdit, EM_UNDO, 0, 0L);
602 break;
603
604 case M_WW:
605 style= (!fWrap) ? ES_STD : (ES_STD | WS_HSCROLL);
606 if( NpReCreate( style ) )
607 {
608 fWrap= !fWrap;
609 }
610 else
611 {
612 MessageBox(hwndNP, szNoWW, szNN,
613 MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION);
614 }
615 break;
616
617 case ID_EDIT:
618 break;
619
620 case M_PRINT:
621 PrintIt( UseDialog );
622 break;
623
624 case M_PAGESETUP:
625 TryPrintDlgAgain:
626
627 if( PageSetupDlg(&g_PageSetupDlg) )
628 {
629 // We know it's okay to copy these strings over...
630 lstrcpy(chPageText[HEADER], chPageTextTemp[HEADER]);
631 lstrcpy(chPageText[FOOTER], chPageTextTemp[FOOTER]);
632 }
633 else
634 {
635 rc= CommDlgExtendedError();
636
637 if( rc == PDERR_PRINTERNOTFOUND ||
638 rc == PDERR_DNDMMISMATCH ||
639 rc == PDERR_DEFAULTDIFFERENT )
640 {
641 FreeGlobal();
642 g_PageSetupDlg.hDevMode= g_PageSetupDlg.hDevNames= 0;
643 goto TryPrintDlgAgain;
644 }
645
646 // Check for Dialog Failure
647
648 SignalCommDlgError( );
649
650 }
651 break;
652
653 case M_SETFONT:
654 {
655 CHOOSEFONT cf;
656 HFONT hFontNew;
657 HDC hDisplayDC; // display DC
658
659 hDisplayDC= GetDC(NULL); // try to get display DC
660 if( !hDisplayDC )
661 break;
662
663 /* calls the font chooser (in commdlg)
664 * We set lfHeight; choosefont returns ipointsize
665 */
666 cf.lStructSize = sizeof(CHOOSEFONT);
667 cf.hwndOwner = hwnd;
668 cf.lpLogFont = &FontStruct; // filled in by init
669 FontStruct.lfHeight= -MulDiv(iPointSize,GetDeviceCaps(hDisplayDC,LOGPIXELSY),720);
670 cf.Flags = CF_INITTOLOGFONTSTRUCT |
671 CF_SCREENFONTS |
672 CF_NOVERTFONTS |
673 0;
674 cf.rgbColors = 0; // only if cf_effects
675 cf.lCustData = 0; // for hook function
676 cf.lpfnHook = (LPCFHOOKPROC) NULL;
677 cf.lpTemplateName = (LPTSTR) NULL;
678 cf.hInstance = NULL;
679 cf.lpszStyle = NULL; // iff cf_usestyle
680 cf.nFontType = SCREEN_FONTTYPE;
681 cf.nSizeMin = 0; // iff cf_limitsize
682 cf.nSizeMax = 0; // iff cf_limitsize
683 ReleaseDC( NULL, hDisplayDC );
684
685 if( ChooseFont(&cf) )
686 {
687 SetCursor( hWaitCursor ); // may take some time
688
689 hFontNew= CreateFontIndirect(&FontStruct);
690 if( hFontNew )
691 {
692 DeleteObject( hFont );
693 hFont= hFontNew;
694 SendMessage( hwndEdit, WM_SETFONT,
695 (WPARAM)hFont, MAKELPARAM(TRUE, 0));
696 iPointSize= cf.iPointSize; // remember for printer
697 }
698 SetCursor( hStdCursor );
699 }
700 break;
701 }
702
703 default:
704 return FALSE;
705 }
706 return TRUE;
707}
708
709
710// bugbug
711// for some reason, this procedure tries to maintain
712// a valid 'fp' even though I believe it does not need
713// to be.
714// bugbug
715
716void FileDragOpen(void)
717{
718 HANDLE oldfp;
719
720 oldfp= fp; // remember in case of error
721
722 if( CheckSave(FALSE) )
723 {
724
725 fp= CreateFile( szPath, // filename
726 GENERIC_READ, // access mode
727 FILE_SHARE_READ|FILE_SHARE_WRITE,
728 NULL, // security descriptor
729 OPEN_EXISTING, // how to create
730 FILE_ATTRIBUTE_NORMAL,// file attributes
731 NULL); // hnd to file attrs
732
733 if( fp == INVALID_HANDLE_VALUE )
734 {
735 AlertUser_FileFail( szPath );
736
737 // Restore fp to original file.
738 fp= oldfp;
739 }
740 /* Try to load the file and reset fp if failed */
741 else if( !LoadFile( szPath, FT_UNKNOWN ) )
742 {
743 fp= oldfp;
744 }
745 }
746}
747
748
749/* Proccess file drop/drag options. */
750void doDrop (WPARAM wParam, HWND hwnd)
751{
752 /* If user dragged/dropped a file regardless of keys pressed
753 * at the time, open the first selected file from file manager. */
754
755 if (DragQueryFile ((HANDLE)wParam, 0xFFFFFFFF, NULL, 0)) /* # of files dropped */
756 {
757 DragQueryFile ((HANDLE)wParam, 0, szPath, CharSizeOf(szPath));
758 SetActiveWindow (hwnd);
759 FileDragOpen();
760 }
761 DragFinish ((HANDLE)wParam); /* Delete structure alocated for WM_DROPFILES*/
762}
763
764/* ** if notepad is dirty, check to see if user wants to save contents */
765BOOL FAR CheckSave (BOOL fSysModal)
766{
767 INT mdResult = IDOK;
768 TCHAR szNewName[MAX_PATH] = TEXT(""); /* New file name */
769 TCHAR *pszFileName;
770
771/* If it's untitled and there's no text, don't worry about it */
772 if (fUntitled && !SendMessage (hwndEdit, WM_GETTEXTLENGTH, 0, (LPARAM)0))
773 return (TRUE);
774
775 if (SendMessage (hwndEdit, EM_GETMODIFY, 0, 0L))
776 {
777 if( fUntitled )
778 pszFileName= szUntitled;
779 else
780 pszFileName= szFileName;
781
782 mdResult= AlertBox( hwndNP, szNN, szSCBC, pszFileName,
783 (WORD)((fSysModal ? MB_SYSTEMMODAL :
784 MB_APPLMODAL)|MB_YESNOCANCEL|MB_ICONEXCLAMATION));
785 if( mdResult == IDYES )
786 {
787 if( fUntitled )
788 {
789 lstrcpy( szNewName, TEXT("*.txt") );
790SaveFilePrompt:
791 OFN.lpstrFile = szNewName;
792 OFN.lpstrTitle = szSaveCaption;
793
794 /* Added OFN_PATHMUSTEXIST to eliminate problems in SaveFile.
795 * 12 February 1991 clarkc
796 */
797
798 OFN.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT |
799 OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST |
800 OFN_EXPLORER |
801 OFN_ENABLESIZING |
802 OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
803
804 OFN.lpTemplateName= TEXT("NpSaveDialog");
805 OFN.lpfnHook= NpSaveDialogHookProc;
806
807 /* ALL non-zero long pointers must be defined immediately
808 * before the call, as the DS might move otherwise.
809 * 12 February 1991 clarkc
810 */
811 OFN.lpstrFilter = szSaveFilterSpec;
812 OFN.lpstrDefExt = TEXT("txt");
813
814 OFN.nFilterIndex= FILE_TEXT;
815
816 //
817 // Set dialog checkmark by current file type
818 //
819
820 fInSaveAsDlg = TRUE;
821 if (GetSaveFileName(&OFN))
822 {
823 // since SaveFile() uses near ptr to name (obs.)
824 lstrcpy(szNewName, OFN.lpstrFile);
825 if( SaveFile(hwndNP, szNewName, TRUE) )
826 {
827 lstrcpy(szFileName, szNewName);
828 g_ftOpenedAs= g_ftSaveAs;
829 }
830 else
831 { // Fixing close without saving file when disk-full
832 lstrcpy(szNewName, szFileName);
833 goto SaveFilePrompt;
834 }
835 }
836 else
837 {
838 mdResult= IDCANCEL; /* Don't exit Program */
839 if( CommDlgExtendedError() )/* Dialog box failed, Lo-mem*/
840 DeepTrouble();
841 }
842
843 fInSaveAsDlg = FALSE;
844 }
845 else
846 {
847 // initialize the save type.
848 g_ftSaveAs = g_ftOpenedAs;
849 if( SaveFile(hwndNP, szFileName, FALSE) )
850 return(TRUE);
851 lstrcpy(szNewName, szFileName);
852 goto SaveFilePrompt;
853 }
854 }
855 }
856 return (mdResult != IDCANCEL);
857}
858
859
860/* Notepad window class procedure */
861LRESULT FAR NPWndProc(
862 HWND hwnd,
863 UINT message,
864 WPARAM wParam,
865 LPARAM lParam)
866{
867 RECT rc;
868 LPFINDREPLACE lpfr;
869 DWORD dwFlags;
870 HANDLE hMenu;
871
872
873
874 switch (message)
875 {
876/* If we're being run by Setup and it's the system menu, be certain that
877 * the minimize menu item is disabled. Note that hSysMenuSetup is only
878 * initialized if Notepad is being run by Setup. Don't use it outside
879 * the fRunBySetup conditional! 28 June 1991 Clark Cyr
880 */
881 case WM_INITMENUPOPUP:
882 if (fRunBySetup && HIWORD(lParam))
883 EnableMenuItem(hSysMenuSetup,SC_MINIMIZE,MF_GRAYED|MF_DISABLED);
884 break;
885
886 case WM_SYSCOMMAND:
887 if (fRunBySetup)
888 {
889 /* If we have been spawned by SlipUp we need to make sure the
890 * user doesn't minimize us or alt tab/esc away.
891 */
892 if (wParam == SC_MINIMIZE ||
893 wParam == SC_NEXTWINDOW ||
894 wParam == SC_PREVWINDOW)
895 break;
896 }
897 DefWindowProc(hwnd, message, wParam, lParam);
898 break;
899
900 case WM_SETFOCUS:
901 if (!IsIconic(hwndNP))
902 {
903 SetFocus(hwndEdit);
904 }
905 break;
906
907 case WM_KILLFOCUS:
908 SendMessage (hwndEdit, message, wParam, lParam);
909 break;
910
911 case WM_DESTROY:
912 PostQuitMessage(0);
913 break;
914
915 case WM_CLOSE:
916
917 // Save any globals in the registry if need be
918
919 SaveGlobals();
920
921 if (CheckSave(FALSE))
922 {
923 /* Exit help */
924 if(!WinHelp(hwndNP, (LPTSTR)szHelpFile, HELP_QUIT, 0))
925 DeepTrouble();
926
927 DestroyWindow(hwndNP);
928 DeleteObject(hFont);
929 }
930
931 break;
932
933 case WM_QUERYENDSESSION:
934 if (fInSaveAsDlg)
935 {
936 MessageBeep (0);
937 MessageBeep (0);
938 MessageBox (hwndNP, szCannotQuit, szNN, MB_OK|MB_SYSTEMMODAL);
939 return FALSE;
940 }
941 else
942 return (CheckSave(TRUE));
943 break;
944
945
946 case WM_ACTIVATEAPP:
947 if (wParam)
948 {
949 /* This causes the caret position to be at the end of the selection
950 * but there's no way to ask where it was or set it if known. This
951 * will cause a caret change when the selection is made from bottom
952 * to top.
953 */
954 if( dwCurrentSelectionStart != 0 || dwCurrentSelectionEnd != 0 )
955 {
956 SendMessage( hwndEdit, EM_SETSEL,
957 dwCurrentSelectionStart,
958 dwCurrentSelectionEnd );
959 SendMessage( hwndEdit, EM_SCROLLCARET, 0, 0 );
960 }
961 }
962 else
963 {
964 SendMessage( hwndEdit, EM_GETSEL,
965 (WPARAM) &dwCurrentSelectionStart,
966 (LPARAM) &dwCurrentSelectionEnd);
967 if (dwCurrentSelectionStart == dwCurrentSelectionEnd)
968 {
969 dwCurrentSelectionStart = 0L;
970 dwCurrentSelectionEnd = 0L;
971 }
972 else
973 {
974 SendMessage (hwndEdit, EM_SETSEL, dwCurrentSelectionStart,
975 dwCurrentSelectionEnd);
976 SendMessage (hwndEdit, EM_SCROLLCARET, 0, 0);
977 }
978 }
979 break;
980
981 case WM_ACTIVATE:
982 if ((LOWORD(wParam) == WA_ACTIVE ||
983 LOWORD(wParam) == WA_CLICKACTIVE) &&
984 !IsIconic(hwndNP)
985 )
986 {
987 // active doesn't always mean foreground (ntbug# 53048)
988 if( GetForegroundWindow() == hwndNP )
989 {
990 SetFocus(GetForegroundWindow());
991 }
992 }
993 break;
994
995 case WM_SIZE:
996 switch (wParam)
997 {
998 case SIZENORMAL:
999 case SIZEFULLSCREEN:
1000 NPSize(MAKEPOINTS(lParam).x, MAKEPOINTS(lParam).y);
1001 break;
1002
1003 case SIZEICONIC:
1004 return (DefWindowProc(hwnd, message, wParam, lParam));
1005 break;
1006 }
1007 break;
1008
1009 case WM_INITMENU:
1010 NpResetMenu( hwnd );
1011 break;
1012
1013 //
1014 // Some keyboards come with a "Search" button which the shell team
1015 // wanted us to handle. See ntbug# 380067
1016 //
1017
1018 case WM_APPCOMMAND:
1019
1020 if( ( GET_APPCOMMAND_LPARAM(lParam) == APPCOMMAND_BROWSER_SEARCH ) )
1021 {
1022 NPCommand(hwnd, M_FIND, 0);
1023 break;
1024 }
1025 // otherwise fall through
1026
1027 case WM_COMMAND:
1028 if ((HWND)(lParam) == hwndEdit &&
1029 (HIWORD(wParam) == EN_ERRSPACE ||
1030 HIWORD(wParam) == EN_MAXTEXT))
1031 {
1032 if (dwEmSetHandle == SETHANDLEINPROGRESS)
1033 dwEmSetHandle = SETHANDLEFAILED;
1034 else
1035 DeepTrouble();
1036 return 0L;
1037 }
1038
1039 if (!NPCommand(hwnd, wParam, lParam))
1040 return (DefWindowProc(hwnd, message, wParam, lParam));
1041 break;
1042
1043 case WM_WININICHANGE:
1044 // Ignore for now.
1045 // If you put this back in, be sure it handles both
1046 // the metric change and the decimal change.
1047 //NpWinIniChange ();
1048 break;
1049
1050 case WM_DROPFILES: /*case added 03/26/91 for file drag/drop support*/
1051 doDrop (wParam,hwnd);
1052 break;
1053
1054 case PWM_CHECK_HKL: /* private message: corresponding to HKL change message */
1055 {
1056 LPARAM lParam = 0;
1057
1058 if (PRIMARYLANGID(LOWORD((DWORD) (INT_PTR) GetKeyboardLayout(0))) == LANG_JAPANESE) {
1059 /*
1060 * If new current HKL is Japanese, handle the result string at once.
1061 */
1062 lParam = EIMES_GETCOMPSTRATONCE;
1063 }
1064 SendMessage(hwndEdit, EM_SETIMESTATUS, EMSIS_COMPOSITIONSTRING, lParam);
1065 }
1066 break;
1067
1068 default:
1069 /* this can be a message from the modeless Find Text window */
1070 if (message == wFRMsg)
1071 {
1072 BOOL bStatus; // true if found text
1073
1074 lpfr = (LPFINDREPLACE)lParam;
1075 dwFlags = lpfr->Flags;
1076
1077 fReverse = (dwFlags & FR_DOWN ? FALSE : TRUE);
1078 fCase = (dwFlags & FR_MATCHCASE ? TRUE : FALSE);
1079
1080 if( dwFlags & FR_FINDNEXT )
1081 {
1082 SetCursor( hWaitCursor );
1083 Search( szSearch );
1084 SetCursor( hStdCursor );
1085 }
1086 else if( dwFlags & FR_REPLACE )
1087 {
1088 //
1089 // Replace current selection if it matches
1090 // then highlight the next occurence of the string.
1091 //
1092
1093 SetCursor( hWaitCursor );
1094 ReplaceSel( TRUE );
1095 Search( szSearch );
1096 SetCursor( hStdCursor );
1097 }
1098 else if( dwFlags & FR_REPLACEALL )
1099 {
1100 //
1101 // The replace dialog doesn't allow reverse searches
1102 // but just it cases it changes, for it to false.
1103 //
1104 if( fReverse )
1105 {
1106 fReverse= FALSE;
1107 }
1108
1109 //
1110 // Replace all occurances of text in the file
1111 // starting from the top. Reset the selection
1112 // to the top of the file.
1113 //
1114 SetCursor( hWaitCursor );
1115 SendMessage( hwndEdit, EM_SETSEL, 0, 0 );
1116 do
1117 {
1118 ReplaceSel( FALSE );
1119 bStatus= Search( szSearch );
1120 }
1121 while( bStatus );
1122 SetCursor( hStdCursor );
1123 //
1124 // back to the top of the file.
1125 //
1126 SendMessage( hwndEdit, EM_SETSEL, 0, 0 );
1127 SendMessage( hwndEdit, EM_SCROLLCARET, 0, 0);
1128
1129 }
1130 else if (dwFlags & FR_DIALOGTERM)
1131 hDlgFind = NULL; /* invalidate modeless window handle */
1132 break;
1133 }
1134 return (DefWindowProc(hwnd, message, wParam, lParam));
1135 }
1136 return (0L);
1137}
1138
1139LPTSTR SkipProgramName (LPTSTR lpCmdLine)
1140{
1141 LPTSTR p = lpCmdLine;
1142 BOOL bInQuotes = FALSE;
1143
1144 //
1145 // Skip executable name
1146 //
1147 for (p; *p; p = CharNext(p))
1148 {
1149 if ((*p == TEXT(' ') || *p == TEXT('\t')) && !bInQuotes)
1150 break;
1151
1152 if (*p == TEXT('\"'))
1153 bInQuotes = !bInQuotes;
1154 }
1155
1156 while (*p == TEXT(' ') || *p == TEXT('\t'))
1157 p++;
1158
1159 return (p);
1160}
1161
1162/* ** Main loop */
1163
1164INT WINAPI WinMain(
1165 HINSTANCE hInstance,
1166 HINSTANCE hPrevInstance,
1167 LPSTR lpAnsiCmdLine,
1168 INT cmdShow)
1169{
1170 MSG msg;
1171 VOID (FAR PASCAL *lpfnRegisterPenApp)(WORD, BOOL) = NULL;
1172 LPTSTR lpCmdLine = GetCommandLine ();
1173
1174
1175/* PenWindow registration must be before creating an edit class window.
1176 * Moved here, along with goto statement below for appropriate cleanup.
1177 * 10 July 1991 ClarkC
1178 */
1179 if ((FARPROC) lpfnRegisterPenApp = GetProcAddress((HINSTANCE)(INT_PTR)(GetSystemMetrics(SM_PENWINDOWS)),
1180 "RegisterPenApp"))
1181 (*lpfnRegisterPenApp)(1, TRUE);
1182
1183 if (!NPInit(hInstance, hPrevInstance, SkipProgramName (lpCmdLine), cmdShow))
1184 {
1185 msg.wParam = FALSE;
1186 goto UnRegisterPenWindows;
1187 }
1188
1189 while (GetMessage((LPMSG)&msg, (HWND)NULL, 0, 0))
1190 {
1191 //
1192 // To handle IME status when active KL is changed.
1193 //
1194 if (msg.message == WM_INPUTLANGCHANGEREQUEST) {
1195 //
1196 // WM_INPUTLANGCHANGE will be *sent* to WndProc,
1197 // so there's no chance to catch WM_INPUTLANGCHANGE from the frame window.
1198 // Instead, we post the private message to check the active HKL later.
1199 //
1200 PostMessage(hwndNP, PWM_CHECK_HKL, 0, 0);
1201 }
1202
1203 if (!hDlgFind || !IsDialogMessage(hDlgFind, &msg))
1204 {
1205 if (TranslateAccelerator(hwndNP, hAccel, (LPMSG)&msg) == 0)
1206 {
1207 TranslateMessage ((LPMSG)&msg);
1208 DispatchMessage ((LPMSG)&msg);
1209 }
1210 }
1211 }
1212
1213 /* Clean up any global allocations */
1214
1215 FreeGlobal();
1216
1217 LocalFree( hEdit );
1218
1219UnRegisterPenWindows:
1220
1221 if (lpfnRegisterPenApp)
1222 (*lpfnRegisterPenApp)(1, FALSE);
1223
1224 return (int)(msg.wParam);
1225}
1226
1227/* ** Set Window caption text */
1228void FAR SetTitle( TCHAR *sz )
1229{
1230 TCHAR szWindowText[MAX_PATH+50];
1231 TCHAR szFileName[MAX_PATH];
1232 HANDLE hFindFile;
1233 WIN32_FIND_DATA info;
1234
1235 // if "untitled" then don't do all this work...
1236 if( lstrcmp( sz, szUntitled ) == 0 )
1237 lstrcpy( szWindowText, sz );
1238 else
1239 {
1240 // Get real(file system) name for the file.
1241 hFindFile= FindFirstFile( sz, &info );
1242
1243 if( hFindFile != INVALID_HANDLE_VALUE )
1244 {
1245 lstrcpy( szFileName, info.cFileName );
1246 FindClose( hFindFile );
1247 }
1248 else
1249 lstrcpy( szFileName, sz );
1250
1251 GetFileTitle(szFileName, szWindowText, MAX_PATH);
1252 }
1253
1254 lstrcat(szWindowText, szNpTitle);
1255 SetWindowText(hwndNP, (LPTSTR)szWindowText);
1256}
1257
1258/* ** Given filename which may or maynot include path, return pointer to
1259 filename (not including path part.) */
1260LPTSTR PASCAL far PFileInPath(
1261 LPTSTR sz)
1262{
1263 LPTSTR pch = sz;
1264 LPTSTR psz;
1265
1266 /* Strip path/drive specification from name if there is one */
1267 /* Ripped out AnsiPrev calls. 21 March 1991 clarkc */
1268 for (psz = sz; *psz; psz = CharNext(psz))
1269 {
1270 if ((*psz == TEXT(':')) || (*psz == TEXT('\\')))
1271 pch = psz;
1272 }
1273
1274 if (pch != sz) /* If found slash or colon, return the next character */
1275 pch++; /* increment OK, pch not pointing to DB character */
1276
1277 return(pch);
1278}
1279
1280/* ** Enable or disable menu items according to selection state
1281 This routine is called when user tries to pull down a menu. */
1282
1283VOID NpResetMenu( HWND hwnd )
1284{
1285 LONG lsel;
1286 INT mfcc; /* menuflag for cut, copy */
1287 BOOL fCanUndo;
1288 HANDLE hMenu;
1289 TCHAR msgbuf[20];
1290 BOOL fPaste= FALSE;
1291 UINT uSelState;
1292
1293 hMenu = GetMenu(hwndNP);
1294
1295 // cut, copy and delete only get enabled if there is text selected.
1296
1297 lsel = (LONG)SendMessage(hwndEdit, EM_GETSEL, 0, 0L);
1298 mfcc = LOWORD(lsel) == HIWORD(lsel) ? MF_GRAYED : MF_ENABLED;
1299 EnableMenuItem(GetSubMenu(hMenu, 1), M_CUT, mfcc);
1300 EnableMenuItem(GetSubMenu(hMenu, 1), M_COPY, mfcc);
1301 EnableMenuItem(GetSubMenu(hMenu, 1), M_CLEAR, mfcc);
1302
1303 // check if the selectall is gray (that means the user has already
1304 // done select-all) and it the user has deselected - if so, time
1305 // to re-enable selectall menu.
1306
1307 uSelState = GetMenuState(GetSubMenu(hMenu, 1), M_SELECTALL, MF_BYCOMMAND);
1308 if ((uSelState == MF_GRAYED) && (mfcc == MF_GRAYED))
1309 {
1310 EnableMenuItem(GetSubMenu(hMenu, 1), M_SELECTALL, MF_ENABLED);
1311 }
1312
1313 // paste is enabled if there is text in the clipboard
1314
1315 if( OpenClipboard(hwnd) )
1316 {
1317 fPaste= IsClipboardFormatAvailable(CF_TEXT);
1318 CloseClipboard();
1319 }
1320 EnableMenuItem(GetSubMenu(hMenu, 1), M_PASTE, fPaste ? MF_ENABLED : MF_GRAYED);
1321
1322 // enable Undo only if editcontrol says we can do it.
1323
1324 fCanUndo = (BOOL) SendMessage(hwndEdit, EM_CANUNDO, 0, 0L);
1325 EnableMenuItem(GetSubMenu(hMenu, 1), M_UNDO, fCanUndo ? MF_ENABLED : MF_GRAYED);
1326
1327 // check the word wrap item correctly
1328
1329 CheckMenuItem(GetSubMenu(hMenu, 2), M_WW, fWrap ? MF_CHECKED : MF_UNCHECKED);
1330
1331}
1332
1333
1334void FAR NpWinIniChange(VOID)
1335{
1336 InitLocale ();
1337}
1338
1339/* ** Scan sz1 for merge spec. If found, insert string sz2 at that point.
1340 Then append rest of sz1 NOTE! Merge spec guaranteed to be two chars.
1341 returns TRUE if it does a merge, false otherwise. */
1342BOOL MergeStrings(
1343 TCHAR *szSrc,
1344 TCHAR *szMerge,
1345 TCHAR *szDst)
1346 {
1347 register TCHAR *pchSrc;
1348 register TCHAR *pchDst;
1349
1350 pchSrc = szSrc;
1351 pchDst = szDst;
1352
1353 /* Find merge spec if there is one. */
1354 while ( *pchSrc != chMerge)
1355 {
1356 *pchDst++ = *pchSrc;
1357
1358 /* If we reach end of string before merge spec, just return. */
1359 if (!*pchSrc++)
1360 return FALSE;
1361
1362 }
1363
1364 /* If merge spec found, insert sz2 there. (check for null merge string */
1365 if (szMerge)
1366 {
1367 while (*szMerge)
1368 *pchDst++ = *szMerge++;
1369 }
1370
1371 /* Jump over merge spec */
1372 pchSrc++,pchSrc++;
1373
1374 /* Now append rest of Src String */
1375 while (*pchDst++ = *pchSrc++);
1376 return TRUE;
1377
1378 }
1379
1380/* ** Post a message box */
1381INT FAR AlertBox(
1382 HWND hwndParent,
1383 TCHAR *szCaption,
1384 TCHAR *szText1,
1385 TCHAR *szText2,
1386 UINT style)
1387{
1388 INT iResult; // result of function
1389 INT iAllocSize; // size needed for message
1390 TCHAR* pszMessage; // combined message
1391
1392 // Allocate a message buffer assuming there will be a merge.
1393 // If we cannot do the allocation, tell the user something
1394 // related to the original problem. (not the allocation failure)
1395 // Then pray that MessageBox can get enough memory to actually work.
1396
1397 iAllocSize= (lstrlen(szText1) + (szText2 ? lstrlen(szText2) : 0) + 1 ) * sizeof(TCHAR);
1398
1399 pszMessage= (TCHAR*) LocalAlloc( LPTR, iAllocSize );
1400
1401 if( pszMessage )
1402 {
1403 MergeStrings( szText1, szText2, pszMessage );
1404 iResult= MessageBox( hwndParent, pszMessage, szCaption, style );
1405 LocalFree( (HLOCAL) pszMessage );
1406 }
1407 else
1408 {
1409 iResult= MessageBox( hwndParent, szText1, szCaption, style );
1410 }
1411
1412 return( iResult );
1413}
1414
1415// SignalCommDlgError
1416//
1417// If a common dialog error occurred, put up reasonable message box.
1418//
1419// returns: TRUE if error occurred, FALSE if no error.
1420//
1421
1422typedef struct tagMAPERROR
1423{
1424 DWORD rc; // return code from CommDlgExtendedError()
1425 PTCHAR* ppszMsg; // text of message pointer
1426} MAPERROR;
1427
1428// errors not in this list get generic "common dialog error %x" message.
1429static TCHAR* szNull= TEXT("");
1430
1431MAPERROR maperror[]=
1432{
1433 CDERR_DIALOGFAILURE, &szErrSpace,
1434 CDERR_INITIALIZATION, &szCommDlgInitErr,
1435 CDERR_MEMLOCKFAILURE, &szPDIE,
1436 CDERR_LOADSTRFAILURE, &szErrSpace,
1437 CDERR_FINDRESFAILURE, &szErrSpace,
1438 PDERR_LOADDRVFAILURE, &szLoadDrvFail,
1439 PDERR_GETDEVMODEFAIL, &szErrSpace,
1440 PDERR_NODEFAULTPRN, &szNull, // don't report; common dialog does already
1441};
1442
1443BOOL SignalCommDlgError(VOID)
1444{
1445 DWORD rc; // return code
1446 TCHAR* pszMsg; // message
1447 INT i;
1448 TCHAR szBuf[200]; // just for common dialog failure
1449
1450 rc= CommDlgExtendedError();
1451
1452 // no failure - just return
1453
1454 if( rc == 0 )
1455 {
1456 return FALSE;
1457 }
1458
1459 // some sort of error - pick up message
1460
1461 pszMsg= NULL;
1462 for( i=0; i< sizeof(maperror)/sizeof(maperror[0]); i++ )
1463 {
1464 if( rc == maperror[i].rc )
1465 {
1466 pszMsg= *maperror[i].ppszMsg;
1467 }
1468 }
1469
1470 // if no known mapping - tell user the actual return code
1471 // this may be a bit confusing, but rare hopefully.
1472
1473 if( !pszMsg )
1474 {
1475 wsprintf( szBuf, szCommDlgErr, rc ); // fill in error code
1476 pszMsg= szBuf;
1477 }
1478
1479 // popup if there is any message to give user
1480
1481 if( *pszMsg )
1482 {
1483 MessageBox(hwndNP, pszMsg, szNN, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);
1484 }
1485
1486 return TRUE;
1487
1488}
1489
1490// ReplaceSel
1491//
1492// Replace the current selection with string from FR struct
1493// if the current selection matches our search string.
1494//
1495// MLE will show selection if bView is true.
1496//
1497
1498
1499VOID ReplaceSel( BOOL bView )
1500{
1501 DWORD StartSel; // start of selected text
1502 DWORD EndSel; // end of selected text
1503
1504 HANDLE hEText;
1505 TCHAR* pStart;
1506 DWORD ReplaceWithLength; // length of replacement string
1507 DWORD FindWhatLength;
1508
1509 ReplaceWithLength= lstrlen(FR.lpstrReplaceWith);
1510 FindWhatLength= lstrlen(FR.lpstrFindWhat);
1511
1512 SendMessage( hwndEdit, EM_GETSEL, (WPARAM) &StartSel, (LPARAM) &EndSel );
1513 hEText= (HANDLE) SendMessage( hwndEdit, EM_GETHANDLE, 0, 0 );
1514 if( !hEText ) // silently return if we can't get it
1515 {
1516 return;
1517 }
1518
1519 pStart= LocalLock( hEText );
1520 if( !pStart )
1521 {
1522 return;
1523 }
1524
1525 if( (EndSel-StartSel) == FindWhatLength )
1526 {
1527 if( (fCase &&
1528 !_tcsncmp( FR.lpstrFindWhat, pStart+StartSel, FindWhatLength) ) ||
1529 (!fCase &&
1530 ( 2 == CompareString(LOCALE_USER_DEFAULT,
1531 NORM_IGNORECASE | SORT_STRINGSORT | NORM_STOP_ON_NULL,
1532 FR.lpstrFindWhat, FindWhatLength,
1533 pStart+StartSel, FindWhatLength ) ) ) )
1534 {
1535 SendMessage( hwndEdit, EM_REPLACESEL,
1536 TRUE, (LPARAM) FR.lpstrReplaceWith);
1537 SendMessage( hwndEdit, EM_SETSEL,
1538 StartSel, StartSel+ReplaceWithLength );
1539
1540 if( bView )
1541 {
1542 SendMessage(hwndEdit, EM_SCROLLCARET, 0, 0);
1543 }
1544 }
1545 }
1546
1547 LocalUnlock( hEText );
1548}
1549
1550// GotoDlgProc
1551//
1552// Handle the Goto Dialog window processing
1553//
1554// Returns:
1555//
1556// 1 if successfull
1557// 0 if not (cancelled)
1558//
1559// Modifies global lGotoLine
1560//
1561
1562const DWORD s_GotoHelpIDs[] = {
1563 IDC_GOTO, IDH_GOTO,
1564 0, 0
1565};
1566
1567#define GOTOBUFSIZE 100
1568INT_PTR CALLBACK GotoDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
1569{
1570 TCHAR szBuf[GOTOBUFSIZE];
1571 UINT LineNum;
1572 DWORD SelStart, SelEnd;
1573 POINT pt;
1574 INT id;
1575
1576 switch (message)
1577 {
1578 //
1579 // initialize input field to size of file
1580 //
1581 case WM_INITDIALOG:
1582 SendMessage(hwndEdit,EM_GETSEL,(WPARAM) &SelStart,(WPARAM)&SelEnd);
1583
1584 // the line numbers are 1 based instead 0 based. hence add 1.
1585 LineNum= (UINT)SendMessage( hwndEdit, EM_LINEFROMCHAR, SelStart, 0 ) + 1;
1586 wsprintf(szBuf, TEXT("%d"), LineNum);
1587 SetDlgItemText( hDlg, IDC_GOTO, szBuf );
1588 SetFocus( hDlg );
1589 return TRUE;
1590 break;
1591
1592 // context sensitive help.
1593 case WM_HELP:
1594 WinHelp(((LPHELPINFO) lParam)-> hItemHandle, szHelpFile,
1595 HELP_WM_HELP, (ULONG_PTR) (LPVOID) s_GotoHelpIDs);
1596 break;
1597
1598 case WM_CONTEXTMENU:
1599
1600 WinHelp((HWND) wParam, szHelpFile, HELP_CONTEXTMENU,
1601 (ULONG_PTR) (LPVOID) s_GotoHelpIDs);
1602 break;
1603
1604 case WM_COMMAND:
1605
1606 switch (LOWORD(wParam))
1607 {
1608 UINT CharIndex;
1609
1610 case IDC_GOTO:
1611 return TRUE;
1612 break;
1613
1614 case IDOK:
1615 GetDlgItemText( hDlg, IDC_GOTO, szBuf, GOTOBUFSIZE );
1616
1617 // convert all unicode numbers to range L'0' to L'9'
1618
1619 FoldString( MAP_FOLDDIGITS, szBuf, -1, szBuf, GOTOBUFSIZE);
1620 lGotoLine= _ttol( szBuf );
1621
1622 //
1623 // see if valid line number
1624 //
1625
1626 CharIndex= (UINT)SendMessage( hwndEdit,
1627 EM_LINEINDEX,
1628 lGotoLine-1,
1629 0);
1630 if( lGotoLine > 0 && CharIndex != -1 )
1631 {
1632 EndDialog(hDlg, 0); // successfull
1633 return TRUE;
1634 }
1635
1636 //
1637 // Invalid line number
1638 // warning user and set to reasonable value
1639 //
1640
1641 MessageBox( hDlg, szLineTooLarge, szLineError, MB_OK );
1642
1643 LineNum= (UINT)SendMessage( hwndEdit, EM_GETLINECOUNT, 0, 0 );
1644 wsprintf(szBuf, TEXT("%d"), LineNum);
1645 SetDlgItemText( hDlg, IDC_GOTO, szBuf );
1646 SetFocus( hDlg );
1647 break;
1648
1649 case IDCANCEL :
1650 EndDialog(hDlg, 1 ); // cancelled
1651 return TRUE;
1652 break;
1653
1654 default:
1655
1656 break;
1657
1658 } // switch (wParam)
1659
1660 break;
1661
1662 default:
1663
1664 break;
1665
1666 } // switch (message)
1667
1668
1669 return FALSE; // Didn't process a message
1670
1671
1672} // GotoDlgProc()