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.

896 lines
30 KiB

  1. /*************************************************************************
  2. * *
  3. * CHARTAB.C *
  4. * *
  5. * Copyright (C) Microsoft Corporation 1990-1994 *
  6. * All Rights reserved. *
  7. * *
  8. **************************************************************************
  9. * *
  10. * Module Intent *
  11. * Character table indexing and retrieval. The reasons this module is *
  12. * not put together with ansiusa are: *
  13. * - Like stop words, this involves indexing and retrieval *
  14. * - It is word breaker independent *
  15. * *
  16. **************************************************************************
  17. * *
  18. * Current Owner: Binh Nguyen *
  19. * *
  20. *************************************************************************/
  21. #include <mvopsys.h>
  22. #include <mem.h>
  23. #include <memory.h>
  24. #include <iterror.h>
  25. #include <_mvutil.h>
  26. #include <mvsearch.h>
  27. #include "common.h"
  28. #ifdef _DEBUG
  29. static BYTE NEAR *s_aszModule = __FILE__; // Used by error return functions.
  30. #endif
  31. #define SLASH '/'
  32. #define RETURN '\r'
  33. #define NEWLINE '\n'
  34. #define INBUF_SIZE 256 // Maximum buffer size to store a line
  35. #define BYTE_MAX 256 // Maximum number of characters
  36. #define LIGATURE_BYTES 3 // Number of bytes/ligature
  37. /* External variables */
  38. extern BYTE LigatureTable[];
  39. extern CHARMAP DefaultCMap[];
  40. /*************************************************************************
  41. *
  42. * API FUNCTIONS
  43. * Those functions should be exported in a .DEF file
  44. *************************************************************************/
  45. PUBLIC LPV EXPORT_API FAR PASCAL MVCharTableLoad (HFPB, LSZ, PHRESULT);
  46. PUBLIC LPV EXPORT_API FAR PASCAL MVCharTableGetDefault (PHRESULT);
  47. PUBLIC VOID EXPORT_API FAR PASCAL MVCharTableDispose (LPVOID);
  48. PUBLIC HRESULT EXPORT_API PASCAL FAR MVCharTableFileBuild (HFPB, LPVOID, LSZ);
  49. PUBLIC LPV EXPORT_API FAR PASCAL MVCharTableIndexLoad(HFPB, LSZ, PHRESULT);
  50. /*************************************************************************
  51. *
  52. * INTERNAL PRIVATE FUNCTIONS
  53. * All of them should be declared near
  54. *************************************************************************/
  55. PRIVATE LPB NEAR PASCAL GetNumber (HFPB, LPB, LPB, int FAR *, WORD FAR *);
  56. PRIVATE LPCHARTAB PASCAL NEAR CharTableCreate (int);
  57. PRIVATE VOID PASCAL NEAR StripCRLF (LPB, WORD);
  58. PRIVATE VOID PASCAL NEAR GetWord (LSZ FAR *, LST);
  59. PUBLIC VOID PASCAL FAR FreeHandle2 (HANDLE hd)
  60. {
  61. if (hd) {
  62. _GLOBALUNLOCK(hd);
  63. _GLOBALFREE(hd);
  64. }
  65. }
  66. /*************************************************************************
  67. * @doc EXTERNAL API INDEX
  68. *
  69. * @func LPCHARTAB FAR PASCAL | MVCharTableLoad |
  70. * Open an ASCII file and read in the description of the character
  71. * tables. It then converts them into binary format ready to be used
  72. * The format of the file is:
  73. * Size // How many entries
  74. * char class, normalized value, sorted value, mac display value
  75. * ........
  76. * char class, normalized value, sorted value, mac display value
  77. * Comments are preceded by // and ignored until EOL
  78. * A description of the ligature table, if any, is to followed the
  79. * charmap table
  80. *
  81. * @parm HFPB | hfpbIn |
  82. * Handle to system file or subfile; NULL if file is external.
  83. *
  84. * @parm LSZ | lszFilename |
  85. * DOS filen containing the description of the tables
  86. *
  87. * @parm PHRESULT | phr |
  88. * Error buffer
  89. *
  90. * @rdesc
  91. * The function returns a pointer to the memory block containing
  92. * tables, or NULL if failed. The error buffer will contain
  93. * description for the cause of the failure
  94. *
  95. * @comm About ligature table, there are some assumptions:
  96. * If there is no wcLigature, then the default table is used
  97. * if (wcLigature == 0) no ligature should be used
  98. * if wcLigature != 0, the author provides a ligature table.
  99. *************************************************************************/
  100. PUBLIC LPVOID EXPORT_API FAR PASCAL MVCharTableLoad (HFPB hfpbIn,
  101. LSZ lszFilename, PHRESULT phr)
  102. {
  103. register WORD j; // Scratch index variable
  104. register WORD i; // Scratch index variable
  105. register LPB lpbBuf; // Pointer to input buffer
  106. WORD cbRead; // How many bytes have read (left)
  107. int wcTabEntries; // Number of table entries
  108. int wTmp; // Scratch variable
  109. HFPB hfpb; // Handle of char table file
  110. BOOL fOpenedFile; // TRUE if we have to close the file
  111. BYTE Buffer [INBUF_SIZE]; // Input buffer
  112. LPCMAP lpCMap; // Pointer to character table entries
  113. LPCHARTAB lpCharTab = NULL; // Pointer to general char table struct
  114. int wcLigature;
  115. LPB lpbChar; // Scratch pointer
  116. /* Open subfile if necessary, (and system file if necessary) */
  117. if ((fOpenedFile = FsTypeFromHfpb(hfpb = hfpbIn) != FS_SUBFILE) &&
  118. (hfpb = (HANDLE)FileOpen
  119. (hfpbIn, lszFilename, hfpbIn ? FS_SUBFILE : REGULAR_FILE,
  120. READ, phr)) == 0)
  121. {
  122. SetErrCode (phr, E_FILENOTFOUND);
  123. return NULL;
  124. }
  125. *phr = E_BADFORMAT;
  126. /* Fill in the buffer */
  127. if ((cbRead =
  128. (WORD) FileRead(hfpb, lpbBuf = Buffer, INBUF_SIZE, phr)) == 0 ||
  129. FAILED(*phr))
  130. {
  131. goto ErrorExit;
  132. }
  133. /* Get the table size */
  134. lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wcTabEntries, &cbRead);
  135. if (wcTabEntries == 0 || wcTabEntries > BYTE_MAX) {
  136. goto ErrorExit;
  137. }
  138. /* Allocate memory for the character table */
  139. if ((lpCharTab = CharTableCreate (wcTabEntries)) == NULL)
  140. {
  141. SetErrCode (phr, E_OUTOFMEMORY);
  142. if (fOpenedFile)
  143. FileClose (hfpb);
  144. return NULL;
  145. }
  146. lpCMap = (LPCMAP)lpCharTab->lpCMapTab;
  147. lpCharTab->wcTabEntries = (WORD) wcTabEntries;
  148. /* Now read in invidual char table entry */
  149. for (i = (WORD) wcTabEntries; i > 0; i--, lpCMap++) {
  150. if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
  151. &cbRead)) == NULL) {
  152. /* Missing item */
  153. goto ErrorExit;
  154. }
  155. lpCMap->Class = (WORD) wTmp;
  156. if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
  157. &cbRead)) == NULL) {
  158. /* Missing item */
  159. goto ErrorExit;
  160. }
  161. lpCMap->SortOrder = (WORD) wTmp;
  162. if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
  163. &cbRead)) == NULL) {
  164. /* Missing item */
  165. goto ErrorExit;
  166. }
  167. lpCMap->Norm = (BYTE)wTmp;
  168. if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
  169. &cbRead)) == NULL) {
  170. /* Missing item */
  171. goto ErrorExit;
  172. }
  173. lpCMap->WinCaseSensitiveNorm = (BYTE)wTmp;
  174. if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
  175. &cbRead)) == NULL) {
  176. /* Missing item */
  177. goto ErrorExit;
  178. }
  179. lpCMap->MacDisplay = (BYTE)wTmp;
  180. if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf, &wTmp,
  181. &cbRead)) == NULL) {
  182. /* Missing item */
  183. goto ErrorExit;
  184. }
  185. lpCMap->MacCaseSensitiveNorm = (BYTE)wTmp;
  186. }
  187. /*
  188. * Check for valid table, ie. all reserved characters should not
  189. * be modified
  190. */
  191. /* Check for valid reserved type */
  192. lpCMap = &(((LPCMAP)lpCharTab->lpCMapTab)[1]);
  193. if (lpCMap->Class != CLASS_TYPE)
  194. goto ErrorExit;
  195. /* Check for ligatures */
  196. if ((lpbBuf = GetNumber (hfpb, Buffer, lpbBuf,
  197. &wcLigature, &cbRead)) == NULL) {
  198. /* No ligature table present, use default */
  199. lpCharTab->wcLigature = DEF_LIGATURE_COUNT;
  200. lpCharTab->fFlag = USE_DEF_LIGATURE;
  201. lpCharTab->lpLigature = LigatureTable;
  202. }
  203. else {
  204. if ((lpCharTab->wcLigature = (WORD) wcLigature) != 0) {
  205. /* Ligature table present */
  206. /* Allocate memory block. Notice that we allocate 3 extra bytes
  207. * They will serve as sentinels for the end of the ligature
  208. * table, thus eliminating the need of having to know beforehand
  209. * what is the size of the table
  210. */
  211. if ((lpCharTab->hLigature = _GLOBALALLOC (DLLGMEM_ZEROINIT,
  212. LIGATURE_BYTES * (wcLigature + 1))) == 0) {
  213. SetErrCode (phr, E_OUTOFMEMORY);
  214. goto ErrorExit;
  215. }
  216. lpbChar = lpCharTab->lpLigature =
  217. (LPB)_GLOBALLOCK(lpCharTab->hLigature);
  218. /* Read in the entries */
  219. for (i = (WORD) wcLigature; i > 0; i--) {
  220. for (j = LIGATURE_BYTES; j > 0; j--) {
  221. if (lpbBuf = GetNumber (hfpb, Buffer, lpbBuf,
  222. &wTmp, &cbRead)) {
  223. /* Update entry */
  224. *lpbChar ++ = (BYTE)wTmp;
  225. }
  226. else {
  227. /* Missing item */
  228. goto ErrorExit;
  229. }
  230. }
  231. }
  232. lpCharTab->fFlag = LIGATURE_PROVIDED;
  233. }
  234. else
  235. lpCharTab->fFlag = NO_LIGATURE;
  236. }
  237. if (fOpenedFile)
  238. FileClose (hfpb);
  239. return ((LPV)lpCharTab);
  240. ErrorExit:
  241. if (fOpenedFile)
  242. FileClose (hfpb);
  243. MVCharTableDispose (lpCharTab);
  244. return NULL;
  245. }
  246. /*************************************************************************
  247. * @doc API INDEX
  248. *
  249. * @func HRESULT PASCAL FAR | MVCharTableFileBuild |
  250. * Incorporate the character table into the system file
  251. *
  252. * @parm HFPB | hfpbSysFile |
  253. * Handle to system file. It is non-zero, then the system file is
  254. * already open, else the function will open the system file
  255. *
  256. * @parm LPCHARTAB | lpCharTab |
  257. * Pointer to character table information structure
  258. *
  259. * @parm LSZ | lszFilename |
  260. * File name. If hpfbSysFile is 0, the format is:
  261. * dos filename[!charfilename], else it is the name of the character
  262. * file itself
  263. *
  264. * @rdesc ERR_SUCCESS if succeeded, other errors if failed.
  265. *
  266. * @comm About ligature table, there are some assumptions:
  267. * If hLigature == 0 {
  268. * if (wcLigature == 0)
  269. * There is no ligature table
  270. * else
  271. * We use the default ligature table. There is no need
  272. * to write out the table data
  273. * }
  274. * else
  275. * The author provides a ligature table.
  276. *************************************************************************/
  277. PUBLIC HRESULT EXPORT_API PASCAL FAR MVCharTableFileBuild (HFPB hfpbSysFile,
  278. LPCHARTAB lpCharTab, LSZ lszFilename)
  279. {
  280. HFPB hfpbCharTab; // Pointer to final index file info.
  281. BOOL fCreatedFile;
  282. CHARTAB_HDR CharTab_hdr; // Character table header
  283. BYTE Dummy[CHARTAB_HDR_SIZE]; // Dummy buffer to write 0
  284. FILEOFFSET foOffset; // File's offset
  285. FILEOFFSET foStart;
  286. WORD CharTabSize;
  287. WORD CharLigatureSize;
  288. // char szFullFilename[MAX_PATH];
  289. HRESULT hr = S_OK;
  290. if (lpCharTab == NULL || lpCharTab->wcTabEntries == 0)
  291. {
  292. /* Nothing to build */
  293. return E_INVALIDARG;
  294. }
  295. /* If hfpbSysFile != 0, allocate a temp HFPB to use for the system file */
  296. //if (!(fCloseSysFile = (char)(hfpbSysFile == 0))) {
  297. // if ((hfpb = ALLOCTEMPFPB (hfpbSysFile, phr)) == NULL)
  298. // return ERR_FAILED;
  299. //}
  300. if ((fCreatedFile =
  301. FsTypeFromHfpb(hfpbCharTab = hfpbSysFile) != FS_SUBFILE) &&
  302. 0 == (hfpbCharTab = FileCreate
  303. (hfpbSysFile, lszFilename,
  304. hfpbSysFile ? FS_SUBFILE : REGULAR_FILE, &hr)))
  305. {
  306. return hr;
  307. }
  308. // If we didn't open the file, we need to find out where the file seek
  309. // pointer is initially so that we only seek relative to that starting
  310. // position (i.e. the caller owns the part of the file that comes before).
  311. foStart = (fCreatedFile ? MakeFo(0,0) :
  312. FileSeek (hfpbCharTab, MakeFo (0, 0), wFSSeekCur, &hr));
  313. if (FAILED(hr))
  314. goto exit01;
  315. /* Write out the CharTab file header */
  316. CharTab_hdr.FileStamp = CHRTAB_STAMP;
  317. CharTab_hdr.version = CHARTABVER;
  318. CharTabSize = lpCharTab->wcTabEntries * sizeof(CHARMAP);
  319. /* the ligature table size:
  320. * - is 0 if we are going to use the default table
  321. * - Is non-0 if the author provides a ligature table
  322. */
  323. switch (lpCharTab->fFlag)
  324. {
  325. case NO_LIGATURE:
  326. case USE_DEF_LIGATURE:
  327. CharLigatureSize = 0;
  328. break;
  329. default:
  330. CharLigatureSize = lpCharTab->wcLigature * LIGATURE_BYTES;
  331. }
  332. CharTab_hdr.dwTabSize = CharTabSize + CharLigatureSize;
  333. CharTab_hdr.wcTabEntries = lpCharTab->wcTabEntries;
  334. CharTab_hdr.wcLigature = lpCharTab->wcLigature;
  335. CharTab_hdr.fFlag = lpCharTab->fFlag;
  336. MEMSET(Dummy, (BYTE)0, CHARTAB_HDR_SIZE);
  337. /* Write all zero to the header */
  338. if (FileSeekWrite(hfpbCharTab, Dummy, FoAddFo(foStart, foNil),
  339. CHARTAB_HDR_SIZE, &hr) != CHARTAB_HDR_SIZE)
  340. {
  341. goto exit01;
  342. }
  343. if (FileSeekWrite(hfpbCharTab, &CharTab_hdr, FoAddFo(foStart, foNil),
  344. sizeof(CHARTAB_HDR), &hr) != sizeof(CHARTAB_HDR))
  345. {
  346. goto exit01;
  347. }
  348. foOffset = FoAddFo(foStart, MakeFo(CHARTAB_HDR_SIZE,0L));
  349. /* Write out the character table buffer */
  350. if (FileSeekWrite(hfpbCharTab, lpCharTab->lpCMapTab, foOffset,
  351. CharTabSize, &hr) != CharTabSize)
  352. {
  353. goto exit01;
  354. }
  355. if (CharLigatureSize)
  356. {
  357. foOffset = FoAddDw(foOffset,CharTabSize);
  358. /* Write out the ligature table */
  359. if (FileSeekWrite(hfpbCharTab, lpCharTab->lpLigature, foOffset,
  360. CharLigatureSize, &hr) != CharLigatureSize)
  361. {
  362. goto exit01;
  363. }
  364. }
  365. hr = S_OK;
  366. exit01:
  367. // Close file if we created it.
  368. if (fCreatedFile)
  369. FileClose(hfpbCharTab); // Removed fRet= here.
  370. return hr;
  371. }
  372. /*************************************************************************
  373. * @doc INTERNAL
  374. *
  375. * @func VOID PASCAL NEAR | GetWord |
  376. * This function will scan and get a word from the input buffer
  377. *
  378. * @parm LSZ FAR | *lplszBuf |
  379. * Pointer to input buffer. The content will be updated on exit
  380. *
  381. * @parm LST | lstWord |
  382. * Buffer to received parsed word
  383. *************************************************************************/
  384. PRIVATE VOID PASCAL NEAR GetWord (LSZ FAR *lplszBuf, LST lstWord)
  385. {
  386. LST lstWordStart;
  387. LSZ lszBuf = *lplszBuf;
  388. /* Remember the beginning of the word */
  389. lstWordStart = lstWord++;
  390. /* Skip all beginning blanks */
  391. while (*lszBuf == ' ')
  392. lszBuf++;
  393. /* Now keep accumulating the word's characters */
  394. for (;;) {
  395. switch (*lszBuf) {
  396. case 0:
  397. case ' ':
  398. goto exit0;
  399. case '/':
  400. if (*(lszBuf + 1) == '/') {
  401. /* Skip the inline comment */
  402. while (*lszBuf)
  403. lszBuf++;
  404. goto exit0;
  405. }
  406. default:
  407. *lstWord++ = *lszBuf++;
  408. }
  409. }
  410. exit0:
  411. *lplszBuf = lszBuf;
  412. *lstWordStart = (BYTE)(lstWord - lstWordStart - 1);
  413. }
  414. /*************************************************************************
  415. * @doc INTERNAL
  416. *
  417. * @func VOID PASCAL NEAR | StripCRLF |
  418. * This function will change all CR, LF in the input buffer into
  419. * 0, all tabs into blank
  420. *
  421. * @parm LPB | lpbBuf |
  422. * Input buffer
  423. *
  424. * @parm WORD | BufSize |
  425. * Length of the buffer
  426. *************************************************************************/
  427. PRIVATE VOID PASCAL NEAR StripCRLF (LPB lpbBuf, WORD BufSize)
  428. {
  429. for (; BufSize > 0; BufSize --)
  430. {
  431. switch (*lpbBuf)
  432. {
  433. case RETURN:
  434. case NEWLINE:
  435. *lpbBuf = 0;
  436. break;
  437. case '\t':
  438. *lpbBuf = ' ';
  439. break;
  440. }
  441. lpbBuf++;
  442. }
  443. }
  444. /*************************************************************************
  445. * @doc API RETRIEVAL
  446. *
  447. * @func LPCHARTAB FAR PASCAL | MVCharTableIndexLoad |
  448. * This function will load a character table from a
  449. * system file.
  450. *
  451. * @parm HANDLE | hfpbSysFile |
  452. * If non-zero, this is the handle of an already opened system file
  453. *
  454. * @parm LSZ | lszFilename |
  455. * If hpfbSysFile is non-zero, this is the name of the CharTab's subfile
  456. * else this is the combined filename with the format
  457. * "dos_filename[CharTab_filename]"
  458. * If the subfile's name is not specified, the default CharTab's file
  459. * name will be used
  460. *
  461. * @parm PHRESULT | phr |
  462. * Pointer to error buffer
  463. *
  464. * @rdesc If succeeded, the function will return a pointer the loaded
  465. * CharTab, else NULL. The error buffer will contain information
  466. * about the cause of the failure
  467. *
  468. * @comm About ligature table, there are some assumptions:
  469. * If hLigature == 0 {
  470. * if (wcLigature == 0)
  471. * There is no ligature table
  472. * else
  473. * We use the default ligature table. There is no need
  474. * to write out the table data
  475. * }
  476. * else
  477. * The author provides a ligature table.
  478. *************************************************************************/
  479. PUBLIC LPVOID EXPORT_API FAR PASCAL MVCharTableIndexLoad(HFPB hfpbSysFile,
  480. LSZ lszFilename, PHRESULT phr)
  481. {
  482. HANDLE hfpbCharTabFile;
  483. BOOL fOpenedFile;
  484. LPCHARTAB lpCharTab = NULL;
  485. CHARTAB_HDR FAR *lpCharTabHdr;
  486. CHARTAB_HDR CharTabHdr;
  487. FILEOFFSET foStart;
  488. #if _MAC
  489. int MacClipMap[256], i;
  490. LPCMAP lpCMapEntry;
  491. #endif
  492. *phr = S_OK;
  493. lpCharTabHdr = &CharTabHdr;
  494. /* Open subfile, (and system file if necessary) */
  495. if ((fOpenedFile =
  496. FsTypeFromHfpb(hfpbCharTabFile = hfpbSysFile) != FS_SUBFILE) &&
  497. (hfpbCharTabFile = (HANDLE)FileOpen
  498. (hfpbSysFile, lszFilename, hfpbSysFile ? FS_SUBFILE : REGULAR_FILE,
  499. READ, phr)) == 0)
  500. {
  501. exit0:
  502. return (LPV)lpCharTab;
  503. }
  504. // If we didn't open the file, we need to find out where the file seek
  505. // pointer is initially so that we only seek relative to that starting
  506. // position (i.e. the caller owns the part of the file that comes before).
  507. foStart = (fOpenedFile ? MakeFo(0,0) :
  508. FileSeek (hfpbCharTabFile, MakeFo (0, 0), wFSSeekCur, phr));
  509. /* Read in the header file, and make sure that is a CharTab file */
  510. if (FAILED(*phr) ||
  511. FileSeekRead(hfpbCharTabFile, (LPV)lpCharTabHdr, FoAddFo(foStart, foNil),
  512. sizeof(CHARTAB_HDR), phr) != sizeof(CHARTAB_HDR)) {
  513. exit1:
  514. /* Close the subfile if we opened it */
  515. if (fOpenedFile)
  516. FileClose(hfpbCharTabFile);
  517. /* Close the system file if we open it, the handle will be
  518. * released in the process */
  519. goto exit0;
  520. }
  521. /* MAC code. They will be optimized out */
  522. lpCharTabHdr->FileStamp = SWAPWORD(lpCharTabHdr->FileStamp);
  523. lpCharTabHdr->version = SWAPWORD(lpCharTabHdr->version);
  524. lpCharTabHdr->wcTabEntries = SWAPWORD(lpCharTabHdr->wcTabEntries);
  525. lpCharTabHdr->wcLigature = SWAPWORD(lpCharTabHdr->wcLigature);
  526. lpCharTabHdr->fFlag = SWAPWORD(lpCharTabHdr->fFlag);
  527. lpCharTabHdr->dwTabSize = SWAPLONG(lpCharTabHdr->dwTabSize);
  528. /* Check to see if the data read in is valid */
  529. if (lpCharTabHdr->FileStamp != CHRTAB_STAMP)
  530. { // File stamp
  531. SetErrCode(phr, E_BADVERSION);
  532. goto exit1;
  533. }
  534. /* Allocate memory for the character table. Note that there may be
  535. * some inefficiency im memory usage, since there are 3-bytes per
  536. * ligature entry, and several more for each charmap entry.
  537. */
  538. if ((lpCharTab = CharTableCreate ((lpCharTabHdr->wcTabEntries +
  539. lpCharTabHdr->wcLigature))) == NULL) {
  540. SetErrCode(phr, E_OUTOFMEMORY);
  541. goto exit1;
  542. }
  543. lpCharTab->wcTabEntries = lpCharTabHdr->wcTabEntries;
  544. lpCharTab->fFlag = lpCharTabHdr->fFlag;
  545. lpCharTab->hLigature = 0;
  546. /* Read in the CharTab bitmap data */
  547. if (FileSeekRead(hfpbCharTabFile,
  548. (LPV)lpCharTab->lpCMapTab, FoAddFo(foStart, MakeFo(CHARTAB_HDR_SIZE,0)),
  549. (WORD)lpCharTabHdr->dwTabSize, phr) !=
  550. (WORD)lpCharTabHdr->dwTabSize)
  551. {
  552. MVCharTableDispose(lpCharTab);
  553. lpCharTab = NULL;
  554. goto exit1;
  555. }
  556. #if _MAC
  557. /* Create the mapping from Mac to Windows. This is to deal with the
  558. * situation people entering data on a Mac and look for that string
  559. */
  560. lpCMapEntry = (LPCMAP)lpCharTab->lpCMapTab;
  561. for (i = lpCharTab->wcTabEntries; i > 0; i--)
  562. {
  563. // erinfox: swap class
  564. lpCMapEntry[i].Class = SWAPWORD(lpCMapEntry[i].Class);
  565. lpCMapEntry[i].SortOrder = SWAPWORD(lpCMapEntry[i].SortOrder);
  566. if (lpCMapEntry[i].MacDisplay != 0)
  567. {
  568. lpCMapEntry[lpCMapEntry[i].MacDisplay].MacToWin = i;
  569. }
  570. }
  571. /* Change the Mac clipboard mapping. I am using the 256 value.
  572. * The character table hasthe mapping based on the Windows indices
  573. * but since the WinToMap mapping will change all the character
  574. * values to their corresponding Mac, the new values have to be
  575. * used as indices, ie. there is a need to remap the
  576. * MacCaseSensitiveNorm column based on the new Mac indices
  577. */
  578. MEMSET (MacClipMap, 0, 256);
  579. for ( i = 0; i < lpCharTab->wcTabEntries; i++)
  580. {
  581. MacClipMap[lpCMapEntry[i].MacDisplay] =
  582. lpCMapEntry[i].MacCaseSensitiveNorm;
  583. }
  584. /* Reset the mapping. */
  585. /* Change all 0's to 32 (space) to avoid truncation */
  586. for ( i = 0; i < lpCharTab->wcTabEntries; i++)
  587. {
  588. if ((lpCMapEntry[i].MacCaseSensitiveNorm = MacClipMap[i]) == 0)
  589. lpCMapEntry[i].MacCaseSensitiveNorm = 32;
  590. }
  591. #endif /* _MAC */
  592. /* Look for ligature */
  593. switch (lpCharTab->fFlag) {
  594. case NO_LIGATURE:
  595. break;
  596. case USE_DEF_LIGATURE:
  597. lpCharTab->wcLigature = DEF_LIGATURE_COUNT;
  598. lpCharTab->fFlag = USE_DEF_LIGATURE;
  599. lpCharTab->hLigature = 0;
  600. lpCharTab->lpLigature = LigatureTable;
  601. break;
  602. default:
  603. lpCharTab->lpLigature = (LPB)lpCharTab->lpCMapTab +
  604. lpCharTabHdr->wcTabEntries * sizeof(CHARMAP);
  605. lpCharTab->wcLigature = lpCharTabHdr->wcLigature;
  606. }
  607. goto exit1;
  608. }
  609. /*************************************************************************
  610. * @doc API RETRIEVAL
  611. * @func LPCTAB FAR PASCAL | MVCharTableGetDefault |
  612. * Retrieve the default character mapping table used by MV
  613. * @parm PHRESULT | phr |
  614. * Pointer to error buffer
  615. * @rdesc
  616. * Pointer to character mapping table if successful, NULL otherwise.
  617. * In case of error, phr will contain the error code
  618. *************************************************************************/
  619. PUBLIC LPV EXPORT_API FAR PASCAL MVCharTableGetDefault (PHRESULT phr)
  620. {
  621. LPCHARTAB lpCharTab = NULL;
  622. #if _MAC
  623. int i;
  624. LPCMAP lpCMapEntry;
  625. #endif /* _MAC */
  626. /* Allocate memory for the character table. Note that there may be
  627. * some inefficiency im memory usage, since there are 3-bytes per
  628. * ligature entry, and several more for each charmap entry.
  629. */
  630. if ((lpCharTab = CharTableCreate (MAX_CHAR_COUNT +
  631. DEF_LIGATURE_COUNT)) == NULL) {
  632. SetErrCode(phr, E_OUTOFMEMORY);
  633. return NULL;
  634. }
  635. lpCharTab->wcTabEntries = MAX_CHAR_COUNT;
  636. lpCharTab->wcLigature = DEF_LIGATURE_COUNT;
  637. lpCharTab->fFlag = USE_DEF_LIGATURE;
  638. lpCharTab->hLigature = 0;
  639. lpCharTab->lpLigature = LigatureTable;
  640. lpCharTab->lpCMapTab = DefaultCMap;
  641. #if _MAC
  642. /* Create the mapping from Mac to Windows. This is to deal with the
  643. * situation people entering data on a Mac and look for that string
  644. */
  645. lpCMapEntry = (LPCMAP)lpCharTab->lpCMapTab;
  646. for (i = lpCharTab->wcTabEntries; i > 0; i--) {
  647. if (lpCMapEntry[i].MacDisplay != 0) {
  648. lpCMapEntry[lpCMapEntry[i].MacDisplay].MacToWin = i;
  649. }
  650. }
  651. /* Create the clipboard case sensitive column */
  652. #endif /* _MAC */
  653. return(lpCharTab);
  654. }
  655. /*************************************************************************
  656. * @doc API INDEX RETRIEVAL
  657. *
  658. * @func VOID FAR PASCAL | MVCharTableDispose |
  659. * Free all memory associated with the character table
  660. *
  661. * @parm LPCHARTAB | lpCharTab |
  662. * Pointer to character table structure
  663. *************************************************************************/
  664. PUBLIC VOID EXPORT_API FAR PASCAL MVCharTableDispose (LPCHARTAB lpCharTab)
  665. {
  666. HANDLE hBuf;
  667. if (lpCharTab == NULL)
  668. return;
  669. if (hBuf = lpCharTab->hLigature) {
  670. FreeHandle2(hBuf);
  671. lpCharTab->hLigature = NULL;
  672. }
  673. FreeHandle2(lpCharTab->hStruct);
  674. }
  675. /*************************************************************************
  676. * @doc API INDEX RETRIEVAL
  677. *
  678. * @func VOID FAR PASCAL | MVCharTableSetWildcards |
  679. * Change the property of '*' and '?' to CLASS_WILDCARD.
  680. *
  681. * @parm LPCHARTAB | lpCharTab |
  682. * Pointer to character table structure
  683. *************************************************************************/
  684. PUBLIC VOID EXPORT_API FAR PASCAL MVCharTableSetWildcards (LPCHARTAB lpCharTab)
  685. {
  686. if (lpCharTab == NULL)
  687. return;
  688. (lpCharTab->lpCMapTab)['*'].Class = CLASS_WILDCARD;
  689. (lpCharTab->lpCMapTab)['?'].Class = CLASS_WILDCARD;
  690. }
  691. /*************************************************************************
  692. * @doc INTERNAL
  693. *
  694. * @func LPB NEAR PASCAL | GetNumber |
  695. * This function will try to get to a number in an ASCII and then
  696. * retrieve it. It will fill up the input buffer if necessary
  697. *
  698. * @parm HFPB | hfpb |
  699. * Handle of opened file
  700. *
  701. * @parm LPB | Buffer |
  702. * Buffer to store the input data
  703. *
  704. * @parm LPB | lpbBuf |
  705. * Current location pointer into the input buffer
  706. *
  707. * @parm int far * | lpNum |
  708. * Place to store the retrieved number
  709. *
  710. * @parm WORD FAR * | lpcbRead |
  711. * How many bytes are left in the input buffer
  712. *
  713. * @rdesc If succeeded, the function will return the last location
  714. * of the input buffer, else NULL if failed. If succeeded, the
  715. * number is stored in *lpNum, the number of bytes left in the input
  716. * buffer is updated
  717. *************************************************************************/
  718. PRIVATE LPB NEAR PASCAL GetNumber (HFPB hfpb, LPB Buffer, LPB lpbBuf,
  719. int far *lpNum, WORD FAR *lpcbRead)
  720. {
  721. register WORD fSkipComment = 0;
  722. register WORD cbRead = *lpcbRead;
  723. WORD number = 0;
  724. BYTE fGetNum = FALSE;
  725. HRESULT hr;
  726. for (;;) {
  727. /* Check for empty buffer, and read in new data if necessary */
  728. if (cbRead == 0) {
  729. cbRead = (WORD) FileRead(hfpb, lpbBuf = Buffer, INBUF_SIZE, &hr);
  730. if (cbRead == 0 || FAILED(hr)) {
  731. if (fGetNum == FALSE)
  732. lpbBuf = NULL; // Return error
  733. break;
  734. }
  735. }
  736. if (*lpbBuf == RETURN || *lpbBuf == NEWLINE) {
  737. /* EOL, reset variables, exit if we already got a number */
  738. fSkipComment = 0;
  739. if (fGetNum)
  740. break;
  741. }
  742. else if (fSkipComment != 2) {
  743. /* We are not inside a comment, so look for a number */
  744. if (*lpbBuf >= '0' && *lpbBuf <= '9') {
  745. /* Get the number */
  746. number = number * 10 + *lpbBuf - '0';
  747. fGetNum = TRUE;
  748. }
  749. else if (*lpbBuf == SLASH) {
  750. if (fGetNum)
  751. break;
  752. fSkipComment++; // Increment slash count
  753. }
  754. else {
  755. if (fGetNum)
  756. break;
  757. fSkipComment = 0;
  758. }
  759. }
  760. cbRead--;
  761. lpbBuf++;
  762. }
  763. /* Update the variables */
  764. *lpcbRead = cbRead;
  765. *lpNum = number;
  766. return lpbBuf;
  767. }
  768. /*************************************************************************
  769. * @doc INTERNAL
  770. *
  771. * @func LPCHARTAB PASCAL NEAR | CharTableCreate |
  772. * Allocate memory necessary for the character table. The amount
  773. * needed is based on the number of entries
  774. *
  775. * @parm WORD | wcTabEntries |
  776. * Number of entries in the character table
  777. *
  778. *************************************************************************/
  779. PRIVATE LPCHARTAB PASCAL NEAR CharTableCreate (int wcTabEntries)
  780. {
  781. HANDLE hMem;
  782. LPCHARTAB lpCharTab;
  783. /* Allocate memory for the character table */
  784. if ((hMem = _GLOBALALLOC (DLLGMEM_ZEROINIT,
  785. sizeof(CHARTAB) + wcTabEntries * sizeof(CHARMAP))) == NULL) {
  786. return NULL;
  787. }
  788. lpCharTab = (LPCHARTAB)_GLOBALLOCK(hMem);
  789. lpCharTab->lpCMapTab = (LPCMAP)(lpCharTab + 1);
  790. lpCharTab->hStruct = hMem;
  791. return lpCharTab;
  792. }