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.

1228 lines
33 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. SEARCH.c
  5. ++*/
  6. #include <windows.h>
  7. #include <immdev.h>
  8. #include "imeattr.h"
  9. #include "imedefs.h"
  10. #if !defined(ROMANIME)
  11. #if defined(WINAR30)
  12. /**********************************************************************/
  13. /* SearchQuickKey() */
  14. /* Description: */
  15. /* Search for the quick key table */
  16. /* file format can be changed in different version for */
  17. /* performance consideration, ISVs should not assume its format */
  18. /* Array has the CopyRight of this table file */
  19. /**********************************************************************/
  20. void PASCAL SearchQuickKey(
  21. LPCANDIDATELIST lpCandList,
  22. LPPRIVCONTEXT lpImcP)
  23. {
  24. UINT uStart, uEnd;
  25. HANDLE hHighWordTbl;
  26. LPWORD lpHighWordTbl;
  27. if (lpImcP->bSeq[1]) {
  28. uStart = (lpImcP->bSeq[0] - 1) * 300 + (lpImcP->bSeq[1] - 1) * 10 +
  29. 300;
  30. } else {
  31. uStart = (lpImcP->bSeq[0] - 1) * 10;
  32. }
  33. hHighWordTbl = OpenFileMapping(FILE_MAP_READ, FALSE,
  34. lpImeL->szTblFile[1]);
  35. if (!hHighWordTbl) {
  36. return;
  37. }
  38. lpHighWordTbl = MapViewOfFile(hHighWordTbl, FILE_MAP_READ,
  39. 0, 0, 0);
  40. if (!lpHighWordTbl) {
  41. goto SrchQuickKeyOvr;
  42. }
  43. uEnd = uStart + 10;
  44. for (; uStart < uEnd; uStart++) {
  45. UINT uCode;
  46. uCode = (WORD)*(lpHighWordTbl + uStart);
  47. AddCodeIntoCand(lpCandList, uCode);
  48. }
  49. UnmapViewOfFile(lpHighWordTbl);
  50. SrchQuickKeyOvr:
  51. CloseHandle(hHighWordTbl);
  52. }
  53. #endif
  54. #if defined(DAYI) || defined(UNIIME)
  55. /**********************************************************************/
  56. /* SearchPhraseTbl() */
  57. /* Description: */
  58. /* file format can be changed in different version for */
  59. /* performance consideration, ISVs should not assume its format */
  60. /**********************************************************************/
  61. void PASCAL SearchPhraseTbl( // searching the phrase table files
  62. #if defined(UNIIME)
  63. LPIMEL lpImeL,
  64. #endif
  65. UINT uTblIndex,
  66. LPCANDIDATELIST lpCandList,
  67. DWORD dwPattern)
  68. {
  69. HANDLE hTbl;
  70. LPBYTE lpTbl;
  71. int iLo, iHi, iMid;
  72. BOOL bFound;
  73. LPBYTE lpPattern;
  74. hTbl = OpenFileMapping(FILE_MAP_READ, FALSE,
  75. lpImeL->szTblFile[uTblIndex]);
  76. if (!hTbl) {
  77. return;
  78. }
  79. lpTbl = (LPBYTE)MapViewOfFile(hTbl, FILE_MAP_READ, 0, 0, 0);
  80. if (!lpTbl) {
  81. CloseHandle(hTbl);
  82. return;
  83. }
  84. iLo = 0;
  85. #ifdef UNICODE
  86. iHi = lpImeL->uTblSize[uTblIndex] / (lpImeL->nSeqBytes + sizeof(DWORD));
  87. #else
  88. iHi = lpImeL->uTblSize[uTblIndex] / (lpImeL->nSeqBytes + sizeof(WORD));
  89. #endif
  90. iMid = (iHi + iLo) /2;
  91. // binary search
  92. for (; iLo <= iHi; ) {
  93. LPUNADWORD lpCurr;
  94. #ifdef UNICODE
  95. lpCurr = (LPDWORD)(lpTbl + (lpImeL->nSeqBytes + sizeof(DWORD)) *
  96. iMid);
  97. #else
  98. lpCurr = (LPDWORD)(lpTbl + (lpImeL->nSeqBytes + sizeof(WORD)) *
  99. iMid);
  100. #endif
  101. if (dwPattern > (*lpCurr & lpImeL->dwPatternMask)) {
  102. iLo = iMid + 1;
  103. } else if (dwPattern < (*lpCurr & lpImeL->dwPatternMask)) {
  104. iHi = iMid - 1;
  105. } else {
  106. bFound = TRUE;
  107. break;
  108. }
  109. iMid = (iHi + iLo) /2;
  110. }
  111. if (bFound) {
  112. HANDLE hPhrase;
  113. LPBYTE lpPhrase;
  114. LPWORD lpStart, lpEnd;
  115. // find the lower bound
  116. #ifdef UNICODE
  117. lpPattern = lpTbl + (lpImeL->nSeqBytes + sizeof(DWORD)) * iMid;
  118. #else
  119. lpPattern = lpTbl + (lpImeL->nSeqBytes + sizeof(WORD)) * iMid;
  120. #endif
  121. #ifdef UNICODE
  122. for (; (LPBYTE)lpPattern >= lpTbl; (LPBYTE)lpPattern -=
  123. lpImeL->nSeqBytes + sizeof(DWORD)) {
  124. #else
  125. for (; (LPBYTE)lpPattern >= lpTbl; (LPBYTE)lpPattern -=
  126. lpImeL->nSeqBytes + sizeof(WORD)) {
  127. #endif
  128. if (dwPattern > (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask)) {
  129. // previous one is the lower bound
  130. #ifdef UNICODE
  131. (LPBYTE)lpPattern += lpImeL->nSeqBytes + sizeof(DWORD);
  132. #else
  133. (LPBYTE)lpPattern += lpImeL->nSeqBytes + sizeof(WORD);
  134. #endif
  135. break;
  136. }
  137. }
  138. if ((LPBYTE)lpPattern <= lpTbl) {
  139. goto SrchPhrUnmapPattern;
  140. }
  141. hPhrase = OpenFileMapping(FILE_MAP_READ, FALSE,
  142. lpImeL->szTblFile[uTblIndex + 1]);
  143. if (!hPhrase) {
  144. goto SrchPhrUnmapPattern;
  145. }
  146. lpPhrase = (LPBYTE)MapViewOfFile(hPhrase, FILE_MAP_READ, 0, 0, 0);
  147. if (!lpPhrase) {
  148. goto SrchPhrClosePhr;
  149. }
  150. // offset of the string
  151. #ifdef UNICODE
  152. lpEnd = (LPWORD)lpPhrase + *(LPUNADWORD)(lpPattern +
  153. lpImeL->nSeqBytes);
  154. #else
  155. lpEnd = (LPWORD)lpPhrase + *(LPUNAWORD)(lpPattern + lpImeL->nSeqBytes);
  156. #endif
  157. #ifdef UNICODE
  158. for (; dwPattern == (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask);
  159. (LPBYTE)lpPattern += lpImeL->nSeqBytes + sizeof(DWORD)) {
  160. #else
  161. for (; dwPattern == (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask);
  162. (LPBYTE)lpPattern += lpImeL->nSeqBytes + sizeof(WORD)) {
  163. #endif
  164. WORD wCode;
  165. DWORD dwStrLen;
  166. lpStart = lpEnd;
  167. // offset of next string
  168. #ifdef UNICODE
  169. lpEnd = (LPWORD)lpPhrase + *(LPUNADWORD)(lpPattern +
  170. lpImeL->nSeqBytes * 2 + sizeof(DWORD));
  171. #else
  172. lpEnd = (LPWORD)lpPhrase + *(LPUNAWORD)(lpPattern +
  173. lpImeL->nSeqBytes * 2 + sizeof(WORD));
  174. #endif
  175. for (dwStrLen = 0; lpStart < lpEnd; lpStart++,
  176. dwStrLen += sizeof(WORD)) {
  177. wCode = *lpStart;
  178. #ifndef UNICODE
  179. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  180. #endif
  181. // add this char into candidate list
  182. *(LPWSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  183. lpCandList->dwCount] + dwStrLen) = wCode;
  184. }
  185. // null terminator
  186. *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  187. lpCandList->dwCount] + dwStrLen) = '\0';
  188. dwStrLen += sizeof(TCHAR);
  189. // add one string into candidate list
  190. lpCandList->dwCount++;
  191. if (lpCandList->dwCount >= MAXCAND) {
  192. // Grow memory here and do something,
  193. // if you still want to process it.
  194. break;
  195. }
  196. // string length plus size of the null terminator
  197. lpCandList->dwOffset[lpCandList->dwCount] =
  198. lpCandList->dwOffset[lpCandList->dwCount - 1] +
  199. dwStrLen + sizeof(TCHAR);
  200. }
  201. UnmapViewOfFile(lpPhrase);
  202. SrchPhrClosePhr:
  203. CloseHandle(hPhrase);
  204. }
  205. SrchPhrUnmapPattern:
  206. UnmapViewOfFile(lpTbl);
  207. CloseHandle(hTbl);
  208. return;
  209. }
  210. #endif
  211. #if defined(WINAR30)
  212. /**********************************************************************/
  213. /* SearchPhraseTbl() */
  214. /* Description: */
  215. /* file format can be changed in different version for */
  216. /* performance consideration, ISVs should not assume its format */
  217. /**********************************************************************/
  218. void PASCAL SearchPhraseTbl( // searching the phrase table files
  219. UINT uTblIndex,
  220. LPCANDIDATELIST lpCandList,
  221. DWORD dwPattern)
  222. {
  223. HANDLE hTbl;
  224. LPBYTE lpTbl;
  225. int iLo, iHi, iMid;
  226. BOOL bFound;
  227. LPBYTE lpPattern,lpPattern_end;
  228. hTbl = OpenFileMapping(FILE_MAP_READ, FALSE,
  229. lpImeL->szTblFile[uTblIndex]);
  230. if (!hTbl) {
  231. return;
  232. }
  233. lpTbl = (LPBYTE)MapViewOfFile(hTbl, FILE_MAP_READ, 0, 0, 0);
  234. if (!lpTbl) {
  235. CloseHandle(hTbl);
  236. return;
  237. }
  238. iLo = 1;
  239. // iHi = lpImeL->uTblSize[uTblIndex] / (lpImeL->nSeqBytes *2);
  240. iHi = (*(LPDWORD)(lpTbl) & lpImeL->dwPatternMask);
  241. iMid = (iHi + iLo) /2;
  242. // binary search
  243. for (; iLo <= iHi; ) {
  244. LPUNADWORD lpCurr;
  245. lpCurr = (LPDWORD)(lpTbl + (lpImeL->nSeqBytes * 2 ) *
  246. iMid);
  247. if (dwPattern > (*lpCurr & lpImeL->dwPatternMask)) {
  248. iLo = iMid + 1;
  249. } else if (dwPattern < (*lpCurr & lpImeL->dwPatternMask)) {
  250. iHi = iMid - 1;
  251. } else {
  252. bFound = TRUE;
  253. break;
  254. }
  255. iMid = (iHi + iLo) /2;
  256. }
  257. if (bFound) {
  258. HANDLE hPhrase;
  259. LPBYTE lpPhrase;
  260. LPWORD lpStart, lpEnd;
  261. // find the lower bound
  262. lpPattern = lpTbl + (lpImeL->nSeqBytes * 2) * iMid;
  263. for (; (LPBYTE)lpPattern >= lpTbl; (LPBYTE)lpPattern -=
  264. lpImeL->nSeqBytes * 2 ) {
  265. if (dwPattern > (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask)) {
  266. // previous one is the lower bound
  267. (LPBYTE)lpPattern += lpImeL->nSeqBytes * 2;
  268. break;
  269. }
  270. }
  271. if ((LPBYTE)lpPattern <= lpTbl) {
  272. goto SrchPhrUnmapPattern;
  273. }
  274. hPhrase = OpenFileMapping(FILE_MAP_READ, FALSE,
  275. lpImeL->szTblFile[uTblIndex + 1]);
  276. if (!hPhrase) {
  277. goto SrchPhrUnmapPattern;
  278. }
  279. lpPhrase = (LPBYTE)MapViewOfFile(hPhrase, FILE_MAP_READ, 0, 0, 0);
  280. if (!lpPhrase) {
  281. goto SrchPhrClosePhr;
  282. }
  283. // offset of the string
  284. lpEnd = (LPWORD)lpPhrase + (*(LPUNADWORD)(lpPattern + lpImeL->nSeqBytes) & lpImeL->dwPatternMask);
  285. for (; dwPattern == (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask);
  286. (LPBYTE)lpPattern += lpImeL->nSeqBytes * 2 ) {
  287. WORD wCode;
  288. DWORD dwStrLen;
  289. lpStart = lpEnd;
  290. // offset of next string
  291. lpEnd = (LPWORD)lpPhrase + (*(LPUNADWORD)(lpPattern +
  292. lpImeL->nSeqBytes * 3) & lpImeL->dwPatternMask);
  293. for (dwStrLen = 0; lpStart < lpEnd; lpStart++,
  294. dwStrLen += sizeof(WORD)) {
  295. wCode = *lpStart;
  296. // add this char into candidate list
  297. *(LPWSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  298. lpCandList->dwCount] + dwStrLen) = wCode;
  299. }
  300. // null terminator
  301. *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  302. lpCandList->dwCount] + dwStrLen) = '\0';
  303. dwStrLen += sizeof(TCHAR);
  304. // add one string into candidate list
  305. lpCandList->dwCount++;
  306. if (lpCandList->dwCount >= MAXCAND) {
  307. // Grow memory here and do something,
  308. // if you still want to process it.
  309. break;
  310. }
  311. // string length plus size of the null terminator
  312. lpCandList->dwOffset[lpCandList->dwCount] =
  313. lpCandList->dwOffset[lpCandList->dwCount - 1] +
  314. dwStrLen + sizeof(TCHAR);
  315. }
  316. iHi = (*(LPDWORD)(lpTbl) & lpImeL->dwPatternMask);
  317. lpPattern = lpTbl + (lpImeL->nSeqBytes * 2) * iHi;
  318. iHi = (*(LPDWORD)(lpTbl+4) & lpImeL->dwPatternMask);
  319. lpPattern_end = lpTbl + (lpImeL->nSeqBytes * 2) * iHi;
  320. for (; (LPBYTE)lpPattern < lpPattern_end; (LPBYTE)lpPattern +=
  321. lpImeL->nSeqBytes * 2 ) {
  322. WORD wCode;
  323. DWORD dwStrLen;
  324. if (dwPattern == (*(LPUNADWORD)lpPattern & lpImeL->dwPatternMask)) {
  325. lpStart = (LPWORD)lpPhrase + (*(LPUNADWORD)(lpPattern + lpImeL->nSeqBytes) & lpImeL->dwPatternMask);
  326. lpEnd = (LPWORD)lpPhrase + (*(LPUNADWORD)(lpPattern + (lpImeL->nSeqBytes *3)) & lpImeL->dwPatternMask);
  327. for (dwStrLen = 0; lpStart < lpEnd; lpStart++,
  328. dwStrLen += sizeof(WORD)) {
  329. wCode = *lpStart;
  330. // add this char into candidate list
  331. *(LPWSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  332. lpCandList->dwCount] + dwStrLen) = wCode;
  333. }
  334. // null terminator
  335. *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  336. lpCandList->dwCount] + dwStrLen) = '\0';
  337. dwStrLen += sizeof(TCHAR);
  338. // add one string into candidate list
  339. lpCandList->dwCount++;
  340. if (lpCandList->dwCount >= MAXCAND) {
  341. // Grow memory here and do something,
  342. // if you still want to process it.
  343. break;
  344. }
  345. // string length plus size of the null terminator
  346. lpCandList->dwOffset[lpCandList->dwCount] =
  347. lpCandList->dwOffset[lpCandList->dwCount - 1] +
  348. dwStrLen + sizeof(TCHAR);
  349. }
  350. }
  351. UnmapViewOfFile(lpPhrase);
  352. SrchPhrClosePhr:
  353. CloseHandle(hPhrase);
  354. }
  355. SrchPhrUnmapPattern:
  356. UnmapViewOfFile(lpTbl);
  357. CloseHandle(hTbl);
  358. return;
  359. }
  360. #endif
  361. #if defined(CHAJEI) || defined(QUICK) || defined(WINAR30)
  362. /**********************************************************************/
  363. /* MatchPattern() */
  364. /**********************************************************************/
  365. DWORD PASCAL MatchPattern(
  366. DWORD dwSearchPattern,
  367. LPPRIVCONTEXT lpImcP)
  368. {
  369. int i;
  370. if (lpImcP->iGhostCard == lpImeL->nMaxKey) {
  371. #if defined(WINAR30)
  372. } else if (lpImcP->iGhostCard == 0) {
  373. // no order search
  374. BYTE bSeq[8];
  375. int j;
  376. *(LPDWORD)bSeq = *(LPDWORD)lpImcP->bSeq;
  377. *(LPDWORD)&bSeq[4] = *(LPDWORD)&lpImcP->bSeq[4];
  378. // 0 out the ghost card *XYZ -> 0XYZ
  379. bSeq[0] = 0;
  380. for (j = 0; j < lpImeL->nMaxKey; j++,
  381. dwSearchPattern >>= lpImeL->nSeqBits) {
  382. DWORD dwSeqCode;
  383. dwSeqCode = dwSearchPattern & lpImeL->dwSeqMask;
  384. if (!dwSeqCode) {
  385. continue;
  386. }
  387. for (i = 1; i < lpImcP->iInputEnd; i++) {
  388. if (dwSeqCode == bSeq[i]) {
  389. // find one - turn off this one not search again
  390. bSeq[i] = 0;
  391. break;
  392. }
  393. }
  394. }
  395. if (*(LPDWORD)bSeq) {
  396. // not matched, next one
  397. dwSearchPattern = 0;
  398. } else if (*(LPDWORD)&bSeq[4]) {
  399. // not matched, next one
  400. dwSearchPattern = 0;
  401. } else {
  402. dwSearchPattern = lpImcP->dwPattern;
  403. }
  404. #endif
  405. } else {
  406. DWORD dwPatternTmp;
  407. DWORD dwPrefixMask, dwPostfixMask;
  408. int iGhostCard;
  409. #if defined(QUICK)
  410. if (lpImcP->iInputEnd == 1) {
  411. // for quick the single input X can not get any mask
  412. return (dwSearchPattern);
  413. }
  414. #endif
  415. dwPatternTmp = dwSearchPattern;
  416. // prepare prefix mask - for example XX mask of XX*Y
  417. dwPrefixMask = lpImeL->dwPatternMask;
  418. for (i = lpImeL->nMaxKey - 1; i >= lpImcP->iGhostCard; i--) {
  419. dwPrefixMask <<= lpImeL->nSeqBits;
  420. }
  421. dwSearchPattern &= dwPrefixMask;
  422. // prepare postfix mask - for example YY mask of X*YY
  423. #if defined(QUICK)
  424. // we do not have X*Y for quick IME, we use a virtual * here
  425. iGhostCard = lpImcP->iGhostCard - 1;
  426. #else
  427. iGhostCard = lpImcP->iGhostCard;
  428. #endif
  429. // + 1 because this first mask do not need to shift
  430. // so the shift time will be one time less
  431. for (i = iGhostCard + 1 + 1; i < lpImeL->nMaxKey; i++,
  432. dwPatternTmp >>= lpImeL->nSeqBits) {
  433. if (dwPatternTmp & lpImeL->dwSeqMask) {
  434. break;
  435. }
  436. }
  437. dwPostfixMask = 0;
  438. for (i = iGhostCard + 1; i < lpImcP->iInputEnd; i++) {
  439. dwPostfixMask <<= lpImeL->nSeqBits;
  440. dwPostfixMask |= lpImeL->dwSeqMask;
  441. }
  442. dwPatternTmp &= dwPostfixMask;
  443. for (; i < lpImeL->nMaxKey; i++) {
  444. dwPatternTmp <<= lpImeL->nSeqBits;
  445. }
  446. dwSearchPattern |= dwPatternTmp;
  447. }
  448. return (dwSearchPattern);
  449. }
  450. #endif
  451. #if defined(WINAR30)
  452. /**********************************************************************/
  453. /* WildCardSearchPattern() */
  454. /**********************************************************************/
  455. void PASCAL WildCardSearchPattern(
  456. LPBYTE lpCurr,
  457. LPBYTE lpEnd,
  458. LPPRIVCONTEXT lpImcP,
  459. LPCANDIDATELIST lpCandList)
  460. {
  461. DWORD dwRecLen;
  462. dwRecLen = lpImeL->nSeqBytes + sizeof(WORD);
  463. for (; lpCurr < lpEnd; lpCurr += dwRecLen) {
  464. DWORD dwSearchPattern;
  465. #if defined(WINAR30)
  466. DWORD dwWildCardPattern;
  467. #endif
  468. UINT uCode;
  469. // skip the first word (bank ID) of internal code
  470. dwSearchPattern = *(LPUNADWORD)lpCurr & lpImeL->dwPatternMask;
  471. #if defined(WINAR30)
  472. dwWildCardPattern = dwSearchPattern;
  473. #endif
  474. if (lpImcP->iGhostCard != lpImeL->nMaxKey) {
  475. dwSearchPattern = MatchPattern(dwSearchPattern, lpImcP);
  476. }
  477. #if defined(WINAR30)
  478. dwSearchPattern &= lpImcP->dwWildCardMask;
  479. #endif
  480. if (lpImcP->dwPattern != dwSearchPattern) {
  481. continue;
  482. }
  483. #if defined(WINAR30)
  484. if (!lpImcP->dwLastWildCard) {
  485. } else if (dwWildCardPattern & lpImcP->dwLastWildCard) {
  486. // a ? wild card or a * ghost card must have a stroke there
  487. } else {
  488. // a ? wild card or a * ghost card do not have a stroke there
  489. // - can not match
  490. continue;
  491. }
  492. #endif
  493. uCode = *(LPWSTR)(lpCurr + lpImeL->nSeqBytes);
  494. AddCodeIntoCand(lpCandList, uCode);
  495. if (lpCandList->dwCount >= MAXCAND) {
  496. // Grow memory here and do something,
  497. // if you still want to process it.
  498. break;
  499. }
  500. }
  501. return;
  502. }
  503. #endif
  504. #if !defined(WINIME) && !defined(UNICDIME)
  505. /**********************************************************************/
  506. /* SearchPattern() */
  507. /**********************************************************************/
  508. #if defined(CHAJEI) || defined(QUICK)
  509. int PASCAL SearchPattern(
  510. LPBYTE lpTbl,
  511. LPPRIVCONTEXT lpImcP)
  512. {
  513. int iLo, iMid, iHi;
  514. #if defined(CHAJEI)
  515. DWORD dwCompReadStrLen;
  516. #endif
  517. if (lpImcP->bSeq[0] > lpImeL->nSeqCode) {
  518. return (0);
  519. }
  520. iMid = lpImcP->bSeq[0] * (lpImeL->nSeqCode + 1); // A1 char
  521. #if defined(QUICK)
  522. if (lpImcP->bSeq[1] > lpImeL->nSeqCode) {
  523. return (0);
  524. }
  525. iMid += lpImcP->bSeq[1];
  526. #endif
  527. #if defined(CHAJEI)
  528. if (!lpImcP->bSeq[0]) {
  529. dwCompReadStrLen = 0;
  530. } else if (!lpImcP->bSeq[1]) {
  531. dwCompReadStrLen = sizeof(WORD);
  532. } else if (!lpImcP->bSeq[2]) {
  533. dwCompReadStrLen = 2 * sizeof(WORD);
  534. } else if (!lpImcP->bSeq[3]) {
  535. dwCompReadStrLen = 3 * sizeof(WORD);
  536. } else if (!lpImcP->bSeq[4]) {
  537. dwCompReadStrLen = 4 * sizeof(WORD);
  538. } else {
  539. dwCompReadStrLen = 5 * sizeof(WORD);
  540. }
  541. if (dwCompReadStrLen > sizeof(WORD)) {
  542. if (lpImcP->bSeq[dwCompReadStrLen / 2 - 1] > lpImeL->nSeqCode) {
  543. return (0);
  544. }
  545. iMid += lpImcP->bSeq[dwCompReadStrLen / 2 - 1];
  546. }
  547. #endif
  548. iLo = *((LPWORD)lpTbl + iMid); // start WORD of A234.TBL & ACODE.TBL
  549. iHi = *((LPWORD)lpTbl + iMid + 1); // end WORD of A234.TBL & ACODE.TBL
  550. if (iLo < iHi) {
  551. return (iMid);
  552. } else {
  553. return (0);
  554. }
  555. }
  556. #else
  557. int PASCAL SearchPattern(
  558. #if defined(UNIIME)
  559. LPIMEL lpImeL,
  560. #endif
  561. LPBYTE lpTbl,
  562. UINT uTblIndex,
  563. LPPRIVCONTEXT lpImcP)
  564. {
  565. int iLo, iMid, iHi;
  566. BOOL fFound;
  567. DWORD dwRecLen;
  568. fFound = FALSE;
  569. #if defined(PHON)
  570. dwRecLen = lpImeL->nSeqBytes;
  571. #else
  572. dwRecLen = lpImeL->nSeqBytes + sizeof(WORD);
  573. #endif
  574. iLo = 0;
  575. iHi = lpImeL->uTblSize[uTblIndex] / dwRecLen;
  576. iMid = (iLo + iHi) / 2;
  577. #if defined(WINAR30) //1996/3/3
  578. for (; iHi >= iLo; ) {
  579. LPUNADWORD lpCurr;
  580. lpCurr = (LPDWORD)(lpTbl + dwRecLen * iHi);
  581. if (lpImcP->dwPattern == (*lpCurr & lpImeL->dwPatternMask)) {
  582. fFound = TRUE;
  583. iMid = iHi;
  584. break;
  585. }
  586. iHi = iHi - 1;
  587. #else
  588. for (; iLo <= iHi; ) {
  589. LPUNADWORD lpCurr;
  590. lpCurr = (LPDWORD)(lpTbl + dwRecLen * iMid);
  591. if (lpImcP->dwPattern > (*lpCurr & lpImeL->dwPatternMask)) {
  592. iLo = iMid + 1;
  593. } else if (lpImcP->dwPattern < (*lpCurr & lpImeL->dwPatternMask)) {
  594. iHi = iMid - 1;
  595. } else {
  596. fFound = TRUE;
  597. break;
  598. }
  599. iMid = (iLo + iHi) / 2;
  600. #endif
  601. }
  602. if (fFound) {
  603. return (iMid);
  604. } else {
  605. return (0);
  606. }
  607. }
  608. #endif
  609. /**********************************************************************/
  610. /* FindPattern() */
  611. /**********************************************************************/
  612. void PASCAL FindPattern(
  613. #if defined(UNIIME)
  614. LPIMEL lpImeL,
  615. #endif
  616. LPBYTE lpTbl,
  617. int iMid,
  618. LPCANDIDATELIST lpCandList,
  619. LPPRIVCONTEXT lpImcP)
  620. {
  621. #ifndef WINAR30
  622. int iLo, iHi;
  623. #endif
  624. DWORD dwRecLen;
  625. #if defined(CHAJEI)
  626. HANDLE hTblA234;
  627. LPBYTE lpTblA234, lpA234;
  628. DWORD dwPatternA234;
  629. #endif
  630. #if defined(PHON) || defined(CHAJEI) || defined(QUICK)
  631. HANDLE hTblCode;
  632. LPBYTE lpTblCode;
  633. #endif
  634. LPBYTE lpStart, lpEnd;
  635. #if defined(PHON)
  636. dwRecLen = lpImeL->nSeqBytes;
  637. #elif !defined(CHAJEI) && !defined(QUICK)
  638. dwRecLen = lpImeL->nSeqBytes + sizeof(WORD);
  639. #else
  640. #endif
  641. // find the lower bound
  642. #if defined(PHON)
  643. {
  644. HANDLE hTable;
  645. LPWORD lpTable;
  646. hTable = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[1]);
  647. if (!hTable) {
  648. return;
  649. }
  650. lpTable = MapViewOfFile(hTable, FILE_MAP_READ, 0, 0, 0);
  651. if (!lpTable) {
  652. goto FndPatCloseTbl1;
  653. }
  654. iLo = *(lpTable + iMid);
  655. iHi = *(lpTable + iMid + 1);
  656. UnmapViewOfFile(lpTable);
  657. FndPatCloseTbl1:
  658. CloseHandle(hTable);
  659. if (!lpTable) {
  660. return;
  661. }
  662. }
  663. #elif defined(CHAJEI) || defined(QUICK)
  664. iLo = *((LPWORD)lpTbl + iMid);
  665. iHi = *((LPWORD)lpTbl + iMid + 1);
  666. if (iLo >= iHi) {
  667. return;
  668. }
  669. #else
  670. #if defined(WINAR30) //1996/3/4
  671. lpStart = lpTbl;
  672. lpEnd = lpTbl + dwRecLen * (iMid+1);
  673. #else
  674. // find the lower bound
  675. iLo = iMid - 1;
  676. lpStart = lpTbl + dwRecLen * iLo;
  677. for (; lpStart >= lpTbl; lpStart -= dwRecLen) {
  678. register DWORD dwSearchPattern;
  679. dwSearchPattern = *(LPUNADWORD)lpStart & lpImeL->dwPatternMask;
  680. if (lpImcP->dwPattern > dwSearchPattern) {
  681. // previous one is the lower bound
  682. lpStart += dwRecLen;
  683. break;
  684. }
  685. }
  686. if (lpStart <= lpTbl) {
  687. return;
  688. }
  689. // offset of code
  690. lpStart += lpImeL->nSeqBytes;
  691. // find the higher bound
  692. iHi = iMid + 1;
  693. lpEnd = lpTbl + dwRecLen * iHi;
  694. for (; ; lpEnd += dwRecLen) {
  695. register DWORD dwSearchPattern;
  696. dwSearchPattern = *(LPUNADWORD)lpEnd & lpImeL->dwPatternMask;
  697. if (lpImcP->dwPattern < dwSearchPattern) {
  698. // the one is the higher bound, not including
  699. break;
  700. }
  701. }
  702. // offset of code
  703. lpEnd += lpImeL->nSeqBytes;
  704. #endif
  705. #endif
  706. #if defined(CHAJEI)
  707. // A234.TBL
  708. hTblA234 = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[1]);
  709. if (!hTblA234) {
  710. return;
  711. }
  712. lpTblA234 = MapViewOfFile(hTblA234, FILE_MAP_READ, 0, 0, 0);
  713. if (!lpTblA234) {
  714. goto FndPatCloseTblA234;
  715. }
  716. lpA234 = lpTblA234 + sizeof(WORD) * iLo;
  717. dwPatternA234 = 0;
  718. if (lpImcP->bSeq[2]) {
  719. dwPatternA234 |= lpImcP->bSeq[1] << (lpImeL->nSeqBits * 2);
  720. }
  721. if (lpImcP->bSeq[3]) {
  722. dwPatternA234 |= lpImcP->bSeq[2] << lpImeL->nSeqBits;
  723. }
  724. if (lpImcP->bSeq[4]) {
  725. dwPatternA234 |= lpImcP->bSeq[3];
  726. }
  727. #endif
  728. #if defined(PHON) || defined(CHAJEI) || defined(QUICK)
  729. // PHONCODE.TBL ACODE.TBL
  730. hTblCode = OpenFileMapping(FILE_MAP_READ, FALSE, lpImeL->szTblFile[2]);
  731. if (!hTblCode) {
  732. return;
  733. }
  734. lpTblCode = MapViewOfFile(hTblCode, FILE_MAP_READ, 0, 0, 0);
  735. if (!lpTblCode) {
  736. goto FndPatCloseTblCode;
  737. }
  738. lpStart = lpTblCode + sizeof(WORD) * iLo;
  739. lpEnd = lpTblCode + sizeof(WORD) * iHi;
  740. dwRecLen = sizeof(WORD);
  741. #endif
  742. #if defined(CHAJEI)
  743. for (; lpStart < lpEnd; lpStart += dwRecLen, lpA234 += sizeof(WORD)) {
  744. #else
  745. for (; lpStart < lpEnd; lpStart += dwRecLen) {
  746. #endif
  747. UINT uCode;
  748. #if defined(CHAJEI)
  749. if (lpImcP->bSeq[1] == GHOSTCARD_SEQCODE) {
  750. if (!lpImcP->bSeq[2]) {
  751. // if the 3rd sequence code is 0, it is not a ghost card
  752. continue;
  753. }
  754. } else if (dwPatternA234 != *(LPWORD)lpA234) {
  755. continue;
  756. } else {
  757. }
  758. #endif
  759. #if defined(WINAR30) //1996/3/4
  760. register DWORD dwSearchPattern;
  761. dwSearchPattern = *(LPUNADWORD)lpStart & lpImeL->dwPatternMask;
  762. if (lpImcP->dwPattern == dwSearchPattern) {
  763. uCode = *(LPUNAWORD)(lpStart+lpImeL->nSeqBytes);
  764. AddCodeIntoCand(lpCandList, uCode);
  765. }
  766. #else
  767. uCode = *(LPUNAWORD)lpStart;
  768. #if defined(PHON) || defined(DAYI)
  769. #ifdef UNICODE
  770. if (!IsValidCode(uCode)) {
  771. uCode = InverseEncode(uCode);
  772. }
  773. #else
  774. // resolve duplicate composition for one code
  775. if (!(uCode & 0x8000)) {
  776. uCode |= 0x8000;
  777. }
  778. #endif
  779. #endif
  780. #if defined(UNIIME)
  781. AddCodeIntoCand(lpImeL,lpCandList, uCode);
  782. #else
  783. AddCodeIntoCand(lpCandList, uCode);
  784. #endif
  785. #endif
  786. if (lpCandList->dwCount >= MAXCAND) {
  787. // Grow memory here and do something,
  788. // if you still want to process it.
  789. break;
  790. }
  791. }
  792. #if defined(PHON) || defined(CHAJEI) || defined(QUICK)
  793. UnmapViewOfFile(lpTblCode);
  794. FndPatCloseTblCode:
  795. CloseHandle(hTblCode);
  796. #endif
  797. #if defined(CHAJEI)
  798. UnmapViewOfFile(lpTblA234);
  799. FndPatCloseTblA234:
  800. CloseHandle(hTblA234);
  801. #endif
  802. return;
  803. }
  804. #endif // !defined(WINIME) && !defined(UNICDIME)
  805. /**********************************************************************/
  806. /* SearchTbl() */
  807. /* Description: */
  808. /* file format can be changed in different version for */
  809. /* performance consideration, ISVs should not assume its format */
  810. /**********************************************************************/
  811. void PASCAL SearchTbl( // searching the standard table files
  812. #if defined(UNIIME)
  813. LPIMEL lpImeL,
  814. #endif
  815. UINT uTblIndex,
  816. LPCANDIDATELIST lpCandList,
  817. LPPRIVCONTEXT lpImcP)
  818. {
  819. #if defined(WINIME) || defined(UNICDIME)
  820. if (!lpImcP->bSeq[0]) {
  821. } else if (!lpImcP->bSeq[1]) {
  822. } else if (!lpImcP->bSeq[3]) {
  823. DWORD i;
  824. UINT uCode;
  825. uCode = (lpImcP->bSeq[0] - 1) << 12;
  826. uCode |= (lpImcP->bSeq[1] - 1) << 8;
  827. if (lpImcP->bSeq[2]) {
  828. // we want it match with internal code here so | 0x0001
  829. uCode |= (lpImcP->bSeq[2] - 1) << 4 | 0x0001;
  830. } else {
  831. uCode |= 0x0040;
  832. }
  833. for (i = 0; i < lpCandList->dwPageSize; i++, uCode++) {
  834. #if defined(WINIME) && defined(UNICODE)
  835. CHAR szCode[2];
  836. WCHAR wCode[2];
  837. szCode[0] = HIBYTE(uCode);
  838. szCode[1] = LOBYTE(uCode);
  839. wCode[0] = 0;
  840. MultiByteToWideChar(sImeG.uAnsiCodePage, MB_PRECOMPOSED,
  841. szCode, 2, wCode, sizeof(wCode) / sizeof(WCHAR));
  842. uCode = wCode[0];
  843. #endif
  844. #if defined(UNIIME)
  845. AddCodeIntoCand(lpImeL,lpCandList, uCode);
  846. #else
  847. AddCodeIntoCand(lpCandList, uCode);
  848. #endif
  849. }
  850. } else if (!lpImcP->bSeq[2]) {
  851. return;
  852. } else {
  853. UINT uCode;
  854. #if defined(WINIME) && defined(UNICODE)
  855. CHAR szCode[2];
  856. WCHAR wCode[2];
  857. #endif
  858. uCode = (lpImcP->bSeq[0] - 1) << 12;
  859. uCode |= (lpImcP->bSeq[1] - 1) << 8;
  860. uCode |= (lpImcP->bSeq[2] - 1) << 4;
  861. uCode |= (lpImcP->bSeq[3] - 1);
  862. #if defined(WINIME) && defined(UNICODE)
  863. szCode[0] = HIBYTE(uCode);
  864. szCode[1] = LOBYTE(uCode);
  865. wCode[0] = 0;
  866. MultiByteToWideChar(sImeG.uAnsiCodePage, MB_PRECOMPOSED,
  867. szCode, 2, wCode, sizeof(wCode) / sizeof(WCHAR));
  868. uCode = wCode[0];
  869. #endif
  870. #if defined(UNIIME)
  871. AddCodeIntoCand(lpImeL,lpCandList, uCode);
  872. #else
  873. AddCodeIntoCand(lpCandList, uCode);
  874. #endif
  875. }
  876. return;
  877. #else
  878. HANDLE hTbl;
  879. LPBYTE lpTbl;
  880. if (!lpImcP->dwPattern) {
  881. return;
  882. }
  883. #if defined(WINAR30) // 1996/2/5
  884. if (lpImcP->dwCompChar==0x27)
  885. goto SearchTblOvr;
  886. #endif
  887. hTbl = OpenFileMapping(FILE_MAP_READ, FALSE,
  888. lpImeL->szTblFile[uTblIndex]);
  889. if (!hTbl) {
  890. return;
  891. }
  892. lpTbl = (LPBYTE)MapViewOfFile(hTbl, FILE_MAP_READ, 0, 0, 0);
  893. if (!lpTbl) {
  894. goto SearchTblOvr;
  895. }
  896. #if defined(WINAR30)
  897. if (lpImcP->iGhostCard != lpImeL->nMaxKey) {
  898. WildCardSearchPattern(lpTbl, lpTbl + lpImeL->uTblSize[uTblIndex],
  899. lpImcP, lpCandList);
  900. } else if (lpImcP->dwLastWildCard) {
  901. WildCardSearchPattern(lpTbl, lpTbl + lpImeL->uTblSize[uTblIndex],
  902. lpImcP, lpCandList);
  903. } else {
  904. #else
  905. {
  906. #endif // defined(WINAR30)
  907. int iMid;
  908. #if defined(CHAJEI) || defined(QUICK)
  909. iMid = SearchPattern(lpTbl, lpImcP);
  910. #else
  911. iMid = SearchPattern(
  912. #if defined(UNIIME)
  913. lpImeL,
  914. #endif
  915. lpTbl, uTblIndex, lpImcP);
  916. #endif
  917. if (iMid > 0) {
  918. FindPattern(
  919. #if defined(UNIIME)
  920. lpImeL,
  921. #endif
  922. lpTbl, iMid, lpCandList, lpImcP);
  923. }
  924. }
  925. UnmapViewOfFile(lpTbl);
  926. SearchTblOvr:
  927. CloseHandle(hTbl);
  928. #if defined(DAYI)
  929. if (uTblIndex == 0) { // do not duplciate search the phrase table
  930. SearchPhraseTbl(1, lpCandList, lpImcP->dwPattern);
  931. }
  932. #endif
  933. #if defined(WINAR30) // 1996/2/5
  934. if (uTblIndex == 0 && lpImcP->dwCompChar==0x27) { // do not duplciate search the phrase table
  935. SearchPhraseTbl(4, lpCandList, lpImcP->dwPattern);
  936. }
  937. #endif
  938. #if defined(UNIIME) // same as Dayi need to search phrase table
  939. SearchPhraseTbl(lpImeL, 1, lpCandList, lpImcP->dwPattern);
  940. #endif
  941. return;
  942. #endif // !defined(WINIME) && !defined(UNICDIME)
  943. }
  944. #if !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
  945. /**********************************************************************/
  946. /* SearchUsrDic() */
  947. /**********************************************************************/
  948. void PASCAL SearchUsrDic( // searching the user dictionary
  949. #if defined(UNIIME)
  950. LPIMEL lpImeL,
  951. #endif
  952. LPCANDIDATELIST lpCandList,
  953. LPPRIVCONTEXT lpImcP)
  954. {
  955. HANDLE hUsrDicMem;
  956. LPBYTE lpUsrDicStart, lpCurr, lpUsrDicLimit;
  957. hUsrDicMem = OpenFileMapping(FILE_MAP_READ, FALSE,
  958. lpImeL->szUsrDicMap);
  959. if (!hUsrDicMem) {
  960. return;
  961. }
  962. lpUsrDicStart = (LPBYTE)MapViewOfFile(hUsrDicMem, FILE_MAP_READ,
  963. 0, 0, lpImeL->uUsrDicSize);
  964. if (!lpUsrDicStart) {
  965. goto SearchUsrDicOvr;
  966. }
  967. lpUsrDicLimit = lpUsrDicStart + lpImeL->uUsrDicSize;
  968. for (lpCurr = lpUsrDicStart; lpCurr < lpUsrDicLimit;
  969. lpCurr += lpImeL->nSeqBytes + sizeof(WORD)) {
  970. DWORD dwSearchPattern;
  971. UINT uCode;
  972. // skip the first word (bank ID) of internal code
  973. dwSearchPattern = *(LPUNADWORD)(lpCurr + sizeof(WORD)) &
  974. lpImeL->dwPatternMask;
  975. #if defined(CHAJEI) || defined(QUICK) || defined(WINAR30)
  976. if (lpImcP->iGhostCard != lpImeL->nMaxKey) {
  977. dwSearchPattern = MatchPattern(dwSearchPattern, lpImcP);
  978. }
  979. #endif
  980. #if defined(WINAR30)
  981. dwSearchPattern &= lpImcP->dwWildCardMask;
  982. #endif
  983. if (lpImcP->dwPattern != dwSearchPattern) {
  984. continue;
  985. }
  986. #if defined(WINAR30)
  987. if (!lpImcP->dwLastWildCard) {
  988. } else if (dwSearchPattern & lpImcP->dwLastWildCard) {
  989. // a ? wild card must have a stroke there
  990. } else {
  991. // a ? wild card do not have a stroke there - can not match
  992. continue;
  993. }
  994. #endif
  995. uCode = *(LPUNAWSTR)lpCurr;
  996. #if defined(UNIIME)
  997. AddCodeIntoCand(lpImeL,lpCandList, uCode);
  998. #else
  999. AddCodeIntoCand(lpCandList, uCode);
  1000. #endif
  1001. if (lpCandList->dwCount >= MAXCAND) {
  1002. // Grow memory here and do something,
  1003. // if you still want to process it.
  1004. break;
  1005. }
  1006. }
  1007. UnmapViewOfFile(lpUsrDicStart);
  1008. SearchUsrDicOvr:
  1009. CloseHandle(hUsrDicMem);
  1010. return;
  1011. }
  1012. #endif // !defined(WINIME) && !defined(UNICDIME) && !defined(ROMANIME)
  1013. #endif // !defined(ROMANIME)