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

633 lines
16 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. CONVLIST.c
  5. ++*/
  6. #include <windows.h>
  7. #include <immdev.h>
  8. #include "imeattr.h"
  9. #include "imedefs.h"
  10. #if defined(UNIIME)
  11. #include "uniime.h"
  12. #endif
  13. #if !defined(ROMANIME)
  14. /**********************************************************************/
  15. /* Conversion() */
  16. /**********************************************************************/
  17. DWORD PASCAL Conversion(
  18. #if defined(UNIIME)
  19. LPINSTDATAL lpInstL,
  20. LPIMEL lpImeL,
  21. #endif
  22. LPCTSTR lpszReading,
  23. LPCANDIDATELIST lpCandList,
  24. DWORD dwBufLen)
  25. {
  26. UINT uMaxCand;
  27. DWORD dwSize = // similar to ClearCand
  28. // header length
  29. sizeof(CANDIDATELIST) +
  30. // candidate string pointers
  31. sizeof(DWORD) * MAXCAND +
  32. // string plus NULL terminator
  33. (sizeof(WCHAR) + sizeof(TCHAR)) * MAXCAND;
  34. DWORD dwPattern;
  35. PRIVCONTEXT ImcP;
  36. #if !defined(WINIME) && !defined(UNICDIME)
  37. BOOL fNeedUnload;
  38. #endif
  39. if (!dwBufLen) {
  40. return (dwSize);
  41. }
  42. uMaxCand = dwBufLen - sizeof(CANDIDATELIST);
  43. uMaxCand /= sizeof(DWORD) + sizeof(WCHAR) + sizeof(TCHAR);
  44. if (!uMaxCand) {
  45. // can not even put one string
  46. return (0);
  47. }
  48. lpCandList->dwSize = dwSize;
  49. lpCandList->dwStyle = IME_CAND_READ; // candidate having same reading
  50. lpCandList->dwCount = 0;
  51. lpCandList->dwSelection = 0;
  52. lpCandList->dwPageStart = 0;
  53. lpCandList->dwPageSize = CANDPERPAGE;
  54. lpCandList->dwOffset[0] = sizeof(CANDIDATELIST) + sizeof(DWORD) *
  55. (uMaxCand - 1);
  56. dwPattern = ReadingToPattern(
  57. #if defined(UNIIME)
  58. lpImeL,
  59. #endif
  60. lpszReading, ImcP.bSeq, TRUE);
  61. if (!dwPattern) {
  62. return (0);
  63. }
  64. #if !defined(WINIME) && !defined(UNICDIME)
  65. if (lpInstL->fdwTblLoad == TBL_LOADED) {
  66. fNeedUnload = FALSE;
  67. } else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) {
  68. LoadTable(lpInstL, lpImeL);
  69. fNeedUnload = TRUE;
  70. } else {
  71. return (0);
  72. }
  73. #endif
  74. if (!ConvertSeqCode2Pattern(
  75. #if defined(UNIIME)
  76. lpImeL,
  77. #endif
  78. ImcP.bSeq, &ImcP)) {
  79. return (0);
  80. }
  81. SearchTbl(
  82. #if defined(UNIIME)
  83. lpImeL,
  84. #endif
  85. 0, lpCandList, &ImcP);
  86. #if defined(WINAR30)
  87. if (!lpCandList->dwCount) {
  88. SearchTbl(3, lpCandList, &ImcP);
  89. }
  90. #endif
  91. #if !defined(WINIME) && !defined(UNICDIME)
  92. if (lpInstL->hUsrDicMem) {
  93. SearchUsrDic(
  94. #if defined(UNIIME)
  95. lpImeL,
  96. #endif
  97. lpCandList, &ImcP);
  98. }
  99. if (fNeedUnload) {
  100. FreeTable(lpInstL);
  101. }
  102. #endif
  103. return (dwSize);
  104. }
  105. /**********************************************************************/
  106. /* SearchOffset() */
  107. /* Return Value : */
  108. /* the offset in table file which include this uOffset */
  109. /**********************************************************************/
  110. UINT PASCAL SearchOffset(
  111. LPBYTE lpTbl,
  112. UINT uTblSize,
  113. UINT uOffset)
  114. {
  115. int iLo, iMid, iHi;
  116. LPWORD lpwPtr;
  117. iLo = 0;
  118. iHi = uTblSize / sizeof(WORD);
  119. iMid = (iLo + iHi) / 2;
  120. // binary search
  121. for (; iLo <= iHi; ) {
  122. lpwPtr = (LPWORD)lpTbl + iMid;
  123. if (uOffset > *lpwPtr) {
  124. iLo = iMid + 1;
  125. } else if (uOffset < *lpwPtr) {
  126. iHi = iMid - 1;
  127. } else {
  128. break;
  129. }
  130. iMid = (iLo + iHi) / 2;
  131. }
  132. if (iMid > 0) {
  133. iLo = iMid - 1;
  134. } else {
  135. iLo = 0;
  136. }
  137. iHi = uTblSize / sizeof(WORD);
  138. lpwPtr = (LPWORD)lpTbl + iLo;
  139. for (; iLo < iHi; iLo++, lpwPtr++) {
  140. if (*lpwPtr > uOffset) {
  141. return (iLo - 1);
  142. }
  143. }
  144. return (0);
  145. }
  146. /**********************************************************************/
  147. /* ReverseConversion() */
  148. /**********************************************************************/
  149. #if defined(PHON)
  150. typedef struct {
  151. BYTE szTmpBuf[sizeof(WORD) * 4 + sizeof(TCHAR)];
  152. } PHONREVERSEBUF;
  153. typedef PHONREVERSEBUF FAR *LPPHONREVERSEBUF;
  154. #endif
  155. DWORD PASCAL ReverseConversion(
  156. #if defined(UNIIME)
  157. LPINSTDATAL lpInstL,
  158. LPIMEL lpImeL,
  159. #endif
  160. UINT uCode,
  161. LPCANDIDATELIST lpCandList,
  162. DWORD dwBufLen)
  163. {
  164. UINT uMaxCand;
  165. DWORD dwSize = // similar to ClearCand
  166. // header length
  167. sizeof(CANDIDATELIST) +
  168. // candidate string pointers
  169. sizeof(DWORD) * MAX_COMP +
  170. // string plus NULL terminator
  171. #if defined(QUICK)
  172. (sizeof(WCHAR) * 2 + sizeof(TCHAR)) * MAX_COMP;
  173. #elif defined(WINIME) || defined(UNICDIME)
  174. (sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR));
  175. #else
  176. (sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR)) * MAX_COMP;
  177. #endif
  178. #if defined(WINIME) || defined(UNICDIME)
  179. UINT uTmpCode;
  180. int i;
  181. #else
  182. BOOL fNeedUnload;
  183. HANDLE hTbl;
  184. LPBYTE lpTbl, lpStart, lpEnd;
  185. #endif
  186. #if defined(CHAJEI) || defined(PHON) || defined(QUICK)
  187. HANDLE hTbl0;
  188. LPBYTE lpTbl0;
  189. #endif
  190. #if defined(CHAJEI) || defined(PHON)
  191. HANDLE hTbl1;
  192. LPBYTE lpTbl1;
  193. #endif
  194. if (!dwBufLen) {
  195. return (dwSize);
  196. }
  197. uMaxCand = dwBufLen - sizeof(CANDIDATELIST);
  198. #if defined(QUICK)
  199. uMaxCand /= sizeof(DWORD) +
  200. (sizeof(WCHAR) * 2 + sizeof(TCHAR));
  201. #else
  202. uMaxCand /= sizeof(DWORD) +
  203. (sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR));
  204. #endif
  205. if (uMaxCand == 0) {
  206. // can not put one string
  207. return (0);
  208. }
  209. lpCandList->dwSize = sizeof(CANDIDATELIST) +
  210. sizeof(DWORD) * uMaxCand +
  211. #if defined(QUICK)
  212. (sizeof(WCHAR) * 2 + sizeof(TCHAR)) * uMaxCand;
  213. #elif defined(WINIME) || defined(UNICDIME)
  214. (sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR));
  215. #else
  216. (sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR)) * uMaxCand;
  217. #endif
  218. lpCandList->dwStyle = IME_CAND_READ;
  219. lpCandList->dwCount = 0;
  220. lpCandList->dwSelection = 0;
  221. lpCandList->dwPageSize = CANDPERPAGE;
  222. lpCandList->dwOffset[0] = sizeof(CANDIDATELIST) + sizeof(DWORD) *
  223. (uMaxCand - 1);
  224. #if defined(WINIME) || defined(UNICDIME)
  225. #if defined(WINIME) && defined(UNICODE)
  226. {
  227. int iChars;
  228. CHAR szCode[4];
  229. iChars = WideCharToMultiByte(sImeG.uAnsiCodePage, WC_COMPOSITECHECK,
  230. (LPCWSTR)&uCode, 1, szCode, sizeof(szCode), NULL, NULL);
  231. if (iChars >= 2) {
  232. uTmpCode = ((UINT)(BYTE)szCode[0] << 8) | (BYTE)szCode[1];
  233. } else {
  234. uTmpCode = (BYTE)szCode[0];
  235. }
  236. if (uCode == 0x003F) {
  237. } else if (uTmpCode == 0x003F) {
  238. // no cooresponding BIG5 code
  239. return (0);
  240. } else {
  241. }
  242. uCode = uTmpCode;
  243. }
  244. #endif
  245. uTmpCode = uCode;
  246. for (i = lpImeL->nMaxKey - 1; i >= 0; i--) {
  247. UINT uCompChar;
  248. uCompChar = lpImeL->wSeq2CompTbl[(uTmpCode & 0xF) + 1];
  249. *(LPWSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  250. lpCandList->dwCount] + sizeof(WCHAR) * i) = (WCHAR)uCompChar;
  251. uTmpCode >>= 4;
  252. }
  253. // null terminator
  254. *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  255. lpCandList->dwCount] + sizeof(WCHAR) * lpImeL->nMaxKey) = '\0';
  256. // string count ++
  257. lpCandList->dwCount++;
  258. #else
  259. if (lpInstL->fdwTblLoad == TBL_LOADED) {
  260. fNeedUnload = FALSE;
  261. } else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) {
  262. LoadTable(lpInstL, lpImeL);
  263. fNeedUnload = TRUE;
  264. } else {
  265. return (0);
  266. }
  267. #if defined(CHAJEI) || defined(PHON) || defined(QUICK)
  268. hTbl = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[2]);
  269. #else
  270. hTbl = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[0]);
  271. #endif
  272. if (!hTbl) {
  273. return (0);
  274. }
  275. lpTbl = MapViewOfFile(hTbl, FILE_MAP_READ, 0, 0, 0);
  276. if (!lpTbl) {
  277. dwSize = 0;
  278. goto RevConvCloseCodeTbl;
  279. }
  280. #if defined(CHAJEI) || defined(PHON) || defined(QUICK)
  281. hTbl0 = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[0]);
  282. if (!hTbl0) {
  283. dwSize = 0;
  284. goto RevConvUnmapCodeTbl;
  285. }
  286. lpTbl0 = MapViewOfFile(hTbl0, FILE_MAP_READ, 0, 0, 0);
  287. if (!lpTbl0) {
  288. dwSize = 0;
  289. goto RevConvCloseTbl0;
  290. }
  291. #endif
  292. #if defined(CHAJEI) || defined(PHON)
  293. hTbl1 = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[1]);
  294. if (!hTbl1) {
  295. dwSize = 0;
  296. goto RevConvUnmapTbl0;
  297. }
  298. lpTbl1 = MapViewOfFile(hTbl1, FILE_MAP_READ, 0, 0, 0);
  299. if (!lpTbl1) {
  300. dwSize = 0;
  301. goto RevConvCloseTbl1;
  302. }
  303. #endif
  304. #if defined(CHAJEI) || defined(PHON) || defined(QUICK)
  305. lpStart = lpTbl;
  306. lpEnd = lpTbl + lpImeL->uTblSize[2];
  307. #else
  308. lpStart = lpTbl + lpImeL->nSeqBytes;
  309. lpEnd = lpTbl + lpImeL->uTblSize[0];
  310. #endif
  311. #if defined(CHAJEI) || defined(PHON) || defined(QUICK)
  312. for (; lpStart < lpEnd; lpStart += sizeof(WORD)) {
  313. #else
  314. for (; lpStart < lpEnd; lpStart += lpImeL->nSeqBytes + sizeof(WORD)) {
  315. #endif
  316. DWORD dwPattern;
  317. int i;
  318. #if defined(CHAJEI) || defined(PHON) || defined(QUICK)
  319. UINT uOffset;
  320. #endif
  321. #if defined(CHAJEI) || defined(QUICK)
  322. DWORD dwSeqA1, dwSeqA5;
  323. #endif
  324. #if defined(PHON)
  325. UINT uPhoneticCode;
  326. #endif
  327. #if defined(PHON)
  328. uPhoneticCode = *(LPUNAWORD)lpStart;
  329. #ifdef UNICODE
  330. if (IsValidCode(uPhoneticCode)) {
  331. if (uPhoneticCode != uCode) {
  332. continue;
  333. }
  334. } else {
  335. if (InverseEncode(uPhoneticCode) != uCode) {
  336. continue;
  337. }
  338. }
  339. #else
  340. if ((uPhoneticCode | 0x8000) != uCode) {
  341. continue;
  342. }
  343. #endif
  344. #else
  345. if (*(LPUNAWORD)lpStart != uCode) {
  346. continue;
  347. }
  348. #endif
  349. // find the code
  350. #if defined(CHAJEI) || defined(QUICK)
  351. uOffset = SearchOffset(lpTbl0, lpImeL->uTblSize[0],
  352. (UINT)(lpStart - lpTbl) / sizeof(WORD));
  353. dwSeqA1 = uOffset / 27; // seq code of A1
  354. dwSeqA5 = uOffset % 27; // seq code of A5
  355. #endif
  356. #if defined(PHON)
  357. uOffset = SearchOffset(lpTbl1, lpImeL->uTblSize[1],
  358. (UINT)(lpStart - lpTbl) / sizeof(WORD));
  359. #endif
  360. #if defined(CHAJEI)
  361. // pattern of A234
  362. dwPattern = *(LPWORD)(lpTbl1 + (lpStart - lpTbl)) << lpImeL->nSeqBits;
  363. // sequence code of A1
  364. dwPattern |= dwSeqA1 << (lpImeL->nSeqBits * 4);
  365. // test if 0 for A234 pattern
  366. dwSeqA1 = lpImeL->dwSeqMask << (lpImeL->nSeqBits * 3);
  367. // sequence code of A5
  368. for (i = 1; i < lpImeL->nMaxKey; i++) {
  369. if (!(dwPattern & dwSeqA1)) {
  370. dwPattern |= dwSeqA5 <<
  371. (lpImeL->nSeqBits * (lpImeL->nMaxKey - i - 1));
  372. break;
  373. } else {
  374. dwSeqA1 >>= lpImeL->nSeqBits;
  375. }
  376. }
  377. #elif defined(PHON)
  378. dwPattern = *(LPUNADWORD)(lpTbl0 + uOffset * lpImeL->nSeqBytes) &
  379. lpImeL->dwPatternMask;
  380. #elif defined(QUICK)
  381. dwPattern = (DWORD)dwSeqA1 << lpImeL->nSeqBits;
  382. dwPattern |= dwSeqA5;
  383. #else
  384. dwPattern = *(LPUNADWORD)(lpStart - lpImeL->nSeqBytes) &
  385. lpImeL->dwPatternMask;
  386. #endif
  387. #if defined(QUICK)
  388. for (i = 2 - 1; i >= 0; i--) {
  389. #else
  390. for (i = lpImeL->nMaxKey - 1; i >= 0; i--) {
  391. #endif
  392. WORD wCompChar;
  393. wCompChar = lpImeL->wSeq2CompTbl[dwPattern & lpImeL->dwSeqMask];
  394. *(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[
  395. lpCandList->dwCount] + sizeof(WORD) * i) = wCompChar;
  396. dwPattern >>= lpImeL->nSeqBits;
  397. }
  398. // null terminator
  399. #if defined(QUICK)
  400. *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  401. lpCandList->dwCount] + sizeof(WCHAR) * 2) = '\0';
  402. #else
  403. *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  404. lpCandList->dwCount] + sizeof(WCHAR) * lpImeL->nMaxKey) = '\0';
  405. #endif
  406. #if defined(PHON)
  407. if (!lpCandList->dwCount) {
  408. #ifdef UNICODE
  409. } else if (IsValidCode(uPhoneticCode)) {
  410. #else
  411. } else if (uPhoneticCode & 0x8000) {
  412. #endif
  413. PHONREVERSEBUF phTmpBuf;
  414. phTmpBuf = *(LPPHONREVERSEBUF)((LPBYTE)
  415. lpCandList + lpCandList->dwOffset[lpCandList->dwCount]);
  416. *(LPPHONREVERSEBUF)((LPBYTE)lpCandList +
  417. lpCandList->dwOffset[lpCandList->dwCount]) =
  418. *(LPPHONREVERSEBUF)((LPBYTE)lpCandList +
  419. lpCandList->dwOffset[0]);
  420. *(LPPHONREVERSEBUF)((LPBYTE)lpCandList +
  421. lpCandList->dwOffset[0]) = phTmpBuf;
  422. } else {
  423. }
  424. #endif
  425. // string count ++
  426. lpCandList->dwCount++;
  427. #if defined(CHAJEI) || defined(WINAR30) || defined(DAYI)
  428. // do not need to search more canidate
  429. break;
  430. #endif
  431. if (lpCandList->dwCount >= (DWORD)uMaxCand) {
  432. break;
  433. }
  434. #if defined(QUICK)
  435. lpCandList->dwOffset[lpCandList->dwCount] =
  436. lpCandList->dwOffset[lpCandList->dwCount - 1] +
  437. sizeof(WCHAR) * 2 + sizeof(TCHAR);
  438. #else
  439. lpCandList->dwOffset[lpCandList->dwCount] =
  440. lpCandList->dwOffset[lpCandList->dwCount - 1] +
  441. sizeof(WCHAR) * lpImeL->nMaxKey + sizeof(TCHAR);
  442. #endif
  443. }
  444. if (!lpCandList->dwCount) {
  445. dwSize = 0;
  446. }
  447. #if defined(CHAJEI) || defined(PHON)
  448. UnmapViewOfFile(lpTbl1);
  449. RevConvCloseTbl1:
  450. CloseHandle(hTbl1);
  451. RevConvUnmapTbl0:
  452. #endif
  453. #if defined(CHAJEI) || defined(PHON) || defined(QUICK)
  454. UnmapViewOfFile(lpTbl0);
  455. RevConvCloseTbl0:
  456. CloseHandle(hTbl0);
  457. RevConvUnmapCodeTbl:
  458. #endif
  459. UnmapViewOfFile(lpTbl);
  460. RevConvCloseCodeTbl:
  461. CloseHandle(hTbl);
  462. if (fNeedUnload) {
  463. FreeTable(lpInstL);
  464. }
  465. #endif
  466. return (dwSize);
  467. }
  468. #endif
  469. /**********************************************************************/
  470. /* ImeConversionList() / UniImeConversionList() */
  471. /**********************************************************************/
  472. #if defined(UNIIME)
  473. DWORD WINAPI UniImeConversionList(
  474. LPINSTDATAL lpInstL,
  475. LPIMEL lpImeL,
  476. #else
  477. DWORD WINAPI ImeConversionList(
  478. #endif
  479. HIMC hIMC,
  480. LPCTSTR lpszSrc,
  481. LPCANDIDATELIST lpCandList,
  482. DWORD dwBufLen,
  483. UINT uFlag)
  484. {
  485. #if defined(ROMANIME)
  486. return (0);
  487. #else
  488. UINT uCode;
  489. if (!dwBufLen) {
  490. } else if (!lpszSrc) {
  491. return (0);
  492. } else if (!*lpszSrc) {
  493. return (0);
  494. } else if (!lpCandList) {
  495. return (0);
  496. } else if (dwBufLen <= sizeof(CANDIDATELIST)) {
  497. // buffer size can not even put the header information
  498. return (0);
  499. } else {
  500. }
  501. switch (uFlag) {
  502. case GCL_CONVERSION:
  503. return Conversion(
  504. #if defined(UNIIME)
  505. lpInstL, lpImeL,
  506. #endif
  507. lpszSrc, lpCandList, dwBufLen);
  508. break;
  509. case GCL_REVERSECONVERSION:
  510. if (!dwBufLen) {
  511. return ReverseConversion(
  512. #if defined(UNIIME)
  513. lpInstL, lpImeL,
  514. #endif
  515. 0, lpCandList, dwBufLen);
  516. }
  517. // only support one DBCS char reverse conversion
  518. if (*(LPTSTR)((LPBYTE)lpszSrc + sizeof(WORD)) != '\0') {
  519. return (0);
  520. }
  521. uCode = *(LPUNAWORD)lpszSrc;
  522. #ifndef UNICODE
  523. // swap lead byte & second byte, UNICODE don't need it
  524. uCode = HIBYTE(uCode) | (LOBYTE(uCode) << 8);
  525. #endif
  526. return ReverseConversion(
  527. #if defined(UNIIME)
  528. lpInstL, lpImeL,
  529. #endif
  530. uCode, lpCandList, dwBufLen);
  531. break;
  532. case GCL_REVERSE_LENGTH:
  533. return sizeof(WCHAR);
  534. break;
  535. default:
  536. return (0);
  537. break;
  538. }
  539. #endif
  540. }