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.

500 lines
14 KiB

  1. /*************************************************
  2. * notify.c *
  3. * *
  4. * Copyright (C) 1999 Microsoft Inc. *
  5. * *
  6. *************************************************/
  7. #include <windows.h>
  8. #include <immdev.h>
  9. #include "imeattr.h"
  10. #include "imedefs.h"
  11. /**********************************************************************/
  12. /* GenerateMessage() */
  13. /**********************************************************************/
  14. void PASCAL GenerateMessage(
  15. HIMC hIMC,
  16. LPINPUTCONTEXT lpIMC,
  17. LPPRIVCONTEXT lpImcP)
  18. {
  19. if (!hIMC) {
  20. return;
  21. } else if (!lpIMC) {
  22. return;
  23. } else if (!lpImcP) {
  24. return;
  25. } else if (lpImcP->fdwImeMsg & MSG_IN_IMETOASCIIEX) {
  26. return;
  27. } else {
  28. }
  29. lpIMC->dwNumMsgBuf += TranslateImeMessage(NULL, lpIMC, lpImcP);
  30. lpImcP->fdwImeMsg &= (MSG_STATIC_STATE);
  31. lpImcP->fdwGcsFlag = 0;
  32. ImmGenerateMessage(hIMC);
  33. return;
  34. }
  35. /**********************************************************************/
  36. /* SetString() */
  37. /* Return Value: */
  38. /* TRUE - successful, FALSE - failure */
  39. /**********************************************************************/
  40. BOOL PASCAL SetString(
  41. HIMC hIMC,
  42. LPINPUTCONTEXT lpIMC,
  43. LPCOMPOSITIONSTRING lpCompStr,
  44. LPPRIVCONTEXT lpImcP,
  45. LPTSTR lpszRead,
  46. DWORD dwReadLen)
  47. {
  48. LPGUIDELINE lpGuideLine;
  49. DWORD i;
  50. // convert from byte count to the string length
  51. dwReadLen = dwReadLen / sizeof(TCHAR);
  52. if (dwReadLen > lpImeL->nMaxKey * sizeof(WCHAR) / sizeof(TCHAR)) {
  53. return (FALSE);
  54. }
  55. InitCompStr(lpCompStr);
  56. ClearCand(lpIMC);
  57. /*
  58. lpGuideLine = (LPGUIDELINE)ImmLockIMCC(lpIMC->hGuideLine);
  59. if (lpGuideLine) {
  60. InitGuideLine(lpGuideLine);
  61. ImmUnlockIMCC(lpIMC->hGuideLine);
  62. }
  63. */
  64. // compoition/reading attribute
  65. lpCompStr->dwCompReadAttrLen = dwReadLen;
  66. lpCompStr->dwCompAttrLen = lpCompStr->dwCompReadAttrLen;
  67. // The IME has converted these chars
  68. for (i = 0; i < dwReadLen; i++) {
  69. *((LPBYTE)lpCompStr + lpCompStr->dwCompReadAttrOffset + i) =
  70. ATTR_TARGET_CONVERTED;
  71. }
  72. // composition/reading clause, 1 clause only
  73. lpCompStr->dwCompReadClauseLen = 2 * sizeof(DWORD);
  74. lpCompStr->dwCompClauseLen = lpCompStr->dwCompReadClauseLen;
  75. *(LPDWORD)((LPBYTE)lpCompStr + lpCompStr->dwCompReadClauseOffset +
  76. sizeof(DWORD)) = dwReadLen;
  77. lpCompStr->dwCompReadStrLen = dwReadLen;
  78. lpCompStr->dwCompStrLen = lpCompStr->dwCompReadStrLen;
  79. CopyMemory((LPBYTE)lpCompStr + lpCompStr->dwCompReadStrOffset, lpszRead,
  80. dwReadLen * sizeof(TCHAR) + sizeof(TCHAR));
  81. // dlta start from 0;
  82. lpCompStr->dwDeltaStart = 0;
  83. // cursor is next to composition string
  84. lpCompStr->dwCursorPos = lpCompStr->dwCompStrLen;
  85. lpCompStr->dwResultReadClauseLen = 0;
  86. lpCompStr->dwResultReadStrLen = 0;
  87. lpCompStr->dwResultClauseLen = 0;
  88. lpCompStr->dwResultStrLen = 0;
  89. // set private input context
  90. lpImcP->iImeState = CST_INPUT;
  91. if (lpImcP->fdwImeMsg & MSG_ALREADY_OPEN) {
  92. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_CLOSE_CANDIDATE) &
  93. ~(MSG_OPEN_CANDIDATE|MSG_CHANGE_CANDIDATE);
  94. }
  95. if (!(lpImcP->fdwImeMsg & MSG_ALREADY_START)) {
  96. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_START_COMPOSITION) &
  97. ~(MSG_END_COMPOSITION);
  98. }
  99. lpImcP->fdwImeMsg |= MSG_COMPOSITION;
  100. lpImcP->dwCompChar = (DWORD)lpImeL->wSeq2CompTbl[
  101. lpImcP->bSeq[lpCompStr->dwCompReadStrLen / 2 - 1]];
  102. lpImcP->fdwGcsFlag = GCS_COMPREAD|GCS_COMP|
  103. GCS_DELTASTART|GCS_CURSORPOS;
  104. lpImcP->fdwImeMsg |= MSG_GUIDELINE;
  105. if (lpIMC->fdwConversion & IME_CMODE_EUDC) {
  106. if (lpCompStr->dwCompReadStrLen >= sizeof(WORD) * lpImeL->nMaxKey) {
  107. lpImcP->fdwImeMsg |= MSG_COMPOSITION;
  108. lpImcP->fdwGcsFlag |= GCS_RESULTREAD|GCS_RESULTSTR;
  109. }
  110. } else {
  111. if (dwReadLen < sizeof(WCHAR) / sizeof(TCHAR) * lpImeL->nMaxKey) {
  112. }
  113. }
  114. GenerateMessage(hIMC, lpIMC, lpImcP);
  115. return (TRUE);
  116. }
  117. /**********************************************************************/
  118. /* CompCancel() */
  119. /**********************************************************************/
  120. void PASCAL CompCancel(
  121. HIMC hIMC,
  122. LPINPUTCONTEXT lpIMC)
  123. {
  124. LPPRIVCONTEXT lpImcP;
  125. if (!lpIMC->hPrivate) {
  126. return;
  127. }
  128. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  129. if (!lpImcP) {
  130. return;
  131. }
  132. lpImcP->fdwGcsFlag = 0;
  133. if (lpImcP->fdwImeMsg & (MSG_ALREADY_START|MSG_START_COMPOSITION)) {
  134. LPCOMPOSITIONSTRING lpCompStr;
  135. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  136. CompEscapeKey(lpIMC, lpCompStr, lpImcP);
  137. if (lpCompStr) {
  138. ImmUnlockIMCC(lpIMC->hCompStr);
  139. }
  140. } else {
  141. ImmUnlockIMCC(lpIMC->hPrivate);
  142. return;
  143. }
  144. GenerateMessage(hIMC, lpIMC, lpImcP);
  145. ImmUnlockIMCC(lpIMC->hPrivate);
  146. return;
  147. }
  148. /**********************************************************************/
  149. /* ImeSetCompositionString() */
  150. /* Return Value: */
  151. /* TRUE - successful, FALSE - failure */
  152. /**********************************************************************/
  153. BOOL WINAPI ImeSetCompositionString(
  154. HIMC hIMC,
  155. DWORD dwIndex,
  156. LPVOID lpComp,
  157. DWORD dwCompLen,
  158. LPVOID lpRead,
  159. DWORD dwReadLen)
  160. {
  161. LPINPUTCONTEXT lpIMC;
  162. LPCOMPOSITIONSTRING lpCompStr;
  163. LPPRIVCONTEXT lpImcP;
  164. BOOL fRet;
  165. TCHAR szReading[16];
  166. if (!hIMC) {
  167. return (FALSE);
  168. }
  169. // composition string must == reading string
  170. // reading is more important
  171. if (!dwReadLen) {
  172. dwReadLen = dwCompLen;
  173. }
  174. // composition string must == reading string
  175. // reading is more important
  176. if (!lpRead) {
  177. lpRead = lpComp;
  178. }
  179. if (!dwReadLen) {
  180. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  181. if (!lpIMC) {
  182. return (FALSE);
  183. }
  184. CompCancel(hIMC, lpIMC);
  185. ImmUnlockIMC(hIMC);
  186. return (TRUE);
  187. } else if (!lpRead) {
  188. return (FALSE);
  189. } else if (dwReadLen >= sizeof(szReading)) {
  190. return (FALSE);
  191. } else if (!dwCompLen) {
  192. } else if (!lpComp) {
  193. } else if (dwReadLen != dwCompLen) {
  194. return (FALSE);
  195. } else if (lpRead == lpComp) {
  196. } else if (!lstrcmp(lpRead, lpComp)) {
  197. // composition string must == reading string
  198. } else {
  199. // composition string != reading string
  200. return (FALSE);
  201. }
  202. if (dwIndex != SCS_SETSTR) {
  203. return (FALSE);
  204. }
  205. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  206. if (!lpIMC) {
  207. return (FALSE);
  208. }
  209. fRet = FALSE;
  210. if ((lpIMC->fdwConversion & (IME_CMODE_NATIVE|IME_CMODE_SYMBOL)) !=
  211. IME_CMODE_NATIVE) {
  212. goto ImeSetCompStrUnlockIMC;
  213. }
  214. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  215. if (!lpCompStr) {
  216. goto ImeSetCompStrUnlockIMC;
  217. }
  218. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  219. if (!lpImcP) {
  220. goto ImeSetCompStrUnlockCompStr;
  221. }
  222. if (*(LPTSTR)((LPBYTE)lpRead + dwReadLen) != '\0') {
  223. CopyMemory(szReading, (LPBYTE)lpRead, dwReadLen);
  224. lpRead = szReading;
  225. *(LPTSTR)((LPBYTE)lpRead + dwReadLen) = '\0';
  226. }
  227. fRet = SetString(
  228. hIMC, lpIMC, lpCompStr, lpImcP, lpRead, dwReadLen);
  229. ImmUnlockIMCC(lpIMC->hPrivate);
  230. ImeSetCompStrUnlockCompStr:
  231. ImmUnlockIMCC(lpIMC->hCompStr);
  232. ImeSetCompStrUnlockIMC:
  233. ImmUnlockIMC(hIMC);
  234. return (fRet);
  235. }
  236. /**********************************************************************/
  237. /* GenerateImeMessage() */
  238. /**********************************************************************/
  239. void PASCAL GenerateImeMessage(
  240. HIMC hIMC,
  241. LPINPUTCONTEXT lpIMC,
  242. DWORD fdwImeMsg)
  243. {
  244. LPPRIVCONTEXT lpImcP;
  245. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  246. if (!lpImcP) {
  247. return;
  248. }
  249. lpImcP->fdwImeMsg |= fdwImeMsg;
  250. if (fdwImeMsg & MSG_CLOSE_CANDIDATE) {
  251. lpImcP->fdwImeMsg &= ~(MSG_OPEN_CANDIDATE|MSG_CHANGE_CANDIDATE);
  252. } else if (fdwImeMsg & (MSG_OPEN_CANDIDATE|MSG_CHANGE_CANDIDATE)) {
  253. lpImcP->fdwImeMsg &= ~(MSG_CLOSE_CANDIDATE);
  254. } else {
  255. }
  256. if (fdwImeMsg & MSG_END_COMPOSITION) {
  257. lpImcP->fdwImeMsg &= ~(MSG_START_COMPOSITION);
  258. } else if (fdwImeMsg & MSG_START_COMPOSITION) {
  259. lpImcP->fdwImeMsg &= ~(MSG_END_COMPOSITION);
  260. } else {
  261. }
  262. GenerateMessage(hIMC, lpIMC, lpImcP);
  263. ImmUnlockIMCC(lpIMC->hPrivate);
  264. return;
  265. }
  266. /**********************************************************************/
  267. /* CompComplete() */
  268. /**********************************************************************/
  269. void PASCAL CompComplete(
  270. HIMC hIMC,
  271. LPINPUTCONTEXT lpIMC)
  272. {
  273. LPPRIVCONTEXT lpImcP;
  274. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  275. if (!lpImcP) {
  276. return;
  277. }
  278. if (lpImcP->iImeState == CST_INIT) {
  279. // can not do any thing
  280. CompCancel(hIMC, lpIMC);
  281. } else if (lpImcP->iImeState == CST_CHOOSE) {
  282. LPCOMPOSITIONSTRING lpCompStr;
  283. LPCANDIDATEINFO lpCandInfo;
  284. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  285. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  286. if (lpCandInfo) {
  287. LPCANDIDATELIST lpCandList;
  288. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  289. lpCandInfo->dwOffset[0]);
  290. SelectOneCand(
  291. hIMC, lpIMC, lpCompStr, lpImcP, lpCandList);
  292. ImmUnlockIMCC(lpIMC->hCandInfo);
  293. GenerateMessage(hIMC, lpIMC, lpImcP);
  294. }
  295. if (lpCompStr) ImmUnlockIMCC(lpIMC->hCompStr);
  296. } else if ((lpIMC->fdwConversion & (IME_CMODE_NATIVE|
  297. IME_CMODE_EUDC|IME_CMODE_SYMBOL)) != IME_CMODE_NATIVE) {
  298. CompCancel(hIMC, lpIMC);
  299. } else if (lpImcP->iImeState == CST_INPUT) {
  300. LPCOMPOSITIONSTRING lpCompStr;
  301. LPGUIDELINE lpGuideLine;
  302. LPCANDIDATEINFO lpCandInfo;
  303. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  304. lpGuideLine = (LPGUIDELINE)ImmLockIMCC(lpIMC->hGuideLine);
  305. CompWord(
  306. ' ', hIMC, lpIMC, lpCompStr, lpGuideLine, lpImcP);
  307. if (lpImcP->iImeState == CST_INPUT) {
  308. CompCancel(hIMC, lpIMC);
  309. } else if (lpImcP->iImeState != CST_CHOOSE) {
  310. } else if (lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(
  311. lpIMC->hCandInfo)) {
  312. LPCANDIDATELIST lpCandList;
  313. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  314. lpCandInfo->dwOffset[0]);
  315. SelectOneCand(
  316. hIMC, lpIMC, lpCompStr, lpImcP, lpCandList);
  317. ImmUnlockIMCC(lpIMC->hCandInfo);
  318. } else {
  319. }
  320. if (lpCompStr) ImmUnlockIMCC(lpIMC->hCompStr);
  321. if (lpGuideLine) ImmUnlockIMCC(lpIMC->hGuideLine);
  322. // don't phrase predition under this case
  323. if (lpImcP->fdwImeMsg & MSG_ALREADY_OPEN) {
  324. lpImcP->fdwImeMsg = (lpImcP->fdwImeMsg | MSG_CLOSE_CANDIDATE) &
  325. ~(MSG_OPEN_CANDIDATE|MSG_CHANGE_CANDIDATE);
  326. } else {
  327. lpImcP->fdwImeMsg &= ~(MSG_CLOSE_CANDIDATE|MSG_OPEN_CANDIDATE);
  328. }
  329. GenerateMessage(hIMC, lpIMC, lpImcP);
  330. } else {
  331. CompCancel(hIMC, lpIMC);
  332. }
  333. ImmUnlockIMCC(lpIMC->hPrivate);
  334. return;
  335. }
  336. /**********************************************************************/
  337. /* NotifyIME() / UniNotifyIME() */
  338. /* Return Value: */
  339. /* TRUE - successful, FALSE - failure */
  340. /**********************************************************************/
  341. BOOL WINAPI NotifyIME(
  342. HIMC hIMC,
  343. DWORD dwAction,
  344. DWORD dwIndex,
  345. DWORD dwValue)
  346. {
  347. LPINPUTCONTEXT lpIMC;
  348. BOOL fRet;
  349. fRet = FALSE;
  350. if (!hIMC) {
  351. return (fRet);
  352. }
  353. switch (dwAction) {
  354. case NI_CONTEXTUPDATED:
  355. switch (dwValue) {
  356. case IMC_SETCONVERSIONMODE:
  357. case IMC_SETSENTENCEMODE:
  358. case IMC_SETOPENSTATUS:
  359. break; // need to handle it
  360. case IMC_SETCANDIDATEPOS:
  361. case IMC_SETCOMPOSITIONFONT:
  362. case IMC_SETCOMPOSITIONWINDOW:
  363. return (TRUE); // not important to the IME
  364. default:
  365. return (fRet); // not supported
  366. }
  367. break;
  368. case NI_COMPOSITIONSTR:
  369. switch (dwIndex) {
  370. case CPS_COMPLETE:
  371. break; // need to handle it
  372. case CPS_CONVERT: // all composition string can not be convert
  373. case CPS_REVERT: // any more, it maybe work for some
  374. // intelligent phonetic IMEs
  375. return (fRet);
  376. case CPS_CANCEL:
  377. break; // need to handle it
  378. default:
  379. return (fRet); // not supported
  380. }
  381. break; // need to handle it
  382. default:
  383. return (fRet); // not supported
  384. }
  385. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  386. if (!lpIMC) {
  387. return (fRet);
  388. }
  389. fRet = TRUE;
  390. switch (dwAction) {
  391. case NI_COMPOSITIONSTR:
  392. switch (dwIndex) {
  393. case CPS_CANCEL:
  394. CompCancel(hIMC, lpIMC);
  395. break;
  396. case CPS_COMPLETE:
  397. CompComplete(
  398. hIMC, lpIMC);
  399. break;
  400. default:
  401. break;
  402. }
  403. break;
  404. default:
  405. break;
  406. }
  407. ImmUnlockIMC(hIMC);
  408. return (fRet);
  409. }