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.

589 lines
18 KiB

  1. /*************************************************
  2. * ddis.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. #include "imerc.h"
  12. /**********************************************************************/
  13. /* ImeInquire() / UniImeInquire() */
  14. /* Return Value: */
  15. /* TRUE - successful, FALSE - failure */
  16. /**********************************************************************/
  17. // initialized data structure of IME
  18. BOOL WINAPI ImeInquire(
  19. LPIMEINFO lpImeInfo, // IME specific data report to IMM
  20. LPTSTR lpszWndCls, // the class name of UI
  21. DWORD dwSystemInfoFlags)
  22. {
  23. if (!lpImeInfo) {
  24. return (FALSE);
  25. }
  26. lpImeInfo->dwPrivateDataSize = sizeof(PRIVCONTEXT);
  27. lpImeInfo->fdwProperty = IME_PROP_KBD_CHAR_FIRST|
  28. IME_PROP_UNICODE |
  29. IME_PROP_CANDLIST_START_FROM_1|
  30. IME_PROP_NEED_ALTKEY|IME_PROP_IGNORE_UPKEYS;
  31. lpImeInfo->fdwConversionCaps = IME_CMODE_NATIVE | IME_CMODE_NOCONVERSION;
  32. lpImeInfo->fdwSentenceCaps = IME_SMODE_PHRASEPREDICT;
  33. // composition string is the reading string for simple IME
  34. lpImeInfo->fdwSCSCaps = SCS_CAP_COMPSTR|SCS_CAP_MAKEREAD;
  35. // IME will have different distance base multiple of 900 escapement
  36. lpImeInfo->fdwUICaps = UI_CAP_ROT90|UI_CAP_SOFTKBD;
  37. // IME want to decide conversion mode on ImeSelect
  38. lpImeInfo->fdwSelectCaps = 0;
  39. lstrcpy(lpszWndCls, lpImeL->szUIClassName);
  40. return (TRUE);
  41. }
  42. /**********************************************************************/
  43. /* ImeDestroy() / UniImeDestroy */
  44. /* Return Value: */
  45. /* TRUE - successful, FALSE - failure */
  46. /**********************************************************************/
  47. // this dll is unloaded
  48. BOOL WINAPI ImeDestroy(
  49. UINT uReserved)
  50. {
  51. if (uReserved) {
  52. return (FALSE);
  53. }
  54. // free the IME table or data base
  55. FreeTable(lpInstL);
  56. return (TRUE);
  57. }
  58. /**********************************************************************/
  59. /* InitCompStr() */
  60. /**********************************************************************/
  61. void PASCAL InitCompStr( // init setting for composing string
  62. LPCOMPOSITIONSTRING lpCompStr)
  63. {
  64. if (!lpCompStr) {
  65. return;
  66. }
  67. lpCompStr->dwCompReadAttrLen = 0;
  68. lpCompStr->dwCompReadClauseLen = 0;
  69. lpCompStr->dwCompReadStrLen = 0;
  70. lpCompStr->dwCompAttrLen = 0;
  71. lpCompStr->dwCompClauseLen = 0;
  72. lpCompStr->dwCompStrLen = 0;
  73. lpCompStr->dwCursorPos = 0;
  74. lpCompStr->dwDeltaStart = 0;
  75. lpCompStr->dwResultReadClauseLen = 0;
  76. lpCompStr->dwResultReadStrLen = 0;
  77. lpCompStr->dwResultClauseLen = 0;
  78. lpCompStr->dwResultStrLen = 0;
  79. return;
  80. }
  81. /**********************************************************************/
  82. /* ClearCompStr() */
  83. /* Return Value: */
  84. /* TRUE - successful, FALSE - failure */
  85. /**********************************************************************/
  86. #define NMAXKEY 8
  87. BOOL PASCAL ClearCompStr(
  88. LPINPUTCONTEXT lpIMC)
  89. {
  90. HIMCC hMem;
  91. LPCOMPOSITIONSTRING lpCompStr;
  92. DWORD dwSize;
  93. LPBYTE lpbAttr;
  94. UINT i;
  95. LPDWORD lpdwClause;
  96. LPWSTR lpwStr;
  97. if (!lpIMC) {
  98. return (FALSE);
  99. }
  100. dwSize =
  101. // header length
  102. sizeof(COMPOSITIONSTRING) +
  103. // composition reading attribute plus NULL terminator
  104. NMAXKEY * sizeof(WCHAR) / sizeof(TCHAR) + sizeof(DWORD) +
  105. // composition reading clause
  106. sizeof(DWORD) + sizeof(DWORD) +
  107. // composition reading string plus NULL terminator
  108. NMAXKEY * sizeof(WCHAR) + sizeof(DWORD) +
  109. // result reading clause
  110. sizeof(DWORD) + sizeof(DWORD) +
  111. // result reading string plus NULL terminateor
  112. NMAXKEY * sizeof(WCHAR) + sizeof(DWORD) +
  113. // result clause
  114. sizeof(DWORD) + sizeof(DWORD) +
  115. // result string plus NULL terminateor
  116. MAXSTRLEN * sizeof(WCHAR) + sizeof(DWORD);
  117. if (!lpIMC->hCompStr) {
  118. // it maybe free by other IME, init it
  119. lpIMC->hCompStr = ImmCreateIMCC(dwSize);
  120. } else if (hMem = ImmReSizeIMCC(lpIMC->hCompStr, dwSize)) {
  121. lpIMC->hCompStr = hMem;
  122. } else {
  123. ImmDestroyIMCC(lpIMC->hCompStr);
  124. lpIMC->hCompStr = ImmCreateIMCC(dwSize);
  125. return (FALSE);
  126. }
  127. if (!lpIMC->hCompStr) {
  128. return (FALSE);
  129. }
  130. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  131. if (!lpCompStr) {
  132. ImmDestroyIMCC(lpIMC->hCompStr);
  133. lpIMC->hCompStr = ImmCreateIMCC(dwSize);
  134. return (FALSE);
  135. }
  136. lpCompStr->dwSize = dwSize;
  137. // 1. composition (reading) string - simple IME
  138. // 2. result reading string
  139. // 3. result string
  140. lpCompStr->dwCompReadAttrLen = 0;
  141. lpCompStr->dwCompReadAttrOffset = sizeof(COMPOSITIONSTRING);
  142. lpbAttr = (LPBYTE)lpCompStr + lpCompStr->dwCompReadAttrOffset;
  143. for (i = 0; i < NMAXKEY * sizeof(WCHAR) / sizeof(TCHAR); i++) {
  144. // for simple IMEs, we have no way to reconvert it
  145. *lpbAttr++ = ATTR_TARGET_CONVERTED;
  146. }
  147. *(LPDWORD)lpbAttr = 0;
  148. lpCompStr->dwCompReadClauseLen = 0;
  149. lpCompStr->dwCompReadClauseOffset = lpCompStr->dwCompReadAttrOffset +
  150. NMAXKEY * sizeof(WCHAR) / sizeof(TCHAR) + sizeof(DWORD);
  151. lpdwClause = (LPDWORD)((LPBYTE)lpCompStr +
  152. lpCompStr->dwCompReadClauseOffset);
  153. // clause start from 0
  154. *lpdwClause++ = 0;
  155. // clause length is 0
  156. *lpdwClause = 0;
  157. lpCompStr->dwCompReadStrLen = 0;
  158. lpCompStr->dwCompReadStrOffset = lpCompStr->dwCompReadClauseOffset +
  159. sizeof(DWORD) + sizeof(DWORD);
  160. // clean up the composition reading string
  161. lpwStr = (LPWSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompReadStrOffset);
  162. for (i = 0; i < NMAXKEY; i++) {
  163. *lpwStr++ = 0;
  164. }
  165. *(LPDWORD)((LPBYTE)lpCompStr + lpCompStr->dwCompReadStrOffset +
  166. NMAXKEY * sizeof(WCHAR)) = 0;
  167. // composition string is the same with composition reading string
  168. // for simple IMEs
  169. lpCompStr->dwCompAttrLen = 0;
  170. lpCompStr->dwCompAttrOffset = lpCompStr->dwCompReadAttrOffset;
  171. lpCompStr->dwCompClauseLen = 0;
  172. lpCompStr->dwCompClauseOffset = lpCompStr->dwCompReadClauseOffset;
  173. lpCompStr->dwCompStrLen = 0;
  174. lpCompStr->dwCompStrOffset = lpCompStr->dwCompReadStrOffset;
  175. lpCompStr->dwCursorPos = 0;
  176. lpCompStr->dwDeltaStart = 0;
  177. lpCompStr->dwResultReadClauseLen = 0;
  178. lpCompStr->dwResultReadClauseOffset = lpCompStr->dwCompStrOffset +
  179. NMAXKEY * sizeof(WCHAR) + sizeof(DWORD);
  180. lpdwClause = (LPDWORD)((LPBYTE)lpCompStr +
  181. lpCompStr->dwResultReadClauseOffset);
  182. // clause start from 0
  183. *lpdwClause++ = 0;
  184. // clause length is 0
  185. *lpdwClause = 0;
  186. lpCompStr->dwResultReadStrLen = 0;
  187. lpCompStr->dwResultReadStrOffset = lpCompStr->dwResultReadClauseOffset +
  188. sizeof(DWORD) + sizeof(DWORD);
  189. // clean up the result reading string
  190. lpwStr = (LPWSTR)((LPBYTE)lpCompStr + lpCompStr->dwResultReadStrOffset);
  191. for (i = 0; i < NMAXKEY; i++) {
  192. *lpwStr++ = 0;
  193. }
  194. *(LPDWORD)((LPBYTE)lpCompStr + lpCompStr->dwResultReadStrOffset +
  195. NMAXKEY * sizeof(WCHAR)) = 0;
  196. lpCompStr->dwResultClauseLen = 0;
  197. lpCompStr->dwResultClauseOffset = lpCompStr->dwResultReadStrOffset +
  198. NMAXKEY * sizeof(WCHAR) + sizeof(DWORD);
  199. lpdwClause = (LPDWORD)((LPBYTE)lpCompStr +
  200. lpCompStr->dwResultClauseOffset);
  201. // clause start from 0
  202. *lpdwClause++ = 0;
  203. // clause length is 0
  204. *lpdwClause = 0;
  205. lpCompStr->dwResultStrOffset = 0;
  206. lpCompStr->dwResultStrOffset = lpCompStr->dwResultClauseOffset +
  207. sizeof(DWORD) + sizeof(DWORD);
  208. // clean up the result string
  209. lpwStr = (LPWSTR)((LPBYTE)lpCompStr + lpCompStr->dwResultStrOffset);
  210. for (i = 0; i < NMAXKEY; i++) {
  211. *lpwStr++ = 0;
  212. }
  213. *(LPDWORD)((LPBYTE)lpCompStr + lpCompStr->dwResultStrOffset +
  214. NMAXKEY * sizeof(WCHAR)) = 0;
  215. ImmUnlockIMCC(lpIMC->hCompStr);
  216. return (TRUE);
  217. }
  218. /**********************************************************************/
  219. /* ClearCand() */
  220. /* Return Value: */
  221. /* TRUE - successful, FALSE - failure */
  222. /**********************************************************************/
  223. BOOL PASCAL ClearCand(
  224. LPINPUTCONTEXT lpIMC)
  225. {
  226. HIMCC hMem;
  227. LPCANDIDATEINFO lpCandInfo;
  228. LPCANDIDATELIST lpCandList;
  229. DWORD dwSize =
  230. // header length
  231. sizeof(CANDIDATEINFO) + sizeof(CANDIDATELIST) +
  232. // candidate string pointers
  233. sizeof(DWORD) * (MAXCAND) +
  234. // string plus NULL terminator
  235. (sizeof(WCHAR) + sizeof(TCHAR)) * MAXCAND;
  236. if (!lpIMC) {
  237. return (FALSE);
  238. }
  239. if (!lpIMC->hCandInfo) {
  240. // it maybe free by other IME, init it
  241. lpIMC->hCandInfo = ImmCreateIMCC(dwSize);
  242. } else if (hMem = ImmReSizeIMCC(lpIMC->hCandInfo, dwSize)) {
  243. lpIMC->hCandInfo = hMem;
  244. } else {
  245. ImmDestroyIMCC(lpIMC->hCandInfo);
  246. lpIMC->hCandInfo = ImmCreateIMCC(dwSize);
  247. return (FALSE);
  248. }
  249. if (!lpIMC->hCandInfo) {
  250. return (FALSE);
  251. }
  252. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  253. if (!lpCandInfo) {
  254. ImmDestroyIMCC(lpIMC->hCandInfo);
  255. lpIMC->hCandInfo = ImmCreateIMCC(dwSize);
  256. return (FALSE);
  257. }
  258. // ordering of strings are
  259. // buffer size
  260. lpCandInfo->dwSize = dwSize;
  261. lpCandInfo->dwCount = 0;
  262. lpCandInfo->dwOffset[0] = sizeof(CANDIDATEINFO);
  263. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  264. lpCandInfo->dwOffset[0]);
  265. // whole candidate info size - header
  266. lpCandList->dwSize = lpCandInfo->dwSize - sizeof(CANDIDATEINFO);
  267. lpCandList->dwStyle = IME_CAND_READ;
  268. lpCandList->dwCount = 0;
  269. lpCandList->dwPageStart = lpCandList->dwSelection = 0;
  270. lpCandList->dwPageSize = CANDPERPAGE;
  271. lpCandList->dwOffset[0] = sizeof(CANDIDATELIST) +
  272. sizeof(DWORD) * (MAXCAND - 1);
  273. ImmUnlockIMCC(lpIMC->hCandInfo);
  274. return (TRUE);
  275. }
  276. /**********************************************************************/
  277. /* InitContext() */
  278. /**********************************************************************/
  279. void PASCAL InitContext(
  280. LPINPUTCONTEXT lpIMC,
  281. LPPRIVCONTEXT lpImcP)
  282. {
  283. if (lpIMC->fdwInit & INIT_STATUSWNDPOS) {
  284. } else if (!lpIMC->hWnd) {
  285. } else if (lpImcP->fdwInit & INIT_STATUSWNDPOS) {
  286. } else {
  287. POINT ptWnd;
  288. ptWnd.x = 0;
  289. ptWnd.y = 0;
  290. ClientToScreen(lpIMC->hWnd, &ptWnd);
  291. if (ptWnd.x > sImeG.rcWorkArea.right / 3) {
  292. ptWnd.x = sImeG.rcWorkArea.right / 3;
  293. }
  294. if (ptWnd.x < sImeG.rcWorkArea.left) {
  295. lpIMC->ptStatusWndPos.x = sImeG.rcWorkArea.left;
  296. } else if (ptWnd.x + lpImeL->xStatusWi > sImeG.rcWorkArea.right) {
  297. lpIMC->ptStatusWndPos.x = sImeG.rcWorkArea.right -
  298. lpImeL->xStatusWi;
  299. } else {
  300. lpIMC->ptStatusWndPos.x = ptWnd.x;
  301. }
  302. lpIMC->ptStatusWndPos.y = sImeG.rcWorkArea.bottom -
  303. lpImeL->yStatusHi - 2 * UI_MARGIN;
  304. lpImcP->fdwInit |= INIT_STATUSWNDPOS;
  305. }
  306. if (!(lpIMC->fdwInit & INIT_COMPFORM)) {
  307. lpIMC->cfCompForm.dwStyle = CFS_DEFAULT;
  308. }
  309. if (lpIMC->cfCompForm.dwStyle != CFS_DEFAULT) {
  310. } else if (!lpIMC->hWnd) {
  311. } else if (lpImcP->fdwInit & INIT_COMPFORM) {
  312. } else {
  313. lpIMC->cfCompForm.ptCurrentPos.x = lpIMC->ptStatusWndPos.x +
  314. lpImeL->xStatusWi + UI_MARGIN;
  315. if (lpIMC->cfCompForm.ptCurrentPos.x + lpImeL->xCompWi >
  316. sImeG.rcWorkArea.right) {
  317. lpIMC->cfCompForm.ptCurrentPos.x = lpIMC->ptStatusWndPos.x -
  318. lpImeL->xCompWi - lpImeL->cxCompBorder * 2 -
  319. UI_MARGIN;
  320. }
  321. lpIMC->cfCompForm.ptCurrentPos.y = sImeG.rcWorkArea.bottom -
  322. lpImeL->yCompHi - 2 * UI_MARGIN;
  323. ScreenToClient(lpIMC->hWnd, &lpIMC->cfCompForm.ptCurrentPos);
  324. lpImcP->fdwInit |= INIT_COMPFORM;
  325. }
  326. return;
  327. }
  328. /**********************************************************************/
  329. /* Select() */
  330. /* Return Value: */
  331. /* TRUE - successful, FALSE - failure */
  332. /**********************************************************************/
  333. BOOL PASCAL Select(
  334. LPINPUTCONTEXT lpIMC,
  335. BOOL fSelect)
  336. {
  337. LPPRIVCONTEXT lpImcP;
  338. if (fSelect) { // init "every" fields of hPrivate, please!!!
  339. if (!ClearCompStr(
  340. lpIMC)) {
  341. return (FALSE);
  342. }
  343. if (!ClearCand(lpIMC)) {
  344. return (FALSE);
  345. }
  346. }
  347. if (lpIMC->cfCandForm[0].dwIndex != 0) {
  348. lpIMC->cfCandForm[0].dwStyle = CFS_DEFAULT;
  349. }
  350. if (!lpIMC->hPrivate) {
  351. return (FALSE);
  352. }
  353. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  354. if (!lpImcP) {
  355. return (FALSE);
  356. }
  357. if (fSelect) { // init "every" fields of hPrivate, please!!!
  358. lpImcP->iImeState = CST_INIT; // init the IME state machine
  359. lpImcP->fdwImeMsg = 0; // no message be generated now
  360. lpImcP->dwCompChar = 0;
  361. lpImcP->fdwGcsFlag = 0;
  362. lpImcP->fdwInit = 0;
  363. *(LPDWORD)lpImcP->bSeq = 0;
  364. lpIMC->fOpen = TRUE;
  365. if (!(lpIMC->fdwInit & INIT_CONVERSION)) {
  366. lpIMC->fdwConversion = (lpIMC->fdwConversion & IME_CMODE_SOFTKBD) |
  367. IME_CMODE_NATIVE;
  368. lpIMC->fdwInit |= INIT_CONVERSION;
  369. }
  370. if (lpIMC->fdwInit & INIT_SENTENCE) {
  371. } else if (lpImeL->fdwModeConfig & MODE_CONFIG_PREDICT) {
  372. *(LPWORD)&lpIMC->fdwSentence |= IME_SMODE_PHRASEPREDICT;
  373. } else {
  374. }
  375. if (!(lpIMC->fdwInit & INIT_LOGFONT)) {
  376. HDC hDC;
  377. HGDIOBJ hSysFont;
  378. hDC = GetDC(NULL);
  379. hSysFont = GetCurrentObject(hDC, OBJ_FONT);
  380. GetObject(hSysFont, sizeof(LOGFONT), &lpIMC->lfFont.A);
  381. ReleaseDC(NULL, hDC);
  382. lpIMC->fdwInit |= INIT_LOGFONT;
  383. }
  384. // if this IME is run under Chicago Simplified Chinese version
  385. lpIMC->lfFont.A.lfCharSet = NATIVE_CHARSET;
  386. InitContext(
  387. lpIMC, lpImcP);
  388. }
  389. ImmUnlockIMCC(lpIMC->hPrivate);
  390. return (TRUE);
  391. }
  392. /**********************************************************************/
  393. /* ImeSelect() / UniImeSelect() */
  394. /* Return Value: */
  395. /* TRUE - successful, FALSE - failure */
  396. /**********************************************************************/
  397. BOOL WINAPI ImeSelect(
  398. HIMC hIMC,
  399. BOOL fSelect)
  400. {
  401. LPINPUTCONTEXT lpIMC;
  402. BOOL fRet;
  403. if (!hIMC) {
  404. return (TRUE);
  405. }
  406. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  407. if (!lpIMC) {
  408. return (FALSE);
  409. }
  410. // to load/free IME table
  411. if (fSelect) {
  412. if (!lpInstL->cRefCount++) {
  413. LoadTable(lpInstL, lpImeL);
  414. }
  415. } else {
  416. if (!--lpInstL->cRefCount) {
  417. FreeTable(lpInstL);
  418. }
  419. }
  420. fRet = Select(
  421. lpIMC, fSelect);
  422. ImmUnlockIMC(hIMC);
  423. return (fRet);
  424. }
  425. /**********************************************************************/
  426. /* ImeSetActiveContext() / UniImeSetActiveContext() */
  427. /* Return Value: */
  428. /* TRUE - successful, FALSE - failure */
  429. /**********************************************************************/
  430. BOOL WINAPI ImeSetActiveContext(
  431. HIMC hIMC,
  432. BOOL fOn)
  433. {
  434. if (!fOn) {
  435. } else if (!hIMC) {
  436. } else {
  437. LPINPUTCONTEXT lpIMC;
  438. LPPRIVCONTEXT lpImcP;
  439. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  440. if (!lpIMC) {
  441. goto SetActSyncDic;
  442. }
  443. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  444. if (!lpImcP) {
  445. goto SetActUnlockIMC;
  446. }
  447. InitContext(
  448. lpIMC, lpImcP);
  449. ImmUnlockIMCC(lpIMC->hPrivate);
  450. SetActUnlockIMC:
  451. ImmUnlockIMC(hIMC);
  452. SetActSyncDic:
  453. ; // NULL statement for goto
  454. }
  455. return (TRUE);
  456. }
  457. /**********************************************************************/
  458. /* LoadTable() */
  459. /* Return Value: */
  460. /* TRUE - successful, FALSE - failure */
  461. /**********************************************************************/
  462. BOOL PASCAL LoadTable( // check the table files of IME, include user
  463. // defined dictionary
  464. LPINSTDATAL lpInstL,
  465. LPIMEL lpImeL)
  466. {
  467. if (lpInstL->fdwTblLoad == TBL_LOADED) {
  468. return (TRUE);
  469. }
  470. lpInstL->fdwTblLoad = TBL_LOADED;
  471. return (TRUE);
  472. }
  473. /**********************************************************************/
  474. /* FreeTable() */
  475. /**********************************************************************/
  476. void PASCAL FreeTable(
  477. LPINSTDATAL lpInstL)
  478. {
  479. lpInstL->fdwTblLoad = TBL_NOTLOADED;
  480. return;
  481. }