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.

1216 lines
36 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. TOASCII.c
  5. ++*/
  6. #include <windows.h>
  7. #include <immdev.h>
  8. #include "imeattr.h"
  9. #include "imedefs.h"
  10. #if defined(UNIIME)
  11. #include "uniime.h"
  12. #endif
  13. #if HANDLE_PRIVATE_HOTKEY
  14. /**********************************************************************/
  15. /* ChkIMEHotKey() */
  16. /* Return Value: */
  17. /* the ID of hot key */
  18. /**********************************************************************/
  19. UINT PASCAL ChkIMEHotKey(
  20. UINT uVirtKey,
  21. CONST LPBYTE lpbKeyState)
  22. {
  23. UINT uModifyKeys;
  24. UINT uRL;
  25. UINT i;
  26. // find IME hot keys
  27. uModifyKeys = 0;
  28. uRL = 0;
  29. if (lpbKeyState[VK_MENU] & 0x80) {
  30. uModifyKeys |= MOD_ALT;
  31. if (lpbKeyState[VK_LMENU] & 0x80) {
  32. uRL |= MOD_LEFT;
  33. } else if (lpbKeyState[VK_RMENU] & 0x80) {
  34. uRL |= MOD_RIGHT;
  35. } else {
  36. // above can not work in Win95, so fall into this
  37. uRL = (MOD_LEFT|MOD_RIGHT);
  38. }
  39. }
  40. if (lpbKeyState[VK_CONTROL] & 0x80) {
  41. uModifyKeys |= MOD_CONTROL;
  42. if (lpbKeyState[VK_LCONTROL] & 0x80) {
  43. uRL |= MOD_LEFT;
  44. } else if (lpbKeyState[VK_RCONTROL] & 0x80) {
  45. uRL |= MOD_RIGHT;
  46. } else {
  47. // above can not work in Win95, so fall into this
  48. uRL = (MOD_LEFT|MOD_RIGHT);
  49. }
  50. }
  51. if (lpbKeyState[VK_SHIFT] & 0x80) {
  52. uModifyKeys |= MOD_SHIFT;
  53. if (lpbKeyState[VK_LSHIFT] & 0x80) {
  54. uRL |= MOD_LEFT;
  55. } else if (lpbKeyState[VK_RSHIFT] & 0x80) {
  56. uRL |= MOD_RIGHT;
  57. } else {
  58. // above can not work in Win95, so fall into this
  59. uRL = (MOD_LEFT|MOD_RIGHT);
  60. }
  61. }
  62. if (lpbKeyState[VK_LWIN] & 0x80) {
  63. uModifyKeys |= MOD_WIN;
  64. uRL |= MOD_LEFT;
  65. } else if (lpbKeyState[VK_RWIN] & 0x80) {
  66. uModifyKeys |= MOD_WIN;
  67. uRL |= MOD_RIGHT;
  68. } else {
  69. }
  70. if (!uRL) {
  71. uRL = (MOD_LEFT|MOD_RIGHT);
  72. }
  73. for (i = 0; i < NUM_OF_IME_HOTKEYS; i++) {
  74. // virtual key
  75. if (sImeG.uVKey[i] != uVirtKey) {
  76. // virtual key unmatched!
  77. continue;
  78. }
  79. if (sImeG.uModifiers[i] & MOD_IGNORE_ALL_MODIFIER) {
  80. } else if ((sImeG.uModifiers[i] &
  81. (MOD_ALT|MOD_CONTROL|MOD_SHIFT|MOD_WIN)) != uModifyKeys) {
  82. // modifiers unmatched!
  83. continue;
  84. } else {
  85. }
  86. if ((sImeG.uModifiers[i] & (MOD_LEFT|MOD_RIGHT)) ==
  87. (MOD_LEFT|MOD_RIGHT)) {
  88. return (CST_IME_HOTKEYS + i);
  89. }
  90. // we don't have way to distinguish left & right yet
  91. if ((sImeG.uModifiers[i] & (MOD_LEFT|MOD_RIGHT)) == uRL) {
  92. return (CST_IME_HOTKEYS + i);
  93. }
  94. }
  95. // not a hot key
  96. return (0);
  97. }
  98. #endif
  99. /**********************************************************************/
  100. /* ProcessKey() */
  101. /* Return Value: */
  102. /* different state which input key will change IME to */
  103. /**********************************************************************/
  104. UINT PASCAL ProcessKey( // this key will cause the IME go to what state
  105. #if defined(UNIIME)
  106. LPINSTDATAL lpInstL,
  107. LPIMEL lpImeL,
  108. #endif
  109. WORD wCharCode,
  110. UINT uVirtKey,
  111. UINT uScanCode,
  112. CONST LPBYTE lpbKeyState,
  113. LPINPUTCONTEXT lpIMC,
  114. LPPRIVCONTEXT lpImcP)
  115. {
  116. if (!lpIMC) {
  117. return (CST_INVALID);
  118. }
  119. if (!lpImcP) {
  120. return (CST_INVALID);
  121. }
  122. //
  123. // On NT 4.0, the hotkey checking is done by the system and the
  124. // system will call ImeEscape( himc, IME_ESC_PRIVATE_HOTKEY, pdwHotkeyID).
  125. // If you build IMEs that support the ImeEscape(IME_ESC_PRIVATE_HOTKEY),
  126. // HANDLE_PRIVATE_HOTKEY should be disabled.
  127. //
  128. #ifdef HANDLE_PRIVATE_HOTKEY
  129. if ((lpIMC->fdwConversion & (IME_CMODE_NATIVE|IME_CMODE_EUDC|
  130. IME_CMODE_NOCONVERSION|IME_CMODE_CHARCODE)) == IME_CMODE_NATIVE) {
  131. UINT uHotKeyID;
  132. uHotKeyID = ChkIMEHotKey(uVirtKey, lpbKeyState);
  133. if (uHotKeyID) {
  134. return (uHotKeyID);
  135. }
  136. }
  137. #endif
  138. if (uVirtKey == VK_MENU) { // no ALT key
  139. return (CST_INVALID);
  140. } else if (uScanCode & KF_ALTDOWN) { // no ALT-xx key
  141. return (CST_INVALID);
  142. } else if (uVirtKey == VK_CONTROL) { // no CTRL key
  143. return (CST_INVALID);
  144. } else if (lpbKeyState[VK_CONTROL] & 0x80) { // no CTRL-xx key
  145. return (CST_INVALID);
  146. } else if (uVirtKey == VK_SHIFT) { // no SHIFT key
  147. return (CST_INVALID);
  148. } else if (!lpIMC->fOpen) { // don't compose in close status
  149. return (CST_INVALID);
  150. } else if (lpIMC->fdwConversion & IME_CMODE_NOCONVERSION) {
  151. // don't compose in no coversion status
  152. return (CST_INVALID);
  153. } else if (lpIMC->fdwConversion & IME_CMODE_CHARCODE) {
  154. // not support
  155. return (CST_INVALID);
  156. } else {
  157. // need more check
  158. }
  159. #if !defined(ROMANIME)
  160. if (lpIMC->fdwConversion & IME_CMODE_SYMBOL) {
  161. if (uVirtKey == VK_ESCAPE) {
  162. return (CST_SYMBOL);
  163. }
  164. }
  165. #endif
  166. #if defined(DAYI)
  167. if (lpIMC->fdwConversion & IME_CMODE_NATIVE) {
  168. if (wCharCode == '=') {
  169. return (CST_SYMBOL);
  170. }
  171. }
  172. #endif
  173. #if !defined(ROMANIME)
  174. if (lpImcP->fdwImeMsg & (MSG_ALREADY_OPEN|MSG_ALREADY_OPEN2)) {
  175. if (uVirtKey == VK_PRIOR) {
  176. return (CST_CHOOSE);
  177. } else if (uVirtKey == VK_NEXT) {
  178. return (CST_CHOOSE);
  179. } else if (uVirtKey == VK_ESCAPE) {
  180. return (CST_CHOOSE);
  181. #if defined(DAYI)
  182. } else if (uVirtKey == VK_LEFT) {
  183. return (CST_CHOOSE);
  184. } else if (uVirtKey == VK_UP) {
  185. return (CST_CHOOSE);
  186. } else if (uVirtKey == VK_RIGHT) {
  187. return (CST_CHOOSE);
  188. #elif defined(WINAR30)
  189. #else
  190. } else if (wCharCode == '<') {
  191. return (CST_CHOOSE);
  192. } else if (wCharCode == '>') {
  193. return (CST_CHOOSE);
  194. } else if (wCharCode == '?') {
  195. return (CST_CHOOSE);
  196. #endif
  197. } else {
  198. // need more check
  199. }
  200. }
  201. if (lpImcP->iImeState == CST_CHOOSE) {
  202. if (wCharCode > 'z') {
  203. return (CST_INVALID);
  204. } else if (wCharCode < ' ') {
  205. return (CST_INVALID);
  206. } else if (wCharCode >= '0' && wCharCode <= '9') {
  207. #if defined(WINAR30)
  208. } else if (wCharCode == '<') {
  209. return (CST_CHOOSE);
  210. } else if (wCharCode == '>') {
  211. return (CST_CHOOSE);
  212. } else if (wCharCode == '?') {
  213. return (CST_CHOOSE);
  214. #endif
  215. } else {
  216. wCharCode = bUpper[wCharCode - ' '];
  217. #if defined(PHON)
  218. // convert different phonetic keyboard layout to ACER
  219. wCharCode = bStandardLayout[lpImeL->nReadLayout]
  220. [wCharCode - ' '];
  221. #endif
  222. }
  223. if (wCharCode > '_') {
  224. } else if (uVirtKey >= VK_NUMPAD0 && uVirtKey <= VK_NUMPAD9) {
  225. if (uVirtKey >= (VK_NUMPAD0 + (UINT)lpImeL->wCandRangeStart)) {
  226. return (CST_CHOOSE);
  227. } else {
  228. return (CST_ALPHANUMERIC);
  229. }
  230. } else if (lpImeL->fChooseChar[(wCharCode - ' ') >> 4] &
  231. fMask[wCharCode & 0x000F]) { // convert to upper case
  232. return (CST_CHOOSE);
  233. } else {
  234. }
  235. if (!(lpIMC->fdwConversion & IME_CMODE_NATIVE)) {
  236. // alphanumeric mode
  237. if (wCharCode >= ' ' && wCharCode <= '~') {
  238. return (CST_ALPHANUMERIC);
  239. } else {
  240. return (CST_INVALID);
  241. }
  242. } else if (uVirtKey >= 'A' && uVirtKey <= 'Z') {
  243. return (CST_ALPHABET);
  244. } else if (wCharCode >= ' ' && wCharCode <= '~') {
  245. return (CST_ALPHANUMERIC);
  246. } else {
  247. return (CST_INVALID);
  248. }
  249. }
  250. // not in choose mode but candidate alaredy open,
  251. // we must under quick view or phrase prediction
  252. if (lpImcP->fdwImeMsg & (MSG_ALREADY_OPEN|MSG_ALREADY_OPEN2)) {
  253. if (lpImcP->iImeState == CST_INIT) {
  254. if (lpbKeyState[VK_SHIFT] & 0x80) {
  255. if ((uVirtKey >= '0' + (UINT)lpImeL->wCandRangeStart) &&
  256. uVirtKey <= '9') {
  257. return (CST_CHOOSE);
  258. }
  259. }
  260. #if defined(WINAR30)
  261. } else {
  262. if (wCharCode >= '0' && wCharCode <= '9') {
  263. if (*(LPDWORD)lpImcP->bSeq != 0x1B) { //1996/12/12
  264. return (CST_CHOOSE);
  265. }
  266. }
  267. #endif
  268. }
  269. }
  270. if (uVirtKey >= VK_NUMPAD0 && uVirtKey <= VK_DIVIDE) {
  271. // as PM decide all numpad should be past to app
  272. return (CST_ALPHANUMERIC);
  273. }
  274. #endif
  275. #if defined(ROMANIME)
  276. if (wCharCode >= ' ' && wCharCode <= '~') {
  277. if (lpIMC->fdwConversion & IME_CMODE_FULLSHAPE) {
  278. return (CST_ALPHANUMERIC);
  279. } else {
  280. return (CST_INVALID);
  281. }
  282. }
  283. #else
  284. if (!(lpIMC->fdwConversion & IME_CMODE_NATIVE)) {
  285. // alphanumeric mode
  286. if (wCharCode >= ' ' && wCharCode <= '~') {
  287. if (lpIMC->fdwConversion & IME_CMODE_FULLSHAPE) {
  288. return (CST_ALPHANUMERIC);
  289. } else {
  290. return (CST_INVALID);
  291. }
  292. } else {
  293. return (CST_INVALID);
  294. }
  295. } else if (!(lpbKeyState[VK_SHIFT] & 0x80)) {
  296. // need more check for IME_CMODE_NATIVE
  297. #if defined(DAYI)
  298. } else if (lpIMC->fdwConversion & IME_CMODE_SYMBOL) {
  299. #endif
  300. } else if (uVirtKey >= 'A' && uVirtKey <= 'Z') {
  301. return (CST_ALPHABET);
  302. } else if (wCharCode >= ' ' && wCharCode <= '~') {
  303. // need more check for IME_CMODE_NATIVE
  304. } else {
  305. return (CST_INVALID);
  306. }
  307. // IME_CMODE _EUDC will use the same state with IME_CMODE_NATIVE
  308. if (wCharCode >= ' ' && wCharCode <= 'z') {
  309. wCharCode = bUpper[wCharCode - ' '];
  310. #if defined(PHON)
  311. {
  312. // convert different phonetic keyboard layout to ACER
  313. wCharCode = bStandardLayout[lpImeL->nReadLayout][wCharCode - ' '];
  314. }
  315. #endif
  316. }
  317. if (uVirtKey == VK_ESCAPE) {
  318. register LPGUIDELINE lpGuideLine;
  319. register UINT iImeState;
  320. if (lpImcP->fdwImeMsg & MSG_ALREADY_START) {
  321. return (CST_INPUT);
  322. }
  323. lpGuideLine = ImmLockIMCC(lpIMC->hGuideLine);
  324. if (!lpGuideLine) {
  325. return (CST_INVALID);
  326. } else if (lpGuideLine->dwLevel == GL_LEVEL_NOGUIDELINE) {
  327. iImeState = CST_INVALID;
  328. } else {
  329. // need this key to clean information string or guideline state
  330. iImeState = CST_INPUT;
  331. }
  332. ImmUnlockIMCC(lpIMC->hGuideLine);
  333. return (iImeState);
  334. } else if (uVirtKey == VK_BACK) {
  335. if (lpImcP->fdwImeMsg & MSG_ALREADY_START) {
  336. return (CST_INPUT);
  337. } else {
  338. return (CST_INVALID);
  339. }
  340. #if 0
  341. } else if (uVirtKey >= VK_NUMPAD0 && uVirtKey <= VK_DIVIDE) {
  342. // as PM decide all numpad should be past to app
  343. return (CST_ALPHANUMERIC);
  344. #endif
  345. } else if (wCharCode > '~') {
  346. return (CST_INVALID);
  347. } else if (wCharCode < ' ') {
  348. return (CST_INVALID);
  349. #if !defined(ROMANIME)
  350. } else if (lpIMC->fdwConversion & IME_CMODE_EUDC) {
  351. } else if (lpIMC->fdwConversion & IME_CMODE_SYMBOL) {
  352. return (CST_SYMBOL);
  353. } else if (lpInstL->fdwTblLoad == TBL_LOADERR) {
  354. return (CST_INVALID);
  355. } else if (lpInstL->fdwTblLoad == TBL_NOTLOADED) {
  356. if (++lpInstL->cRefCount <= 0) {
  357. lpInstL->cRefCount = 1;
  358. }
  359. LoadTable(lpInstL, lpImeL);
  360. #endif
  361. } else {
  362. }
  363. // check finalize char
  364. if (wCharCode == ' ' && lpImcP->iImeState == CST_INIT) {
  365. if (lpIMC->fdwConversion & IME_CMODE_FULLSHAPE) {
  366. return (CST_ALPHANUMERIC);
  367. } else {
  368. return (CST_INVALID);
  369. }
  370. #if defined(WINAR30) //**** 1996/2/5
  371. } else if (wCharCode == 0x27 && lpImcP->iImeState == CST_INIT) {
  372. if (lpIMC->fdwConversion & IME_CMODE_FULLSHAPE) {
  373. return (CST_ALPHANUMERIC);
  374. } else {
  375. return (CST_INVALID);
  376. }
  377. #endif
  378. } else if (lpImeL->fCompChar[(wCharCode - ' ') >> 4] &
  379. fMask[wCharCode & 0x000F]) {
  380. return (CST_INPUT);
  381. #if defined(WINAR30) //**** 1996/2/5
  382. } else if (wCharCode ==0x27) {
  383. return (CST_INPUT);
  384. #endif
  385. } else if (lpIMC->fdwConversion & IME_CMODE_EUDC) {
  386. return (CST_INVALID);
  387. #if defined(WINAR30)
  388. } else if (*(LPDWORD)lpImcP->bSeq == 0x1B && wCharCode >= '0' && //1996/12/12
  389. wCharCode <= '9') {
  390. return (CST_SYMBOL);
  391. #elif defined(DAYI)
  392. } else if (lpImeL->wChar2SeqTbl[wCharCode - ' '] >= 0x30 &&
  393. lpImeL->wChar2SeqTbl[wCharCode - ' '] <= 0x35) {
  394. return (CST_ROAD);
  395. #elif !defined(ROMANIME) // for all other IMEs, input EURO.
  396. // Porbably, different Value for different IMEs.
  397. // But Now, we take use 3D as all IMEs EURO Input Key's Seq value.
  398. } else if (lpImeL->wChar2SeqTbl[wCharCode - ' '] == 0x3D ) {
  399. return (CST_EURO);
  400. #endif
  401. } else if (lpIMC->fdwConversion & IME_CMODE_FULLSHAPE) {
  402. return (CST_ALPHANUMERIC);
  403. } else {
  404. return (CST_INVALID);
  405. }
  406. #endif // !ROMANIME
  407. return (CST_INVALID);
  408. }
  409. /**********************************************************************/
  410. /* ImeProcessKey() / UniImeProcessKey() */
  411. /* Return Value: */
  412. /* TRUE - successful, FALSE - failure */
  413. /**********************************************************************/
  414. // if this key is need by IME?
  415. #if defined(UNIIME)
  416. BOOL WINAPI UniImeProcessKey(
  417. LPINSTDATAL lpInstL,
  418. LPIMEL lpImeL,
  419. #else
  420. BOOL WINAPI ImeProcessKey(
  421. #endif
  422. HIMC hIMC,
  423. UINT uVirtKey,
  424. LPARAM lParam,
  425. CONST LPBYTE lpbKeyState)
  426. {
  427. LPINPUTCONTEXT lpIMC;
  428. LPPRIVCONTEXT lpImcP;
  429. BYTE szAscii[4];
  430. int nChars;
  431. BOOL fRet;
  432. // can't compose in NULL hIMC
  433. if (!hIMC) {
  434. return (FALSE);
  435. }
  436. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  437. if (!lpIMC) {
  438. return (FALSE);
  439. }
  440. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  441. if (!lpImcP) {
  442. ImmUnlockIMC(hIMC);
  443. return (FALSE);
  444. }
  445. nChars = ToAscii(uVirtKey, HIWORD(lParam), lpbKeyState,
  446. (LPVOID)szAscii, 0);
  447. if (!nChars) {
  448. szAscii[0] = 0;
  449. }
  450. if (ProcessKey(
  451. #if defined(UNIIME)
  452. lpInstL, lpImeL,
  453. #endif
  454. (WORD)szAscii[0], uVirtKey, HIWORD(lParam), lpbKeyState,
  455. lpIMC, lpImcP) == CST_INVALID) {
  456. fRet = FALSE;
  457. } else {
  458. fRet = TRUE;
  459. }
  460. ImmUnlockIMCC(lpIMC->hPrivate);
  461. ImmUnlockIMC(hIMC);
  462. return (fRet);
  463. }
  464. /**********************************************************************/
  465. /* TranslateToAscii() */
  466. /* Return Value: */
  467. /* the number of translated chars */
  468. /**********************************************************************/
  469. UINT PASCAL TranslateToAscii( // translate the key to WM_CHAR
  470. // as keyboard driver
  471. UINT uVirtKey,
  472. UINT uScanCode,
  473. LPTRANSMSGLIST lpTransBuf,
  474. UINT uNumMsg,
  475. WORD wCharCode)
  476. {
  477. LPTRANSMSG lpTransMsg;
  478. if (wCharCode) { // one char code
  479. // 3 DWORD (message, wParam, lParam)
  480. lpTransMsg = (lpTransBuf->TransMsg) + uNumMsg;
  481. lpTransMsg->message = WM_CHAR;
  482. lpTransMsg->wParam = wCharCode;
  483. lpTransMsg->lParam = (uScanCode << 16) | 1UL;
  484. return (1);
  485. }
  486. // no char code case
  487. return (0);
  488. }
  489. /**********************************************************************/
  490. /* TranslateImeMessage() */
  491. /* Return Value: */
  492. /* the number of translated messages */
  493. /**********************************************************************/
  494. UINT PASCAL TranslateImeMessage(
  495. LPTRANSMSGLIST lpTransBuf,
  496. LPINPUTCONTEXT lpIMC,
  497. LPPRIVCONTEXT lpImcP)
  498. {
  499. UINT uNumMsg;
  500. UINT i;
  501. BOOL bLockMsgBuf;
  502. LPTRANSMSG lpTransMsg;
  503. uNumMsg = 0;
  504. bLockMsgBuf = FALSE;
  505. for (i = 0; i < 2; i++) {
  506. #if !defined(ROMANIME)
  507. if (lpImcP->fdwImeMsg & MSG_IMN_COMPOSITIONSIZE) {
  508. if (!i) {
  509. uNumMsg++;
  510. } else {
  511. lpTransMsg->message = WM_IME_NOTIFY;
  512. lpTransMsg->wParam = IMN_PRIVATE;
  513. lpTransMsg->lParam = IMN_PRIVATE_COMPOSITION_SIZE;
  514. lpTransMsg++;
  515. }
  516. }
  517. if (lpImcP->fdwImeMsg & MSG_START_COMPOSITION) {
  518. if (!(lpImcP->fdwImeMsg & MSG_ALREADY_START)) {
  519. if (!i) {
  520. uNumMsg++;
  521. } else {
  522. lpTransMsg->message = WM_IME_STARTCOMPOSITION;
  523. lpTransMsg->wParam = 0;
  524. lpTransMsg->lParam = 0;
  525. lpTransMsg++;
  526. lpImcP->fdwImeMsg |= MSG_ALREADY_START;
  527. }
  528. }
  529. }
  530. if (lpImcP->fdwImeMsg & MSG_IMN_COMPOSITIONPOS) {
  531. if (!i) {
  532. uNumMsg++;
  533. } else {
  534. lpTransMsg->message = WM_IME_NOTIFY;
  535. lpTransMsg->wParam = IMN_SETCOMPOSITIONWINDOW;
  536. lpTransMsg->lParam = 0;
  537. lpTransMsg++;
  538. }
  539. }
  540. #endif
  541. if (lpImcP->fdwImeMsg & MSG_COMPOSITION) {
  542. if (!i) {
  543. uNumMsg++;
  544. } else {
  545. lpTransMsg->message = WM_IME_COMPOSITION;
  546. lpTransMsg->wParam = (DWORD)lpImcP->dwCompChar;
  547. lpTransMsg->lParam = (DWORD)lpImcP->fdwGcsFlag;
  548. lpTransMsg++;
  549. }
  550. }
  551. #if !defined(ROMANIME)
  552. if (lpImcP->fdwImeMsg & MSG_GUIDELINE) {
  553. if (!i) {
  554. uNumMsg++;
  555. } else {
  556. lpTransMsg->message = WM_IME_NOTIFY;
  557. lpTransMsg->wParam = IMN_GUIDELINE;
  558. lpTransMsg->lParam = 0;
  559. lpTransMsg++;
  560. }
  561. }
  562. if (lpImcP->fdwImeMsg & MSG_IMN_PAGEUP) {
  563. if (!i) {
  564. uNumMsg++;
  565. } else {
  566. lpTransMsg->message = WM_IME_NOTIFY;
  567. lpTransMsg->wParam = IMN_PRIVATE;
  568. lpTransMsg->lParam = IMN_PRIVATE_PAGEUP;
  569. lpTransMsg++;
  570. }
  571. }
  572. if (lpImcP->fdwImeMsg & MSG_OPEN_CANDIDATE) {
  573. if (!(lpImcP->fdwImeMsg & MSG_ALREADY_OPEN)) {
  574. if (!i) {
  575. uNumMsg++;
  576. } else {
  577. lpTransMsg->message = WM_IME_NOTIFY;
  578. lpTransMsg->wParam = IMN_OPENCANDIDATE;
  579. lpTransMsg->lParam = 0x0001;
  580. lpTransMsg++;
  581. lpImcP->fdwImeMsg |= MSG_ALREADY_OPEN;
  582. }
  583. }
  584. }
  585. if (lpImcP->fdwImeMsg & MSG_CHANGE_CANDIDATE) {
  586. if (!i) {
  587. uNumMsg++;
  588. } else {
  589. lpTransMsg->message = WM_IME_NOTIFY;
  590. lpTransMsg->wParam = IMN_CHANGECANDIDATE;
  591. lpTransMsg->lParam = 0x0001;
  592. lpTransMsg++;
  593. }
  594. }
  595. if (lpImcP->fdwImeMsg & MSG_IMN_UPDATE_PREDICT) {
  596. if (!i) {
  597. uNumMsg++;
  598. } else {
  599. lpTransMsg->message = WM_IME_NOTIFY;
  600. lpTransMsg->wParam = IMN_PRIVATE;
  601. lpTransMsg->lParam = IMN_PRIVATE_UPDATE_PREDICT;
  602. lpTransMsg++;
  603. }
  604. }
  605. #if defined(WINAR30)
  606. if (lpImcP->fdwImeMsg & MSG_IMN_UPDATE_QUICK_KEY) {
  607. if (!i) {
  608. uNumMsg++;
  609. } else {
  610. lpTransMsg->message = WM_IME_NOTIFY;
  611. lpTransMsg->wParam = IMN_PRIVATE;
  612. lpTransMsg->lParam = IMN_PRIVATE_UPDATE_QUICK_KEY;
  613. lpTransMsg++;
  614. }
  615. }
  616. #else
  617. if (lpImcP->fdwImeMsg & MSG_IMN_UPDATE_SOFTKBD) {
  618. if (!i) {
  619. uNumMsg++;
  620. } else {
  621. lpTransMsg->message = WM_IME_NOTIFY;
  622. lpTransMsg->wParam = IMN_PRIVATE;
  623. lpTransMsg->lParam = IMN_PRIVATE_UPDATE_SOFTKBD;
  624. lpTransMsg++;
  625. }
  626. }
  627. #endif
  628. if (lpImcP->fdwImeMsg & MSG_CLOSE_CANDIDATE) {
  629. if (lpImcP->fdwImeMsg & MSG_ALREADY_OPEN) {
  630. if (!i) {
  631. uNumMsg++;
  632. } else {
  633. lpTransMsg->message = WM_IME_NOTIFY;
  634. lpTransMsg->wParam = IMN_CLOSECANDIDATE;
  635. lpTransMsg->lParam = 0x0001;
  636. lpTransMsg++;
  637. lpImcP->fdwImeMsg &= ~(MSG_ALREADY_OPEN);
  638. }
  639. }
  640. }
  641. if (lpImcP->fdwImeMsg & MSG_END_COMPOSITION) {
  642. if (lpImcP->fdwImeMsg & MSG_ALREADY_START) {
  643. if (!i) {
  644. uNumMsg++;
  645. } else {
  646. lpTransMsg->message = WM_IME_ENDCOMPOSITION;
  647. lpTransMsg->wParam = 0;
  648. lpTransMsg->lParam = 0;
  649. lpTransMsg++;
  650. lpImcP->fdwImeMsg &= ~(MSG_ALREADY_START);
  651. }
  652. }
  653. }
  654. #endif
  655. if (lpImcP->fdwImeMsg & MSG_IMN_TOGGLE_UI) {
  656. if (!i) {
  657. uNumMsg++;
  658. } else {
  659. lpTransMsg->message = WM_IME_NOTIFY;
  660. lpTransMsg->wParam = IMN_PRIVATE;
  661. lpTransMsg->lParam = IMN_PRIVATE_TOGGLE_UI;
  662. lpTransMsg++;
  663. }
  664. }
  665. if (!i) {
  666. HIMCC hMem;
  667. if (!uNumMsg) {
  668. return (uNumMsg);
  669. }
  670. if (lpImcP->fdwImeMsg & MSG_IN_IMETOASCIIEX) {
  671. UINT uNumMsgLimit;
  672. // ++ for the start position of buffer to strore the messages
  673. uNumMsgLimit = lpTransBuf->uMsgCount;
  674. if (uNumMsg <= uNumMsgLimit) {
  675. lpTransMsg = lpTransBuf->TransMsg;
  676. continue;
  677. }
  678. }
  679. // we need to use message buffer
  680. if (!lpIMC->hMsgBuf) {
  681. lpIMC->hMsgBuf = ImmCreateIMCC(uNumMsg * sizeof(TRANSMSG));
  682. lpIMC->dwNumMsgBuf = 0;
  683. } else if (hMem = ImmReSizeIMCC(lpIMC->hMsgBuf,
  684. (lpIMC->dwNumMsgBuf + uNumMsg) * sizeof(TRANSMSG))) {
  685. if (hMem != lpIMC->hMsgBuf) {
  686. ImmDestroyIMCC(lpIMC->hMsgBuf);
  687. lpIMC->hMsgBuf = hMem;
  688. }
  689. } else {
  690. return (0);
  691. }
  692. lpTransMsg = (LPTRANSMSG)ImmLockIMCC(lpIMC->hMsgBuf);
  693. if (!lpTransMsg) {
  694. return (0);
  695. }
  696. lpTransMsg += lpIMC->dwNumMsgBuf;
  697. bLockMsgBuf = TRUE;
  698. } else {
  699. if (bLockMsgBuf) {
  700. ImmUnlockIMCC(lpIMC->hMsgBuf);
  701. }
  702. }
  703. }
  704. return (uNumMsg);
  705. }
  706. /**********************************************************************/
  707. /* TranslateFullChar() */
  708. /* Return Value: */
  709. /* the number of translated chars */
  710. /**********************************************************************/
  711. UINT PASCAL TranslateFullChar( // convert to Double Byte Char
  712. LPTRANSMSGLIST lpTransBuf,
  713. LPINPUTCONTEXT lpIMC,
  714. LPPRIVCONTEXT lpImcP,
  715. WCHAR wCharCode)
  716. {
  717. LPCOMPOSITIONSTRING lpCompStr;
  718. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  719. if (!lpCompStr) {
  720. return TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
  721. }
  722. lpCompStr->dwResultReadClauseLen = 0;
  723. lpCompStr->dwResultReadStrLen = 0;
  724. lpCompStr->dwResultStrLen = sizeof(WCHAR) / sizeof(TCHAR);
  725. #if defined(UNICODE)
  726. *(LPWSTR)((LPBYTE)lpCompStr + lpCompStr->dwResultStrOffset) =
  727. wCharCode;
  728. #else
  729. *((LPBYTE)lpCompStr + lpCompStr->dwResultStrOffset) =
  730. HIBYTE(wCharCode);
  731. *((LPBYTE)lpCompStr + lpCompStr->dwResultStrOffset + sizeof(BYTE)) =
  732. LOBYTE(wCharCode);
  733. #endif
  734. // add a null terminator
  735. *(LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwResultStrOffset +
  736. sizeof(WCHAR)) = '\0';
  737. lpCompStr->dwResultClauseLen = 2 * sizeof(DWORD);
  738. *(LPDWORD)((LPBYTE)lpCompStr + lpCompStr->dwResultClauseOffset +
  739. sizeof(DWORD)) = lpCompStr->dwResultStrLen;
  740. ImmUnlockIMCC(lpIMC->hCompStr);
  741. lpImcP->fdwImeMsg |= MSG_COMPOSITION;
  742. lpImcP->dwCompChar = 0;
  743. lpImcP->fdwGcsFlag |= GCS_RESULTREAD|GCS_RESULT;
  744. return TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
  745. }
  746. /**********************************************************************/
  747. /* ImeToAsciiEx() / UniImeToAsciiex() */
  748. /* Return Value: */
  749. /* the number of translated message */
  750. /**********************************************************************/
  751. #if defined(UNIIME)
  752. UINT WINAPI UniImeToAsciiEx(
  753. LPINSTDATAL lpInstL,
  754. LPIMEL lpImeL,
  755. #else
  756. UINT WINAPI ImeToAsciiEx(
  757. #endif
  758. UINT uVirtKey,
  759. UINT uScanCode,
  760. CONST LPBYTE lpbKeyState,
  761. LPTRANSMSGLIST lpTransBuf,
  762. UINT fuState,
  763. HIMC hIMC)
  764. {
  765. WORD wCharCode;
  766. LPINPUTCONTEXT lpIMC;
  767. LPCOMPOSITIONSTRING lpCompStr;
  768. #if !defined(ROMANIME)
  769. LPGUIDELINE lpGuideLine;
  770. #endif
  771. LPPRIVCONTEXT lpImcP;
  772. UINT uNumMsg;
  773. int iRet;
  774. #ifdef UNICODE
  775. wCharCode = HIWORD(uVirtKey);
  776. #else
  777. wCharCode = HIBYTE(uVirtKey);
  778. #endif
  779. uVirtKey = LOBYTE(uVirtKey);
  780. if (!hIMC) {
  781. uNumMsg = TranslateToAscii(uVirtKey, uScanCode, lpTransBuf,
  782. 0, wCharCode);
  783. return (uNumMsg);
  784. }
  785. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  786. if (!lpIMC) {
  787. uNumMsg = TranslateToAscii(uVirtKey, uScanCode, lpTransBuf,
  788. 0, wCharCode);
  789. return (uNumMsg);
  790. }
  791. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  792. if (!lpImcP) {
  793. ImmUnlockIMC(hIMC);
  794. uNumMsg = TranslateToAscii(uVirtKey, uScanCode, lpTransBuf,
  795. 0, wCharCode);
  796. return (uNumMsg);
  797. }
  798. // Now all composition realated information already pass to app
  799. // a brand new start
  800. #if defined(ROMANIME)
  801. lpImcP->fdwImeMsg = MSG_IN_IMETOASCIIEX;
  802. #else
  803. lpImcP->fdwImeMsg = lpImcP->fdwImeMsg & (MSG_STATIC_STATE) |
  804. MSG_IN_IMETOASCIIEX;
  805. #endif
  806. iRet = ProcessKey(
  807. #if defined(UNIIME)
  808. lpInstL, lpImeL,
  809. #endif
  810. wCharCode, uVirtKey, uScanCode, lpbKeyState, lpIMC, lpImcP);
  811. #if !defined(ROMANIME)
  812. if (iRet == CST_ALPHABET) {
  813. // A-Z convert to a-z, a-z convert to A-Z
  814. wCharCode ^= 0x20;
  815. iRet = CST_ALPHANUMERIC;
  816. }
  817. if (iRet == CST_CHOOSE) {
  818. } else if (iRet == CST_TOGGLE_UI) {
  819. } else if (lpImcP->iImeState == CST_INPUT) {
  820. } else if (lpImcP->iImeState == CST_CHOOSE) {
  821. } else {
  822. ClearCand(lpIMC);
  823. if (lpImcP->fdwImeMsg & MSG_ALREADY_OPEN) {
  824. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg |
  825. MSG_CLOSE_CANDIDATE) & ~(MSG_OPEN_CANDIDATE);
  826. } else {
  827. lpImcP->fdwImeMsg &= ~(MSG_OPEN_CANDIDATE);
  828. }
  829. }
  830. #endif
  831. if (iRet == CST_ALPHANUMERIC) {
  832. if (lpIMC->fdwConversion & IME_CMODE_FULLSHAPE) { // convert to DBCS
  833. uNumMsg = TranslateFullChar(lpTransBuf, lpIMC, lpImcP,
  834. sImeG.wFullABC[wCharCode - ' ']);
  835. } else {
  836. uNumMsg = TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
  837. uNumMsg += TranslateToAscii(uVirtKey, uScanCode, lpTransBuf,
  838. uNumMsg, wCharCode);
  839. }
  840. #if !defined(ROMANIME)
  841. } else if (iRet == CST_SYMBOL) {
  842. if (uVirtKey == VK_ESCAPE) {
  843. CandEscapeKey(lpIMC, lpImcP);
  844. ImmSetConversionStatus(hIMC,
  845. lpIMC->fdwConversion & ~(IME_CMODE_SYMBOL),
  846. lpIMC->fdwSentence);
  847. } else if (lpIMC->fdwConversion & IME_CMODE_SYMBOL) {
  848. #if defined(WINAR30) || defined(DAYI)
  849. #if defined(DAYI)
  850. if (wCharCode == '=') {
  851. CandEscapeKey(lpIMC, lpImcP);
  852. ImmSetConversionStatus(hIMC,
  853. lpIMC->fdwConversion ^ (IME_CMODE_SYMBOL),
  854. lpIMC->fdwSentence);
  855. #endif
  856. #if defined(WINAR30)
  857. if (wCharCode >= '0' && wCharCode <= '9') {
  858. #endif
  859. #if defined(DAYI)
  860. } else if (wCharCode >= ' ' && wCharCode <= '~') {
  861. #endif
  862. CandEscapeKey(lpIMC, lpImcP);
  863. ImmSetConversionStatus(hIMC,
  864. lpIMC->fdwConversion | IME_CMODE_SYMBOL,
  865. lpIMC->fdwSentence);
  866. SearchSymbol(wCharCode, hIMC, lpIMC, lpImcP);
  867. } else {
  868. MessageBeep((UINT)-1);
  869. CandEscapeKey(lpIMC, lpImcP);
  870. ImmSetConversionStatus(hIMC,
  871. lpIMC->fdwConversion & ~(IME_CMODE_SYMBOL),
  872. lpIMC->fdwSentence);
  873. }
  874. #else
  875. ImmSetConversionStatus(hIMC,
  876. lpIMC->fdwConversion & ~(IME_CMODE_SYMBOL),
  877. lpIMC->fdwSentence);
  878. if (wCharCode >= ' ' && wCharCode <= '}') {
  879. wCharCode = bUpper[wCharCode - ' '];
  880. uNumMsg = TranslateFullChar(lpTransBuf, lpIMC, lpImcP,
  881. sImeG.wSymbol[wCharCode - ' ']);
  882. goto ImToAsExExit;
  883. }
  884. #endif
  885. } else {
  886. #if defined(WINAR30) || defined(DAYI)
  887. CandEscapeKey(lpIMC, lpImcP);
  888. ImmSetConversionStatus(hIMC,
  889. lpIMC->fdwConversion | IME_CMODE_SYMBOL,
  890. lpIMC->fdwSentence);
  891. #if defined(WINAR30)
  892. SearchSymbol(wCharCode, hIMC, lpIMC, lpImcP);
  893. #endif
  894. #endif
  895. }
  896. uNumMsg = TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
  897. } else if (iRet == CST_CHOOSE) {
  898. LPCANDIDATEINFO lpCandInfo;
  899. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  900. if (uVirtKey == VK_PRIOR) {
  901. wCharCode = CHOOSE_PREVPAGE;
  902. } else if (uVirtKey == VK_NEXT) {
  903. wCharCode = CHOOSE_NEXTPAGE;
  904. } else if (uVirtKey >= (VK_NUMPAD0 + (UINT)lpImeL->wCandRangeStart) &&
  905. uVirtKey <= VK_NUMPAD9) {
  906. wCharCode = uVirtKey - VK_NUMPAD0;
  907. #if defined(DAYI)
  908. } else if (lpImcP->iImeState != CST_CHOOSE && uVirtKey >= '0' &&
  909. uVirtKey <= '9') {
  910. // convert shift-0 ... shift-9 to 0 ... 9
  911. wCharCode = uVirtKey - '0';
  912. } else if (uVirtKey == VK_LEFT) {
  913. wCharCode = CHOOSE_PREVPAGE;
  914. } else if (uVirtKey == VK_UP) {
  915. wCharCode = CHOOSE_HOME;
  916. } else if (uVirtKey == VK_RIGHT) {
  917. wCharCode = CHOOSE_NEXTPAGE;
  918. } else if (wCharCode < ' ') {
  919. } else if (wCharCode > '~') {
  920. } else {
  921. wCharCode = lpImeL->cChooseTrans[wCharCode - ' '];
  922. #else
  923. } else if (uVirtKey >= ('0' + (UINT)lpImeL->wCandRangeStart) &&
  924. uVirtKey <= '9') {
  925. // convert shift-0 ... shift-9 to 0 ... 9
  926. wCharCode = uVirtKey - '0';
  927. } else if (wCharCode == '<') {
  928. wCharCode = CHOOSE_PREVPAGE;
  929. } else if (wCharCode == '?') {
  930. wCharCode = CHOOSE_HOME;
  931. } else if (wCharCode == '>') {
  932. wCharCode = CHOOSE_NEXTPAGE;
  933. } else if (wCharCode == ' ') {
  934. wCharCode = CHOOSE_CIRCLE;
  935. } else {
  936. #endif
  937. }
  938. ChooseCand(
  939. #if defined(UNIIME)
  940. lpInstL, lpImeL,
  941. #endif
  942. wCharCode, hIMC, lpIMC, lpCandInfo, lpImcP);
  943. ImmUnlockIMCC(lpIMC->hCandInfo);
  944. uNumMsg = TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
  945. } else if (iRet == CST_INPUT) {
  946. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  947. lpGuideLine = (LPGUIDELINE)ImmLockIMCC(lpIMC->hGuideLine);
  948. CompWord(
  949. #if defined(UNIIME)
  950. lpInstL, lpImeL,
  951. #endif
  952. wCharCode, hIMC, lpIMC, lpCompStr, lpGuideLine, lpImcP);
  953. if (lpGuideLine) {
  954. ImmUnlockIMCC(lpIMC->hGuideLine);
  955. }
  956. if (lpCompStr) {
  957. ImmUnlockIMCC(lpIMC->hCompStr);
  958. }
  959. uNumMsg = TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
  960. #endif
  961. #if defined(DAYI)
  962. } else if (iRet == CST_ROAD) {
  963. wCharCode = lpImeL->wSeq2CompTbl[lpImeL->wChar2SeqTbl[wCharCode - ' ']];
  964. #ifndef UNICODE
  965. wCharCode = HIBYTE(wCharCode)|(LOBYTE(wCharCode) << 8);
  966. #endif
  967. uNumMsg = TranslateFullChar(lpTransBuf, lpIMC, lpImcP, wCharCode);
  968. #endif
  969. #if !defined(DAYI) && !defined(ROMANIME)
  970. } else if (iRet == CST_EURO) {
  971. wCharCode = lpImeL->wSeq2CompTbl[lpImeL->wChar2SeqTbl[wCharCode - ' ']];
  972. #ifndef UNICODE
  973. wCharCode = HIBYTE(wCharCode)|(LOBYTE(wCharCode) << 8);
  974. #endif
  975. uNumMsg = TranslateFullChar(lpTransBuf, lpIMC, lpImcP, wCharCode);
  976. #endif
  977. }
  978. #ifdef HANDLE_PRIVATE_HOTKEY
  979. else if (iRet == CST_RESEND_RESULT) {
  980. DWORD dwResultStrLen;
  981. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  982. if (lpCompStr) {
  983. if (lpCompStr->dwResultStrLen) {
  984. dwResultStrLen = lpCompStr->dwResultStrLen;
  985. } else {
  986. dwResultStrLen = 0;
  987. }
  988. ImmUnlockIMCC(lpIMC->hCompStr);
  989. } else {
  990. dwResultStrLen = 0;
  991. }
  992. if (dwResultStrLen) {
  993. lpImcP->fdwImeMsg |= MSG_COMPOSITION;
  994. lpImcP->dwCompChar = 0;
  995. lpImcP->fdwGcsFlag |= GCS_RESULTREAD|GCS_RESULT;
  996. } else {
  997. MessageBeep((UINT)-1);
  998. }
  999. uNumMsg = TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
  1000. } else if (iRet == CST_PREVIOUS_COMP) {
  1001. DWORD dwResultReadStrLen;
  1002. TCHAR szReading[16];
  1003. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  1004. if (lpCompStr) {
  1005. if (lpCompStr->dwResultReadStrLen) {
  1006. dwResultReadStrLen = lpCompStr->dwResultReadStrLen;
  1007. if (dwResultReadStrLen > lpImeL->nMaxKey * sizeof(WCHAR)
  1008. / sizeof(TCHAR)) {
  1009. dwResultReadStrLen = lpImeL->nMaxKey * sizeof(WCHAR)
  1010. / sizeof(TCHAR);
  1011. }
  1012. CopyMemory(szReading, (LPBYTE)lpCompStr +
  1013. lpCompStr->dwResultReadStrOffset,
  1014. dwResultReadStrLen * sizeof(TCHAR));
  1015. // NULL termainator
  1016. szReading[dwResultReadStrLen] = '\0';
  1017. } else {
  1018. dwResultReadStrLen = 0;
  1019. }
  1020. ImmUnlockIMCC(lpIMC->hCompStr);
  1021. } else {
  1022. dwResultReadStrLen = 0;
  1023. }
  1024. if (dwResultReadStrLen) {
  1025. #if defined(UNIIME)
  1026. UniImeSetCompositionString(lpInstL, lpImeL, hIMC, SCS_SETSTR,
  1027. NULL, 0, szReading, dwResultReadStrLen * sizeof(TCHAR));
  1028. #else
  1029. ImeSetCompositionString(hIMC, SCS_SETSTR, NULL, 0, szReading,
  1030. dwResultReadStrLen * sizeof(TCHAR));
  1031. #endif
  1032. } else {
  1033. MessageBeep((UINT)-1);
  1034. }
  1035. uNumMsg = TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
  1036. } else if (iRet == CST_TOGGLE_UI) {
  1037. lpImeL->fdwModeConfig ^= MODE_CONFIG_OFF_CARET_UI;
  1038. SetUserSetting(
  1039. #if defined(UNIIME)
  1040. lpImeL,
  1041. #endif
  1042. szRegModeConfig, REG_DWORD, (LPBYTE)&lpImeL->fdwModeConfig,
  1043. sizeof(lpImeL->fdwModeConfig));
  1044. InitImeUIData(lpImeL);
  1045. lpImcP->fdwImeMsg |= MSG_IMN_TOGGLE_UI;
  1046. uNumMsg = TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
  1047. }
  1048. #endif // HANDLE_PRIVATE_HOTKEY
  1049. else {
  1050. uNumMsg = TranslateToAscii(uVirtKey, uScanCode, lpTransBuf,
  1051. 0, wCharCode);
  1052. }
  1053. #if !defined(ROMANIME)
  1054. #if !defined(DAYI) && !defined(WINAR30)
  1055. ImToAsExExit:
  1056. #endif
  1057. lpImcP->fdwImeMsg &= (MSG_STATIC_STATE);
  1058. lpImcP->fdwGcsFlag = 0;
  1059. #endif
  1060. ImmUnlockIMCC(lpIMC->hPrivate);
  1061. ImmUnlockIMC(hIMC);
  1062. return (uNumMsg);
  1063. }