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.

1486 lines
37 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. //
  4. // CThaiTrieIter - class CThaiTrieIter use for traversing trie.
  5. //
  6. // History:
  7. // created 7/99 aarayas
  8. //
  9. // �1999 Microsoft Corporation
  10. //----------------------------------------------------------------------------
  11. #include "CThaiTrieIter.hpp"
  12. static unsigned int iStackSize = 0;
  13. //+---------------------------------------------------------------------------
  14. //
  15. // Function: IsThaiBeginClusterCharacter
  16. //
  17. // Synopsis:
  18. //
  19. // Arguments:
  20. //
  21. // Modifies:
  22. //
  23. // History: created 8/99 aarayas
  24. //
  25. // Notes:
  26. //
  27. //----------------------------------------------------------------------------
  28. BOOL IsThaiBeginClusterCharacter(WCHAR wc)
  29. {
  30. return ( ( wc >= THAI_Vowel_Sara_E ) && (wc <= THAI_Vowel_Sara_AI_MaiMaLai) );
  31. }
  32. //+---------------------------------------------------------------------------
  33. //
  34. // Function: IsThaiUpperAndLowerClusterCharacter
  35. //
  36. // Synopsis:
  37. //
  38. // Arguments:
  39. //
  40. // Modifies:
  41. //
  42. // History: created 7/99 aarayas
  43. //
  44. // Notes:
  45. //
  46. //----------------------------------------------------------------------------
  47. BOOL IsThaiUpperAndLowerClusterCharacter(WCHAR wc)
  48. {
  49. return ( ( (wc == THAI_Vowel_Sign_Mai_HanAkat) ) ||
  50. ( (wc >= THAI_Vowel_Sign_Sara_Am) && (wc <= THAI_Vowel_Sign_Phinthu) ) ||
  51. ( (wc >= THAI_Tone_MaiTaiKhu) && (wc <= THAI_Nikhahit) ) );
  52. }
  53. //+---------------------------------------------------------------------------
  54. //
  55. // Function: IsThaiEndingClusterCharacter
  56. //
  57. // Synopsis:
  58. //
  59. // Arguments:
  60. //
  61. // Modifies:
  62. //
  63. // History: created 8/99 aarayas
  64. //
  65. // Notes:
  66. //
  67. //----------------------------------------------------------------------------
  68. BOOL IsThaiEndingClusterCharacter(WCHAR wc)
  69. {
  70. return ( (wc == THAI_Sign_PaiYanNoi) ||
  71. (wc == THAI_Vowel_Sara_A) ||
  72. (wc == THAI_Vowel_Sara_AA) ||
  73. (wc == THAI_Vowel_LakKhangYao) ||
  74. (wc == THAI_Vowel_MaiYaMok) );
  75. }
  76. //+---------------------------------------------------------------------------
  77. //
  78. // Function: IsThaiMostlyBeginCharacter
  79. //
  80. // Synopsis:
  81. //
  82. // Arguments:
  83. //
  84. // Modifies:
  85. //
  86. // History: created 8/99 aarayas
  87. //
  88. // Notes:
  89. //
  90. //----------------------------------------------------------------------------
  91. bool IsThaiMostlyBeginCharacter(WCHAR wc)
  92. {
  93. return ( (wc >= THAI_Vowel_Sara_E && wc <= THAI_Vowel_Sara_AI_MaiMaLai) || // Character always in front of a word.
  94. (wc == THAI_Cho_Ching) || // Character always in front of a word.
  95. (wc == THAI_Pho_Phung) || // Character always in front of a word.
  96. (wc == THAI_Fo_Fa) || // Character always in front of a word.
  97. (wc == THAI_Ho_Nok_Huk) || // Character always in front of a word.
  98. (wc == THAI_Ho_Hip) || // Character most like in front of a word.
  99. (wc == THAI_Pho_Samphao) || // Character most like in front of a word.
  100. (wc == THAI_Kho_Rakhang) || // Character most like in front of a word.
  101. (wc == THAI_Fo_Fan) || // Character most like in front of a word.
  102. (wc == THAI_So_So) || // Character most like in front of a word.
  103. (wc == THAI_Tho_NangmonTho) ); // Character most like in front of a word.
  104. }
  105. //+---------------------------------------------------------------------------
  106. //
  107. // Function: IsThaiMostlyLastCharacter
  108. //
  109. // Synopsis:
  110. //
  111. // Arguments:
  112. //
  113. // Modifies:
  114. //
  115. // History: created 8/99 aarayas
  116. //
  117. // Notes:
  118. //
  119. //----------------------------------------------------------------------------
  120. bool IsThaiMostlyLastCharacter(WCHAR wc)
  121. {
  122. return ( (wc == THAI_Vowel_Sign_Sara_Am) || // Always the end of word.
  123. (wc == THAI_Sign_PaiYanNoi) || // Always the end of word.
  124. (wc == THAI_Vowel_MaiYaMok) || // Always the end of word.
  125. (wc == THAI_Vowel_LakKhangYao) || // Most likely the end of word.
  126. (wc == THAI_Thanthakhat) ); // Most likely the end of word.
  127. }
  128. //+---------------------------------------------------------------------------
  129. //
  130. // Function: IsThaiToneMark
  131. //
  132. // Synopsis:
  133. //
  134. // Arguments:
  135. //
  136. // Modifies:
  137. //
  138. // History: created 8/99 aarayas
  139. //
  140. // Notes:
  141. //
  142. //----------------------------------------------------------------------------
  143. bool IsThaiToneMark(WCHAR wc)
  144. {
  145. return ( (wc >= 0x0e48) && (wc <= 0x0e4b) ||
  146. (wc == 0x0e31));
  147. }
  148. //+---------------------------------------------------------------------------
  149. //
  150. // Function: GetCluster
  151. //
  152. // Synopsis: The function return the next number of character which represent
  153. // a cluster of Thai text.
  154. //
  155. // ie. Kor Kai, Kor Kai -> 1
  156. // Kor Kai, Sara Um -> 2
  157. //
  158. // * Note this function will not return no more than 3 character,
  159. // for cluster as this would represent invalid sequence of character.
  160. //
  161. // Arguments:
  162. //
  163. // Modifies:
  164. //
  165. // History: created 7/99 aarayas
  166. //
  167. // Notes:
  168. //
  169. //----------------------------------------------------------------------------
  170. /*
  171. unsigned int GetCluster(WCHAR* pszIndex)
  172. {
  173. int iRetValue = 0;
  174. // Take all begin cluster character.
  175. while (IsThaiBeginClusterCharacter(*pszIndex))
  176. {
  177. pszIndex++;
  178. iRetValue++;
  179. }
  180. if (IsThaiConsonant(*pszIndex))
  181. {
  182. pszIndex++;
  183. iRetValue++;
  184. while (IsThaiUpperAndLowerClusterCharacter(*pszIndex))
  185. {
  186. pszIndex++;
  187. iRetValue++;
  188. }
  189. while (IsThaiEndingClusterCharacter(*pszIndex))
  190. {
  191. pszIndex++;
  192. iRetValue++;
  193. }
  194. }
  195. if (iRetValue == 0)
  196. // The character is probably a punctuation.
  197. iRetValue++;
  198. return iRetValue;
  199. }
  200. */
  201. //+---------------------------------------------------------------------------
  202. //
  203. // Function: IsThaiConsonant
  204. //
  205. // Synopsis:
  206. //
  207. // Arguments:
  208. //
  209. // Modifies:
  210. //
  211. // History: created 7/99 aarayas
  212. //
  213. // Notes:
  214. //
  215. //----------------------------------------------------------------------------
  216. BOOL IsThaiConsonant(WCHAR wc)
  217. {
  218. return ( (wc >= THAI_Ko_Kai) && (wc <= THAI_Ho_Nok_Huk) );
  219. }
  220. //+---------------------------------------------------------------------------
  221. //
  222. // Define the different part of speech for Thai.
  223. //
  224. //----------------------------------------------------------------------------
  225. WCHAR wzPOSLookup[POSTYPE][46] =
  226. { L"NONE", // 0 . No tags.
  227. L"NPRP", // 1 . Proper noun
  228. L"NCNM", // 2 . Cardinal number
  229. L"NONM", // 3 . Ordinal number
  230. L"NLBL", // 4 . Label noun
  231. L"NCMN", // 5 . Common noun
  232. L"NTTL", // 6 . Title noun
  233. L"PPRS", // 7 . Personal pronoun
  234. L"PDMN", // 8 . Demonstrative pronoun
  235. L"PNTR", // 9 . Interrogative pronoun
  236. L"PREL", // 10. Relative pronoun
  237. L"VACT", // 11. Active verb
  238. L"VSTA", // 12. Stative verb
  239. L"VATT", // 13. Attributive verb
  240. L"XVBM", // 14. Pre-verb auxiliary, before negator
  241. L"XVAM", // 15. Pre-verb auxiliary, after negator
  242. L"XVMM", // 16. Pre-verb, before or after negator
  243. L"XVBB", // 17. Pre-verb auxiliary, in imperative mood
  244. L"XVAE", // 18. Post-verb auxiliary
  245. L"DDAN", // 19. Definite determiner, after noun without classifier in between
  246. L"DDAC", // 20. Definite determiner, allowing classifier in between
  247. L"DDBQ", // 21. Definite determiner, between noun and classifier or preceding quantitative expression
  248. L"DDAQ", // 22. Definite determiner, following quantitative expression
  249. L"DIAC", // 23. Indefinite determiner, following noun; allowing classifier in between
  250. L"DIBQ", // 24. Indefinite determiner, between noun and classifier or preceding quantitative expression
  251. L"DIAQ", // 25. Indefinite determiner, following quantitative expression
  252. L"DCNM", // 26. Determiner, cardinal number expression
  253. L"DONM", // 27. Determiner, ordinal number expression
  254. L"ADVN", // 28. Adverb with normal form
  255. L"ADVI", // 29. Adverb with iterative form
  256. L"ADVP", // 30. Adverb with prefixed form
  257. L"ADVS", // 31. Sentential adverb
  258. L"CNIT", // 32. Unit classifier
  259. L"CLTV", // 33. Collective classifier
  260. L"CMTR", // 34. Measurement classifier
  261. L"CFQC", // 35. Frequency classifier
  262. L"CVBL", // 36. Verbal classifier
  263. L"JCRG", // 37. Coordinating conjunction
  264. L"JCMP", // 38. Comparative conjunction
  265. L"JSBR", // 39. Subordinating conjunction
  266. L"RPRE", // 40. Preposition
  267. L"INT", // 41. Interjection
  268. L"FIXN", // 42. Nominal prefix
  269. L"FIXV", // 43. Adverbial prefix
  270. L"EAFF", // 44. Ending for affirmative sentencev
  271. L"EITT", // 45. Ending for interrogative sentence
  272. L"NEG", // 46. Negator
  273. L"PUNC", // 47. Punctuation
  274. L"ADVI ADVN",
  275. // 48.
  276. L"ADVI ADVN NCMN",
  277. // 49.
  278. L"ADVI ADVN VSTA",
  279. // 50.
  280. L"ADVI VATT",
  281. // 51.
  282. L"ADVN ADVP",
  283. // 52.
  284. L"ADVN ADVP ADVS",
  285. // 53.
  286. L"ADVN ADVP DIAQ DIBQ JCMP JSBR RPRE",
  287. // 54.
  288. L"ADVN ADVP NCMN VATT",
  289. // 55.
  290. L"ADVN ADVP VSTA",
  291. // 56.
  292. L"ADVN ADVS DDAC DDAN DIAC VATT XVAE",
  293. // 57.
  294. L"ADVN ADVS DDAN NCMN VATT VSTA",
  295. // 58.
  296. L"ADVN ADVS NCMN",
  297. // 59.
  298. L"ADVN ADVS NCMN VATT",
  299. // 60.
  300. L"ADVN ADVS VACT",
  301. // 61.
  302. L"ADVN ADVS VATT",
  303. // 62.
  304. L"ADVN CFQC NCMN RPRE VSTA",
  305. // 63.
  306. L"ADVN CLTV CNIT NCMN RPRE",
  307. // 64.
  308. L"ADVN DCNM",
  309. // 65.
  310. L"ADVN DDAC DDAN",
  311. // 66.
  312. L"ADVN DDAC DDAN NCMN PDMN",
  313. // 67.
  314. L"ADVN DDAC DDAN PDMN",
  315. // 68.
  316. L"ADVN DDAN DDBQ",
  317. // 69.
  318. L"ADVN DDAN DIAC PDMN VSTA",
  319. // 70.
  320. L"ADVN DDAN FIXN PDMN",
  321. // 71.
  322. L"ADVN DDAN NCMN",
  323. // 72.
  324. L"ADVN DDAQ",
  325. // 73.
  326. L"ADVN DDBQ",
  327. // 74.
  328. L"ADVN DDBQ RPRE VATT",
  329. // 75.
  330. L"ADVN DDBQ VATT VSTA XVAE",
  331. // 76.
  332. L"ADVN DIAC",
  333. // 77.
  334. L"ADVN DIAC PDMN",
  335. // 78.
  336. L"ADVN DIBQ",
  337. // 79.
  338. L"ADVN DIBQ NCMN",
  339. // 80.
  340. L"ADVN DIBQ VACT VSTA",
  341. // 81.
  342. L"ADVN DIBQ VATT",
  343. // 82.
  344. L"ADVN DONM JCMP",
  345. // 83.
  346. L"ADVN DONM JSBR NCMN RPRE VATT XVAE",
  347. // 84.
  348. L"ADVN EITT PNTR",
  349. // 85.
  350. L"ADVN FIXN",
  351. // 86.
  352. L"ADVN JCMP",
  353. // 87.
  354. L"ADVN JCRG",
  355. // 88.
  356. L"ADVN JCRG JSBR",
  357. // 89.
  358. L"ADVN JCRG JSBR XVBM XVMM",
  359. // 90.
  360. L"ADVN JCRG RPRE VACT VSTA XVAE",
  361. // 91.
  362. L"ADVN JSBR",
  363. // 92.
  364. L"ADVN JSBR NCMN",
  365. // 93.
  366. L"ADVN JSBR RPRE VATT",
  367. // 94.
  368. L"ADVN JSBR RPRE XVAE",
  369. // 95.
  370. L"ADVN JSBR VSTA",
  371. // 96.
  372. L"ADVN JSBR XVAE XVBM",
  373. // 97.
  374. L"ADVN NCMN",
  375. // 98.
  376. L"ADVN NCMN RPRE VACT VATT VSTA",
  377. // 99.
  378. L"ADVN NCMN RPRE VACT XVAE",
  379. // 100.
  380. L"ADVN NCMN RPRE VATT",
  381. // 101.
  382. L"ADVN NCMN VACT VATT VSTA",
  383. // 102.
  384. L"ADVN NCMN VACT VSTA",
  385. // 103.
  386. L"ADVN NCMN VATT",
  387. // 104.
  388. L"ADVN NCMN VATT VSTA",
  389. // 105.
  390. L"ADVN NEG",
  391. // 106.
  392. L"ADVN NPRP VATT",
  393. // 107.
  394. L"ADVN PDMN VACT",
  395. // 108.
  396. L"ADVN PNTR",
  397. // 109.
  398. L"ADVN RPRE",
  399. // 110.
  400. L"ADVN RPRE VACT VATT XVAE",
  401. // 111.
  402. L"ADVN RPRE VACT XVAM XVBM",
  403. // 112.
  404. L"ADVN RPRE VATT VSTA",
  405. // 113.
  406. L"ADVN RPRE VSTA",
  407. // 114.
  408. L"ADVN VACT",
  409. // 115.
  410. L"ADVN VACT VATT",
  411. // 116.
  412. L"ADVN VACT VATT VSTA",
  413. // 117.
  414. L"ADVN VACT VATT VSTA XVAM XVBM",
  415. // 118.
  416. L"ADVN VACT VSTA",
  417. // 119.
  418. L"ADVN VACT VSTA XVAE",
  419. // 120.
  420. L"ADVN VACT XVAE",
  421. // 121.
  422. L"ADVN VATT",
  423. // 122.
  424. L"ADVN VATT VSTA",
  425. // 123.
  426. L"ADVN VATT VSTA XVAM XVBM XVMM",
  427. // 124.
  428. L"ADVN VATT XVBM",
  429. // 125.
  430. L"ADVN VSTA",
  431. // 126.
  432. L"ADVN VSTA XVAE",
  433. // 127.
  434. L"ADVN VSTA XVBM",
  435. // 128.
  436. L"ADVN XVAE",
  437. // 129.
  438. L"ADVN XVAM",
  439. // 130.
  440. L"ADVN XVBM XVMM",
  441. // 131.
  442. L"ADVP JSBR RPRE VATT",
  443. // 132.
  444. L"ADVP VATT",
  445. // 133.
  446. L"ADVS DDAC JCRG",
  447. // 134.
  448. L"ADVS DDAC JSBR",
  449. // 135.
  450. L"ADVS DDAN VSTA",
  451. // 136.
  452. L"ADVS DIAC",
  453. // 137.
  454. L"ADVS DONM",
  455. // 138.
  456. L"ADVS JCRG JSBR",
  457. // 139.
  458. L"ADVS JCRG JSBR RPRE",
  459. // 140.
  460. L"ADVS JSBR",
  461. // 141.
  462. L"ADVS JSBR RPRE",
  463. // 142.
  464. L"ADVS NCMN",
  465. // 143.
  466. L"ADVS VATT",
  467. // 144.
  468. L"CFQC CLTV CNIT DCNM JCRG JSBR NCMN RPRE XVBM",
  469. // 145.
  470. L"CFQC CNIT PREL",
  471. // 146.
  472. L"CFQC NCMN",
  473. // 147.
  474. L"CLTV CNIT NCMN",
  475. // 148.
  476. L"CLTV CNIT NCMN RPRE",
  477. // 149.
  478. L"CLTV CNIT NCMN VSTA",
  479. // 150.
  480. L"CLTV NCMN",
  481. // 151.
  482. L"CLTV NCMN VACT VATT",
  483. // 152.
  484. L"CLTV NCMN VATT",
  485. // 153.
  486. L"CMTR CNIT NCMN",
  487. // 154.
  488. L"CMTR NCMN",
  489. // 155.
  490. L"CMTR NCMN VATT VSTA",
  491. // 156.
  492. L"CNIT DDAC NCMN VATT",
  493. // 157.
  494. L"CNIT DONM NCMN RPRE VATT",
  495. // 158.
  496. L"CNIT FIXN FIXV JSBR NCMN",
  497. // 159.
  498. L"CNIT JCRG JSBR NCMN PREL RPRE VATT",
  499. // 160.
  500. L"CNIT JSBR RPRE",
  501. // 161.
  502. L"CNIT NCMN",
  503. // 162.
  504. L"CNIT NCMN RPRE",
  505. // 163.
  506. L"CNIT NCMN RPRE VATT",
  507. // 164.
  508. L"CNIT NCMN VACT",
  509. // 165.
  510. L"CNIT NCMN VSTA",
  511. // 166.
  512. L"CNIT NCNM",
  513. // 167.
  514. L"CNIT PPRS",
  515. // 168.
  516. L"DCNM DDAC DIAC DONM VATT VSTA",
  517. // 169.
  518. L"DCNM DDAN DIAC",
  519. // 170.
  520. L"DCNM DIAC NCMN NCNM",
  521. // 171.
  522. L"DCNM DIBQ NCMN",
  523. // 172.
  524. L"DCNM DONM",
  525. // 173.
  526. L"DCNM NCMN",
  527. // 174.
  528. L"DCNM NCNM",
  529. // 175.
  530. L"DCNM NCNM VACT",
  531. // 176.
  532. L"DCNM VATT",
  533. // 177.
  534. L"DDAC DDAN",
  535. // 178.
  536. L"DDAC DDAN DIAC NCMN",
  537. // 179.
  538. L"DDAC DDAN DIAC VATT",
  539. // 180.
  540. L"DDAC DDAN EAFF PDMN",
  541. // 181.
  542. L"DDAC DDAN PDMN",
  543. // 182.
  544. L"DDAC DIAC VSTA",
  545. // 183.
  546. L"DDAC NCMN",
  547. // 184.
  548. L"DDAN DDBQ",
  549. // 185.
  550. L"DDAN DIAC PNTR",
  551. // 186.
  552. L"DDAN NCMN",
  553. // 187.
  554. L"DDAN NCMN RPRE VATT",
  555. // 188.
  556. L"DDAN PDMN",
  557. // 189.
  558. L"DDAN RPRE",
  559. // 190.
  560. L"DDAN VATT",
  561. // 191.
  562. L"DDAQ VATT",
  563. // 192.
  564. L"DDBQ DIBQ",
  565. // 193.
  566. L"DDBQ JCRG JSBR",
  567. // 194.
  568. L"DDBQ JCRG NCMN",
  569. // 195.
  570. L"DIAC PDMN",
  571. // 196.
  572. L"DIBQ JSBR RPRE VSTA",
  573. // 197.
  574. L"DIBQ NCMN",
  575. // 198.
  576. L"DIBQ VATT",
  577. // 199.
  578. L"DIBQ VATT VSTA",
  579. // 200.
  580. L"DIBQ XVBM",
  581. // 201.
  582. L"DONM NCMN RPRE",
  583. // 202.
  584. L"DONM VACT VATT VSTA",
  585. // 203.
  586. L"DONM VATT",
  587. // 204.
  588. L"EAFF XVAE XVAM XVBM",
  589. // 205.
  590. L"EITT JCRG",
  591. // 206.
  592. L"FIXN FIXV NCMN",
  593. // 207.
  594. L"FIXN FIXV RPRE VSTA",
  595. // 208.
  596. L"FIXN JSBR NCMN PREL RPRE VSTA XVBM",
  597. // 209.
  598. L"FIXN NCMN",
  599. // 210.
  600. L"FIXN VACT",
  601. // 211.
  602. L"FIXN VACT VSTA",
  603. // 212.
  604. L"FIXV JSBR RPRE",
  605. // 213.
  606. L"JCMP JSBR",
  607. // 214.
  608. L"JCMP RPRE VSTA",
  609. // 215.
  610. L"JCMP VATT VSTA",
  611. // 216.
  612. L"JCMP VSTA",
  613. // 217.
  614. L"JCRG JSBR",
  615. // 218.
  616. L"JCRG JSBR NCMN RPRE",
  617. // 219.
  618. L"JCRG JSBR RPRE",
  619. // 220.
  620. L"JCRG RPRE",
  621. // 221.
  622. L"JCRG RPRE VATT VSTA",
  623. // 222.
  624. L"JCRG VSTA",
  625. // 223.
  626. L"JSBR NCMN",
  627. // 224.
  628. L"JSBR NCMN XVAE",
  629. // 225.
  630. L"JSBR NCMN XVAM XVBM XVMM",
  631. // 226.
  632. L"JSBR PREL",
  633. // 227.
  634. L"JSBR PREL RPRE",
  635. // 228.
  636. L"JSBR PREL XVBM",
  637. // 229.
  638. L"JSBR RPRE",
  639. // 230.
  640. L"JSBR RPRE VACT",
  641. // 231.
  642. L"JSBR RPRE VACT VSTA",
  643. // 232.
  644. L"JSBR RPRE VACT XVAE XVAM",
  645. // 233.
  646. L"JSBR RPRE VATT",
  647. // 234.
  648. L"JSBR RPRE VSTA",
  649. // 235.
  650. L"JSBR RPRE XVAM",
  651. // 236.
  652. L"JSBR VACT",
  653. // 237.
  654. L"JSBR VACT VSTA",
  655. // 238.
  656. L"JSBR VATT XVBM XVMM",
  657. // 239.
  658. L"JSBR VSTA",
  659. // 240.
  660. L"JSBR XVBM",
  661. // 241.
  662. L"NCMN NCNM",
  663. // 242.
  664. L"NCMN NCNM NPRP",
  665. // 243.
  666. L"NCMN NLBL NPRP",
  667. // 244.
  668. L"NCMN NPRP",
  669. // 245.
  670. L"NCMN NPRP RPRE",
  671. // 246.
  672. L"NCMN NTTL",
  673. // 247.
  674. L"NCMN PDMN PPRS",
  675. // 248.
  676. L"NCMN PDMN VATT",
  677. // 249.
  678. L"NCMN PNTR",
  679. // 250.
  680. L"NCMN PPRS PREL VACT",
  681. // 251.
  682. L"NCMN RPRE",
  683. // 252.
  684. L"NCMN RPRE VACT VATT",
  685. // 253.
  686. L"NCMN RPRE VATT",
  687. // 254.
  688. L"NCMN VACT",
  689. // 255.
  690. L"NCMN VACT VATT",
  691. // 256.
  692. L"NCMN VACT VATT VSTA XVAE",
  693. // 257.
  694. L"NCMN VACT VSTA",
  695. // 258.
  696. L"NCMN VACT VSTA XVAM",
  697. // 259.
  698. L"NCMN VACT VSTA XVBB",
  699. // 260.
  700. L"NCMN VATT",
  701. // 261.
  702. L"NCMN VATT VSTA",
  703. // 262.
  704. L"NCMN VATT XVAM",
  705. // 263.
  706. L"NCMN VSTA",
  707. // 264.
  708. L"NCMN XVBM",
  709. // 265.
  710. L"NPRP RPRE",
  711. // 266.
  712. L"NPRP VATT",
  713. // 267.
  714. L"NTTL PPRS",
  715. // 268.
  716. L"PDMN PPRS",
  717. // 269.
  718. L"PDMN VATT",
  719. // 270.
  720. L"PDMN VATT VSTA",
  721. // 271.
  722. L"PPRS PREL",
  723. // 272.
  724. L"PPRS VATT",
  725. // 273.
  726. L"RPRE VACT",
  727. // 274.
  728. L"RPRE VACT VATT",
  729. // 275.
  730. L"RPRE VACT VSTA",
  731. // 276.
  732. L"RPRE VACT VSTA XVAE",
  733. // 277.
  734. L"RPRE VACT XVAE",
  735. // 278.
  736. L"RPRE VATT",
  737. // 279.
  738. L"RPRE VATT VSTA",
  739. // 280.
  740. L"RPRE VSTA",
  741. // 281.
  742. L"VACT VATT",
  743. // 282.
  744. L"VACT VATT VSTA",
  745. // 283.
  746. L"VACT VATT XVAE XVAM XVBM",
  747. // 284.
  748. L"VACT VSTA",
  749. // 285.
  750. L"VACT VSTA XVAE",
  751. // 286.
  752. L"VACT VSTA XVAE XVAM",
  753. // 287.
  754. L"VACT VSTA XVAE XVAM XVMM",
  755. // 288.
  756. L"VACT VSTA XVAM",
  757. // 289.
  758. L"VACT VSTA XVAM XVMM",
  759. // 290.
  760. L"VACT XVAE",
  761. // 291.
  762. L"VACT XVAM",
  763. // 292.
  764. L"VACT XVAM XVMM",
  765. // 293.
  766. L"VACT XVMM",
  767. // 294.
  768. L"VATT VSTA",
  769. // 295.
  770. L"VSTA XVAE",
  771. // 296.
  772. L"VSTA XVAM",
  773. // 297.
  774. L"VSTA XVAM XVMM",
  775. // 298.
  776. L"VSTA XVBM",
  777. // 299.
  778. L"XVAM XVBM",
  779. // 300.
  780. L"XVAM XVBM XVMM",
  781. // 301.
  782. L"XVAM XVMM",
  783. // 302.
  784. L"UNKN", // 303. Unknown
  785. };
  786. //+---------------------------------------------------------------------------
  787. //
  788. // Function: POSCompress
  789. //
  790. // Synopsis: Part Of Speech Compress - translating string to unique id.
  791. //
  792. // Arguments:
  793. //
  794. // Modifies:
  795. //
  796. // History: created 7/99 aarayas
  797. //
  798. // Notes:
  799. //
  800. //----------------------------------------------------------------------------
  801. DWORD POSCompress(WCHAR* szTag)
  802. {
  803. int i;
  804. for (i = 0; i < POSTYPE; i++)
  805. {
  806. if (wcscmp(szTag, &wzPOSLookup[i][0]) == 0)
  807. {
  808. return (DWORD)i;
  809. }
  810. }
  811. return POSTYPE;
  812. }
  813. //+---------------------------------------------------------------------------
  814. //
  815. // Function: POSDecompress
  816. //
  817. // Synopsis: Part Of Speech Decompress - Decompress tag get
  818. //
  819. // Arguments:
  820. //
  821. // Modifies:
  822. //
  823. // History: created 7/99 aarayas
  824. //
  825. // Notes:
  826. //
  827. //----------------------------------------------------------------------------
  828. inline WCHAR* POSDecompress(DWORD dwTag)
  829. {
  830. return (&wzPOSLookup[dwTag][0]);
  831. }
  832. //+---------------------------------------------------------------------------
  833. //
  834. // Class: CThaiTrieIter
  835. //
  836. // Synoposis: Constructor:
  837. //
  838. // Arguments:
  839. //
  840. // Modifies:
  841. //
  842. // History: created 8/99 aarayas
  843. //
  844. // Notes:
  845. //
  846. //----------------------------------------------------------------------------
  847. CThaiTrieIter::CThaiTrieIter() : resultWord(NULL), soundexWord(NULL), tempWord(NULL),
  848. pTrieScanArray(NULL), m_fThaiNumber(false)
  849. {
  850. resultWord = new WCHAR[64];
  851. tempWord = new WCHAR[64];
  852. pTrieScanArray = new TRIESCAN[53];
  853. }
  854. //+---------------------------------------------------------------------------
  855. //
  856. // Class: CThaiTrieIter
  857. //
  858. // Synoposis: Destructor
  859. //
  860. // Arguments:
  861. //
  862. // Modifies:
  863. //
  864. // History: created 8/99 aarayas
  865. //
  866. // Notes:
  867. //
  868. //----------------------------------------------------------------------------
  869. CThaiTrieIter::~CThaiTrieIter()
  870. {
  871. if (resultWord)
  872. delete resultWord;
  873. if (tempWord)
  874. delete tempWord;
  875. if (pTrieScanArray)
  876. delete pTrieScanArray;
  877. }
  878. //+---------------------------------------------------------------------------
  879. //
  880. // Class: CThaiTrieIter
  881. //
  882. // Synopsis: Initialize variables.
  883. //
  884. // Arguments:
  885. //
  886. // Modifies:
  887. //
  888. // History: created 8/99 aarayas
  889. //
  890. // Notes:
  891. //
  892. //----------------------------------------------------------------------------
  893. void CThaiTrieIter::Init(CTrie* ctrie)
  894. {
  895. // Declare varialbes.
  896. WCHAR wc;
  897. // Initialize parent.
  898. CTrieIter::Init(ctrie);
  899. // Initialize Hash table.
  900. for (wc = THAI_Ko_Kai; wc <= THAI_Ho_Nok_Huk; wc++)
  901. GetScanFirstChar(wc,&pTrieScanArray[wc - THAI_Ko_Kai]);
  902. for (wc = THAI_Vowel_Sara_E; wc <= THAI_Vowel_Sara_AI_MaiMaLai; wc++)
  903. GetScanFirstChar(wc,&pTrieScanArray[wc - THAI_Ko_Kai - 17]);
  904. }
  905. //+---------------------------------------------------------------------------
  906. //
  907. // Class: CThaiTrieIter
  908. //
  909. // Synopsis: Initialize variables.
  910. //
  911. // Arguments:
  912. //
  913. // Modifies:
  914. //
  915. // History: created 8/99 aarayas
  916. //
  917. // Notes:
  918. //
  919. //----------------------------------------------------------------------------
  920. bool CThaiTrieIter::GetScanFirstChar(WCHAR wc, TRIESCAN* pTrieScan)
  921. {
  922. // Reset the trie scan.
  923. memset(&trieScan1, 0, sizeof(TRIESCAN));
  924. if (!TrieGetNextState(pTrieCtrl, &trieScan1))
  925. return false;
  926. while (wc != trieScan1.wch)
  927. {
  928. // Keep moving the the right of the trie.
  929. if (!TrieGetNextNode(pTrieCtrl, &trieScan1))
  930. {
  931. memset(pTrieScan, 0, sizeof(TRIESCAN));
  932. return false;
  933. }
  934. }
  935. memcpy(pTrieScan, &trieScan1, sizeof(TRIESCAN));
  936. return true;
  937. }
  938. //+---------------------------------------------------------------------------
  939. //
  940. // Class: CThaiTrieIter
  941. //
  942. // Synopsis: The function move trieScan to the relevant node matching with
  943. // with the cluster of Thai character.
  944. //
  945. // Arguments: szCluster - contain the thai character cluster.
  946. // iNumCluster - contain the size of character.
  947. //
  948. // Modifies:
  949. //
  950. // History: created 7/99 aarayas
  951. //
  952. // Notes:
  953. //
  954. //----------------------------------------------------------------------------
  955. BOOL CThaiTrieIter::MoveCluster(WCHAR* szCluster, unsigned int iNumCluster)
  956. {
  957. // Declare and initailze local variables.
  958. unsigned int i = 0;
  959. Assert(iNumCluster <= 6, "Invalid cluster");
  960. CopyScan();
  961. if (!TrieGetNextState(pTrieCtrl, &trieScan1))
  962. return FALSE;
  963. while (TRUE)
  964. {
  965. if (szCluster[i] == trieScan1.wch)
  966. {
  967. i++;
  968. if (i == iNumCluster)
  969. {
  970. memcpy(&trieScan, &trieScan1, sizeof(TRIESCAN));
  971. GetNode();
  972. return TRUE;
  973. }
  974. // Move down the Trie Branch.
  975. else if (!TrieGetNextState(pTrieCtrl, &trieScan1)) break;
  976. }
  977. // Move the Trie right one node.
  978. else if (!TrieGetNextNode(pTrieCtrl, &trieScan1)) break;
  979. }
  980. return FALSE;
  981. }
  982. //+---------------------------------------------------------------------------
  983. //
  984. // Class: CThaiTrieIter
  985. //
  986. // Synopsis: The function move trieScan to the relevant node matching with
  987. // with the cluster of Thai character.
  988. //
  989. // Arguments: szCluster - contain the thai character cluster.
  990. // iNumCluster - contain the size of character.
  991. //
  992. // Modifies:
  993. //
  994. // History: created 7/99 aarayas
  995. //
  996. // Notes:
  997. //
  998. //----------------------------------------------------------------------------
  999. bool CThaiTrieIter::MoveCluster(WCHAR* szCluster, unsigned int iNumCluster, bool fBeginNewWord)
  1000. {
  1001. // Declare and initailze local variables.
  1002. unsigned int i = 0;
  1003. Assert(iNumCluster <= 6, "Invalid cluster");
  1004. // No need to move.
  1005. if (iNumCluster == 0)
  1006. return false;
  1007. // Use a look indexes for where the first character is at.
  1008. if (fBeginNewWord)
  1009. {
  1010. m_fThaiNumber = false;
  1011. // Quick look up for proper characters.
  1012. if (szCluster[i] >= THAI_Ko_Kai && szCluster[i] <= THAI_Ho_Nok_Huk)
  1013. memcpy(&trieScan,&pTrieScanArray[(szCluster[i] - THAI_Ko_Kai)], sizeof(TRIESCAN));
  1014. else if (szCluster[i] >= THAI_Vowel_Sara_E && szCluster[i] <= THAI_Vowel_Sara_AI_MaiMaLai)
  1015. memcpy(&trieScan,&pTrieScanArray[(szCluster[i] - THAI_Ko_Kai - 17)], sizeof(TRIESCAN));
  1016. else
  1017. {
  1018. Reset();
  1019. m_fThaiNumber = IsThaiNumeric(szCluster[i]);
  1020. }
  1021. if (trieScan.wch == szCluster[i])
  1022. i++;
  1023. if (i == iNumCluster)
  1024. {
  1025. GetNode();
  1026. return true;
  1027. }
  1028. }
  1029. CopyScan();
  1030. if (!TrieGetNextState(pTrieCtrl, &trieScan1))
  1031. return false;
  1032. if (m_fThaiNumber)
  1033. {
  1034. fWordEnd = true;
  1035. if (IsThaiNumeric(szCluster[i]) || szCluster[i] == L',' || szCluster[i] == L'.')
  1036. return true;
  1037. else
  1038. return false;
  1039. }
  1040. while (true)
  1041. {
  1042. if (szCluster[i] == trieScan1.wch)
  1043. {
  1044. i++;
  1045. if ((i == iNumCluster) ||
  1046. ( (szCluster[i] == THAI_Vowel_MaiYaMok || szCluster[i] == THAI_Sign_PaiYanNoi)/* && (i+1 == iNumCluster )*/) )
  1047. {
  1048. memcpy(&trieScan, &trieScan1, sizeof(TRIESCAN));
  1049. GetNode();
  1050. return true;
  1051. }
  1052. // Move down the Trie Branch.
  1053. else if (!TrieGetNextState(pTrieCtrl, &trieScan1)) break;
  1054. }
  1055. // Move the Trie right one node.
  1056. else if (!TrieGetNextNode(pTrieCtrl, &trieScan1)) break;
  1057. }
  1058. if (fBeginNewWord)
  1059. Reset();
  1060. return false;
  1061. }
  1062. //+---------------------------------------------------------------------------
  1063. //
  1064. // Class: CThaiTrieIter
  1065. //
  1066. // Synopsis:
  1067. //
  1068. // Arguments:
  1069. //
  1070. // Modifies:
  1071. //
  1072. // History: created 7/99 aarayas
  1073. //
  1074. // Notes:
  1075. //
  1076. //----------------------------------------------------------------------------
  1077. SOUNDEXSTATE CThaiTrieIter::MoveSoundexByCluster(WCHAR* szCluster, unsigned int iNumCluster, unsigned int iNumNextCluster)
  1078. {
  1079. // Declare and initailze local variables.
  1080. unsigned int i = 0 , x = 0;
  1081. bool fStoreScan = false;
  1082. TRIESCAN trieScanPush;
  1083. Assert(iNumCluster <= 6, "Invalid cluster");
  1084. Assert(iNumNextCluster <= 6, "Invalid cluster");
  1085. CopyScan();
  1086. if (!TrieGetNextState(pTrieCtrl, &trieScan1))
  1087. return UNABLE_TO_MOVE;
  1088. // Match as much as possible
  1089. while (true)
  1090. {
  1091. if (szCluster[i] == trieScan1.wch)
  1092. {
  1093. i++;
  1094. if (i == iNumCluster)
  1095. {
  1096. memcpy(&trieScan, &trieScan1, sizeof(TRIESCAN));
  1097. GetNode();
  1098. return NOSUBSTITUTE;
  1099. }
  1100. // Move down the Trie Branch.
  1101. else if (!TrieGetNextState(pTrieCtrl, &trieScan1)) break;
  1102. // Save our current scan position.
  1103. memcpy(&trieScanPush, &trieScan1, sizeof(TRIESCAN));
  1104. fStoreScan = true;
  1105. }
  1106. // Move the Trie right one node.
  1107. else if (!TrieGetNextNode(pTrieCtrl, &trieScan1)) break;
  1108. }
  1109. // Try doing some tonemark substitution.
  1110. if (fStoreScan && IsThaiToneMark(szCluster[i]) )
  1111. {
  1112. // Restore trieScan1 to last matched.
  1113. memcpy(&trieScan1, &trieScanPush, sizeof(TRIESCAN));
  1114. while (true)
  1115. {
  1116. if (IsThaiToneMark(trieScan1.wch))
  1117. {
  1118. if ( (i + 1) == iNumCluster)
  1119. {
  1120. if (CheckNextCluster(szCluster+iNumCluster,iNumNextCluster))
  1121. {
  1122. memcpy(&trieScan, &trieScan1, sizeof(TRIESCAN));
  1123. GetNode();
  1124. return SUBSTITUTE_DIACRITIC;
  1125. }
  1126. }
  1127. }
  1128. // Move the Trie right one node.
  1129. // Goes through all the none Tonemark.
  1130. if (!TrieGetNextNode(pTrieCtrl, &trieScan1)) break;
  1131. }
  1132. }
  1133. // Try doing droping the current tonemark.
  1134. // Example is case can be best found "Click" is spelt in Thai from the
  1135. // different group at Microsoft.
  1136. if (fStoreScan && !IsThaiToneMark(szCluster[i]) )
  1137. {
  1138. // Restore trieScan1 to last matched.
  1139. memcpy(&trieScan1, &trieScanPush, sizeof(TRIESCAN));
  1140. while (true)
  1141. {
  1142. if (IsThaiToneMark(trieScan1.wch))
  1143. {
  1144. if ( (i + 1) == iNumCluster)
  1145. {
  1146. if (CheckNextCluster(szCluster+iNumCluster,iNumNextCluster))
  1147. {
  1148. memcpy(&trieScan, &trieScan1, sizeof(TRIESCAN));
  1149. GetNode();
  1150. return SUBSTITUTE_DIACRITIC;
  1151. }
  1152. }
  1153. }
  1154. // Move the Trie right one node.
  1155. // Drop all the Tonemark.
  1156. if (!TrieGetNextNode(pTrieCtrl, &trieScan1)) break;
  1157. }
  1158. }
  1159. return UNABLE_TO_MOVE;
  1160. }
  1161. //+---------------------------------------------------------------------------
  1162. //
  1163. // Class: CThaiTrieIter
  1164. //
  1165. // Synopsis: set trieScan1 = trieScan.
  1166. //
  1167. // Arguments:
  1168. //
  1169. // Modifies:
  1170. //
  1171. // History: created 7/99 aarayas
  1172. //
  1173. // Notes:
  1174. //
  1175. //----------------------------------------------------------------------------
  1176. inline void CThaiTrieIter::CopyScan()
  1177. {
  1178. // Let trieScan1 = trieScan
  1179. memcpy(&trieScan1,&trieScan, sizeof(TRIESCAN));
  1180. }
  1181. //+---------------------------------------------------------------------------
  1182. //
  1183. // Class: CThaiTrieIter
  1184. //
  1185. // Synoposis: the function traverse through the whole dictionary
  1186. // to find the best possible match words.
  1187. //
  1188. // Arguments:
  1189. //
  1190. // Modifies:
  1191. //
  1192. // History: created 8/99 aarayas
  1193. //
  1194. // Notes:
  1195. //
  1196. //----------------------------------------------------------------------------
  1197. int CThaiTrieIter::Soundex(WCHAR* word)
  1198. {
  1199. // Reset Trie.
  1200. Reset();
  1201. // Move Down.
  1202. Down();
  1203. // Clean soundexWord.
  1204. memset(resultWord, 0, sizeof(WCHAR) * 64);
  1205. memset(tempWord, 0, sizeof(WCHAR) * 64);
  1206. soundexWord = word;
  1207. iResultScore = GetScore(L"\x0e04\x0e25\x0e34\x0e01\x0e01\x0e01",soundexWord);
  1208. iResultScore = 2000;
  1209. #if defined (_DEBUG)
  1210. iStackSize = 0;
  1211. #endif
  1212. Traverse(0,1000);
  1213. return iResultScore;
  1214. }
  1215. //+---------------------------------------------------------------------------
  1216. //
  1217. // Class: CThaiTrieIter
  1218. //
  1219. // Synoposis:
  1220. //
  1221. // Arguments:
  1222. //
  1223. // Modifies:
  1224. //
  1225. // History: created 8/99 aarayas
  1226. //
  1227. // Notes:
  1228. //
  1229. //----------------------------------------------------------------------------
  1230. unsigned int CThaiTrieIter::GetScore(WCHAR* idealWord, WCHAR* inputWord)
  1231. {
  1232. unsigned int iScore = 1000;
  1233. unsigned int idealWordLen = wcslen(idealWord);
  1234. unsigned int iInputWordLen = wcslen(inputWord);
  1235. unsigned int iIndexBegin = 0;
  1236. unsigned int i,x;
  1237. unsigned int iMaxCompare;
  1238. bool fShouldExit;
  1239. for (i=0; i < iInputWordLen; i++)
  1240. {
  1241. iMaxCompare = ( (iIndexBegin + 2) < idealWordLen ) ? (iIndexBegin + 2) : idealWordLen;
  1242. if (i <= idealWordLen)
  1243. {
  1244. x = iIndexBegin;
  1245. fShouldExit = false;
  1246. while (true)
  1247. {
  1248. if ((x >= iMaxCompare) || (fShouldExit) )
  1249. break;
  1250. if (idealWord[x] == inputWord[i])
  1251. {
  1252. x++;
  1253. iIndexBegin = x;
  1254. break;
  1255. }
  1256. if (IsThaiUpperAndLowerClusterCharacter(inputWord[i]))
  1257. iScore += 5;
  1258. else
  1259. iScore += 10;
  1260. x++;
  1261. fShouldExit = true;
  1262. }
  1263. }
  1264. else
  1265. {
  1266. if (IsThaiUpperAndLowerClusterCharacter(inputWord[i]))
  1267. iScore += 20;
  1268. else
  1269. iScore += 30;
  1270. }
  1271. }
  1272. while (x <= idealWordLen)
  1273. {
  1274. if (IsThaiUpperAndLowerClusterCharacter(idealWord[x]))
  1275. iScore += 5;
  1276. else
  1277. iScore += 10;
  1278. x++;
  1279. }
  1280. return iScore;
  1281. }
  1282. //+---------------------------------------------------------------------------
  1283. //
  1284. // Class: CThaiTrieIter
  1285. //
  1286. // Synoposis:
  1287. //
  1288. // Arguments:
  1289. //
  1290. // Modifies:
  1291. //
  1292. // History: created 8/99 aarayas
  1293. //
  1294. // Notes:
  1295. //
  1296. //----------------------------------------------------------------------------
  1297. bool CThaiTrieIter::Traverse(unsigned int iCharPos, unsigned int score)
  1298. {
  1299. TRIESCAN trieScanLevel;
  1300. #if defined(_DEBUG)
  1301. iStackSize++;
  1302. #endif
  1303. // push current trieScan into local stack trieScanLevel.
  1304. memcpy(&trieScanLevel,&trieScan, sizeof(TRIESCAN));
  1305. // Get Node information
  1306. GetNode();
  1307. // Store the current character to result word.
  1308. tempWord[iCharPos] = wc;
  1309. tempWord[iCharPos + 1] = 0;
  1310. // Determine the distance between two string.
  1311. score = GetScore(tempWord, soundexWord);
  1312. // See if we have reached the end of a word.
  1313. if (fWordEnd)
  1314. {
  1315. tempWord[iCharPos + 1] = 0;
  1316. // Is Soundex score lower than we have.
  1317. if (score < iResultScore)
  1318. {
  1319. wcscpy(resultWord,tempWord);
  1320. iResultScore = score;
  1321. }
  1322. }
  1323. // See if we can prune the result of the words.
  1324. if (score > (iResultScore + APPROXIMATEWEIGHT))
  1325. {
  1326. #if defined(_DEBUG)
  1327. iStackSize--;
  1328. #endif
  1329. return true;
  1330. }
  1331. // Move down Trie branch.
  1332. if (Down())
  1333. {
  1334. Traverse(iCharPos + 1, score);
  1335. if (Right())
  1336. Traverse(iCharPos + 1, score);
  1337. // restore trieScan
  1338. memcpy(&trieScan,&trieScanLevel, sizeof(TRIESCAN));
  1339. if (Right())
  1340. Traverse(iCharPos, score);
  1341. }
  1342. #if defined(_DEBUG)
  1343. iStackSize--;
  1344. #endif
  1345. return true;
  1346. }
  1347. //+---------------------------------------------------------------------------
  1348. //
  1349. // Class: CThaiTrieIter
  1350. //
  1351. // Synoposis: This function will trieScan1 to the next cluster if
  1352. // the move is possible.
  1353. //
  1354. // Arguments:
  1355. //
  1356. // Modifies:
  1357. //
  1358. // History: created 8/99 aarayas
  1359. //
  1360. // Notes:
  1361. //
  1362. //----------------------------------------------------------------------------
  1363. bool CThaiTrieIter::CheckNextCluster(WCHAR* szCluster, unsigned int iNumCluster)
  1364. {
  1365. // Declare and initailze local variables.
  1366. unsigned int i = 0;
  1367. TRIESCAN trieScan2;
  1368. Assert(iNumCluster <= 6, "Invalid cluster");
  1369. // If there are no cluster to check consider cluster found.
  1370. if (0 == iNumCluster)
  1371. return true;
  1372. memcpy(&trieScan2, &trieScan1, sizeof(TRIESCAN));
  1373. // Move down the Trie Branch.
  1374. if (!TrieGetNextState(pTrieCtrl, &trieScan2))
  1375. return false;
  1376. while (true)
  1377. {
  1378. if (szCluster[i] == trieScan2.wch)
  1379. {
  1380. i++;
  1381. if (i == iNumCluster)
  1382. {
  1383. return true;
  1384. }
  1385. // Move down the Trie Branch.
  1386. else if (!TrieGetNextState(pTrieCtrl, &trieScan2)) break;
  1387. }
  1388. // Move the Trie right one node.
  1389. else if (!TrieGetNextNode(pTrieCtrl, &trieScan2)) break;
  1390. }
  1391. return false;
  1392. }