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.

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