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.

1131 lines
32 KiB

  1. /******************************************************************************
  2. *
  3. * File Name: hatmt.c
  4. *
  5. * - HangeulAutomata of IME for Chicago-H.
  6. *
  7. * Author: Beomseok Oh (BeomOh)
  8. *
  9. * Copyright (C) Microsoft Corp 1993-1994. All rights reserved.
  10. *
  11. ******************************************************************************/
  12. #include "precomp.h"
  13. extern DWORD gdwSystemInfoFlags;
  14. BOOL HangeulAutomata(BYTE bCode, LPDWORD lpdwTransKey, LPCOMPOSITIONSTRING lpCompStr)
  15. {
  16. BYTE bKind;
  17. BOOL fOpen = FALSE;
  18. if (bCode > 0xE0) bKind = JongSung;
  19. else if (bCode > 0xC0) bKind = ChoSung;
  20. else if (bCode > 0xA0) bKind = MoEum;
  21. else if (bCode > 0x80) bKind = JaEum;
  22. else if (bCode == 0x80) // For Backspace handling.
  23. {
  24. if (fCurrentCompDel == FALSE)
  25. {
  26. // Simulate CHO state deletion - just clear current interim char.
  27. bState = CHO;
  28. mCho = 0;
  29. }
  30. switch (bState)
  31. {
  32. case JONG :
  33. if (mJong)
  34. {
  35. mJong = 0;
  36. if (!fComplete && uCurrentInputMethod == IDD_2BEOL)
  37. {
  38. Cho1 = Jong2Cho[Jong1];
  39. bState = CHO;
  40. }
  41. break;
  42. }
  43. else if (fComplete)
  44. {
  45. bState = JUNG;
  46. break;
  47. }
  48. // fall through...
  49. case JUNG :
  50. if (mJung)
  51. {
  52. mJung = 0;
  53. break;
  54. }
  55. else if (fComplete)
  56. {
  57. bState = CHO;
  58. fComplete = FALSE;
  59. break;
  60. }
  61. // fall through...
  62. case CHO :
  63. if (mCho)
  64. {
  65. mCho = 0;
  66. break;
  67. }
  68. else
  69. {
  70. lpCompStr->dwCompStrLen = lpCompStr->dwCompAttrLen = 0;
  71. *((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset) = 0;
  72. *((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset) = 0;
  73. *((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset + 1) = 0;
  74. // Initialize all Automata Variables.
  75. bState = NUL;
  76. JohabChar.w = WansungChar.w = mCho = mJung = mJong = 0;
  77. fComplete = FALSE;
  78. if (lpdwTransKey)
  79. {
  80. // Send Empty Composition String Clear Message.
  81. lpdwTransKey += iTotalNumMsg*3 + 1;
  82. *lpdwTransKey++ = WM_IME_COMPOSITION;
  83. *lpdwTransKey++ = 0L;
  84. *lpdwTransKey++ = GCS_COMPSTR | GCS_COMPATTR | CS_INSERTCHAR | CS_NOMOVECARET;
  85. // Send Close Composition Window Message.
  86. *lpdwTransKey++ = WM_IME_ENDCOMPOSITION;
  87. *lpdwTransKey++ = 0L;
  88. *lpdwTransKey++ = 0L;
  89. iTotalNumMsg += 2;
  90. }
  91. return TRUE;
  92. }
  93. case NUL :
  94. if (lpdwTransKey)
  95. {
  96. // Put the Backspace message into return buffer.
  97. lpdwTransKey += iTotalNumMsg*3 + 1;
  98. *lpdwTransKey++ = WM_CHAR;
  99. *lpdwTransKey++ = (DWORD)VK_BACK;
  100. *lpdwTransKey++ = VKBACK_LPARAM;
  101. iTotalNumMsg++;
  102. }
  103. return FALSE;
  104. }
  105. MakeInterim(lpCompStr);
  106. // Put the interim character into return buffer.
  107. if (lpdwTransKey)
  108. {
  109. lpdwTransKey += iTotalNumMsg*3 + 1;
  110. *lpdwTransKey++ = WM_IME_COMPOSITION;
  111. *lpdwTransKey++ = (DWORD)WansungChar.w;
  112. *lpdwTransKey++ = GCS_COMPSTR | GCS_COMPATTR | CS_INSERTCHAR | CS_NOMOVECARET;
  113. iTotalNumMsg++;
  114. }
  115. return TRUE;
  116. }
  117. else bKind = Wrong;
  118. bCode &= 0x1F; // Mask out for Component code
  119. switch (bState)
  120. {
  121. case NUL :
  122. switch (bKind)
  123. {
  124. case JaEum :
  125. case ChoSung :
  126. Cho1 = bCode;
  127. bState = CHO;
  128. break;
  129. case MoEum :
  130. Cho1 = CFILL;
  131. Jung1 = bCode;
  132. bState = JUNG;
  133. break;
  134. case JongSung :
  135. Cho1 = CFILL;
  136. Jung1 = VFILL;
  137. Jong1 = bCode;
  138. bState = JONG;
  139. break;
  140. }
  141. MakeInterim(lpCompStr);
  142. fOpen = TRUE;
  143. break;
  144. case CHO :
  145. switch (bKind)
  146. {
  147. case JaEum :
  148. Jong1 = Cho2Jong[Cho1];
  149. if (CheckMJong(Cho2Jong[bCode]))
  150. {
  151. Cho1 = CFILL;
  152. Jung1 = VFILL;
  153. Jong2 = Cho2Jong[bCode];
  154. bState = JONG;
  155. }
  156. else
  157. {
  158. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  159. Cho1 = bCode;
  160. bState = CHO;
  161. }
  162. break;
  163. case MoEum :
  164. Jung1 = bCode;
  165. bState = JUNG;
  166. fComplete = TRUE;
  167. break;
  168. case ChoSung :
  169. if (!mCho && CheckMCho(bCode))
  170. {
  171. Cho2 = bCode;
  172. }
  173. else
  174. {
  175. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  176. Cho1 = bCode;
  177. bState = CHO;
  178. }
  179. break;
  180. case JongSung :
  181. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  182. Cho1 = CFILL;
  183. Jung1 = VFILL;
  184. Jong1 = bCode;
  185. bState = JONG;
  186. break;
  187. }
  188. if (!MakeInterim(lpCompStr))// Check whether can be WANSUNG code.
  189. { // For MoEum case only.
  190. bState = CHO; // Other case can NOT fall in here.
  191. fComplete = FALSE;
  192. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  193. Cho1 = CFILL;
  194. Jung1 = bCode;
  195. bState = JUNG;
  196. MakeInterim(lpCompStr);
  197. }
  198. break;
  199. case JUNG :
  200. switch (bKind)
  201. {
  202. case JaEum :
  203. if (!fComplete)
  204. {
  205. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  206. Cho1 = bCode;
  207. bState = CHO;
  208. MakeInterim(lpCompStr);
  209. }
  210. else
  211. {
  212. Jong1 = Cho2Jong[bCode];
  213. bState = JONG;
  214. if (!MakeInterim(lpCompStr))
  215. {
  216. bState = JUNG;
  217. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  218. Cho1 = bCode;
  219. bState = CHO;
  220. MakeInterim(lpCompStr);
  221. }
  222. }
  223. break;
  224. case MoEum :
  225. if (!mJung && CheckMJung(bCode))
  226. {
  227. Jung2 = bCode;
  228. if (!MakeInterim(lpCompStr))
  229. {
  230. mJung = 0;
  231. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  232. Cho1 = CFILL;
  233. Jung1 = bCode;
  234. bState = JUNG;
  235. MakeInterim(lpCompStr);
  236. }
  237. }
  238. else
  239. {
  240. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  241. Cho1 = CFILL;
  242. Jung1 = bCode;
  243. bState = JUNG;
  244. MakeInterim(lpCompStr);
  245. }
  246. break;
  247. case ChoSung :
  248. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  249. Cho1 = bCode;
  250. bState = CHO;
  251. MakeInterim(lpCompStr);
  252. break;
  253. case JongSung :
  254. if (!fComplete)
  255. {
  256. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  257. Cho1 = CFILL;
  258. Jung1 = VFILL;
  259. Jong1 = bCode;
  260. bState = JONG;
  261. MakeInterim(lpCompStr);
  262. }
  263. else
  264. {
  265. Jong1 = bCode;
  266. bState = JONG;
  267. if (!MakeInterim(lpCompStr))
  268. {
  269. bState = JUNG;
  270. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  271. Cho1 = CFILL;
  272. Jung1 = VFILL;
  273. Jong1 = bCode;
  274. bState = JONG;
  275. MakeInterim(lpCompStr);
  276. }
  277. }
  278. break;
  279. }
  280. break;
  281. case JONG :
  282. switch (bKind)
  283. {
  284. case JaEum :
  285. if (!mJong && CheckMJong(Cho2Jong[bCode]))
  286. {
  287. Jong2 = Cho2Jong[bCode];
  288. if (!MakeInterim(lpCompStr))
  289. {
  290. mJong = 0;
  291. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  292. Cho1 = bCode;
  293. bState = CHO;
  294. MakeInterim(lpCompStr);
  295. }
  296. }
  297. else
  298. {
  299. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  300. Cho1 = bCode;
  301. bState = CHO;
  302. MakeInterim(lpCompStr);
  303. }
  304. break;
  305. case MoEum :
  306. if (uCurrentInputMethod == IDD_2BEOL)
  307. {
  308. JOHAB tmpJohab;
  309. WORD tmpWansung;
  310. BOOL tmpfComplete;
  311. tmpJohab.h.flag = 1;
  312. tmpJohab.h.cho = (mJong)? Jong2Cho[Jong2]: Jong2Cho[Jong1];
  313. tmpJohab.h.jung = bCode;
  314. tmpJohab.h.jong = CFILL;
  315. tmpfComplete = fComplete;
  316. fComplete = TRUE;
  317. #ifdef JOHAB_IME
  318. tmpWansung = tmpJohab.w;
  319. #else
  320. tmpWansung = Johab2Wansung(tmpJohab.w);
  321. #endif
  322. fComplete = tmpfComplete;
  323. if (!tmpWansung)
  324. {
  325. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  326. Cho1 = CFILL;
  327. Jung1 = bCode;
  328. bState = JUNG;
  329. }
  330. else
  331. {
  332. MakeFinal(TRUE, lpdwTransKey, FALSE, lpCompStr);
  333. Cho1 = (mJong)? Jong2Cho[Jong2]: Jong2Cho[Jong1];
  334. Jung1 = bCode;
  335. fComplete = TRUE;
  336. bState = JUNG;
  337. mJong = 0;
  338. }
  339. }
  340. else
  341. {
  342. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  343. Cho1 = CFILL;
  344. Jung1 = bCode;
  345. bState = JUNG;
  346. }
  347. MakeInterim(lpCompStr);
  348. break;
  349. case ChoSung :
  350. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  351. Cho1 = bCode;
  352. bState = CHO;
  353. MakeInterim(lpCompStr);
  354. break;
  355. case JongSung :
  356. if (!mJong && CheckMJong(bCode))
  357. {
  358. Jong2 = bCode;
  359. if (!MakeInterim(lpCompStr))
  360. {
  361. mJong = 0;
  362. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  363. Cho1 = CFILL;
  364. Jung1 = VFILL;
  365. Jong1 = bCode;
  366. bState = JONG;
  367. MakeInterim(lpCompStr);
  368. }
  369. }
  370. else
  371. {
  372. MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
  373. Cho1 = CFILL;
  374. Jung1 = VFILL;
  375. Jong1 = bCode;
  376. bState = JONG;
  377. MakeInterim(lpCompStr);
  378. }
  379. break;
  380. }
  381. break;
  382. }
  383. if (lpdwTransKey)
  384. {
  385. lpdwTransKey += iTotalNumMsg*3 + 1;
  386. if (fOpen)
  387. {
  388. // Send Open Composition Window Message.
  389. *lpdwTransKey++ = WM_IME_STARTCOMPOSITION;
  390. *lpdwTransKey++ = 0L;
  391. *lpdwTransKey++ = 0L;
  392. iTotalNumMsg++;
  393. }
  394. // Put the interim character into return buffer.
  395. *lpdwTransKey++ = WM_IME_COMPOSITION;
  396. *lpdwTransKey++ = (DWORD)WansungChar.w;
  397. *lpdwTransKey++ = GCS_COMPSTR | GCS_COMPATTR | CS_INSERTCHAR | CS_NOMOVECARET;
  398. iTotalNumMsg++;
  399. }
  400. return FALSE;
  401. }
  402. BOOL MakeInterim(LPCOMPOSITIONSTRING lpCompStr)
  403. {
  404. JohabChar.h.flag = 1;
  405. JohabChar.h.cho = (mCho)? mCho: Cho1;
  406. switch (bState)
  407. {
  408. case CHO :
  409. JohabChar.h.jung = VFILL;
  410. JohabChar.h.jong = CFILL;
  411. break;
  412. case JUNG :
  413. JohabChar.h.jung = (mJung)? mJung: Jung1;
  414. JohabChar.h.jong = CFILL;
  415. break;
  416. case JONG :
  417. JohabChar.h.jung = (mJung)? mJung: Jung1;
  418. JohabChar.h.jong = (mJong)? mJong: Jong1;
  419. break;
  420. }
  421. #ifdef JOHAB_IME
  422. WansungChar.w = JohabChar.w;
  423. #else
  424. WansungChar.w = Johab2Wansung(JohabChar.w);
  425. #endif
  426. if (WansungChar.w)
  427. {
  428. // Update IME Context.
  429. *((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset) = WansungChar.e.high;
  430. *((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset + 1) = WansungChar.e.low;
  431. lpCompStr->dwCompStrLen = 2;
  432. // AttrLen should be 2.
  433. *((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset) = 0;
  434. *((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset + 1) = 0;
  435. lpCompStr->dwCompAttrLen = 2;
  436. return TRUE;
  437. }
  438. else
  439. return FALSE;
  440. }
  441. void MakeFinal(BOOL bCount, LPDWORD lpdwTransKey, BOOL fClose, LPCOMPOSITIONSTRING lpCompStr)
  442. {
  443. if (bCount == TRUE)
  444. if (mJong)
  445. if (fComplete)
  446. {
  447. mJong = 0;
  448. MakeInterim(lpCompStr);
  449. mJong = 1;
  450. }
  451. else
  452. {
  453. Cho1 = Jong2Cho[Jong1];
  454. bState = CHO;
  455. MakeInterim(lpCompStr);
  456. }
  457. else
  458. {
  459. bState = JUNG;
  460. MakeInterim(lpCompStr);
  461. }
  462. else
  463. {
  464. if (!WansungChar.w)
  465. MakeInterim(lpCompStr);
  466. mJong = 0;
  467. }
  468. if (lpdwTransKey)
  469. {
  470. lpdwTransKey += iTotalNumMsg*3 + 1;
  471. if (fClose)
  472. {
  473. // Send Close Composition Window Message.
  474. *lpdwTransKey++ = WM_IME_ENDCOMPOSITION;
  475. *lpdwTransKey++ = 0L;
  476. *lpdwTransKey++ = 0L;
  477. iTotalNumMsg++;
  478. }
  479. // Put the finalized character into return buffer.
  480. *lpdwTransKey++ = WM_IME_COMPOSITION;
  481. *lpdwTransKey++ = (DWORD)WansungChar.w;
  482. *lpdwTransKey++ = GCS_RESULTSTR;
  483. iTotalNumMsg++;
  484. }
  485. // Update IME Context.
  486. lpCompStr->dwCompStrLen = lpCompStr->dwCompAttrLen = 0;
  487. *((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset) = 0;
  488. *((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset + 1) = 0;
  489. *((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset) = 0;
  490. *((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset + 1) = 0;
  491. *((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset) = WansungChar.e.high;
  492. *((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 1) = WansungChar.e.low;
  493. lpCompStr->dwResultStrLen = 2;
  494. // add a null terminator
  495. *(LPTSTR)((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + sizeof(WCHAR)) = '\0';
  496. // Initialize all Automata Variables.
  497. bState = NUL;
  498. JohabChar.w = WansungChar.w = mCho = mJung = 0;
  499. fComplete = FALSE;
  500. }
  501. void MakeFinalMsgBuf(HIMC hIMC, WPARAM VKey)
  502. {
  503. LPINPUTCONTEXT lpIMC;
  504. LPCOMPOSITIONSTRING lpCompStr;
  505. LPDWORD lpdwMsgBuf;
  506. lpIMC = ImmLockIMC(hIMC);
  507. if (lpIMC == NULL)
  508. return;
  509. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  510. if (lpCompStr == NULL) {
  511. ImmUnlockIMC(hIMC);
  512. return;
  513. }
  514. if (!WansungChar.w)
  515. MakeInterim(lpCompStr);
  516. mJong = 0;
  517. // Put the finalized character into return buffer.
  518. lpIMC->dwNumMsgBuf = (VKey)? 3: 2;
  519. lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, sizeof(DWORD)*3 * lpIMC->dwNumMsgBuf);
  520. lpdwMsgBuf = (LPDWORD)ImmLockIMCC(lpIMC->hMsgBuf);
  521. *lpdwMsgBuf++ = WM_IME_ENDCOMPOSITION;
  522. *lpdwMsgBuf++ = 0L;
  523. *lpdwMsgBuf++ = 0L;
  524. *lpdwMsgBuf++ = WM_IME_COMPOSITION;
  525. *lpdwMsgBuf++ = (DWORD)WansungChar.w;
  526. *lpdwMsgBuf++ = GCS_RESULTSTR;
  527. if (VKey)
  528. {
  529. *lpdwMsgBuf++ = WM_IME_KEYDOWN;
  530. *lpdwMsgBuf++ = VKey;
  531. *lpdwMsgBuf++ = 1L;
  532. }
  533. ImmUnlockIMCC(lpIMC->hMsgBuf);
  534. // Update IME Context.
  535. lpCompStr->dwCompStrLen = lpCompStr->dwCompAttrLen = 0;
  536. *((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset) = 0;
  537. *((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset + 1) = 0;
  538. *((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset) = 0;
  539. *((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset + 1) = 0;
  540. *((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset) = WansungChar.e.high;
  541. *((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 1) = WansungChar.e.low;
  542. lpCompStr->dwResultStrLen = 2;
  543. // add a null terminator
  544. *(LPTSTR)((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + sizeof(WCHAR)) = '\0';
  545. ImmUnlockIMCC(lpIMC->hCompStr);
  546. ImmUnlockIMC(hIMC);
  547. ImmGenerateMessage(hIMC);
  548. // Initialize all Automata Variables.
  549. bState = NUL;
  550. JohabChar.w = WansungChar.w = mCho = mJung = 0;
  551. fComplete = FALSE;
  552. }
  553. void Banja2Junja(BYTE bChar, LPDWORD lpdwTransKey, LPCOMPOSITIONSTRING lpCompStr)
  554. {
  555. if (bChar == ' ')
  556. #ifdef JOHAB_IME
  557. WansungChar.w = 0xD931;
  558. #else
  559. WansungChar.w = 0xA1A1;
  560. #endif
  561. else if (bChar == '~')
  562. #ifdef JOHAB_IME
  563. WansungChar.w = 0xD9A6;
  564. #else
  565. WansungChar.w = 0xA2A6;
  566. #endif
  567. else
  568. {
  569. #ifdef JOHAB_IME
  570. WansungChar.e.high = 0xDA;
  571. WansungChar.e.low = bChar + (BYTE)((bChar <= 'n')? 0x10: 0x22);
  572. #else
  573. WansungChar.e.high = 0xA3;
  574. WansungChar.e.low = bChar + (BYTE)0x80;
  575. #endif
  576. }
  577. // Update IME Context.
  578. lpCompStr->dwCompStrLen = lpCompStr->dwCompAttrLen = 0;
  579. *((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset) = 0;
  580. *((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset + 1) = 0;
  581. *((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset) = 0;
  582. *((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset + 1) = 0;
  583. if (lpCompStr->dwResultStrLen)
  584. {
  585. *((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 2) = WansungChar.e.high;
  586. *((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 3) = WansungChar.e.low;
  587. // add a null terminator
  588. *(LPTSTR)((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 2 + sizeof(WCHAR)) = '\0';
  589. }
  590. else
  591. {
  592. *((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset) = WansungChar.e.high;
  593. *((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 1) = WansungChar.e.low;
  594. // add a null terminator
  595. *(LPTSTR)((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + sizeof(WCHAR)) = '\0';
  596. if (lpdwTransKey)
  597. {
  598. // Put the finalized character into return buffer.
  599. lpdwTransKey += iTotalNumMsg*3 + 1;
  600. *lpdwTransKey++ = WM_IME_COMPOSITION;
  601. *lpdwTransKey++ = (DWORD)WansungChar.w;
  602. *lpdwTransKey++ = GCS_RESULTSTR;
  603. iTotalNumMsg++;
  604. }
  605. }
  606. lpCompStr->dwResultStrLen += 2;
  607. }
  608. BOOL CheckMCho(BYTE bCode)
  609. {
  610. int i;
  611. if (Cho1 != bCode)
  612. return FALSE;
  613. for (i = 0; i < 5; i++)
  614. if (rgbMChoTbl[i][0] == Cho1 && rgbMChoTbl[i][1] == bCode)
  615. {
  616. mCho = rgbMChoTbl[i][2];
  617. return TRUE;
  618. }
  619. return FALSE;
  620. }
  621. BOOL CheckMJung(BYTE bCode)
  622. {
  623. int i;
  624. for (i = 0; i < 7; i++)
  625. if (rgbMJungTbl[i][0] == Jung1 && rgbMJungTbl[i][1] == bCode)
  626. {
  627. mJung = rgbMJungTbl[i][2];
  628. return TRUE;
  629. }
  630. return FALSE;
  631. }
  632. BOOL CheckMJong(BYTE bCode)
  633. {
  634. int i;
  635. if (uCurrentInputMethod == IDD_2BEOL && Jong1 == bCode)
  636. return FALSE;
  637. for (i = 0; i < 13; i++)
  638. if (rgbMJongTbl[i][0] == Jong1 && rgbMJongTbl[i][1] == bCode)
  639. {
  640. mJong = rgbMJongTbl[i][2];
  641. return TRUE;
  642. }
  643. return FALSE;
  644. }
  645. #ifndef JOHAB_IME
  646. #ifdef XWANSUNG_IME
  647. BOOL IsPossibleToUseUHC()
  648. {
  649. /*
  650. * No UHC support for 16-bits app.
  651. */
  652. return (gdwSystemInfoFlags & IME_SYSINFO_WOW16) == 0;
  653. }
  654. BOOL UseXWansung(void)
  655. {
  656. #ifdef LATER
  657. DWORD idProcess;
  658. idProcess = GetCurrentProcessId();
  659. if ((fCurrentUseXW && (!(GetProcessDword(idProcess, GPD_FLAGS) & GPF_WIN16_PROCESS)
  660. || (GetProcessDword(idProcess, GPD_EXP_WINVER) >= 0x0400)))
  661. || (IMECOMPAT_USEXWANSUNG & ImmGetAppIMECompatFlags(0L)))
  662. #else
  663. if ( fCurrentUseXW && IsPossibleToUseUHC())
  664. #endif
  665. return TRUE;
  666. else
  667. return FALSE;
  668. }
  669. //
  670. // iXWType array is 8x3 matrix of Lead for Row, Tail for Column
  671. //
  672. static BYTE iXWType[8][3] =
  673. {
  674. XWT_EXTENDED, XWT_EXTENDED, XWT_EXTENDED, // Lead = 0x81-0xA0
  675. XWT_EXTENDED, XWT_EXTENDED, XWT_JUNJA, // Lead = 0xA1-0xAC
  676. XWT_EXTENDED, XWT_EXTENDED, XWT_INVALID, // Lead = 0xAD-0xAF
  677. XWT_EXTENDED, XWT_EXTENDED, XWT_WANSUNG, // Lead = 0xB0-0xC5
  678. XWT_EXTENDED, XWT_INVALID, XWT_WANSUNG, // Lead = 0xC6
  679. XWT_INVALID, XWT_INVALID, XWT_WANSUNG, // Lead = 0xC7-0xC8
  680. XWT_INVALID, XWT_INVALID, XWT_UDC, // Lead = 0xC9, 0xFE
  681. XWT_INVALID, XWT_INVALID, XWT_HANJA // Lead = 0xCA-0xFD
  682. };
  683. int GetXWType( WORD wXW )
  684. {
  685. BYTE bL = ( wXW >> 8 ) & 0xFF;
  686. BYTE bT = wXW & 0xFF;
  687. int iLType = -1, iTType = -1;
  688. if ( ( bT >= 0x41 ) && ( bT <= 0xFE ) )
  689. {
  690. if ( bT <= 0x52 )
  691. iTType = 0; // Tail Range 0x41-0x52
  692. else
  693. {
  694. if ( bT >= 0xA1 )
  695. iTType = 2; // Tail Range 0xA1-0xFE
  696. else if ( ( bT <= 0x5A ) || ( bT >= 0x81 ) ||
  697. ( ( bT >= 0x61 ) && ( bT <= 0x7A ) ) )
  698. iTType = 1; // Tail Range 0x53-0x5A, 0x61-0x7A, 0x81-0xA0
  699. }
  700. }
  701. if ( iTType < 0 ) return( -1 );
  702. if ( ( bL >= 0x81 ) && ( bL <= 0xFE ) )
  703. {
  704. if ( bL < 0xB0 )
  705. {
  706. if ( bL <= 0xA0 )
  707. iLType = 0; // Lead Range 0x81-0xA0
  708. else if ( bL <= 0xAC )
  709. iLType = 1; // Lead Range 0xA1-0xAC
  710. else
  711. iLType = 2; // Lead Range 0xAD-0xAF
  712. }
  713. else
  714. {
  715. if ( bL <= 0xC8 )
  716. {
  717. if ( bL < 0xC6 )
  718. iLType = 3; // Lead Range 0xB0-0xC5
  719. else if ( bL == 0xC6 )
  720. iLType = 4; // Lead Range 0xC6
  721. else
  722. iLType = 5; // Lead Range 0xC7-0xC8
  723. }
  724. else
  725. {
  726. if ( ( bL == 0xC9 ) || ( bL == 0xFE ) )
  727. iLType = 6; // Lead Range 0xC9, 0xFE
  728. else
  729. iLType = 7; // Lead Range 0xCA-0xFD
  730. }
  731. }
  732. }
  733. return( ( iLType < 0 ) ? -1 : iXWType[iLType][iTType] );
  734. }
  735. WORD ConvXW2J( WORD wXW )
  736. {
  737. const WORD *pTF;
  738. int iTO;
  739. BYTE bL, bT;
  740. switch ( GetXWType( wXW ) )
  741. {
  742. case XWT_EXTENDED :
  743. bL = ( ( wXW >> 8 ) & 0xFF ) - 0x81;
  744. bT = wXW & 0xFF;
  745. if ( ( bT -= 0x41 ) > 0x19 )
  746. if ( ( bT -= 6 ) > 0x33 )
  747. bT -= 6;
  748. iTO = bT + iTailOffX[bL];
  749. pTF = iTailFirstX + ( bL = iLeadMapX[bL] );
  750. break;
  751. case XWT_WANSUNG :
  752. bL = ( ( wXW >> 8 ) & 0xFF ) - 0xB0;
  753. iTO = ( wXW & 0xFF ) - 0xA1 + iTailOff[bL];
  754. pTF = iTailFirst + ( bL = iLeadMap[bL] );
  755. break;
  756. default:
  757. return( 0 );
  758. }
  759. iTO += *pTF++;
  760. while ( iTO >= *pTF++ ) bL++;
  761. return( (WORD) ( bL + 0x88 ) * 256 + bTailTable[iTO] );
  762. }
  763. static int BinarySearch( WORD wJ, const WORD iTF[] )
  764. {
  765. int iL;
  766. BYTE bT;
  767. int iStart, iEnd, iMiddle;
  768. iL = ( ( wJ >> 8 ) & 0xFF ) - 0x88;
  769. bT = wJ & 0xFF;
  770. iStart = iTF[iL];
  771. iEnd = iTF[iL+1] - 1;
  772. while ( iStart <= iEnd )
  773. {
  774. iMiddle = ( iStart + iEnd ) / 2;
  775. if ( bT == bTailTable[iMiddle] )
  776. return( iMiddle );
  777. else if ( bT < bTailTable[iMiddle] )
  778. iEnd = iMiddle - 1;
  779. else
  780. iStart = iMiddle + 1;
  781. }
  782. return( -1 );
  783. }
  784. WORD ConvJ2XW( WORD wJ )
  785. {
  786. int iIndex;
  787. BYTE bL, bT;
  788. iIndex = BinarySearch( wJ, iTailFirst );
  789. if ( iIndex < 0 )
  790. {
  791. if (!UseXWansung())
  792. return 0;
  793. iIndex = BinarySearch( wJ, iTailFirstX ) - N_WANSUNG;
  794. if ( iIndex < 5696 )
  795. {
  796. bL = iIndex / 178 + 0x81;
  797. bT = iIndex % 178;
  798. }
  799. else
  800. {
  801. iIndex -= 5696;
  802. bL = iIndex / 84 + 0xA1;
  803. bT = iIndex % 84;
  804. }
  805. if ( ( bT += 0x41 ) > 0x5A )
  806. if ( ( bT += 6 ) > 0x7A )
  807. bT += 6;
  808. return( (WORD) bL * 256 + bT );
  809. }
  810. else
  811. return( ( iIndex / 94 + 0xB0 ) * 256 + ( iIndex % 94 ) + 0xA1 );
  812. }
  813. #endif
  814. WORD Johab2Wansung(WORD wJohab)
  815. {
  816. #ifndef XWANSUNG_IME
  817. int iHead = 0, iTail = 2349, iMid;
  818. #endif
  819. BYTE bCount, bMaxCount;
  820. WORD wWansung;
  821. PWORD pwKSCompCode;
  822. if (fComplete)
  823. {
  824. #ifdef XWANSUNG_IME
  825. wWansung = ConvJ2XW(wJohab);
  826. #else
  827. wWansung = 0;
  828. while (iHead <= iTail && !wWansung)
  829. {
  830. iMid = (iHead + iTail) / 2;
  831. if (wKSCharCode[iMid] > wJohab)
  832. iTail = iMid - 1;
  833. else if (wKSCharCode[iMid] < wJohab)
  834. iHead = iMid + 1;
  835. else
  836. wWansung = ((iMid / 94 + 0xB0) << 8) | (iMid % 94 + 0xA1);
  837. }
  838. #endif
  839. }
  840. else
  841. {
  842. if (bState == JONG)
  843. { // For 3 Beolsik only.
  844. bMaxCount = 30;
  845. pwKSCompCode = (PWORD)wKSCompCode2;
  846. }
  847. else
  848. {
  849. bMaxCount = 51;
  850. pwKSCompCode = (PWORD)wKSCompCode;
  851. }
  852. for (bCount = 0; pwKSCompCode[bCount] != wJohab
  853. && bCount < bMaxCount; bCount++)
  854. ;
  855. wWansung = (bCount == bMaxCount)? 0: bCount + 0xA4A1;
  856. }
  857. return (wWansung);
  858. }
  859. WORD Wansung2Johab(WORD wWansung)
  860. {
  861. WORD wJohab;
  862. #ifndef XWANSUNG_IME
  863. UINT uLoc;
  864. #endif
  865. if (wWansung >= (WORD)0xA4A1 && wWansung <= (WORD)0xA4D3)
  866. wJohab = wKSCompCode[wWansung - 0xA4A1];
  867. #ifdef XWANSUNG_IME
  868. else
  869. wJohab = ConvXW2J(wWansung);
  870. #else
  871. else if (wWansung >= (WORD)0xB0A1 && wWansung <= (WORD)0xC8FE
  872. && (wWansung & 0x00FF) != (BYTE)0xFF)
  873. {
  874. uLoc = ((wWansung >> 8) - 176) * 94;
  875. uLoc += (wWansung & 0x00FF) - 161;
  876. wJohab = wKSCharCode[uLoc];
  877. }
  878. else
  879. wJohab = 0;
  880. #endif
  881. return (wJohab);
  882. }
  883. #endif
  884. void Code2Automata(void)
  885. {
  886. int i;
  887. #ifdef JOHAB_IME
  888. JohabChar.w = WansungChar.w;
  889. #else
  890. JohabChar.w = Wansung2Johab(WansungChar.w);
  891. #endif
  892. // Initialize all Automata Variables.
  893. bState = NUL;
  894. Cho1 = Cho2 = Jung1 = Jung2 = Jong1 = Jong2 = 0;
  895. mCho = mJung = mJong = 0;
  896. fComplete = FALSE;
  897. if (JohabChar.w)
  898. {
  899. if (JohabChar.h.cho != CFILL)
  900. {
  901. if (uCurrentInputMethod == IDD_2BEOL)
  902. {
  903. Cho1 = (BYTE)JohabChar.h.cho;
  904. Cho2 = mCho = 0;
  905. }
  906. else
  907. {
  908. for (i = 0; i < 5; i++)
  909. if (rgbMChoTbl[i][2] == JohabChar.h.cho)
  910. {
  911. Cho1 = rgbMChoTbl[i][0];
  912. Cho2 = rgbMChoTbl[i][1];
  913. mCho = rgbMChoTbl[i][2];
  914. break;
  915. }
  916. if (i == 5)
  917. {
  918. Cho1 = (BYTE)JohabChar.h.cho;
  919. Cho2 = mCho = 0;
  920. }
  921. }
  922. fComplete = FALSE;
  923. bState = CHO;
  924. }
  925. else
  926. {
  927. Cho1 = CFILL;
  928. Cho2 = mCho = 0;
  929. }
  930. if (JohabChar.h.jung != VFILL)
  931. {
  932. for (i = 0; i < 7; i++)
  933. if (rgbMJungTbl[i][2] == JohabChar.h.jung)
  934. {
  935. Jung1 = rgbMJungTbl[i][0];
  936. Jung2 = rgbMJungTbl[i][1];
  937. mJung = rgbMJungTbl[i][2];
  938. break;
  939. }
  940. if (i == 7)
  941. {
  942. Jung1 = (BYTE)JohabChar.h.jung;
  943. Jung2 = mJung = 0;
  944. }
  945. if (bState == CHO)
  946. fComplete = TRUE;
  947. bState = JUNG;
  948. }
  949. else
  950. {
  951. Jung1 = VFILL;
  952. Jung2 = mJung = 0;
  953. }
  954. if (JohabChar.h.jong != CFILL)
  955. {
  956. for (i = 0; i < 13; i++)
  957. if (rgbMJongTbl[i][2] == JohabChar.h.jong)
  958. {
  959. if (uCurrentInputMethod == IDD_2BEOL
  960. && rgbMJongTbl[i][0] == rgbMJongTbl[i][1])
  961. {
  962. Jong1 = (BYTE)JohabChar.h.jong;
  963. Jong2 = mJong = 0;
  964. }
  965. else
  966. {
  967. Jong1 = rgbMJongTbl[i][0];
  968. Jong2 = rgbMJongTbl[i][1];
  969. mJong = rgbMJongTbl[i][2];
  970. }
  971. break;
  972. }
  973. if (i == 13)
  974. {
  975. Jong1 = (BYTE)JohabChar.h.jong;
  976. Jong2 = mJong = 0;
  977. }
  978. if (bState != JUNG)
  979. fComplete = FALSE;
  980. bState = JONG;
  981. }
  982. else
  983. {
  984. Jong1 = CFILL;
  985. Jong2 = mJong = 0;
  986. }
  987. }
  988. }
  989. void UpdateOpenCloseState(HIMC hIMC)
  990. {
  991. LPINPUTCONTEXT lpIMC;
  992. lpIMC = ImmLockIMC(hIMC);
  993. if (lpIMC != NULL) {
  994. if ((lpIMC->fdwConversion & IME_CMODE_HANGEUL) ||
  995. (lpIMC->fdwConversion & IME_CMODE_FULLSHAPE))
  996. ImmSetOpenStatus(hIMC, TRUE);
  997. else
  998. ImmSetOpenStatus(hIMC, FALSE);
  999. ImmUnlockIMC(hIMC);
  1000. }
  1001. }
  1002. int SearchHanjaIndex(WORD wHChar)
  1003. {
  1004. int iHead = 0, iTail = 490, iMid;
  1005. #ifdef JOHAB_IME
  1006. while (iHead < 18)
  1007. if (wHanjaMap[iHead++] == wHChar)
  1008. return (iHead - 1);
  1009. #endif
  1010. while (iHead <= iTail)
  1011. {
  1012. iMid = (iHead + iTail) / 2;
  1013. if (wHanjaMap[iMid] > wHChar)
  1014. iTail = iMid - 1;
  1015. else if (wHanjaMap[iMid] < wHChar)
  1016. iHead = iMid + 1;
  1017. else
  1018. return (iMid);
  1019. }
  1020. return (-1);
  1021. }