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.

859 lines
25 KiB

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