Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2204 lines
73 KiB

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