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.

482 lines
13 KiB

  1. /*************************************************
  2. * ui.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. /* CreateUIWindow() */
  13. /**********************************************************************/
  14. void PASCAL CreateUIWindow( // create composition window
  15. HWND hUIWnd)
  16. {
  17. HGLOBAL hUIPrivate;
  18. LPUIPRIV lpUIPrivate;
  19. // create storage for UI setting
  20. hUIPrivate = GlobalAlloc(GHND, sizeof(UIPRIV));
  21. if (!hUIPrivate) { // Oh! Oh!
  22. return;
  23. }
  24. SetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE, (LONG_PTR)hUIPrivate);
  25. // set the default position for UI window, it is hide now
  26. SetWindowPos(hUIWnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER);
  27. ShowWindow(hUIWnd, SW_SHOWNOACTIVATE);
  28. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  29. if (!lpUIPrivate) { // can not draw candidate window
  30. return;
  31. }
  32. GlobalUnlock(hUIPrivate);
  33. return;
  34. }
  35. /**********************************************************************/
  36. /* DestroyUIWindow() */
  37. /**********************************************************************/
  38. void PASCAL DestroyUIWindow( // destroy composition window
  39. HWND hUIWnd)
  40. {
  41. HGLOBAL hUIPrivate;
  42. LPUIPRIV lpUIPrivate;
  43. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  44. if (!hUIPrivate) { // Oh! Oh!
  45. return;
  46. }
  47. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  48. if (!lpUIPrivate) { // Oh! Oh!
  49. return;
  50. }
  51. // composition window need to be destroyed
  52. if (lpUIPrivate->hCompWnd) {
  53. DestroyWindow(lpUIPrivate->hCompWnd);
  54. }
  55. GlobalUnlock(hUIPrivate);
  56. // free storage for UI settings
  57. GlobalFree(hUIPrivate);
  58. return;
  59. }
  60. /**********************************************************************/
  61. /* ShowUI() */
  62. /**********************************************************************/
  63. void PASCAL ShowUI( // show the sub windows
  64. HWND hUIWnd,
  65. int nShowCmd)
  66. {
  67. HIMC hIMC;
  68. LPINPUTCONTEXT lpIMC;
  69. LPPRIVCONTEXT lpImcP;
  70. HGLOBAL hUIPrivate;
  71. LPUIPRIV lpUIPrivate;
  72. if (nShowCmd == SW_HIDE) {
  73. } else if (!(hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC))) {
  74. nShowCmd = SW_HIDE;
  75. } else if (!(lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC))) {
  76. nShowCmd = SW_HIDE;
  77. } else if (!(lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate))) {
  78. ImmUnlockIMC(hIMC);
  79. nShowCmd = SW_HIDE;
  80. } else {
  81. }
  82. if (nShowCmd == SW_HIDE) {
  83. ShowComp(hUIWnd, nShowCmd);
  84. return;
  85. }
  86. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  87. if (!hUIPrivate) { // can not darw status window
  88. goto ShowUIUnlockIMCC;
  89. }
  90. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  91. if (!lpUIPrivate) { // can not draw status window
  92. goto ShowUIUnlockIMCC;
  93. }
  94. if ((lpUIPrivate->fdwSetContext & ISC_SHOWUICOMPOSITIONWINDOW)
  95. #if 0
  96. && (lpImcP->fdwImeMsg & MSG_ALREADY_START)
  97. #endif
  98. ) {
  99. if (lpUIPrivate->hCompWnd) {
  100. if ((UINT)GetWindowLong(lpUIPrivate->hCompWnd, UI_MOVE_XY) !=
  101. lpImeL->nRevMaxKey) {
  102. ChangeCompositionSize(hUIWnd);
  103. }
  104. if (lpUIPrivate->nShowCompCmd != SW_HIDE) {
  105. // some time the WM_ERASEBKGND is eaten by the app
  106. RedrawWindow(lpUIPrivate->hCompWnd, NULL, NULL,
  107. RDW_FRAME|RDW_INVALIDATE|RDW_ERASE);
  108. }
  109. SendMessage(lpUIPrivate->hCompWnd, WM_IME_NOTIFY,
  110. IMN_SETCOMPOSITIONWINDOW, 0);
  111. if (lpUIPrivate->nShowCompCmd == SW_HIDE) {
  112. ShowComp(hUIWnd, nShowCmd);
  113. }
  114. } else {
  115. CreateCompWindow(hUIWnd);
  116. }
  117. } else if (lpUIPrivate->nShowCompCmd == SW_HIDE) {
  118. } else if (lpUIPrivate->fdwSetContext & ISC_OPEN_STATUS_WINDOW) {
  119. // delay the hide with status window
  120. lpUIPrivate->fdwSetContext |= ISC_HIDE_COMP_WINDOW;
  121. } else {
  122. ShowComp(hUIWnd, SW_HIDE);
  123. }
  124. if (lpIMC->fdwInit & INIT_SENTENCE) {
  125. // app set the sentence mode so we should not change it
  126. // with the configure option set by end user
  127. } else if (lpImeL->fdwModeConfig & MODE_CONFIG_PREDICT) {
  128. if (!(lpIMC->fdwSentence & IME_SMODE_PHRASEPREDICT)) {
  129. DWORD fdwSentence;
  130. fdwSentence = lpIMC->fdwSentence;
  131. *(LPWORD)&fdwSentence |= IME_SMODE_PHRASEPREDICT;
  132. ImmSetConversionStatus(hIMC, lpIMC->fdwConversion, fdwSentence);
  133. }
  134. } else {
  135. if (lpIMC->fdwSentence & IME_SMODE_PHRASEPREDICT) {
  136. DWORD fdwSentence;
  137. fdwSentence = lpIMC->fdwSentence;
  138. *(LPWORD)&fdwSentence &= ~(IME_SMODE_PHRASEPREDICT);
  139. ImmSetConversionStatus(hIMC, lpIMC->fdwConversion, fdwSentence);
  140. }
  141. }
  142. // we switch to this hIMC
  143. lpUIPrivate->hCacheIMC = hIMC;
  144. GlobalUnlock(hUIPrivate);
  145. ShowUIUnlockIMCC:
  146. ImmUnlockIMCC(lpIMC->hPrivate);
  147. ImmUnlockIMC(hIMC);
  148. return;
  149. }
  150. /**********************************************************************/
  151. /* NotifyUI() */
  152. /**********************************************************************/
  153. void PASCAL NotifyUI(
  154. HWND hUIWnd,
  155. WPARAM wParam,
  156. LPARAM lParam)
  157. {
  158. HWND hStatusWnd;
  159. switch (wParam) {
  160. case IMN_SETSENTENCEMODE:
  161. break;
  162. case IMN_SETCOMPOSITIONFONT:
  163. // we are not going to change font, but an IME can do this if it want
  164. break;
  165. case IMN_SETCOMPOSITIONWINDOW:
  166. // if (!(lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI))
  167. {
  168. HWND hCompWnd;
  169. hCompWnd = GetCompWnd(hUIWnd);
  170. if (!hCompWnd) {
  171. return;
  172. }
  173. PostMessage(hCompWnd, WM_IME_NOTIFY, wParam, lParam);
  174. }
  175. break;
  176. case IMN_PRIVATE:
  177. switch (lParam) {
  178. case IMN_PRIVATE_COMPOSITION_SIZE:
  179. ChangeCompositionSize(
  180. hUIWnd);
  181. break;
  182. default:
  183. break;
  184. }
  185. break;
  186. default:
  187. break;
  188. }
  189. return;
  190. }
  191. /**********************************************************************/
  192. /* UIChange() */
  193. /**********************************************************************/
  194. LRESULT PASCAL UIChange(
  195. HWND hUIWnd)
  196. {
  197. HGLOBAL hUIPrivate;
  198. LPUIPRIV lpUIPrivate;
  199. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  200. if (!hUIPrivate) {
  201. return (0L);
  202. }
  203. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  204. if (!lpUIPrivate) {
  205. return (0L);
  206. }
  207. if (lpUIPrivate->fdwSetContext & ISC_SHOW_UI_ALL) {
  208. ShowUI(hUIWnd, SW_SHOWNOACTIVATE);
  209. } else {
  210. ShowUI(hUIWnd, SW_HIDE);
  211. }
  212. GlobalUnlock(hUIPrivate);
  213. return (0L);
  214. }
  215. /**********************************************************************/
  216. /* SetContext() */
  217. /**********************************************************************/
  218. void PASCAL SetContext( // the context activated/deactivated
  219. HWND hUIWnd,
  220. BOOL fOn,
  221. LPARAM lShowUI)
  222. {
  223. HGLOBAL hUIPrivate;
  224. register LPUIPRIV lpUIPrivate;
  225. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  226. if (!hUIPrivate) {
  227. return;
  228. }
  229. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  230. if (!lpUIPrivate) {
  231. return;
  232. }
  233. if (fOn) {
  234. HIMC hIMC;
  235. LPINPUTCONTEXT lpIMC;
  236. register DWORD fdwSetContext;
  237. lpUIPrivate->fdwSetContext = lpUIPrivate->fdwSetContext &
  238. ~(ISC_SHOWUIALL|ISC_HIDE_SOFTKBD);
  239. lpUIPrivate->fdwSetContext |= (lShowUI & ISC_SHOWUIALL) |
  240. ISC_SHOW_SOFTKBD;
  241. fdwSetContext = lpUIPrivate->fdwSetContext &
  242. (ISC_SHOWUICOMPOSITIONWINDOW|ISC_HIDE_COMP_WINDOW);
  243. if (fdwSetContext == ISC_HIDE_COMP_WINDOW) {
  244. ShowComp(
  245. hUIWnd, SW_HIDE);
  246. } else if (fdwSetContext & ISC_HIDE_COMP_WINDOW) {
  247. lpUIPrivate->fdwSetContext &= ~(ISC_HIDE_COMP_WINDOW);
  248. } else {
  249. }
  250. fdwSetContext = lpUIPrivate->fdwSetContext &
  251. (ISC_SHOWUICANDIDATEWINDOW|ISC_HIDE_CAND_WINDOW);
  252. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  253. if (!hIMC) {
  254. goto SetCxtUnlockUIPriv;
  255. }
  256. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  257. if (!lpIMC) {
  258. goto SetCxtUnlockUIPriv;
  259. }
  260. if (lpIMC->cfCandForm[0].dwIndex != 0) {
  261. lpIMC->cfCandForm[0].dwStyle = CFS_DEFAULT;
  262. }
  263. ImmUnlockIMC(hIMC);
  264. } else {
  265. lpUIPrivate->fdwSetContext &= ~ISC_SETCONTEXT_UI;
  266. }
  267. SetCxtUnlockUIPriv:
  268. GlobalUnlock(hUIPrivate);
  269. UIChange(
  270. hUIWnd);
  271. return;
  272. }
  273. /**********************************************************************/
  274. /* GetCompWindow() */
  275. /**********************************************************************/
  276. LRESULT PASCAL GetCompWindow(
  277. HWND hUIWnd,
  278. LPCOMPOSITIONFORM lpCompForm)
  279. {
  280. HWND hCompWnd;
  281. RECT rcCompWnd;
  282. HIMC hIMC;
  283. LPINPUTCONTEXT lpIMC;
  284. hCompWnd = GetCompWnd(hUIWnd);
  285. if (!hCompWnd) {
  286. return (1L);
  287. }
  288. if (!GetWindowRect(hCompWnd, &rcCompWnd)) {
  289. return (1L);
  290. }
  291. lpCompForm->dwStyle = CFS_RECT;
  292. lpCompForm->ptCurrentPos = *(LPPOINT)&rcCompWnd;
  293. lpCompForm->rcArea = rcCompWnd;
  294. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  295. if (!hIMC) {
  296. return (1L);
  297. }
  298. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  299. if (!lpIMC) {
  300. return (1L);
  301. }
  302. ScreenToClient(lpIMC->hWnd, &lpCompForm->ptCurrentPos);
  303. lpCompForm->rcArea.right += lpCompForm->ptCurrentPos.x -
  304. lpCompForm->rcArea.left;
  305. lpCompForm->rcArea.bottom += lpCompForm->ptCurrentPos.y -
  306. lpCompForm->rcArea.top;
  307. *(LPPOINT)&lpCompForm->rcArea = lpCompForm->ptCurrentPos;
  308. ImmUnlockIMC(hIMC);
  309. return (0L);
  310. }
  311. /**********************************************************************/
  312. /* UIWndProc() / UniUIWndProc() */
  313. /**********************************************************************/
  314. LRESULT CALLBACK UIWndProc(
  315. HWND hUIWnd,
  316. UINT uMsg,
  317. WPARAM wParam,
  318. LPARAM lParam)
  319. {
  320. switch (uMsg) {
  321. case WM_CREATE:
  322. CreateUIWindow(hUIWnd);
  323. break;
  324. case WM_DESTROY:
  325. DestroyUIWindow(hUIWnd);
  326. break;
  327. case WM_IME_STARTCOMPOSITION:
  328. //
  329. // Create a window as the composition window.
  330. //
  331. CreateCompWindow(hUIWnd);
  332. break;
  333. case WM_IME_COMPOSITION:
  334. {
  335. HWND hCompWnd;
  336. if (lParam & GCS_RESULTSTR)
  337. {
  338. MoveDefaultCompPosition(hUIWnd);
  339. }
  340. hCompWnd = GetCompWnd(hUIWnd);
  341. if (hCompWnd)
  342. {
  343. RECT rcRect;
  344. rcRect = lpImeL->rcCompText;
  345. // off by 1
  346. rcRect.right += 1;
  347. rcRect.bottom += 1;
  348. RedrawWindow(hCompWnd, &rcRect, NULL, RDW_INVALIDATE);
  349. }
  350. break;
  351. }
  352. case WM_IME_ENDCOMPOSITION:
  353. //
  354. // We can destroy the composition window here. But we don't have a
  355. // status window. So we keep the composition window displayed
  356. // to show our presence.
  357. //
  358. return (0L);
  359. case WM_IME_NOTIFY:
  360. NotifyUI(hUIWnd, wParam, lParam);
  361. break;
  362. case WM_IME_SETCONTEXT:
  363. SetContext(hUIWnd, (BOOL)wParam, lParam);
  364. break;
  365. case WM_IME_CONTROL:
  366. switch (wParam) {
  367. case IMC_GETCOMPOSITIONWINDOW:
  368. return GetCompWindow(hUIWnd, (LPCOMPOSITIONFORM)lParam);
  369. }
  370. case WM_IME_COMPOSITIONFULL:
  371. return (0L);
  372. case WM_IME_SELECT:
  373. //
  374. // try to use SetContext
  375. // SelectIME(hUIWnd, (BOOL)wParam);
  376. //
  377. SetContext( hUIWnd, (BOOL)wParam, 0);
  378. //
  379. // We want a comp window immediately after IME starts.
  380. //
  381. CreateCompWindow(hUIWnd);
  382. return (0L);
  383. case WM_MOUSEACTIVATE:
  384. return (MA_NOACTIVATE);
  385. case WM_USER_UICHANGE:
  386. return UIChange(
  387. hUIWnd);
  388. default:
  389. return DefWindowProc(hUIWnd, uMsg, wParam, lParam);
  390. }
  391. return (0L);
  392. }