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

915 lines
32 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. compose.c
  5. ++*/
  6. #include <windows.h>
  7. #include <immdev.h>
  8. #include <imedefs.h>
  9. void PASCAL XGBAddCodeIntoCand(LPCANDIDATELIST, WORD);
  10. #if defined(COMBO_IME)
  11. void PASCAL UnicodeAddCodeIntoCand(LPCANDIDATELIST, WORD);
  12. #endif
  13. #if defined(COMBO_IME)
  14. /**********************************************************************/
  15. /* UnicodeEngine() */
  16. /* Description: */
  17. /* Conv GBcode */
  18. /**********************************************************************/
  19. WORD PASCAL UnicodeEngine(LPPRIVCONTEXT lpImcP)
  20. {
  21. if (lpImcP->bSeq[3] || lpImcP->bSeq[2] == TEXT('?') || lpImcP->bSeq[2] == TEXT(' ')) {
  22. if (lpImcP->bSeq[2] == TEXT('?') || lpImcP->bSeq[2] == TEXT(' ')){
  23. lpImcP->bSeq[2] = TEXT('0');
  24. lpImcP->bSeq[3] = TEXT('0');
  25. }
  26. return (AsciiToGB(lpImcP));
  27. } else {
  28. return (0);
  29. }
  30. }
  31. #endif //COMBO_IME
  32. /**********************************************************************/
  33. /* XGBEngine() */
  34. /* Description: */
  35. /* Conv GBcode */
  36. /**********************************************************************/
  37. WORD PASCAL XGBEngine(LPPRIVCONTEXT lpImcP)
  38. {
  39. WORD wCode;
  40. if (lpImcP->bSeq[3] ||(lpImcP->bSeq[2] == TEXT('?'))) {
  41. if (lpImcP->bSeq[2] == TEXT('?')){ //add 626
  42. lpImcP->bSeq[2] = TEXT('4');
  43. lpImcP->bSeq[3] = TEXT('0');
  44. }
  45. wCode = AsciiToGB(lpImcP);
  46. return wCode;
  47. } else {
  48. return ((WORD)NULL);
  49. }
  50. }
  51. /**********************************************************************/
  52. /* XGBSpcEng() */
  53. /* Description: */
  54. /* Conv GBcode for Space */
  55. /**********************************************************************/
  56. WORD PASCAL XGBSpcEng(LPPRIVCONTEXT lpImcP)
  57. {
  58. WORD wCode;
  59. lpImcP->bSeq[2] = TEXT('4');
  60. lpImcP->bSeq[3] = TEXT('0');
  61. wCode = AsciiToGB(lpImcP);
  62. return wCode;
  63. }
  64. /**********************************************************************/
  65. /* GBEngine() */
  66. /* Description: */
  67. /* Conv GBcode */
  68. /**********************************************************************/
  69. WORD PASCAL GBEngine(LPPRIVCONTEXT lpImcP)
  70. {
  71. WORD wCode;
  72. if (lpImcP->bSeq[3] ||(lpImcP->bSeq[2] == TEXT('?'))) {
  73. if (lpImcP->bSeq[0] >=TEXT('0') && lpImcP->bSeq[0] <=TEXT('9')) { //Area mode
  74. if (lpImcP->bSeq[2] == TEXT('?')){
  75. lpImcP->bSeq[2] = TEXT('0');
  76. lpImcP->bSeq[3] = TEXT('1');
  77. }
  78. return (AsciiToArea(lpImcP));
  79. }
  80. else if (lpImcP->bSeq[0] >=TEXT('a') && lpImcP->bSeq[0] <=TEXT('f')) { //GB mode
  81. if (lpImcP->bSeq[2] == TEXT('?')){
  82. lpImcP->bSeq[2] = TEXT('a');
  83. lpImcP->bSeq[3] = TEXT('1');
  84. }
  85. wCode = AsciiToGB(lpImcP);
  86. return wCode;
  87. } else {
  88. return ((WORD)NULL);
  89. }
  90. } else
  91. return ((WORD)NULL);
  92. }
  93. /**********************************************************************/
  94. /* GBSpcEng() */
  95. /* Description: */
  96. /* Conv GBcode for Space */
  97. /**********************************************************************/
  98. WORD PASCAL GBSpcEng(LPPRIVCONTEXT lpImcP)
  99. {
  100. if (lpImcP->bSeq[0] >=TEXT('0') && lpImcP->bSeq[0] <=TEXT('9')) { //Area mode
  101. lpImcP->bSeq[2] = TEXT('0');
  102. lpImcP->bSeq[3] = TEXT('1');
  103. return (AsciiToArea(lpImcP));
  104. } else if (lpImcP->bSeq[0] >=TEXT('a') && lpImcP->bSeq[0] <=TEXT('f')) { //GB mode
  105. lpImcP->bSeq[2] = TEXT('a');
  106. lpImcP->bSeq[3] = TEXT('1');
  107. return (AsciiToGB(lpImcP));
  108. } else {
  109. return ((WORD)NULL);
  110. }
  111. }
  112. /**********************************************************************/
  113. /* AsciiToGB */
  114. /* Description: */
  115. /**********************************************************************/
  116. WORD PASCAL AsciiToGB(LPPRIVCONTEXT lpImcP)
  117. {
  118. WORD GBCode;
  119. GBCode = (CharToHex(lpImcP->bSeq[2]) << 4) + CharToHex(lpImcP->bSeq[3]);
  120. GBCode = GBCode * 256;
  121. GBCode = (CharToHex(lpImcP->bSeq[0]) << 4) + CharToHex(lpImcP->bSeq[1]) + GBCode;
  122. return (GBCode);
  123. }
  124. /**********************************************************************/
  125. /* AsciiToArea */
  126. /* Description: */
  127. /**********************************************************************/
  128. WORD PASCAL AsciiToArea(LPPRIVCONTEXT lpImcP)
  129. {
  130. WORD AreaCode;
  131. AreaCode = (CharToHex(lpImcP->bSeq[2]) * 10) + CharToHex(lpImcP->bSeq[3]) + 0xa0;
  132. AreaCode = AreaCode * 256;
  133. AreaCode = (CharToHex(lpImcP->bSeq[0]) * 10) + CharToHex(lpImcP->bSeq[1]) + AreaCode + 0xa0;
  134. return (AreaCode);
  135. }
  136. WORD PASCAL CharToHex(
  137. TCHAR cChar)
  138. {
  139. if (cChar >= TEXT('0') && cChar <= TEXT('9'))
  140. return((WORD)(cChar - TEXT('0')));
  141. else if (cChar >= TEXT('a') && cChar <= TEXT('f'))
  142. return((WORD)(cChar-TEXT('a')+ 0x0a));
  143. else
  144. return ((WORD)NULL);
  145. }
  146. /**********************************************************************/
  147. /* Engine() */
  148. /* Description: */
  149. /* search MB and fill lpCompStr and lpCandList */
  150. /**********************************************************************/
  151. int PASCAL Engine(
  152. LPCOMPOSITIONSTRING lpCompStr,
  153. LPCANDIDATELIST lpCandList,
  154. LPPRIVCONTEXT lpImcP,
  155. LPINPUTCONTEXT lpIMC,
  156. WORD wCharCode)
  157. {
  158. if(lpCompStr->dwCursorPos < 4
  159. && (lpImcP->bSeq[2] != TEXT('?'))
  160. && (wCharCode != TEXT(' '))) {
  161. return (ENGINE_COMP);
  162. } else if((lpCompStr->dwCursorPos==4)
  163. ||(lpImcP->bSeq[2] == TEXT('?'))
  164. ||((wCharCode == TEXT(' ')) && (lpCompStr->dwCursorPos == 2))) {
  165. if (!lpCompStr) {
  166. MessageBeep((UINT)-1);
  167. return -1;
  168. }
  169. if (!lpImcP) {
  170. MessageBeep((UINT)-1);
  171. return -1;
  172. }
  173. #if defined(COMBO_IME)
  174. if(sImeL.dwRegImeIndex == INDEX_GB)
  175. {
  176. // GB
  177. DWORD i;
  178. WORD wCode;
  179. TCHAR ResaultStr[3];
  180. if((lpImcP->bSeq[2] == TEXT('?'))) {
  181. wCode = GBEngine(lpImcP);
  182. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  183. for (i = 0; i < IME_MAXCAND; i++, wCode++) {
  184. AddCodeIntoCand(lpCandList, wCode);
  185. }
  186. return (ENGINE_COMP);
  187. } else if(wCharCode == TEXT(' ')) {
  188. wCode = GBSpcEng(lpImcP);
  189. lpImcP->bSeq[2] = 0;
  190. lpImcP->bSeq[3] = 0;
  191. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  192. for (i = 0; i < IME_MAXCAND; i++, wCode++) {
  193. AddCodeIntoCand(lpCandList, wCode);
  194. }
  195. return (ENGINE_COMP);
  196. } else {
  197. InitCompStr(lpCompStr);
  198. // the result string = the selected candidate;
  199. wCode = GBEngine(lpImcP);
  200. #ifdef UNICODE
  201. MultiByteToWideChar(NATIVE_ANSI_CP, 0, (LPCSTR)&wCode, 2, ResaultStr, sizeof(ResaultStr)/sizeof(TCHAR));
  202. ResaultStr[1] = TEXT('\0');
  203. #else
  204. ResaultStr[0] = LOBYTE(wCode);
  205. ResaultStr[1] = HIBYTE(wCode);
  206. ResaultStr[2] = 0x00;
  207. #endif
  208. lstrcpy((LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwResultStrOffset),ResaultStr);
  209. // calculate result string length
  210. lpCompStr->dwResultStrLen = lstrlen(ResaultStr);
  211. return (ENGINE_RESAULT);
  212. }
  213. }else if(sImeL.dwRegImeIndex == INDEX_GBK)
  214. {
  215. // XGB
  216. DWORD i;
  217. WORD wCode;
  218. TCHAR ResaultStr[3];
  219. if((lpImcP->bSeq[2] == TEXT('?'))) {
  220. wCode = XGBEngine(lpImcP);
  221. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  222. for (i = 0; i < (0x7e-0x40+1); i++, wCode++) {
  223. XGBAddCodeIntoCand(lpCandList, wCode);
  224. }
  225. wCode ++;
  226. for (i = 0; i < (0xfe-0x80+1); i++, wCode++) {
  227. XGBAddCodeIntoCand(lpCandList, wCode);
  228. }
  229. return (ENGINE_COMP);
  230. } else if(wCharCode == TEXT(' ')) {
  231. wCode = XGBSpcEng(lpImcP);
  232. lpImcP->bSeq[2] = 0;
  233. lpImcP->bSeq[3] = 0;
  234. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  235. for (i = 0; i < (0x7e-0x40+1); i++, wCode++) {
  236. XGBAddCodeIntoCand(lpCandList, wCode);
  237. }
  238. wCode ++;
  239. for (i = 0; i < (0xfe-0x80+1); i++, wCode++) {
  240. XGBAddCodeIntoCand(lpCandList, wCode);
  241. }
  242. return (ENGINE_COMP);
  243. } else {
  244. InitCompStr(lpCompStr);
  245. // the result string = the selected candidate;
  246. wCode = XGBEngine(lpImcP);
  247. #ifdef UNICODE
  248. MultiByteToWideChar(NATIVE_ANSI_CP, 0, (LPCSTR)&wCode, 2, ResaultStr, sizeof(ResaultStr)/sizeof(TCHAR));
  249. ResaultStr[1] = TEXT('\0');
  250. #else
  251. ResaultStr[0] = LOBYTE(wCode);
  252. ResaultStr[1] = HIBYTE(wCode);
  253. ResaultStr[2] = 0x00;
  254. #endif
  255. lstrcpy((LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwResultStrOffset),ResaultStr);
  256. // calculate result string length
  257. lpCompStr->dwResultStrLen = lstrlen(ResaultStr);
  258. return (ENGINE_RESAULT);
  259. }
  260. }else if(sImeL.dwRegImeIndex == INDEX_UNICODE)
  261. {
  262. // UNICODE
  263. DWORD i;
  264. WORD wCode, xCode;
  265. TCHAR ResaultStr[3];
  266. memset(ResaultStr, 0, sizeof(ResaultStr));
  267. if((lpImcP->bSeq[2] == TEXT('?') || wCharCode == TEXT(' '))) {
  268. lpImcP->bSeq[2] = TEXT('0');
  269. lpImcP->bSeq[3] = TEXT('0');
  270. lpImcP->bSeq[4] = TEXT('\0');
  271. wCode = UnicodeEngine(lpImcP);
  272. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  273. lpCandList->dwCount = 0;
  274. for (i = 0; i < IME_UNICODE_MAXCAND; i++, wCode++) {
  275. #ifdef UNICODE
  276. // add this string into candidate list
  277. *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  278. lpCandList->dwCount]) = wCode;
  279. #else
  280. WideCharToMultiByte(NATIVE_ANSI_CP, NULL, &wCode, 1, &xCode, 2, NULL, NULL);
  281. // add this string into candidate list
  282. *(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[
  283. lpCandList->dwCount]) = xCode;
  284. #endif
  285. // null terminator
  286. *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  287. lpCandList->dwCount] + sizeof(WORD)) = TEXT('\0');
  288. lpCandList->dwOffset[lpCandList->dwCount + 1] =
  289. lpCandList->dwOffset[lpCandList->dwCount] +
  290. sizeof(WORD) + sizeof(TCHAR);
  291. lpCandList->dwCount++;
  292. }
  293. return (ENGINE_COMP);
  294. } else {
  295. InitCompStr(lpCompStr);
  296. // the result string = the selected candidate;
  297. wCode = UnicodeEngine(lpImcP);
  298. {
  299. WCHAR UniStr[2];
  300. UniStr[0] = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  301. UniStr[1] = 0;
  302. lstrcpy((LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwResultStrOffset),UniStr);
  303. // calculate result string length
  304. lpCompStr->dwResultStrLen = lstrlen(UniStr);
  305. }
  306. return (ENGINE_RESAULT);
  307. }
  308. }
  309. #else //COMBO_IME
  310. #ifdef GB
  311. {
  312. // GB
  313. DWORD i;
  314. WORD wCode;
  315. TCHAR ResaultStr[3];
  316. if((lpImcP->bSeq[2] == TEXT('?'))) {
  317. wCode = GBEngine(lpImcP);
  318. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  319. for (i = 0; i < IME_MAXCAND; i++, wCode++) {
  320. AddCodeIntoCand(lpCandList, wCode);
  321. }
  322. return (ENGINE_COMP);
  323. } else if(wCharCode == TEXT(' ')) {
  324. wCode = GBSpcEng(lpImcP);
  325. lpImcP->bSeq[2] = 0;
  326. lpImcP->bSeq[3] = 0;
  327. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  328. for (i = 0; i < IME_MAXCAND; i++, wCode++) {
  329. AddCodeIntoCand(lpCandList, wCode);
  330. }
  331. return (ENGINE_COMP);
  332. } else {
  333. InitCompStr(lpCompStr);
  334. // the result string = the selected candidate;
  335. wCode = GBEngine(lpImcP);
  336. #ifdef UNICODE
  337. // change CP_ACP to 936, so that it can work under Multilingul Env.
  338. MultiByteToWideChar(NATIVE_ANSI_CP, NULL, &wCode, 2, ResaultStr, sizeof(ResaultStr)/sizeof(TCHAR));
  339. ResaultStr[1] = TEXT('\0');
  340. #else
  341. ResaultStr[0] = LOBYTE(wCode);
  342. ResaultStr[1] = HIBYTE(wCode);
  343. ResaultStr[2] = 0x00;
  344. #endif
  345. lstrcpy((LPTSTR)lpCompStr + lpCompStr->dwResultStrOffset,ResaultStr);
  346. // calculate result string length
  347. lpCompStr->dwResultStrLen = lstrlen(ResaultStr);
  348. return (ENGINE_RESAULT);
  349. }
  350. }
  351. #else
  352. {
  353. // XGB
  354. DWORD i;
  355. WORD wCode;
  356. TCHAR ResaultStr[3];
  357. if((lpImcP->bSeq[2] == TEXT('?'))) {
  358. wCode = XGBEngine(lpImcP);
  359. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  360. for (i = 0; i < (0x7e-0x40+1); i++, wCode++) {
  361. XGBAddCodeIntoCand(lpCandList, wCode);
  362. }
  363. wCode ++;
  364. for (i = 0; i < (0xfe-0x80+1); i++, wCode++) {
  365. XGBAddCodeIntoCand(lpCandList, wCode);
  366. }
  367. return (ENGINE_COMP);
  368. } else if(wCharCode == TEXT(' ')) {
  369. wCode = XGBSpcEng(lpImcP);
  370. lpImcP->bSeq[2] = 0;
  371. lpImcP->bSeq[3] = 0;
  372. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  373. for (i = 0; i < (0x7e-0x40+1); i++, wCode++) {
  374. XGBAddCodeIntoCand(lpCandList, wCode);
  375. }
  376. wCode ++;
  377. for (i = 0; i < (0xfe-0x80+1); i++, wCode++) {
  378. XGBAddCodeIntoCand(lpCandList, wCode);
  379. }
  380. return (ENGINE_COMP);
  381. } else {
  382. InitCompStr(lpCompStr);
  383. // the result string = the selected candidate;
  384. wCode = XGBEngine(lpImcP);
  385. #ifdef UNICODE
  386. // change CP_ACP to 936, so that it can work under Multilingul Env.
  387. MultiByteToWideChar(NATIVE_ANSI_CP, NULL, &wCode, 2, ResaultStr, sizeof(ResaultStr)/sizeof(TCHAR));
  388. ResaultStr[1] = TEXT('\0');
  389. #else
  390. ResaultStr[0] = LOBYTE(wCode);
  391. ResaultStr[1] = HIBYTE(wCode);
  392. ResaultStr[2] = 0x00;
  393. #endif
  394. lstrcpy((LPTSTR)lpCompStr + lpCompStr->dwResultStrOffset,ResaultStr);
  395. // calculate result string length
  396. lpCompStr->dwResultStrLen = lstrlen(ResaultStr);
  397. return (ENGINE_RESAULT);
  398. }
  399. }
  400. #endif //GB
  401. #endif //COMBO_IME
  402. }
  403. MessageBeep((UINT)-1);
  404. return (ENGINE_COMP);
  405. }
  406. /**********************************************************************/
  407. /* AddCodeIntoCand() */
  408. /**********************************************************************/
  409. void PASCAL AddCodeIntoCand(
  410. LPCANDIDATELIST lpCandList,
  411. WORD wCode)
  412. {
  413. WORD wInCode;
  414. if (lpCandList->dwCount >= IME_MAXCAND) {
  415. return;
  416. }
  417. wInCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  418. #ifdef UNICODE
  419. {
  420. TCHAR wUnicode;
  421. // change CP_ACP to 936, so that it can work under Multilingul Env.
  422. MultiByteToWideChar(NATIVE_ANSI_CP, 0, (LPCSTR) &wInCode, 2, &wUnicode, 1);
  423. *(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[
  424. lpCandList->dwCount]) = wUnicode;
  425. }
  426. #else
  427. // add GB string into candidate list
  428. *(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[
  429. lpCandList->dwCount]) = wInCode;
  430. #endif
  431. // null terminator
  432. *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  433. lpCandList->dwCount] + sizeof(WORD)) = TEXT('\0');
  434. lpCandList->dwOffset[lpCandList->dwCount + 1] =
  435. lpCandList->dwOffset[lpCandList->dwCount] +
  436. sizeof(WORD) + sizeof(TCHAR);
  437. lpCandList->dwCount++;
  438. return;
  439. }
  440. #if defined(COMBO_IME)
  441. /**********************************************************************/
  442. /* UnicodeAddCodeIntoCand() */
  443. /**********************************************************************/
  444. void PASCAL UnicodeAddCodeIntoCand(
  445. LPCANDIDATELIST lpCandList,
  446. WORD wCode)
  447. {
  448. if (lpCandList->dwCount >= IME_UNICODE_MAXCAND) {
  449. return;
  450. }
  451. // add this string into candidate list
  452. *(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[
  453. lpCandList->dwCount]) = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  454. // null terminator
  455. *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  456. lpCandList->dwCount] + sizeof(WORD)) = TEXT('\0');
  457. lpCandList->dwOffset[lpCandList->dwCount + 1] =
  458. lpCandList->dwOffset[lpCandList->dwCount] +
  459. sizeof(WORD) + sizeof(TCHAR);
  460. lpCandList->dwCount++;
  461. return;
  462. }
  463. #endif //COMBO_IME
  464. /**********************************************************************/
  465. /* XGBAddCodeIntoCand() */
  466. /**********************************************************************/
  467. void PASCAL XGBAddCodeIntoCand(
  468. LPCANDIDATELIST lpCandList,
  469. WORD wCode)
  470. {
  471. WORD wInCode;
  472. if (lpCandList->dwCount >= IME_XGB_MAXCAND) {
  473. return;
  474. }
  475. wInCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  476. #ifdef UNICODE
  477. {
  478. TCHAR wUnicode;
  479. // change CP_ACP to 936, so that it can work under Multilingul Env.
  480. MultiByteToWideChar(NATIVE_ANSI_CP, 0, (LPCSTR) &wInCode, 2, &wUnicode, 1);
  481. *(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[
  482. lpCandList->dwCount]) = wUnicode;
  483. }
  484. #else
  485. // add GB string into candidate list
  486. *(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[
  487. lpCandList->dwCount]) = wInCode;
  488. #endif
  489. *(LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[
  490. lpCandList->dwCount] + sizeof(WORD)) = TEXT('\0');
  491. lpCandList->dwOffset[lpCandList->dwCount + 1] =
  492. lpCandList->dwOffset[lpCandList->dwCount] +
  493. sizeof(WORD) + sizeof(TCHAR);
  494. lpCandList->dwCount++;
  495. return;
  496. }
  497. /**********************************************************************/
  498. /* CompEscapeKey() */
  499. /**********************************************************************/
  500. void PASCAL CompEscapeKey(
  501. LPINPUTCONTEXT lpIMC,
  502. LPCOMPOSITIONSTRING lpCompStr,
  503. LPGUIDELINE lpGuideLine,
  504. LPPRIVCONTEXT lpImcP)
  505. {
  506. if (!lpGuideLine) {
  507. MessageBeep((UINT)-1);
  508. } else if (lpGuideLine->dwLevel != GL_LEVEL_NOGUIDELINE) {
  509. lpGuideLine->dwLevel = GL_LEVEL_NOGUIDELINE;
  510. lpGuideLine->dwIndex = GL_ID_UNKNOWN;
  511. lpGuideLine->dwStrLen = 0;
  512. lpImcP->fdwImeMsg |= MSG_GUIDELINE;
  513. }
  514. if (lpImcP->iImeState != CST_CHOOSE) {
  515. if (lpImcP->fdwImeMsg & MSG_ALREADY_START) {
  516. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_END_COMPOSITION) &
  517. ~(MSG_START_COMPOSITION);
  518. }
  519. }
  520. lpImcP->iImeState = CST_INIT;
  521. *(LPDWORD)lpImcP->bSeq = 0;
  522. if (lpCompStr) {
  523. InitCompStr(lpCompStr);
  524. lpImcP->fdwImeMsg |= MSG_COMPOSITION;
  525. lpImcP->dwCompChar = VK_ESCAPE;
  526. lpImcP->fdwGcsFlag |= (GCS_COMPREAD|GCS_COMP|GCS_CURSORPOS|
  527. GCS_DELTASTART);
  528. }
  529. return;
  530. }
  531. /**********************************************************************/
  532. /* CompBackSpaceKey() */
  533. /**********************************************************************/
  534. void PASCAL CompBackSpaceKey(
  535. LPINPUTCONTEXT lpIMC,
  536. LPCOMPOSITIONSTRING lpCompStr,
  537. LPPRIVCONTEXT lpImcP)
  538. {
  539. if (lpCompStr->dwCursorPos < sizeof(BYTE)) {
  540. lpCompStr->dwCursorPos = sizeof(BYTE);
  541. }
  542. lpImcP->bSeq[3] = 0;
  543. // go back a compsoition char
  544. lpCompStr->dwCursorPos -= sizeof(BYTE);
  545. // clean the sequence code
  546. lpImcP->bSeq[lpCompStr->dwCursorPos] = 0;
  547. lpImcP->fdwImeMsg |= MSG_COMPOSITION;
  548. lpImcP->dwCompChar = TEXT('\b');
  549. lpImcP->fdwGcsFlag |= (GCS_COMPREAD|GCS_COMP|GCS_CURSORPOS|
  550. GCS_DELTASTART);
  551. if (!lpCompStr->dwCursorPos) {
  552. if (lpImcP->fdwImeMsg & (MSG_ALREADY_OPEN)) {
  553. ClearCand(lpIMC);
  554. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_CLOSE_CANDIDATE) &
  555. ~(MSG_OPEN_CANDIDATE);
  556. }
  557. if(lpImcP->iImeState != CST_INIT) {
  558. lpImcP->iImeState = CST_INIT;
  559. lpCompStr->dwCompReadStrLen = lpCompStr->dwCompStrLen =
  560. lpCompStr->dwDeltaStart = lpCompStr->dwCursorPos;
  561. Finalize(lpIMC, lpCompStr, lpImcP, TEXT('\b'));
  562. return;
  563. }
  564. if (lpImcP->fdwImeMsg & MSG_ALREADY_START) {
  565. InitCompStr(lpCompStr);
  566. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_END_COMPOSITION) &
  567. ~(MSG_START_COMPOSITION);
  568. return;
  569. }
  570. }
  571. // reading string is composition string for some simple IMEs
  572. // delta start is the same as cursor position for backspace
  573. lpCompStr->dwCompReadStrLen = lpCompStr->dwCompStrLen =
  574. lpCompStr->dwDeltaStart = lpCompStr->dwCursorPos;
  575. Finalize(lpIMC, lpCompStr, lpImcP, TEXT('\b'));
  576. return;
  577. }
  578. /**********************************************************************/
  579. /* CompStrInfo() */
  580. /**********************************************************************/
  581. void PASCAL CompStrInfo(
  582. LPCOMPOSITIONSTRING lpCompStr,
  583. LPPRIVCONTEXT lpImcP,
  584. LPGUIDELINE lpGuideLine,
  585. WORD wCharCode)
  586. {
  587. register DWORD dwCursorPos;
  588. //
  589. dwCursorPos = lpCompStr->dwCursorPos;
  590. // dwCrusorPos limit
  591. if (dwCursorPos >= lpImeL->nMaxKey) {
  592. // exceed the max input key limitation
  593. lpGuideLine->dwLevel = GL_LEVEL_ERROR;
  594. lpGuideLine->dwIndex = GL_ID_TOOMANYSTROKE;
  595. lpImcP->fdwImeMsg |= MSG_GUIDELINE;
  596. return;
  597. }
  598. // set MSG_START_COMPOSITION
  599. if (!(lpImcP->fdwImeMsg & MSG_ALREADY_START)) {
  600. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_START_COMPOSITION) &
  601. ~(MSG_END_COMPOSITION);
  602. }
  603. if (lpImcP->iImeState == CST_INIT) {
  604. // clean the 4 bytes in one time
  605. *(LPDWORD)lpImcP->bSeq = 0;
  606. }
  607. lpImcP->bSeq[dwCursorPos] = (BYTE)wCharCode;
  608. // composition/reading string - UsedCode(Full Shape)
  609. lpImcP->dwCompChar = (DWORD)wCharCode;
  610. // set reading string for lpCompStr
  611. *((LPUNAWORD)((LPBYTE)lpCompStr + lpCompStr->dwCompReadStrOffset +
  612. dwCursorPos*sizeof(TCHAR))) = (BYTE)lpImcP->dwCompChar;
  613. *((LPUNAWORD)((LPBYTE)lpCompStr + lpCompStr->dwCompReadAttrOffset +
  614. dwCursorPos*sizeof(TCHAR))) = ((ATTR_TARGET_CONVERTED << 8)|ATTR_TARGET_CONVERTED);
  615. // set reading string lenght for lpCompStr
  616. if (lpCompStr->dwCompReadStrLen <= dwCursorPos) {
  617. lpCompStr->dwCompReadStrLen += sizeof(BYTE);
  618. }
  619. // composition string is reading string for some simple IMEs
  620. lpCompStr->dwCompStrLen = lpCompStr->dwCompReadStrLen;
  621. // composition/reading attribute length is equal to reading string length
  622. lpCompStr->dwCompReadAttrLen = lpCompStr->dwCompReadStrLen;
  623. lpCompStr->dwCompAttrLen = lpCompStr->dwCompStrLen;
  624. // delta start from previous cursor position
  625. lpCompStr->dwDeltaStart = lpCompStr->dwCursorPos;
  626. // set new cursor with next to the composition string
  627. lpCompStr->dwCursorPos = lpCompStr->dwCompStrLen;
  628. // set lpImcp->iImeState
  629. lpImcP->iImeState = CST_INPUT;
  630. // tell app, there is a composition char generated
  631. lpImcP->fdwImeMsg |= MSG_COMPOSITION;
  632. // set lpImeP->fdwGcsFlag
  633. lpImcP->fdwGcsFlag |= GCS_COMPREAD|GCS_COMP|GCS_CURSORPOS|GCS_DELTASTART;
  634. return;
  635. }
  636. /**********************************************************************/
  637. /* Finalize() */
  638. /* Return vlaue */
  639. /* Engine Flag */
  640. /* Description: */
  641. /* Call Engine finalize Chinese word(s) by searching table */
  642. /* (Set lpCompStr and lpCandList) */
  643. /* Set lpImeP(iImeState, fdwImeMsg, fdwGcsFlag) */
  644. /**********************************************************************/
  645. UINT PASCAL Finalize(
  646. LPINPUTCONTEXT lpIMC,
  647. LPCOMPOSITIONSTRING lpCompStr,
  648. LPPRIVCONTEXT lpImcP,
  649. WORD wCharCode)
  650. {
  651. LPCANDIDATEINFO lpCandInfo;
  652. LPCANDIDATELIST lpCandList;
  653. UINT fEngine;
  654. if (!lpIMC->hCandInfo) {
  655. return (0);
  656. }
  657. // get lpCandInfo
  658. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  659. if (!lpCandInfo) {
  660. return (0);
  661. }
  662. // get lpCandList and init dwCount & dwSelection
  663. lpCandList = (LPCANDIDATELIST)
  664. ((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[0]);
  665. lpCandList->dwCount = 0;
  666. lpCandList->dwSelection = 0;
  667. // search the IME tables
  668. fEngine =Engine(lpCompStr, lpCandList, lpImcP, lpIMC, wCharCode);
  669. if (fEngine == ENGINE_COMP) {
  670. lpCandInfo->dwCount = 1;
  671. if (((lpCompStr->dwCursorPos < 3) && (wCharCode != TEXT(' ')))
  672. || ((lpCompStr->dwCursorPos == 3)
  673. && (wCharCode != TEXT(' ')) && (wCharCode != TEXT('?')))) {
  674. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_CLOSE_CANDIDATE) &
  675. ~(MSG_OPEN_CANDIDATE);
  676. ImmUnlockIMCC(lpIMC->hCandInfo);
  677. return (fEngine);
  678. }
  679. if(lpCandList->dwCount != 0x0000) {
  680. // open composition candidate UI window for the string(s)
  681. if ((lpImcP->fdwImeMsg & (MSG_ALREADY_OPEN|MSG_CLOSE_CANDIDATE)) ==
  682. (MSG_ALREADY_OPEN|MSG_CLOSE_CANDIDATE)) {
  683. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_CHANGE_CANDIDATE) &
  684. ~(MSG_CLOSE_CANDIDATE);
  685. } else if (lpImcP->fdwImeMsg & MSG_ALREADY_OPEN) {
  686. lpImcP->fdwImeMsg |= MSG_CHANGE_CANDIDATE;
  687. } else {
  688. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_OPEN_CANDIDATE) &
  689. ~(MSG_CLOSE_CANDIDATE);
  690. }
  691. }
  692. if (lpImcP->fdwImeMsg & MSG_ALREADY_START) {
  693. lpImcP->fdwImeMsg |= MSG_COMPOSITION;
  694. }
  695. } else if (fEngine == ENGINE_ASCII) {
  696. } else if (fEngine == ENGINE_RESAULT) {
  697. // Set lpImep! and tell application, there is a reslut string
  698. lpImcP->fdwImeMsg |= MSG_COMPOSITION;
  699. lpImcP->dwCompChar = (DWORD)0;
  700. lpImcP->fdwGcsFlag |= GCS_COMPREAD|GCS_COMP|GCS_CURSORPOS|
  701. GCS_DELTASTART|GCS_RESULTREAD|GCS_RESULT;
  702. if (lpImcP->fdwImeMsg & MSG_ALREADY_OPEN) {
  703. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_CLOSE_CANDIDATE) &
  704. ~(MSG_OPEN_CANDIDATE);
  705. }
  706. // clear candidate now
  707. lpCandList->dwCount = 0;
  708. // set iImeState with CST_INIT
  709. lpImcP->iImeState = CST_INIT;
  710. *(LPDWORD)lpImcP->bSeq = 0;
  711. #ifdef CROSSREF
  712. CrossReverseConv(lpIMC, lpCompStr, lpImcP, lpCandList);
  713. #endif
  714. }
  715. ImmUnlockIMCC(lpIMC->hCandInfo);
  716. return fEngine;
  717. }
  718. /**********************************************************************/
  719. /* CompWord() */
  720. /**********************************************************************/
  721. void PASCAL CompWord( // compose the Chinese word(s) according to
  722. // input key
  723. WORD wCharCode,
  724. LPINPUTCONTEXT lpIMC,
  725. LPCOMPOSITIONSTRING lpCompStr,
  726. LPPRIVCONTEXT lpImcP,
  727. LPGUIDELINE lpGuideLine)
  728. {
  729. // lpComStr=NULL?
  730. if (!lpCompStr) {
  731. MessageBeep((UINT)-1);
  732. return;
  733. }
  734. // escape key
  735. if (wCharCode == VK_ESCAPE) { // not good to use VK as char, but...
  736. CompEscapeKey(lpIMC, lpCompStr, lpGuideLine, lpImcP);
  737. return;
  738. }
  739. // GuideLine
  740. if (!lpGuideLine) {
  741. } else if (lpGuideLine->dwLevel == GL_LEVEL_NOGUIDELINE) {
  742. lpGuideLine->dwStrLen = 0;
  743. } else {
  744. // previous input error cause us trancate some chars
  745. if (lpGuideLine->dwLevel == GL_LEVEL_ERROR) {
  746. lpImcP->bSeq[lpCompStr->dwCursorPos / 2] = 0;
  747. lpCompStr->dwCompReadStrLen = lpCompStr->dwCompStrLen =
  748. lpCompStr->dwCursorPos;
  749. lpCompStr->dwCompReadAttrLen = lpCompStr->dwCompReadStrLen;
  750. lpCompStr->dwCompAttrLen = lpCompStr->dwCompStrLen;
  751. }
  752. lpGuideLine->dwLevel = GL_LEVEL_NOGUIDELINE;
  753. lpGuideLine->dwIndex = GL_ID_UNKNOWN;
  754. lpGuideLine->dwStrLen = 0;
  755. lpImcP->fdwImeMsg |= MSG_GUIDELINE;
  756. }
  757. // backspace key
  758. if (wCharCode == TEXT('\b')) {
  759. CompBackSpaceKey(lpIMC, lpCompStr, lpImcP);
  760. return;
  761. }
  762. if(wCharCode == TEXT(' ')) {
  763. } else {
  764. // build up composition string info
  765. CompStrInfo(lpCompStr, lpImcP, lpGuideLine, wCharCode);
  766. }
  767. Finalize(lpIMC, lpCompStr, lpImcP, wCharCode); // compsition
  768. return;
  769. }