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.

910 lines
26 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. notify.c
  5. ++*/
  6. #include <windows.h>
  7. #include <immdev.h>
  8. #include <imedefs.h>
  9. /**********************************************************************/
  10. /* GenerateMessage() */
  11. /**********************************************************************/
  12. void PASCAL GenerateMessage(
  13. HIMC hIMC,
  14. LPINPUTCONTEXT lpIMC,
  15. LPPRIVCONTEXT lpImcP)
  16. {
  17. if (!hIMC) {
  18. return;
  19. } else if (!lpIMC) {
  20. return;
  21. } else if (!lpImcP) {
  22. return;
  23. } else if (lpImcP->fdwImeMsg & MSG_IN_IMETOASCIIEX) {
  24. return;
  25. } else {
  26. }
  27. lpIMC->dwNumMsgBuf += TranslateImeMessage(NULL, lpIMC, lpImcP);
  28. lpImcP->fdwImeMsg &= (MSG_ALREADY_OPEN|MSG_ALREADY_START);
  29. lpImcP->fdwGcsFlag = 0;
  30. ImmGenerateMessage(hIMC);
  31. return;
  32. }
  33. /**********************************************************************/
  34. /* GenerateImeMessage() */
  35. /**********************************************************************/
  36. void PASCAL GenerateImeMessage(
  37. HIMC hIMC,
  38. LPINPUTCONTEXT lpIMC,
  39. DWORD fdwImeMsg)
  40. {
  41. LPPRIVCONTEXT lpImcP;
  42. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  43. if (!lpImcP) {
  44. return;
  45. }
  46. lpImcP->fdwImeMsg |= fdwImeMsg;
  47. if (fdwImeMsg & MSG_CLOSE_CANDIDATE) {
  48. lpImcP->fdwImeMsg &= ~(MSG_OPEN_CANDIDATE|MSG_CHANGE_CANDIDATE);
  49. } else if (fdwImeMsg & (MSG_OPEN_CANDIDATE|MSG_CHANGE_CANDIDATE)) {
  50. lpImcP->fdwImeMsg &= ~(MSG_CLOSE_CANDIDATE);
  51. }
  52. if (fdwImeMsg & MSG_END_COMPOSITION) {
  53. lpImcP->fdwImeMsg &= ~(MSG_START_COMPOSITION);
  54. } else if (fdwImeMsg & MSG_START_COMPOSITION) {
  55. lpImcP->fdwImeMsg &= ~(MSG_END_COMPOSITION);
  56. }
  57. GenerateMessage(hIMC, lpIMC, lpImcP);
  58. ImmUnlockIMCC(lpIMC->hPrivate);
  59. return;
  60. }
  61. /**********************************************************************/
  62. /* CompCancel() */
  63. /**********************************************************************/
  64. void PASCAL CompCancel(
  65. HIMC hIMC,
  66. LPINPUTCONTEXT lpIMC)
  67. {
  68. LPPRIVCONTEXT lpImcP;
  69. if (!lpIMC->hPrivate) {
  70. return;
  71. }
  72. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  73. if (!lpImcP) {
  74. return;
  75. }
  76. lpImcP->fdwGcsFlag = (DWORD)0;
  77. if (lpImcP->fdwImeMsg & MSG_ALREADY_OPEN) {
  78. CandEscapeKey(lpIMC, lpImcP);
  79. } else if (lpImcP->fdwImeMsg & MSG_ALREADY_START) {
  80. LPCOMPOSITIONSTRING lpCompStr;
  81. LPGUIDELINE lpGuideLine;
  82. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  83. if (!lpCompStr) {
  84. ImmUnlockIMCC(lpIMC->hCompStr);
  85. ImmUnlockIMCC(lpIMC->hPrivate);
  86. return;
  87. }
  88. lpGuideLine = (LPGUIDELINE)ImmLockIMCC(lpIMC->hGuideLine);
  89. if (!lpGuideLine) {
  90. ImmUnlockIMCC(lpIMC->hGuideLine);
  91. ImmUnlockIMCC(lpIMC->hPrivate);
  92. return;
  93. }
  94. CompEscapeKey(lpIMC, lpCompStr, lpGuideLine, lpImcP);
  95. if (lpGuideLine) {
  96. ImmUnlockIMCC(lpIMC->hGuideLine);
  97. }
  98. if (lpCompStr) {
  99. ImmUnlockIMCC(lpIMC->hCompStr);
  100. }
  101. } else {
  102. ImmUnlockIMCC(lpIMC->hPrivate);
  103. return;
  104. }
  105. GenerateMessage(hIMC, lpIMC, lpImcP);
  106. ImmUnlockIMCC(lpIMC->hPrivate);
  107. return;
  108. }
  109. /**********************************************************************/
  110. /* SetString() */
  111. /* Return Value: */
  112. /* TRUE - successful, FALSE - failure */
  113. /**********************************************************************/
  114. BOOL PASCAL SetString(
  115. HIMC hIMC,
  116. LPINPUTCONTEXT lpIMC,
  117. LPCOMPOSITIONSTRING lpCompStr,
  118. LPPRIVCONTEXT lpImcP,
  119. LPTSTR lpszRead,
  120. DWORD dwReadLen)
  121. {
  122. LPCANDIDATELIST lpCandList;
  123. LPCANDIDATEINFO lpCandInfo;
  124. LPGUIDELINE lpGuideLine;
  125. UINT iRet,ii;
  126. UINT MAX_COMP,i;
  127. WORD wCode;
  128. // For Windows NT Unicode,
  129. // dwCompReadStrLen is the number of the Unicode characters(Not in Bytes)
  130. // But the above the Parameter dwReadLen is in Bytes.
  131. // the length of the attribute information is
  132. // the same as the length in Unicode character counts.
  133. // Each attribute byte corresponds to each Unicode character of
  134. // the string.
  135. //
  136. // convert from byte count to the string length
  137. dwReadLen = dwReadLen / sizeof(TCHAR);
  138. lstrcpy (lpImcP->bSeq,lpszRead);
  139. if(lpImcP->bSeq[3] == TEXT('?')){
  140. MAX_COMP = 94;
  141. } else {
  142. MAX_COMP = 1;
  143. }
  144. if (dwReadLen > 4) {
  145. return (FALSE);
  146. }
  147. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  148. if (!lpCandInfo) {
  149. return (-1);
  150. }
  151. // get lpCandList and init dwCount & dwSelection
  152. lpCandList = (LPCANDIDATELIST)
  153. ((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[0]);
  154. InitCompStr(lpCompStr);
  155. ClearCand(lpIMC);
  156. lpGuideLine = (LPGUIDELINE)ImmLockIMCC(lpIMC->hGuideLine);
  157. if (lpGuideLine) {
  158. ImmUnlockIMCC(lpIMC->hGuideLine);
  159. }
  160. CopyMemory((LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompReadStrOffset), lpszRead,
  161. dwReadLen * sizeof(TCHAR) + sizeof(TCHAR) );
  162. CopyMemory((LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset),lpszRead,
  163. dwReadLen * sizeof(TCHAR) + sizeof(TCHAR) );
  164. lpCompStr->dwCompReadAttrLen = dwReadLen;
  165. lpCompStr->dwCompAttrLen = lpCompStr->dwCompReadAttrLen;
  166. for (i = 0; i < dwReadLen; i++) { // The IME has converted these chars
  167. *((LPBYTE)lpCompStr + lpCompStr->dwCompReadAttrOffset + i) =
  168. ATTR_TARGET_CONVERTED;
  169. }
  170. lpCompStr->dwCompReadStrLen = dwReadLen;
  171. lpCompStr->dwCompStrLen = lpCompStr->dwCompReadStrLen;
  172. // dlta start from 0;
  173. lpCompStr->dwDeltaStart = 0;
  174. // cursor is next to composition string
  175. lpCompStr->dwCursorPos = lpCompStr->dwCompStrLen;
  176. lpCompStr->dwResultReadClauseLen = 0;
  177. lpCompStr->dwResultReadStrLen = 0;
  178. lpCompStr->dwResultClauseLen = 0;
  179. lpCompStr->dwResultStrLen = 0;
  180. // set private input context
  181. lpImcP->iImeState = CST_INPUT;
  182. if (lpImcP->fdwImeMsg & MSG_ALREADY_OPEN) {
  183. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_CLOSE_CANDIDATE) &
  184. ~(MSG_OPEN_CANDIDATE);
  185. }
  186. if (!(lpImcP->fdwImeMsg & MSG_ALREADY_START)) {
  187. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_START_COMPOSITION) &
  188. ~(MSG_END_COMPOSITION);
  189. }
  190. lpImcP->fdwImeMsg |= MSG_COMPOSITION;
  191. lpImcP->fdwGcsFlag = GCS_COMPREAD|GCS_COMP|
  192. GCS_DELTASTART|GCS_CURSORPOS;
  193. lpImcP->fdwImeMsg |= MSG_GUIDELINE;
  194. lpCandList->dwCount = 0;
  195. if (dwReadLen < 4) {
  196. goto Finalize;
  197. }
  198. lpImcP->bSeq[0] = 0;
  199. lpImcP->bSeq[1] = 0;
  200. lpImcP->bSeq[2] = 0;
  201. lpImcP->bSeq[3] = 0;
  202. #if defined(COMBO_IME)
  203. if(sImeL.dwRegImeIndex == INDEX_GB){
  204. for (ii=0;ii<4;ii++) {
  205. iRet = GBProcessKey(*(LPBYTE)((LPBYTE)lpszRead+ii),lpImcP);
  206. if (iRet == CST_INPUT) {
  207. lpImcP->bSeq[ii] = *(LPBYTE)((LPBYTE)lpszRead+ii);
  208. } else {
  209. goto Finalize;
  210. }
  211. }
  212. wCode = GBEngine (lpImcP);
  213. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  214. for (i = 0; i < MAX_COMP;i++, wCode++) {
  215. AddCodeIntoCand(lpCandList, wCode);
  216. }
  217. }else if(sImeL.dwRegImeIndex == INDEX_GBK){
  218. for (ii=0;ii<4;ii++) {
  219. iRet = XGBProcessKey(*(LPBYTE)((LPBYTE)lpszRead+ii),lpImcP);
  220. if (iRet == CST_INPUT) {
  221. lpImcP->bSeq[ii] = *(LPBYTE)((LPBYTE)lpszRead+ii);
  222. } else {
  223. goto Finalize;
  224. }
  225. }
  226. wCode = XGBEngine(lpImcP);
  227. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  228. for (i = 0; i < (0x7e-0x40+1); i++, wCode++) {
  229. XGBAddCodeIntoCand(lpCandList, wCode);
  230. }
  231. wCode ++;
  232. for (i = 0; i < (0xfe-0x80+1); i++, wCode++) {
  233. XGBAddCodeIntoCand(lpCandList, wCode);
  234. }
  235. }else if(sImeL.dwRegImeIndex == INDEX_UNICODE){
  236. for (ii=0;ii<4;ii++) {
  237. iRet = UnicodeProcessKey(*(LPBYTE)((LPBYTE)lpszRead+ii),lpImcP);
  238. if (iRet == CST_INPUT) {
  239. lpImcP->bSeq[ii] = *(LPBYTE)((LPBYTE)lpszRead+ii);
  240. } else {
  241. goto Finalize;
  242. }
  243. }
  244. wCode = UnicodeEngine(lpImcP);
  245. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  246. for (i = 0; i < (0x100); i++, wCode++) {
  247. UnicodeAddCodeIntoCand(lpCandList, wCode);
  248. }
  249. }
  250. #else //COMBO_IME
  251. #ifdef GB
  252. {
  253. for (ii=0;ii<4;ii++) {
  254. iRet = GBProcessKey(*(LPBYTE)((LPBYTE)lpszRead+ii),lpImcP);
  255. if (iRet == CST_INPUT) {
  256. lpImcP->bSeq[ii] = *(LPBYTE)((LPBYTE)lpszRead+ii);
  257. } else {
  258. goto Finalize;
  259. }
  260. }
  261. wCode = GBEngine (lpImcP);
  262. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  263. for (i = 0; i < MAX_COMP;i++, wCode++) {
  264. AddCodeIntoCand(lpCandList, wCode);
  265. }
  266. }
  267. #else
  268. {
  269. for (ii=0;ii<4;ii++) {
  270. iRet = XGBProcessKey(*(LPBYTE)((LPBYTE)lpszRead+ii),lpImcP);
  271. if (iRet == CST_INPUT) {
  272. lpImcP->bSeq[ii] = *(LPBYTE)((LPBYTE)lpszRead+ii);
  273. } else {
  274. goto Finalize;
  275. }
  276. }
  277. wCode = XGBEngine(lpImcP);
  278. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  279. for (i = 0; i < (0x7e-0x40+1); i++, wCode++) {
  280. XGBAddCodeIntoCand(lpCandList, wCode);
  281. }
  282. wCode ++;
  283. for (i = 0; i < (0xfe-0x80+1); i++, wCode++) {
  284. XGBAddCodeIntoCand(lpCandList, wCode);
  285. }
  286. }
  287. #endif //GB
  288. #endif //COMBO_IME
  289. if (lpCandList->dwCount == 1) {
  290. lstrcpy((LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwResultStrOffset),
  291. (LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[0]));
  292. // calculate result string length
  293. lpCompStr->dwResultStrLen =
  294. lstrlen((LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[0]));
  295. lpImcP->fdwImeMsg |= MSG_COMPOSITION;
  296. lpImcP->dwCompChar = (DWORD)0;
  297. lpImcP->fdwGcsFlag |= GCS_CURSORPOS|GCS_RESULTREAD|GCS_RESULT;
  298. if (lpImcP->fdwImeMsg & MSG_ALREADY_OPEN) {
  299. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_CLOSE_CANDIDATE) &
  300. ~(MSG_OPEN_CANDIDATE);
  301. } else {
  302. lpImcP->fdwImeMsg &= ~(MSG_CLOSE_CANDIDATE|MSG_OPEN_CANDIDATE);
  303. }
  304. lpImcP->iImeState = CST_INIT;
  305. *(LPDWORD)lpImcP->bSeq = 0;
  306. lpCandList->dwCount = 0;
  307. } else if(lpCandList->dwCount > 1) {
  308. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg |MSG_OPEN_CANDIDATE ) &
  309. ~(MSG_CLOSE_CANDIDATE);
  310. } else if(lpCandList->dwCount == 0) {
  311. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg |MSG_CLOSE_CANDIDATE ) &
  312. ~(MSG_OPEN_CANDIDATE);
  313. }
  314. ;
  315. Finalize:
  316. GenerateMessage(hIMC, lpIMC, lpImcP);
  317. return (TRUE);
  318. }
  319. /**********************************************************************/
  320. /* ImeSetCompositionString() */
  321. /* Return Value: */
  322. /* TRUE - successful, FALSE - failure */
  323. /**********************************************************************/
  324. BOOL WINAPI ImeSetCompositionString(
  325. HIMC hIMC,
  326. DWORD dwIndex,
  327. LPVOID lpComp,
  328. DWORD dwCompLen,
  329. LPVOID lpRead,
  330. DWORD dwReadLen)
  331. {
  332. LPINPUTCONTEXT lpIMC;
  333. LPCOMPOSITIONSTRING lpCompStr;
  334. LPPRIVCONTEXT lpImcP;
  335. BOOL fRet;
  336. if (!hIMC) {
  337. return (FALSE);
  338. }
  339. // composition string must == reading string
  340. // reading is more important
  341. if (!dwReadLen) {
  342. dwReadLen = dwCompLen;
  343. }
  344. // composition string must == reading string
  345. // reading is more important
  346. if (!lpRead) {
  347. lpRead = lpComp;
  348. }
  349. if (!dwReadLen) {
  350. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  351. if (!lpIMC) {
  352. return (FALSE);
  353. }
  354. CompCancel(hIMC, lpIMC);
  355. ImmUnlockIMC(hIMC);
  356. return (TRUE);
  357. } else if (!lpRead) {
  358. return (FALSE);
  359. } else if (!dwCompLen) {
  360. } else if (!lpComp) {
  361. } else if (dwReadLen != dwCompLen) {
  362. return (FALSE);
  363. } else if (lpRead == lpComp) {
  364. } else if (!lstrcmp(lpRead, lpComp)) {
  365. // composition string must == reading string
  366. } else {
  367. // composition string != reading string
  368. return (FALSE);
  369. }
  370. if (dwIndex != SCS_SETSTR) {
  371. return (FALSE);
  372. }
  373. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  374. if (!lpIMC) {
  375. return (FALSE);
  376. }
  377. if (!lpIMC->hCompStr) {
  378. ImmUnlockIMC(hIMC);
  379. return (FALSE);
  380. }
  381. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  382. if (!lpCompStr) {
  383. ImmUnlockIMC(hIMC);
  384. return (FALSE);
  385. }
  386. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  387. if (!lpCompStr) {
  388. ImmUnlockIMCC(lpIMC->hCompStr);
  389. ImmUnlockIMC(hIMC);
  390. return (FALSE);
  391. }
  392. fRet = SetString(hIMC, lpIMC, lpCompStr, lpImcP, lpRead, dwReadLen);
  393. ImmUnlockIMCC(lpIMC->hPrivate);
  394. ImmUnlockIMCC(lpIMC->hCompStr);
  395. ImmUnlockIMC(hIMC);
  396. return (fRet);
  397. }
  398. /**********************************************************************/
  399. /* ToggleSoftKbd() */
  400. /**********************************************************************/
  401. void PASCAL ToggleSoftKbd(
  402. HIMC hIMC,
  403. LPINPUTCONTEXT lpIMC)
  404. {
  405. LPPRIVCONTEXT lpImcP;
  406. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  407. if (!lpImcP) {
  408. return;
  409. }
  410. lpImcP->fdwImeMsg |= MSG_IMN_UPDATE_SOFTKBD;
  411. GenerateMessage(hIMC, lpIMC, lpImcP);
  412. ImmUnlockIMCC(lpIMC->hPrivate);
  413. return;
  414. }
  415. /**********************************************************************/
  416. /* NotifySelectCand() */
  417. /**********************************************************************/
  418. void PASCAL NotifySelectCand( // app tell IME that one candidate string is
  419. // selected (by mouse or non keyboard action
  420. // - for example sound)
  421. HIMC hIMC,
  422. LPINPUTCONTEXT lpIMC,
  423. LPCANDIDATEINFO lpCandInfo,
  424. DWORD dwIndex,
  425. DWORD dwValue)
  426. {
  427. LPCANDIDATELIST lpCandList;
  428. LPCOMPOSITIONSTRING lpCompStr;
  429. LPPRIVCONTEXT lpImcP;
  430. if (!lpCandInfo) {
  431. return;
  432. }
  433. if (dwIndex >= lpCandInfo->dwCount) {
  434. // wanted candidate list is not created yet!
  435. return;
  436. } else if (dwIndex == 0) {
  437. if (lpIMC->fdwConversion & IME_CMODE_CHARCODE) {
  438. return; // not implemented yet
  439. }
  440. }
  441. lpCandList = (LPCANDIDATELIST)
  442. ((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[0]);
  443. // the selected value even more than the number of total candidate
  444. // strings, it is imposible. should be error of app
  445. if (dwValue >= lpCandList->dwCount) {
  446. return;
  447. }
  448. // app select this candidate string
  449. lpCandList->dwSelection = dwValue;
  450. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  451. if(!lpCompStr){
  452. return;
  453. }
  454. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  455. if(!lpCompStr){
  456. ImmUnlockIMCC(lpIMC->hCompStr);
  457. return;
  458. }
  459. // translate into message buffer
  460. SelectOneCand(lpIMC, lpCompStr, lpImcP, lpCandList);
  461. // let app generate those messages in its message loop
  462. GenerateMessage(hIMC, lpIMC, lpImcP);
  463. ImmUnlockIMCC(lpIMC->hPrivate);
  464. ImmUnlockIMCC(lpIMC->hCompStr);
  465. return;
  466. }
  467. /**********************************************************************/
  468. /* NotifyIME() */
  469. /* Return Value: */
  470. /* TRUE - successful, FALSE - failure */
  471. /**********************************************************************/
  472. BOOL WINAPI NotifyIME(
  473. HIMC hIMC,
  474. DWORD dwAction,
  475. DWORD dwIndex,
  476. DWORD dwValue)
  477. {
  478. LPINPUTCONTEXT lpIMC;
  479. DWORD fdwImeMsg;
  480. BOOL fRet;
  481. fRet = FALSE;
  482. if (!hIMC) {
  483. return (fRet);
  484. }
  485. switch (dwAction) {
  486. case NI_OPENCANDIDATE: // after a composition string is determined
  487. // if an IME can open candidate, it will.
  488. // if it can not, app also can not open it.
  489. case NI_CLOSECANDIDATE:
  490. return (fRet); // not supported
  491. case NI_SELECTCANDIDATESTR:
  492. case NI_SETCANDIDATE_PAGESTART:
  493. case NI_SETCANDIDATE_PAGESIZE:
  494. break; // need to handle it
  495. case NI_CHANGECANDIDATELIST:
  496. break;
  497. case NI_CONTEXTUPDATED:
  498. switch (dwValue) {
  499. case IMC_SETCONVERSIONMODE:
  500. case IMC_SETOPENSTATUS:
  501. break; // need to handle it
  502. case IMC_SETCANDIDATEPOS:
  503. case IMC_SETCOMPOSITIONFONT:
  504. case IMC_SETCOMPOSITIONWINDOW:
  505. return (TRUE); // not important to the IME
  506. default:
  507. return (fRet); // not supported
  508. }
  509. break;
  510. case NI_COMPOSITIONSTR:
  511. switch (dwIndex) {
  512. case CPS_COMPLETE:
  513. break; // need to handle it
  514. case CPS_CONVERT: // all composition string can not be convert
  515. case CPS_REVERT: // any more, it maybe work for some
  516. // intelligent phonetic IMEs
  517. return (fRet);
  518. case CPS_CANCEL:
  519. break; // need to handle it
  520. default:
  521. return (fRet); // not supported
  522. }
  523. break; // need to handle it
  524. default:
  525. return (fRet); // not supported
  526. }
  527. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  528. if (!lpIMC) {
  529. return (fRet);
  530. }
  531. fRet = TRUE;
  532. switch (dwAction) {
  533. case NI_CONTEXTUPDATED:
  534. switch (dwValue) {
  535. case IMC_SETCONVERSIONMODE:
  536. if ((lpIMC->fdwConversion ^ dwIndex) & IME_CMODE_CHARCODE) {
  537. // reject CHARCODE
  538. lpIMC->fdwConversion &= ~IME_CMODE_CHARCODE;
  539. MessageBeep((UINT)-1);
  540. break;
  541. }
  542. fdwImeMsg = 0;
  543. if ((lpIMC->fdwConversion ^ dwIndex) & IME_CMODE_NOCONVERSION) {
  544. lpIMC->fdwConversion |= IME_CMODE_NATIVE;
  545. lpIMC->fdwConversion &= ~(IME_CMODE_CHARCODE|
  546. IME_CMODE_EUDC|IME_CMODE_SYMBOL);
  547. }
  548. if ((lpIMC->fdwConversion ^ dwIndex) & IME_CMODE_EUDC) {
  549. lpIMC->fdwConversion |= IME_CMODE_NATIVE;
  550. lpIMC->fdwConversion &= ~(IME_CMODE_CHARCODE|
  551. IME_CMODE_NOCONVERSION|IME_CMODE_SYMBOL);
  552. }
  553. if ((lpIMC->fdwConversion ^ dwIndex) & IME_CMODE_SOFTKBD) {
  554. fdwImeMsg |= MSG_IMN_UPDATE_SOFTKBD;
  555. }
  556. if ((lpIMC->fdwConversion ^ dwIndex) == IME_CMODE_NATIVE) {
  557. lpIMC->fdwConversion &= ~(IME_CMODE_CHARCODE|
  558. IME_CMODE_NOCONVERSION|IME_CMODE_EUDC);
  559. fdwImeMsg |= MSG_IMN_UPDATE_SOFTKBD;
  560. }
  561. if (fdwImeMsg) {
  562. GenerateImeMessage(hIMC, lpIMC, fdwImeMsg);
  563. }
  564. if ((lpIMC->fdwConversion ^ dwIndex) & ~(IME_CMODE_FULLSHAPE|
  565. IME_CMODE_SOFTKBD)) {
  566. } else {
  567. break;
  568. }
  569. CompCancel(hIMC, lpIMC);
  570. break;
  571. case IMC_SETOPENSTATUS:
  572. if (lpIMC->fdwConversion & IME_CMODE_SOFTKBD) {
  573. GenerateImeMessage(hIMC, lpIMC, MSG_IMN_UPDATE_SOFTKBD);
  574. }
  575. CompCancel(hIMC, lpIMC);
  576. break;
  577. default:
  578. break;
  579. }
  580. break;
  581. case NI_SELECTCANDIDATESTR:
  582. if (!lpIMC->fOpen) {
  583. fRet = FALSE;
  584. break;
  585. } else if (lpIMC->fdwConversion & IME_CMODE_NOCONVERSION) {
  586. fRet = FALSE;
  587. break;
  588. } else if (lpIMC->fdwConversion & IME_CMODE_EUDC) {
  589. fRet = FALSE;
  590. break;
  591. } else if (!lpIMC->hCandInfo) {
  592. fRet = FALSE;
  593. break;
  594. } else {
  595. LPCANDIDATEINFO lpCandInfo;
  596. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  597. if(!lpCandInfo){
  598. fRet = FALSE;
  599. break;
  600. }
  601. NotifySelectCand(hIMC, lpIMC, lpCandInfo, dwIndex, dwValue);
  602. ImmUnlockIMCC(lpIMC->hCandInfo);
  603. }
  604. break;
  605. case NI_CHANGECANDIDATELIST:
  606. fdwImeMsg = 0;
  607. fdwImeMsg |= MSG_CHANGE_CANDIDATE;
  608. GenerateImeMessage(hIMC, lpIMC, fdwImeMsg);
  609. break;
  610. case NI_SETCANDIDATE_PAGESTART:
  611. case NI_SETCANDIDATE_PAGESIZE:
  612. if (dwIndex != 0) {
  613. fRet = FALSE;
  614. break;
  615. } else if (!lpIMC->fOpen) {
  616. fRet = FALSE;
  617. break;
  618. } else if (lpIMC->fdwConversion & IME_CMODE_NOCONVERSION) {
  619. fRet = FALSE;
  620. break;
  621. } else if (lpIMC->fdwConversion & (IME_CMODE_EUDC|IME_CMODE_SYMBOL)) {
  622. fRet = FALSE;
  623. break;
  624. } else if (!lpIMC->hCandInfo) {
  625. fRet = FALSE;
  626. break;
  627. } else {
  628. LPCANDIDATEINFO lpCandInfo;
  629. LPCANDIDATELIST lpCandList;
  630. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  631. if (!lpCandInfo) {
  632. fRet = FALSE;
  633. break;
  634. }
  635. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  636. lpCandInfo->dwOffset[0]);
  637. if (dwAction == NI_SETCANDIDATE_PAGESTART) {
  638. if (dwValue < lpCandList->dwCount) {
  639. lpCandList->dwPageStart = lpCandList->dwSelection =
  640. dwValue;
  641. }
  642. } else {
  643. if (lpCandList->dwCount) {
  644. lpCandList->dwPageSize = dwValue;
  645. }
  646. }
  647. ImmUnlockIMCC(lpIMC->hCandInfo);
  648. }
  649. break;
  650. case NI_COMPOSITIONSTR:
  651. switch (dwIndex) {
  652. case CPS_CANCEL:
  653. CompCancel(hIMC, lpIMC);
  654. break;
  655. case CPS_COMPLETE:
  656. {
  657. LPPRIVCONTEXT lpImcP;
  658. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  659. if (!lpImcP) {
  660. break;
  661. }
  662. if (lpImcP->iImeState == CST_INIT) {
  663. CompCancel(hIMC, lpIMC);
  664. // can not do any thing
  665. } else if (lpImcP->iImeState == CST_CHOOSE) {
  666. LPCOMPOSITIONSTRING lpCompStr;
  667. LPCANDIDATEINFO lpCandInfo;
  668. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  669. if(!lpCompStr){
  670. break;
  671. }
  672. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  673. if (lpCandInfo) {
  674. LPCANDIDATELIST lpCandList;
  675. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  676. lpCandInfo->dwOffset[0]);
  677. SelectOneCand(lpIMC, lpCompStr, lpImcP, lpCandList);
  678. ImmUnlockIMCC(lpIMC->hCandInfo);
  679. GenerateMessage(hIMC, lpIMC, lpImcP);
  680. }
  681. if (lpCompStr) ImmUnlockIMCC(lpIMC->hCompStr);
  682. } else if ((lpIMC->fdwConversion & (IME_CMODE_NATIVE|
  683. IME_CMODE_EUDC|IME_CMODE_SYMBOL)) != IME_CMODE_NATIVE) {
  684. CompCancel(hIMC, lpIMC);
  685. } else if (lpImcP->iImeState == CST_INPUT) {
  686. LPCOMPOSITIONSTRING lpCompStr;
  687. LPGUIDELINE lpGuideLine;
  688. LPCANDIDATEINFO lpCandInfo;
  689. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  690. if(!lpCompStr){
  691. break;
  692. }
  693. lpGuideLine = (LPGUIDELINE)ImmLockIMCC(lpIMC->hGuideLine);
  694. if(!lpGuideLine){
  695. ImmUnlockIMCC(lpIMC->hCompStr);
  696. break;
  697. }
  698. CompWord(' ', lpIMC, lpCompStr, lpImcP, lpGuideLine);
  699. if (lpImcP->iImeState == CST_INPUT) {
  700. CompCancel(hIMC, lpIMC);
  701. } else if (lpImcP->iImeState != CST_CHOOSE) {
  702. } else if (lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(
  703. lpIMC->hCandInfo)) {
  704. LPCANDIDATELIST lpCandList;
  705. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  706. lpCandInfo->dwOffset[0]);
  707. // SelectOneCand(hIMC, lpIMC, lpCompStr, lpImcP, lpCandList);
  708. SelectOneCand(lpIMC, lpCompStr, lpImcP, lpCandList);
  709. ImmUnlockIMCC(lpIMC->hCandInfo);
  710. } else {
  711. }
  712. if (lpCompStr) ImmUnlockIMCC(lpIMC->hCompStr);
  713. if (lpGuideLine) ImmUnlockIMCC(lpIMC->hGuideLine);
  714. // don't phrase predition under this case
  715. if (lpImcP->fdwImeMsg & MSG_ALREADY_OPEN) {
  716. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_CLOSE_CANDIDATE) &
  717. ~(MSG_OPEN_CANDIDATE|MSG_CHANGE_CANDIDATE);
  718. } else {
  719. lpImcP->fdwImeMsg &= ~(MSG_CLOSE_CANDIDATE|MSG_OPEN_CANDIDATE);
  720. }
  721. GenerateMessage(hIMC, lpIMC, lpImcP);
  722. } else {
  723. CompCancel(hIMC, lpIMC);
  724. }
  725. ImmUnlockIMCC(lpIMC->hPrivate);
  726. }
  727. break;
  728. default:
  729. break;
  730. }
  731. break;
  732. default:
  733. break;
  734. }
  735. ImmUnlockIMC(hIMC);
  736. return (fRet);
  737. }