Source code of Windows XP (NT5)
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.

2074 lines
63 KiB

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