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.

827 lines
24 KiB

  1. /*
  2. * sxspadfile.c - Routines for file i/o for sxspad
  3. * Copyright (C) 1984-2000 Microsoft Inc.
  4. */
  5. #include "precomp.h"
  6. HANDLE hFirstMem;
  7. CHAR BOM_UTF8[3]= {(BYTE) 0xEF, (BYTE) 0xBB, (BYTE)0xBF};
  8. //****************************************************************
  9. //
  10. // ReverseEndian
  11. //
  12. // Purpose: copies unicode character from one endian source
  13. // to another.
  14. //
  15. // may work on lpDst == lpSrc
  16. //
  17. VOID ReverseEndian( PTCHAR lpDst, PTCHAR lpSrc, DWORD nChars )
  18. {
  19. DWORD cnt;
  20. for( cnt=0; cnt < nChars; cnt++,lpDst++,lpSrc++ )
  21. {
  22. *lpDst= (TCHAR) (((*lpSrc<<8) & 0xFF00) + ((*lpSrc>>8)&0xFF));
  23. }
  24. }
  25. //*****************************************************************
  26. //
  27. // AnsiWriteFile()
  28. //
  29. // Purpose : To simulate the effects of _lwrite() in a Unicode
  30. // environment by converting to ANSI buffer and
  31. // writing out the ANSI text.
  32. // Returns : TRUE is successful, FALSE if not
  33. // GetLastError() will have the error code.
  34. //
  35. //*****************************************************************
  36. BOOL AnsiWriteFile(HANDLE hFile, // file to write to
  37. UINT uCodePage, // code page to convert unicode to
  38. LPVOID lpBuffer, // unicode buffer
  39. DWORD nChars, // number of unicode chars
  40. DWORD nBytes ) // number of ascii chars to produce
  41. {
  42. LPSTR lpAnsi; // pointer to allocate buffer
  43. BOOL Done; // status from write (returned)
  44. BOOL fDefCharUsed; // flag that conversion wasn't perfect
  45. BOOL* pfDefCharUsed; // pointer to flag
  46. DWORD nBytesWritten; // number of bytes written
  47. lpAnsi= (LPSTR) LocalAlloc( LPTR, nBytes + 1 );
  48. if( !lpAnsi )
  49. {
  50. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  51. return (FALSE);
  52. }
  53. pfDefCharUsed= NULL;
  54. if( (uCodePage != CP_UTF8 ) && (uCodePage != CP_UTF7) )
  55. {
  56. pfDefCharUsed= &fDefCharUsed;
  57. }
  58. WideCharToMultiByte( uCodePage, // code page
  59. 0, // performance and mapping flags
  60. (LPWSTR) lpBuffer,// wide char buffer
  61. nChars, // chars in wide char buffer
  62. lpAnsi, // resultant ascii string
  63. nBytes, // size of ascii string buffer
  64. NULL, // char to sub. for unmapped chars
  65. pfDefCharUsed); // flag to set if default char used
  66. Done= WriteFile( hFile, lpAnsi, nBytes, &nBytesWritten, NULL );
  67. LocalFree( lpAnsi );
  68. return (Done);
  69. } // end of AnsiWriteFile()
  70. // not used anymore ..
  71. #if 0
  72. /* IsSxspadEmpty
  73. * Check if the edit control is empty. If it is, put up a messagebox
  74. * offering to delete the file if it already exists, or just warning
  75. * that it can't be saved if it doesn't already exist
  76. *
  77. * Return value: TRUE, warned, no further action should take place
  78. * FALSE, not warned, or further action is necessary
  79. * 30 July 1991 Clark Cyr
  80. */
  81. INT FAR IsSxspadEmpty (HWND hwndParent, TCHAR *szFileSave, BOOL fNoDelete)
  82. {
  83. unsigned nChars;
  84. INT nRetVal = FALSE;
  85. nChars = (unsigned) SendMessage (hwndEdit, WM_GETTEXTLENGTH, 0, (LPARAM)0);
  86. /* If sxspad is empty, complain and delete file if necessary. */
  87. if (!nChars)
  88. {
  89. if (fNoDelete)
  90. nRetVal = MessageBox(hwndParent, szCSEF, szNN,
  91. MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION);
  92. else if ((nRetVal = AlertBox(hwndSP, szNN, szEFD, szFileSave,
  93. MB_APPLMODAL | MB_OKCANCEL | MB_ICONEXCLAMATION)) == IDOK)
  94. {
  95. DeleteFile (szFileSave);
  96. New(FALSE);
  97. }
  98. }
  99. return nRetVal;
  100. }
  101. #endif
  102. #define NOTUSED 0
  103. static DWORD dwStartSel; // saved start of selection
  104. static DWORD dwEndSel; // saved end of selection
  105. VOID ClearFmt(VOID)
  106. {
  107. DWORD SelStart;
  108. DWORD SelEnd;
  109. SendMessage( hwndEdit, EM_GETSEL, (WPARAM) &dwStartSel, (LPARAM) &dwEndSel );
  110. SendMessage( hwndEdit, EM_SETSEL, (WPARAM) 0, (LPARAM) 0 ); // this is always legal
  111. // should we scrollcaret here?
  112. SendMessage( hwndEdit, EM_FMTLINES, (WPARAM)FALSE, NOTUSED ); // remove soft EOLs
  113. }
  114. VOID RestoreFmt(VOID)
  115. {
  116. UINT CharIndex;
  117. SendMessage( hwndEdit, EM_FMTLINES, (WPARAM)TRUE, NOTUSED ); // restore soft EOLS
  118. CharIndex= (UINT) SendMessage( hwndEdit, EM_SETSEL, (WPARAM) dwStartSel, (LPARAM) dwEndSel);
  119. }
  120. /* Save sxspad file to disk. szFileSave points to filename. fSaveAs
  121. is TRUE iff we are being called from SaveAsDlgProc. This implies we must
  122. open file on current directory, whether or not it already exists there
  123. or somewhere else in our search path.
  124. Assumes that text exists within hwndEdit. 30 July 1991 Clark Cyr
  125. */
  126. BOOL FAR SaveFile (HWND hwndParent, TCHAR *szFileSave, BOOL fSaveAs )
  127. {
  128. LPTSTR lpch;
  129. UINT nChars;
  130. BOOL flag;
  131. BOOL fNew = FALSE;
  132. BOOL fDefCharUsed = FALSE;
  133. BOOL* pfDefCharUsed;
  134. static WCHAR wchBOM = BYTE_ORDER_MARK;
  135. static WCHAR wchRBOM= REVERSE_BYTE_ORDER_MARK;
  136. HLOCAL hEText; // handle to MLE text
  137. DWORD nBytesWritten; // number of bytes written
  138. DWORD nAsciiLength; // length of equivalent ascii file
  139. UINT cpTemp= CP_ACP; // code page to convert to
  140. /* If saving to an existing file, make sure correct disk is in drive */
  141. if (!fSaveAs)
  142. {
  143. fp= CreateFile( szFileSave, // name of file
  144. GENERIC_READ|GENERIC_WRITE, // access mode
  145. FILE_SHARE_READ, // share mode
  146. NULL, // security descriptor
  147. OPEN_EXISTING, // how to create
  148. FILE_ATTRIBUTE_NORMAL, // file attributes
  149. NULL); // hnd of file with attrs
  150. }
  151. else
  152. {
  153. // Carefully open the file. Do not truncate it if it exists.
  154. // set the fNew flag if it had to be created.
  155. // We do all this in case of failures later in the process.
  156. fp= CreateFile( szFileSave, // name of file
  157. GENERIC_READ|GENERIC_WRITE, // access mode
  158. FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
  159. NULL, // security descriptor
  160. OPEN_ALWAYS, // how to create
  161. FILE_ATTRIBUTE_NORMAL, // file attributes
  162. NULL); // hnd of file with attrs
  163. if( fp != INVALID_HANDLE_VALUE )
  164. {
  165. fNew= (GetLastError() != ERROR_ALREADY_EXISTS );
  166. }
  167. }
  168. if( fp == INVALID_HANDLE_VALUE )
  169. {
  170. if (fSaveAs)
  171. AlertBox( hwndParent, szNN, szCREATEERR, szFileSave,
  172. MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION);
  173. return FALSE;
  174. }
  175. // if wordwrap, remove soft carriage returns
  176. // Also move the cursor to a safe place to get around MLE bugs
  177. if( fWrap )
  178. {
  179. ClearFmt();
  180. }
  181. /* Must get text length after formatting */
  182. nChars = (UINT)SendMessage (hwndEdit, WM_GETTEXTLENGTH, 0, (LPARAM)0);
  183. hEText= (HANDLE) SendMessage( hwndEdit, EM_GETHANDLE, 0,0 );
  184. if( !hEText || !(lpch= (LPTSTR) LocalLock(hEText) ))
  185. {
  186. AlertUser_FileFail( szFileSave );
  187. goto CleanUp;
  188. }
  189. // Determine the SaveAs file type, and write the appropriate BOM.
  190. // If the filetype is UTF-8 or Ansi, do the conversion.
  191. switch(g_ftSaveAs)
  192. {
  193. case FT_UNICODE:
  194. WriteFile( fp, &wchBOM, ByteCountOf(1), &nBytesWritten, NULL );
  195. flag= WriteFile(fp, lpch, ByteCountOf(nChars), &nBytesWritten, NULL);
  196. break;
  197. case FT_UNICODEBE:
  198. WriteFile( fp, &wchRBOM, ByteCountOf(1), &nBytesWritten, NULL );
  199. ReverseEndian( lpch, lpch,nChars );
  200. flag= WriteFile(fp, lpch, ByteCountOf(nChars), &nBytesWritten, NULL);
  201. ReverseEndian( lpch, lpch, nChars );
  202. break;
  203. // If it UTF-8, write the BOM (3 bytes), set the code page and fall
  204. // through to the default case.
  205. case FT_UTF8:
  206. WriteFile( fp, &BOM_UTF8, 3, &nBytesWritten, NULL );
  207. cpTemp= CP_UTF8;
  208. // fall through to convert and write the file
  209. default:
  210. pfDefCharUsed= NULL;
  211. if (g_ftSaveAs != FT_UTF8)
  212. {
  213. //
  214. // Always use the current locale code page to do the translation
  215. // If the user changes locales, they will need to know what locale
  216. // this version of the file was saved with. Since we don't save that
  217. // information, the user may be backed into a corner. Unicode would
  218. // save his bacon.
  219. //
  220. cpTemp= GetACP();
  221. pfDefCharUsed= &fDefCharUsed;
  222. }
  223. nAsciiLength= WideCharToMultiByte( cpTemp,
  224. 0,
  225. (LPWSTR)lpch,
  226. nChars,
  227. NULL,
  228. 0,
  229. NULL,
  230. pfDefCharUsed);
  231. if( fDefCharUsed )
  232. {
  233. if ( AlertBox( hwndParent, szNN, szErrUnicode, szFileSave,
  234. MB_APPLMODAL|MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL)
  235. goto CleanUp;
  236. }
  237. flag= AnsiWriteFile( fp, cpTemp, lpch, nChars, nAsciiLength );
  238. break;
  239. }
  240. if (!flag)
  241. {
  242. SetCursor(hStdCursor); /* display normal cursor */
  243. AlertUser_FileFail( szFileSave );
  244. CleanUp:
  245. SetCursor( hStdCursor );
  246. CloseHandle (fp); fp=INVALID_HANDLE_VALUE;
  247. if( hEText )
  248. LocalUnlock( hEText );
  249. if (fNew)
  250. DeleteFile (szFileSave);
  251. /* if wordwrap, insert soft carriage returns */
  252. if (fWrap)
  253. {
  254. RestoreFmt();
  255. }
  256. return FALSE;
  257. }
  258. else
  259. {
  260. SetEndOfFile (fp);
  261. SendMessage (hwndEdit, EM_SETMODIFY, FALSE, 0L);
  262. SetTitle (szFileSave);
  263. fUntitled = FALSE;
  264. }
  265. CloseHandle (fp); fp=INVALID_HANDLE_VALUE;
  266. if( hEText )
  267. LocalUnlock( hEText );
  268. /* if wordwrap, insert soft carriage returns */
  269. if (fWrap)
  270. {
  271. RestoreFmt();
  272. }
  273. /* Display the hour glass cursor */
  274. SetCursor(hStdCursor);
  275. return TRUE;
  276. } // end of SaveFile()
  277. /* Read contents of file from disk.
  278. * Do any conversions required.
  279. * File is already open, referenced by handle fp
  280. * Close the file when done.
  281. * If typeFlag>=0, then use it as filetype, otherwise do automagic guessing.
  282. */
  283. BOOL FAR LoadFile (TCHAR * sz, INT typeFlag )
  284. {
  285. UINT len, i, nChars;
  286. LPTSTR lpch=NULL;
  287. LPTSTR lpBuf;
  288. LPSTR lpBufAfterBOM;
  289. BOOL fLog=FALSE;
  290. TCHAR* p;
  291. TCHAR szSave[MAX_PATH]; /* Private copy of current filename */
  292. BOOL bUnicode=FALSE; /* true if file detected as unicode */
  293. BOOL bUTF8=FALSE; /* true if file detected as UTF-8 */
  294. DWORD nBytesRead; // number of bytes read
  295. BY_HANDLE_FILE_INFORMATION fiFileInfo;
  296. BOOL bStatus; // boolean status
  297. HLOCAL hNewEdit=NULL; // new handle for edit buffer
  298. HANDLE hMap; // file mapping handle
  299. TCHAR szNullFile[2]; // fake null mapped file
  300. INT cpTemp = CP_ACP;
  301. SP_FILETYPE ftOpenedAs=FT_UNKNOWN;
  302. if( fp == INVALID_HANDLE_VALUE )
  303. {
  304. AlertUser_FileFail( sz );
  305. return (FALSE);
  306. }
  307. //
  308. // Get size of file
  309. // We use this heavy duty GetFileInformationByHandle API
  310. // because it finds bugs. It takes longer, but it only is
  311. // called at user interaction time.
  312. //
  313. bStatus= GetFileInformationByHandle( fp, &fiFileInfo );
  314. len= (UINT) fiFileInfo.nFileSizeLow;
  315. // NT may delay giving this status until the file is accessed.
  316. // i.e. the open succeeds, but operations may fail on damaged files.
  317. if( !bStatus )
  318. {
  319. AlertUser_FileFail( sz );
  320. CloseHandle( fp ); fp=INVALID_HANDLE_VALUE;
  321. return( FALSE );
  322. }
  323. // If the file is too big, fail now.
  324. // -1 not valid because we need a zero on the end.
  325. if( len == -1 || fiFileInfo.nFileSizeHigh != 0 )
  326. {
  327. AlertBox( hwndSP, szNN, szErrSpace, sz,
  328. MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION );
  329. CloseHandle (fp); fp=INVALID_HANDLE_VALUE;
  330. return (FALSE);
  331. }
  332. SetCursor(hWaitCursor); // physical I/O takes time
  333. //
  334. // Create a file mapping so we don't page the file to
  335. // the pagefile. This is a big win on small ram machines.
  336. //
  337. if( len != 0 )
  338. {
  339. lpBuf= NULL;
  340. hMap= CreateFileMapping( fp, NULL, PAGE_READONLY, 0, len, NULL );
  341. if( hMap )
  342. {
  343. lpBuf= MapViewOfFile( hMap, FILE_MAP_READ, 0,0,len);
  344. CloseHandle( hMap );
  345. }
  346. }
  347. else // file mapping doesn't work on zero length files
  348. {
  349. lpBuf= (LPTSTR) &szNullFile;
  350. *lpBuf= 0; // null terminate
  351. }
  352. CloseHandle( fp ); fp=INVALID_HANDLE_VALUE;
  353. if( lpBuf == NULL )
  354. {
  355. SetCursor( hStdCursor );
  356. AlertBox( hwndSP, szNN, szErrSpace, sz,
  357. MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION );
  358. return( FALSE );
  359. }
  360. //
  361. // protect access to the mapped file with a try/except so we
  362. // can detect I/O errors.
  363. //
  364. //
  365. // WARNING: be very very careful. This code is pretty fragile.
  366. // Files across the network, or RSM files (tape) may throw excepts
  367. // at random points in this code. Anywhere the code touches the
  368. // memory mapped file can cause an AV. Make sure variables are
  369. // in consistent state if an exception is thrown. Be very careful
  370. // with globals.
  371. __try
  372. {
  373. /* Determine the file type and number of characters
  374. * If the user overrides, use what is specified.
  375. * Otherwise, we depend on 'IsTextUnicode' getting it right.
  376. * If it doesn't, bug IsTextUnicode.
  377. */
  378. lpBufAfterBOM= (LPSTR) lpBuf;
  379. if( typeFlag == FT_UNKNOWN )
  380. {
  381. switch(*lpBuf)
  382. {
  383. case BYTE_ORDER_MARK:
  384. bUnicode= TRUE;
  385. ftOpenedAs= FT_UNICODE;
  386. // don't count the BOM.
  387. nChars= len / sizeof(TCHAR) -1;
  388. break;
  389. case REVERSE_BYTE_ORDER_MARK:
  390. bUnicode= TRUE;
  391. ftOpenedAs= FT_UNICODEBE;
  392. // don't count the BOM.
  393. nChars= len / sizeof(TCHAR) -1;
  394. break;
  395. // UTF bom has 3 bytes; if it doesn't have UTF BOM just fall through ..
  396. case BOM_UTF8_HALF:
  397. if (len > 2 && ((BYTE) *(((LPSTR)lpBuf)+2) == BOM_UTF8_2HALF) )
  398. {
  399. bUTF8= TRUE;
  400. cpTemp= CP_UTF8;
  401. ftOpenedAs= FT_UTF8;
  402. // Ignore the first three bytes.
  403. lpBufAfterBOM= (LPSTR)lpBuf + 3;
  404. len -= 3;
  405. break;
  406. }
  407. default:
  408. // Is the file unicode without BOM ?
  409. if ((bUnicode= IsInputTextUnicode((LPSTR) lpBuf, len)))
  410. {
  411. ftOpenedAs= FT_UNICODE;
  412. nChars= len / sizeof(TCHAR);
  413. }
  414. else
  415. {
  416. // Is the file UTF-8 even though it doesn't have UTF-8 BOM.
  417. if ((bUTF8= IsTextUTF8((LPSTR) lpBuf, len)))
  418. {
  419. ftOpenedAs= FT_UTF8;
  420. cpTemp= CP_UTF8;
  421. }
  422. // well, not it must be an ansi file!
  423. else
  424. {
  425. ftOpenedAs= FT_ANSI;
  426. cpTemp= CP_ACP;
  427. }
  428. }
  429. break;
  430. }
  431. }
  432. // find out no. of chars present in the string.
  433. if (!bUnicode)
  434. {
  435. nChars = MultiByteToWideChar (cpTemp,
  436. 0,
  437. (LPSTR)lpBufAfterBOM,
  438. len,
  439. NULL,
  440. 0);
  441. }
  442. //
  443. // Don't display text until all done.
  444. //
  445. SendMessage (hwndEdit, WM_SETREDRAW, (WPARAM)FALSE, (LPARAM)0);
  446. // Reset selection to 0
  447. SendMessage(hwndEdit, EM_SETSEL, 0, 0L);
  448. SendMessage(hwndEdit, EM_SCROLLCARET, 0, 0);
  449. // resize the edit buffer
  450. // if we can't resize the memory, inform the user
  451. if (!(hNewEdit= LocalReAlloc(hEdit,ByteCountOf(nChars + 1),LMEM_MOVEABLE)))
  452. {
  453. /* Bug 7441: New() causes szFileName to be set to "Untitled". Save a
  454. * copy of the filename to pass to AlertBox.
  455. * 17 November 1991 Clark R. Cyr
  456. */
  457. lstrcpy(szSave, sz);
  458. New(FALSE);
  459. /* Display the hour glass cursor */
  460. SetCursor(hStdCursor);
  461. AlertBox( hwndSP, szNN, szFTL, szSave,
  462. MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION);
  463. if( lpBuf != (LPTSTR) &szNullFile )
  464. {
  465. UnmapViewOfFile( lpBuf );
  466. }
  467. // let user see old text
  468. SendMessage (hwndEdit, WM_SETREDRAW, (WPARAM)FALSE, (LPARAM)0);
  469. return FALSE;
  470. }
  471. /* Transfer file from temporary buffer to the edit buffer */
  472. lpch= (LPTSTR) LocalLock(hNewEdit);
  473. if( bUnicode )
  474. {
  475. /* skip the Byte Order Mark */
  476. if (*lpBuf == BYTE_ORDER_MARK)
  477. {
  478. CopyMemory (lpch, lpBuf + 1, ByteCountOf(nChars));
  479. }
  480. else if( *lpBuf == REVERSE_BYTE_ORDER_MARK )
  481. {
  482. ReverseEndian( lpch, lpBuf+1, nChars );
  483. }
  484. else
  485. {
  486. CopyMemory (lpch, lpBuf, ByteCountOf(nChars));
  487. }
  488. }
  489. else
  490. {
  491. nChars = MultiByteToWideChar (cpTemp,
  492. 0,
  493. (LPSTR)lpBufAfterBOM,
  494. len,
  495. (LPWSTR)lpch,
  496. nChars);
  497. }
  498. g_ftOpenedAs= ftOpenedAs; // got everything; update global safe now
  499. }
  500. __except(EXCEPTION_EXECUTE_HANDLER)
  501. {
  502. AlertBox( hwndSP, szNN, szDiskError, sz,
  503. MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION );
  504. nChars= 0; // don't deal with it.
  505. }
  506. /* Free file mapping */
  507. if( lpBuf != (LPTSTR) &szNullFile )
  508. {
  509. UnmapViewOfFile( lpBuf );
  510. }
  511. if( lpch )
  512. {
  513. // Fix any NUL character that came in from the file to be spaces.
  514. for (i = 0, p = lpch; i < nChars; i++, p++)
  515. {
  516. if( *p == (TCHAR) 0 )
  517. *p= TEXT(' ');
  518. }
  519. // null terminate it. Safe even if nChars==0 because it is 1 TCHAR bigger
  520. *(lpch+nChars)= (TCHAR) 0; /* zero terminate the thing */
  521. // Set 'fLog' if first characters in file are ".LOG"
  522. fLog= *lpch++ == TEXT('.') && *lpch++ == TEXT('L') &&
  523. *lpch++ == TEXT('O') && *lpch == TEXT('G');
  524. }
  525. if( hNewEdit )
  526. {
  527. LocalUnlock( hNewEdit );
  528. // now it is safe to set the global edit handle
  529. hEdit= hNewEdit;
  530. }
  531. lstrcpy( szFileName, sz );
  532. SetTitle( sz );
  533. fUntitled= FALSE;
  534. /* Pass handle to edit control. This is more efficient than WM_SETTEXT
  535. * which would require twice the buffer space.
  536. */
  537. /* Bug 7443: If EM_SETHANDLE doesn't have enough memory to complete things,
  538. * it will send the EN_ERRSPACE message. If this happens, don't put up the
  539. * out of memory notification, put up the file to large message instead.
  540. * 17 November 1991 Clark R. Cyr
  541. */
  542. dwEmSetHandle = SETHANDLEINPROGRESS;
  543. SendMessage (hwndEdit, EM_SETHANDLE, (WPARAM)hEdit, (LPARAM)0);
  544. if (dwEmSetHandle == SETHANDLEFAILED)
  545. {
  546. SetCursor(hStdCursor);
  547. dwEmSetHandle = 0;
  548. AlertBox( hwndSP, szNN, szFTL, sz,MB_APPLMODAL|MB_OK|MB_ICONEXCLAMATION);
  549. New (FALSE);
  550. SendMessage (hwndEdit, WM_SETREDRAW, (WPARAM)TRUE, (LPARAM)0);
  551. return (FALSE);
  552. }
  553. dwEmSetHandle = 0;
  554. PostMessage (hwndEdit, EM_LIMITTEXT, (WPARAM)CCHSPMAX, 0L);
  555. /* If file starts with ".LOG" go to end and stamp date time */
  556. if (fLog)
  557. {
  558. SendMessage( hwndEdit, EM_SETSEL, (WPARAM)nChars, (LPARAM)nChars);
  559. SendMessage( hwndEdit, EM_SCROLLCARET, 0, 0);
  560. InsertDateTime(TRUE);
  561. }
  562. /* Move vertical thumb to correct position */
  563. SetScrollPos (hwndSP,
  564. SB_VERT,
  565. (int) SendMessage (hwndEdit, WM_VSCROLL, EM_GETTHUMB, 0L),
  566. TRUE);
  567. /* Now display text */
  568. SendMessage( hwndEdit, WM_SETREDRAW, (WPARAM)TRUE, (LPARAM)0 );
  569. InvalidateRect( hwndEdit, (LPRECT)NULL, TRUE );
  570. UpdateWindow( hwndEdit );
  571. SetCursor(hStdCursor);
  572. return( TRUE );
  573. } // end of LoadFile()
  574. /* New Command - reset everything
  575. */
  576. void FAR New (BOOL fCheck)
  577. {
  578. HANDLE hTemp;
  579. TCHAR* pSz;
  580. if (!fCheck || CheckSave (FALSE))
  581. {
  582. SendMessage( hwndEdit, WM_SETTEXT, (WPARAM)0, (LPARAM)TEXT("") );
  583. fUntitled= TRUE;
  584. lstrcpy( szFileName, szUntitled );
  585. SetTitle(szFileName );
  586. SendMessage( hwndEdit, EM_SETSEL, 0, 0L );
  587. SendMessage( hwndEdit, EM_SCROLLCARET, 0, 0 );
  588. // resize of 1 NULL character i.e. zero length
  589. hTemp= LocalReAlloc( hEdit, sizeof(TCHAR), LMEM_MOVEABLE );
  590. if( hTemp )
  591. {
  592. hEdit= hTemp;
  593. }
  594. // null terminate the buffer. LocalReAlloc won't do it
  595. // because in all cases it is not growing which is the
  596. // only time it would zero out anything.
  597. pSz= LocalLock( hEdit );
  598. *pSz= TEXT('\0');
  599. LocalUnlock( hEdit );
  600. SendMessage (hwndEdit, EM_SETHANDLE, (WPARAM)hEdit, 0L);
  601. szSearch[0] = (TCHAR) 0;
  602. }
  603. } // end of New()
  604. /* If sz does not have extension, append ".Manifest"
  605. * This function is useful for getting to undecorated filenames
  606. * that setup apps use. DO NOT CHANGE the extension. Too many setup
  607. * apps depend on this functionality.
  608. */
  609. void FAR AddExt( TCHAR* sz )
  610. {
  611. TCHAR* pch1;
  612. int ch;
  613. DWORD dwSize;
  614. dwSize= lstrlen(sz);
  615. pch1= sz + dwSize; // point to end
  616. ch= *pch1;
  617. while( ch != TEXT('.') && ch != TEXT('\\') && ch != TEXT(':') && pch1 > sz)
  618. {
  619. //
  620. // backup one character. Do NOT use CharPrev because
  621. // it sometimes doesn't actually backup. Some Thai
  622. // tone marks fit this category but there seems to be others.
  623. // This is safe since it will stop at the beginning of the
  624. // string or on delimiters listed above. bug# 139374 2/13/98
  625. //
  626. // pch1= (TCHAR*)CharPrev (sz, pch1);
  627. pch1--; // back up
  628. ch= *pch1;
  629. }
  630. if( *pch1 != TEXT('.') )
  631. {
  632. if( dwSize + sizeof(".Manifest") <= MAX_PATH ) { // avoid buffer overruns
  633. lstrcat( sz, TEXT(".Manifest") );
  634. }
  635. }
  636. }
  637. /* AlertUser_FileFail( LPTSTR szFileName )
  638. *
  639. * szFileName is the name of file that was attempted to open.
  640. * Some sort of failure on file open. Alert the user
  641. * with some monologue box. At least give him decent
  642. * error messages.
  643. */
  644. VOID FAR AlertUser_FileFail( LPTSTR szFileName )
  645. {
  646. TCHAR msg[256]; // buffer to format message into
  647. DWORD dwStatus; // status from FormatMessage
  648. UINT style= MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION;
  649. // Check GetLastError to see why we failed
  650. dwStatus=
  651. FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS |
  652. FORMAT_MESSAGE_FROM_SYSTEM,
  653. NULL,
  654. GetLastError(),
  655. GetUserDefaultLangID(),
  656. msg, // where message will end up
  657. CharSizeOf(msg), NULL );
  658. if( dwStatus )
  659. {
  660. MessageBox( hwndSP, msg, szNN, style );
  661. }
  662. else
  663. {
  664. AlertBox( hwndSP, szNN, szDiskError, szFileName, style );
  665. }
  666. }