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.

1664 lines
52 KiB

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