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.

366 lines
12 KiB

  1. /****************************************************************************
  2. COMPUI.CPP
  3. Owner: cslim
  4. Copyright (c) 1997-1999 Microsoft Corporation
  5. Composition window UI functions
  6. History:
  7. 14-JUL-1999 cslim Copied from IME98 source tree
  8. *****************************************************************************/
  9. #include "precomp.h"
  10. #include "ui.h"
  11. #include "imedefs.h"
  12. #include "names.h"
  13. #include "escape.h"
  14. #include "winex.h"
  15. #include "cicero.h"
  16. #include "debug.h"
  17. #include "resource.h"
  18. PRIVATE VOID PASCAL PaintCompWindow(HWND hCompWnd, HDC hDC);
  19. ///////////////////////////////////////////////////////////////////////////////
  20. LRESULT CALLBACK CompWndProc(HWND hCompWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
  21. {
  22. Dbg(DBGID_UI, TEXT("CompWndProc():uMessage = 0x%08lX, wParam = 0x%04X, lParam = 0x%08lX"), uMessage, wParam, lParam);
  23. switch (uMessage)
  24. {
  25. case WM_IME_CHAR:
  26. case WM_IME_COMPOSITIONFULL:
  27. case WM_IME_COMPOSITION:
  28. case WM_IME_CONTROL:
  29. case WM_IME_SELECT:
  30. case WM_IME_SETCONTEXT:
  31. case WM_IME_STARTCOMPOSITION:
  32. case WM_IME_ENDCOMPOSITION:
  33. return (0L);
  34. case WM_PAINT:
  35. {
  36. HDC hDC;
  37. PAINTSTRUCT ps;
  38. hDC = BeginPaint(hCompWnd, &ps);
  39. PaintCompWindow(hCompWnd, hDC);
  40. EndPaint(hCompWnd, &ps);
  41. }
  42. break;
  43. default :
  44. return DefWindowProc(hCompWnd, uMessage, wParam, lParam);
  45. }
  46. return (0L);
  47. }
  48. VOID PASCAL PaintCompWindow(HWND hCompWnd, HDC hDC)
  49. {
  50. HWND hWndUI;
  51. HIMC hIMC;
  52. PCIMECtx pImeCtx;
  53. HFONT hFontFix, hOldFont;
  54. HBITMAP hBMComp;
  55. INT iSaveBkMode;
  56. hWndUI = GetWindow(hCompWnd, GW_OWNER);
  57. hIMC = GethImcFromHwnd(hWndUI);
  58. if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
  59. return;
  60. Dbg(DBGID_UI, TEXT("PaintCompWindow():CompCh = 0x%X"), pImeCtx->GetCompBufStr());
  61. if (pImeCtx->GetCompBufLen())
  62. {
  63. // Create font
  64. if (IsWinNT())
  65. hFontFix = CreateFontW(
  66. -16,0,0,0,
  67. 0,0,0,0,
  68. HANGUL_CHARSET,
  69. OUT_DEFAULT_PRECIS,
  70. CLIP_DEFAULT_PRECIS,
  71. DEFAULT_QUALITY,
  72. FIXED_PITCH,
  73. wzIMECompFont);
  74. else
  75. hFontFix = CreateFontA(
  76. -16,0,0,0,
  77. 0,0,0,0,
  78. HANGUL_CHARSET,
  79. OUT_DEFAULT_PRECIS,
  80. CLIP_DEFAULT_PRECIS,
  81. DEFAULT_QUALITY,
  82. FIXED_PITCH,
  83. szIMECompFont);
  84. hOldFont = (HFONT)SelectObject(hDC, hFontFix);
  85. // Draw comp window Bitmap
  86. hBMComp = (HBITMAP)OurLoadImage(MAKEINTRESOURCE(IDB_COMP_WIN), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE|LR_LOADMAP3DCOLORS );
  87. DrawBitmap(hDC, 0, 0, hBMComp);
  88. iSaveBkMode = SetBkMode(hDC, TRANSPARENT);
  89. // Set text color
  90. SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  91. OurTextOutW(hDC, 3, 3, pImeCtx->GetCompBufStr());
  92. // restore and delete created objects
  93. SelectObject(hDC, hOldFont);
  94. SetBkMode(hDC, iSaveBkMode);
  95. DeleteObject(hBMComp);
  96. DeleteObject(hFontFix);
  97. }
  98. }
  99. // open comp window
  100. VOID PASCAL OpenComp(HWND hUIWnd)
  101. {
  102. HGLOBAL hUIPrivate;
  103. LPUIPRIV lpUIPrivate;
  104. HIMC hIMC;
  105. PCIMECtx pImeCtx;
  106. INT nShowCompCmd;
  107. POINT ptClientComp;
  108. CIMEData ImeData;
  109. Dbg(DBGID_UI, TEXT("OpenComp()"));
  110. hUIPrivate = GethUIPrivateFromHwnd(hUIWnd);
  111. // can not draw comp window
  112. if (!hUIPrivate)
  113. {
  114. DbgAssert(0);
  115. return;
  116. }
  117. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  118. if (!lpUIPrivate)
  119. return;
  120. // Check WM_IME_SETCONTEXT lParam
  121. if ((lpUIPrivate->uiShowParam & ISC_SHOWUICOMPOSITIONWINDOW) == 0)
  122. goto OpenCompUnlockUIPriv;
  123. hIMC = GethImcFromHwnd(hUIWnd);
  124. pImeCtx = GetIMECtx(hIMC);
  125. if (pImeCtx == NULL)
  126. {
  127. Dbg(DBGID_UI, TEXT("OpenComp - Invalid hImc"));
  128. ImeData->ptCompPos.x = ImeData->rcWorkArea.right - COMP_SIZEX;
  129. ImeData->ptCompPos.y = ImeData->rcWorkArea.bottom - COMP_SIZEY;
  130. nShowCompCmd = SW_HIDE;
  131. }
  132. else
  133. {
  134. #if 1 // MultiMonitor
  135. RECT rcWorkArea;
  136. ImeMonitorWorkAreaFromWindow(pImeCtx->GetAppWnd(), &rcWorkArea);
  137. // if client window exist in same monitor as status window
  138. if (!IsCicero() && PtInRect(&rcWorkArea, ImeData->ptStatusPos))
  139. {
  140. ImeData->ptCompPos.x =
  141. (ImeData->ptStatusPos.x+ImeData->xStatusWi+UI_GAPX + COMP_SIZEX > ImeData->rcWorkArea.right) ?
  142. ImeData->ptStatusPos.x - UI_GAPX - COMP_SIZEX : ImeData->ptStatusPos.x + ImeData->xStatusWi + UI_GAPX;
  143. ImeData->ptCompPos.y = ImeData->ptStatusPos.y;
  144. Dbg(DBGID_UI, TEXT("OpenComp - PtInRect x = %d, y = %d"), ImeData->ptCompPos.x, ImeData->ptCompPos.y);
  145. }
  146. else
  147. {
  148. // if client window appeared in different monitor from status window resides,
  149. // then display left top of workarea of client window montitor
  150. ImeData->ptCompPos.x = 0;
  151. ImeData->ptCompPos.y = 0;
  152. }
  153. #else
  154. ImeData->ptCompPos.x =
  155. (ImeData->ptStatusPos.x+ImeData->xStatusWi+UI_GAPX + COMP_SIZEX > ImeData->rcWorkArea.right) ?
  156. ImeData->ptStatusPos.x - UI_GAPX - COMP_SIZEX : ImeData->ptStatusPos.x + ImeData->xStatusWi + UI_GAPX;
  157. ImeData->ptCompPos.y = ImeData->ptStatusPos.y;
  158. #endif
  159. // Set Comp wnd position of HIMC in client coordinate
  160. ptClientComp = ImeData->ptCompPos;
  161. ScreenToClient(pImeCtx->GetAppWnd(), &ptClientComp);
  162. pImeCtx->SetCompositionFormPos(ptClientComp);
  163. nShowCompCmd = SW_SHOWNOACTIVATE;
  164. }
  165. if (lpUIPrivate->hCompWnd)
  166. {
  167. SetWindowPos(lpUIPrivate->hCompWnd, NULL,
  168. ImeData->ptCompPos.x, ImeData->ptCompPos.y,
  169. 0, 0,
  170. SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
  171. }
  172. else
  173. {
  174. Dbg(DBGID_UI, TEXT("OpenComp - CreateWindow x = %d, y = %d"), ImeData->ptCompPos.x, ImeData->ptCompPos.y);
  175. // create comp window
  176. lpUIPrivate->hCompWnd = CreateWindow(
  177. szCompClassName, TEXT("\0"),
  178. WS_DISABLED | WS_POPUP,
  179. ImeData->ptCompPos.x, ImeData->ptCompPos.y,
  180. COMP_SIZEX, COMP_SIZEX,
  181. hUIWnd, (HMENU)NULL, vpInstData->hInst, NULL);
  182. DbgAssert(lpUIPrivate->hCompWnd != 0);
  183. //if (!lpUIPrivate->hCompWnd)
  184. // goto OpenCompUnlockUIPriv;
  185. }
  186. //if (pImeCtx)
  187. // ShowComp(hUIWnd, SW_SHOWNOACTIVATE);
  188. OpenCompUnlockUIPriv:
  189. GlobalUnlock(hUIPrivate);
  190. return;
  191. }
  192. // Show the composition window
  193. VOID ShowComp(HWND hUIWnd, INT nShowCompCmd)
  194. {
  195. HGLOBAL hUIPrivate;
  196. LPUIPRIV lpUIPrivate;
  197. HIMC hIMC;
  198. PCIMECtx pImeCtx;
  199. Dbg(DBGID_UI, TEXT("ShowComp(): nShowCompCmd = %d"), nShowCompCmd);
  200. hUIPrivate = GethUIPrivateFromHwnd(hUIWnd);
  201. // can not draw comp window
  202. if (!hUIPrivate)
  203. {
  204. DbgAssert(0);
  205. return;
  206. }
  207. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  208. if (!lpUIPrivate)
  209. {
  210. DbgAssert(0);
  211. return;
  212. }
  213. hIMC = GethImcFromHwnd(hUIWnd);
  214. if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
  215. goto SwCompNoChange;
  216. // b#53794
  217. // Some absurd Apps send WM_IME_START_COMPOSITION and WM_IME_COMPOSITION,
  218. // even though they have no composition string
  219. // In this case wrong composition window appears in screen like white square or something.
  220. if (nShowCompCmd == SW_SHOWNOACTIVATE)
  221. {
  222. if (pImeCtx->GetCompBufLen() == 0 || vfWndOpen[COMP_WINDOW] == fFalse)
  223. nShowCompCmd = SW_HIDE;
  224. }
  225. if (lpUIPrivate->nShowCompCmd == nShowCompCmd)
  226. goto SwCompNoChange;
  227. if (lpUIPrivate->hCompWnd)
  228. {
  229. ShowWindow(lpUIPrivate->hCompWnd, nShowCompCmd);
  230. lpUIPrivate->nShowCompCmd = nShowCompCmd;
  231. }
  232. else
  233. lpUIPrivate->nShowCompCmd = SW_HIDE;
  234. SwCompNoChange:
  235. GlobalUnlock(hUIPrivate);
  236. }
  237. BOOL fSetCompWindowPos(HWND hCompWnd)
  238. {
  239. HIMC hIMC;
  240. PCIMECtx pImeCtx;
  241. RECT rcCur;
  242. POINT ptNew;
  243. CIMEData ImeData;
  244. // No composition window
  245. if (hCompWnd == 0)
  246. return fFalse;
  247. hIMC = GethImcFromHwnd(GetWindow(hCompWnd, GW_OWNER));
  248. //if (!hIMC)
  249. // {
  250. // DbgAssert(0);
  251. // return fFalse;
  252. // }
  253. //lpIMC = (LPINPUTCONTEXT)OurImmLockIMC(hIMC);
  254. //if (!lpIMC)
  255. // {
  256. // DbgAssert(0);
  257. // return fFalse;
  258. // }
  259. if ((pImeCtx = GetIMECtx(hIMC)) == NULL)
  260. return fFalse;
  261. Dbg(DBGID_UI, TEXT("fSetCompWindowPos()"));
  262. if (pImeCtx->GetCompositionFormStyle() & CFS_RECT)
  263. {
  264. Dbg(DBGID_UI, TEXT("fSetCompWindowPos(): CFS_RECT"));
  265. pImeCtx->GetCompositionForm(&rcCur);
  266. ptNew.x = rcCur.left;
  267. ptNew.y = rcCur.top;
  268. ClientToScreen(pImeCtx->GetAppWnd(), &ptNew);
  269. }
  270. else
  271. if (pImeCtx->GetCompositionFormStyle() & CFS_POINT)
  272. {
  273. Dbg(DBGID_UI, TEXT("fSetCompWindowPos(): CFS_POINT"));
  274. pImeCtx->GetCompositionForm(&ptNew);
  275. ClientToScreen(pImeCtx->GetAppWnd(), &ptNew);
  276. }
  277. else
  278. { // For CFS_DEFAULT
  279. Dbg(DBGID_UI, TEXT("fSetCompWindowPos(): CFS_DEFAULT"));
  280. #if 1 // MultiMonitor
  281. RECT rcWorkArea;
  282. ImeMonitorWorkAreaFromWindow(pImeCtx->GetAppWnd(), &rcWorkArea);
  283. // if client window exist in same monitor as status window
  284. if ( PtInRect(&rcWorkArea, ImeData->ptStatusPos) )
  285. {
  286. ptNew.x =
  287. (ImeData->ptStatusPos.x+ImeData->xStatusWi+UI_GAPX + COMP_SIZEX > ImeData->rcWorkArea.right) ?
  288. ImeData->ptStatusPos.x - UI_GAPX - COMP_SIZEX : ImeData->ptStatusPos.x + ImeData->xStatusWi + UI_GAPX;
  289. ptNew.y = ImeData->ptStatusPos.y;
  290. }
  291. else
  292. { // if client window appeared in different monitor from status window resides,
  293. // then display right bottom of workarea of client window montitor
  294. ptNew.x = rcWorkArea.right - COMP_SIZEX;
  295. ptNew.y = rcWorkArea.bottom - COMP_SIZEY;
  296. }
  297. #else
  298. ptNew.x =
  299. (ImeData->ptStatusPos.x+ImeData->xStatusWi+UI_GAPX + COMP_SIZEX > ImeData->rcWorkArea.right) ?
  300. ImeData->ptStatusPos.x - UI_GAPX - COMP_SIZEX : ImeData->ptStatusPos.x + ImeData->xStatusWi + UI_GAPX;
  301. ptNew.y = ImeData->ptStatusPos.y;
  302. #endif
  303. ImeData->ptCompPos = ptNew;
  304. ScreenToClient(pImeCtx->GetAppWnd(), &ptNew);
  305. pImeCtx->SetCompositionFormPos(ptNew);
  306. }
  307. SetWindowPos(hCompWnd, NULL,
  308. ptNew.x, ptNew.y,
  309. 0, 0, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOSIZE|SWP_NOZORDER);
  310. return (fTrue);
  311. }