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.

1338 lines
39 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. COMPUI.c
  5. ++*/
  6. #include <windows.h>
  7. #include <immdev.h>
  8. #include "imeattr.h"
  9. #include "imedefs.h"
  10. #if defined(UNIIME)
  11. #include "uniime.h"
  12. #endif
  13. #if !defined(ROMANIME)
  14. /**********************************************************************/
  15. /* GetCompWnd */
  16. /* Return Value : */
  17. /* window handle of composition */
  18. /**********************************************************************/
  19. HWND PASCAL GetCompWnd(
  20. HWND hUIWnd) // UI window
  21. {
  22. HGLOBAL hUIPrivate;
  23. LPUIPRIV lpUIPrivate;
  24. HWND hCompWnd;
  25. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  26. if (!hUIPrivate) { // can not darw candidate window
  27. return (HWND)NULL;
  28. }
  29. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  30. if (!lpUIPrivate) { // can not draw candidate window
  31. return (HWND)NULL;
  32. }
  33. hCompWnd = lpUIPrivate->hCompWnd;
  34. GlobalUnlock(hUIPrivate);
  35. return (hCompWnd);
  36. }
  37. /**********************************************************************/
  38. /* GetNearCaretPosition() */
  39. /**********************************************************************/
  40. void PASCAL GetNearCaretPosition( // decide a near caret position according
  41. // to the caret position
  42. #if defined(UNIIME)
  43. LPIMEL lpImeL,
  44. #endif
  45. LPPOINT lpptFont,
  46. UINT uEsc,
  47. UINT uRot,
  48. LPPOINT lpptCaret,
  49. LPPOINT lpptNearCaret,
  50. BOOL fFlags)
  51. {
  52. LONG lFontSize;
  53. LONG xWidthUI, yHeightUI, xBorder, yBorder;
  54. RECT rcWorkArea;
  55. #ifdef IDEBUG
  56. _DebugOut(DEB_WARNING, "caret position, x - %d, y - %d",
  57. lpptCaret->x, lpptCaret->y);
  58. #endif
  59. if ((uEsc + uRot) & 0x0001) {
  60. lFontSize = lpptFont->x;
  61. } else {
  62. lFontSize = lpptFont->y;
  63. }
  64. if (fFlags & NEAR_CARET_CANDIDATE) {
  65. xWidthUI = lpImeL->xCandWi;
  66. yHeightUI = lpImeL->yCandHi;
  67. xBorder = lpImeL->cxCandBorder;
  68. yBorder = lpImeL->cyCandBorder;
  69. } else {
  70. xWidthUI = lpImeL->xCompWi;
  71. yHeightUI = lpImeL->yCompHi;
  72. xBorder = lpImeL->cxCompBorder;
  73. yBorder = lpImeL->cyCompBorder;
  74. }
  75. if (fFlags & NEAR_CARET_FIRST_TIME) {
  76. lpptNearCaret->x = lpptCaret->x +
  77. lFontSize * ncUIEsc[uEsc].iLogFontFacX +
  78. sImeG.iPara * ncUIEsc[uEsc].iParaFacX +
  79. sImeG.iPerp * ncUIEsc[uEsc].iPerpFacX;
  80. if (ptInputEsc[uEsc].x >= 0) {
  81. lpptNearCaret->x += xBorder * 2;
  82. } else {
  83. lpptNearCaret->x -= xWidthUI - xBorder * 2;
  84. }
  85. lpptNearCaret->y = lpptCaret->y +
  86. lFontSize * ncUIEsc[uEsc].iLogFontFacY +
  87. sImeG.iPara * ncUIEsc[uEsc].iParaFacY +
  88. sImeG.iPerp * ncUIEsc[uEsc].iPerpFacY;
  89. if (ptInputEsc[uEsc].y >= 0) {
  90. lpptNearCaret->y += yBorder * 2;
  91. } else {
  92. lpptNearCaret->y -= yHeightUI - yBorder * 2;
  93. }
  94. } else {
  95. lpptNearCaret->x = lpptCaret->x +
  96. lFontSize * ncAltUIEsc[uEsc].iLogFontFacX +
  97. sImeG.iPara * ncAltUIEsc[uEsc].iParaFacX +
  98. sImeG.iPerp * ncAltUIEsc[uEsc].iPerpFacX;
  99. if (ptAltInputEsc[uEsc].x >= 0) {
  100. lpptNearCaret->x += xBorder * 2;
  101. } else {
  102. lpptNearCaret->x -= xWidthUI - xBorder * 2;
  103. }
  104. lpptNearCaret->y = lpptCaret->y +
  105. lFontSize * ncAltUIEsc[uEsc].iLogFontFacY +
  106. sImeG.iPara * ncAltUIEsc[uEsc].iParaFacY +
  107. sImeG.iPerp * ncAltUIEsc[uEsc].iPerpFacY;
  108. if (ptAltInputEsc[uEsc].y >= 0) {
  109. lpptNearCaret->y += yBorder * 2;
  110. } else {
  111. lpptNearCaret->y -= yHeightUI - yBorder * 2;
  112. }
  113. }
  114. #if 1 // MultiMonitor
  115. rcWorkArea = ImeMonitorWorkAreaFromPoint(*lpptCaret);
  116. #else
  117. rcWorkArea = sImeG.rcWorkArea;
  118. #endif
  119. if (lpptNearCaret->x < rcWorkArea.left) {
  120. lpptNearCaret->x = rcWorkArea.left;
  121. } else if (lpptNearCaret->x + xWidthUI > rcWorkArea.right) {
  122. lpptNearCaret->x = rcWorkArea.right - xWidthUI;
  123. } else {
  124. }
  125. if (lpptNearCaret->y < rcWorkArea.top) {
  126. lpptNearCaret->y = rcWorkArea.top;
  127. } else if (lpptNearCaret->y + yHeightUI > rcWorkArea.bottom) {
  128. lpptNearCaret->y = rcWorkArea.bottom - yHeightUI;
  129. } else {
  130. }
  131. #ifdef IDEBUG
  132. _DebugOut(DEB_WARNING, "Near caret position, x - %d, y - %d",
  133. lpptNearCaret->x, lpptNearCaret->y);
  134. #endif
  135. return;
  136. }
  137. /**********************************************************************/
  138. /* FitInLazyOperation() */
  139. /* Return Value : */
  140. /* TRUE or FALSE */
  141. /**********************************************************************/
  142. BOOL PASCAL FitInLazyOperation( // fit in lazy operation or not
  143. #if defined(UNIIME)
  144. LPIMEL lpImeL,
  145. #endif
  146. LPPOINT lpptOrg,
  147. LPPOINT lpptNearCaret, // the suggested near caret position
  148. LPRECT lprcInputRect,
  149. UINT uEsc)
  150. {
  151. POINT ptDelta, ptTol;
  152. RECT rcUIRect, rcInterRect;
  153. ptDelta.x = lpptOrg->x - lpptNearCaret->x;
  154. ptDelta.x = (ptDelta.x >= 0) ? ptDelta.x : -ptDelta.x;
  155. ptTol.x = sImeG.iParaTol * ncUIEsc[uEsc].iParaFacX +
  156. sImeG.iPerpTol * ncUIEsc[uEsc].iPerpFacX;
  157. ptTol.x = (ptTol.x >= 0) ? ptTol.x : -ptTol.x;
  158. if (ptDelta.x > ptTol.x) {
  159. return (FALSE);
  160. }
  161. ptDelta.y = lpptOrg->y - lpptNearCaret->y;
  162. ptDelta.y = (ptDelta.y >= 0) ? ptDelta.y : -ptDelta.y;
  163. ptTol.y = sImeG.iParaTol * ncUIEsc[uEsc].iParaFacY +
  164. sImeG.iPerpTol * ncUIEsc[uEsc].iPerpFacY;
  165. ptTol.y = (ptTol.y >= 0) ? ptTol.y : -ptTol.y;
  166. if (ptDelta.y > ptTol.y) {
  167. return (FALSE);
  168. }
  169. // build up the UI rectangle (composition window)
  170. rcUIRect.left = lpptOrg->x;
  171. rcUIRect.top = lpptOrg->y;
  172. rcUIRect.right = rcUIRect.left + lpImeL->xCompWi;
  173. rcUIRect.bottom = rcUIRect.top + lpImeL->yCompHi;
  174. if (IntersectRect(&rcInterRect, &rcUIRect, lprcInputRect)) {
  175. return (FALSE);
  176. }
  177. return (TRUE);
  178. }
  179. /**********************************************************************/
  180. /* AdjustCompPosition() */
  181. /* Return Value : */
  182. /* the position of composition window is changed or not */
  183. /**********************************************************************/
  184. BOOL PASCAL AdjustCompPosition( // IME adjust position according to
  185. // composition form
  186. #if defined(UNIIME)
  187. LPIMEL lpImeL,
  188. #endif
  189. LPINPUTCONTEXT lpIMC,
  190. LPPOINT lpptOrg, // original composition window
  191. // and final position
  192. LPPOINT lpptNew) // new expect position
  193. {
  194. POINT ptNearCaret, ptOldNearCaret, ptCompWnd;
  195. UINT uEsc, uRot;
  196. RECT rcUIRect, rcInputRect, rcInterRect;
  197. POINT ptFont;
  198. #ifdef IDEBUG
  199. _DebugOut(DEB_WARNING, "Original Position, x - %d, y - %d",
  200. lpptOrg->x, lpptOrg->y);
  201. _DebugOut(DEB_WARNING, "New Position, x - %d, y - %d",
  202. lpptNew->x, lpptNew->y);
  203. #endif
  204. // we need to adjust according to font attribute
  205. if (lpIMC->lfFont.A.lfWidth > 0) {
  206. ptFont.x = lpIMC->lfFont.A.lfWidth * 2;
  207. } else if (lpIMC->lfFont.A.lfWidth < 0) {
  208. ptFont.x = -lpIMC->lfFont.A.lfWidth * 2;
  209. } else if (lpIMC->lfFont.A.lfHeight > 0) {
  210. ptFont.x = lpIMC->lfFont.A.lfHeight;
  211. } else if (lpIMC->lfFont.A.lfHeight < 0) {
  212. ptFont.x = -lpIMC->lfFont.A.lfHeight;
  213. } else {
  214. ptFont.x = lpImeL->yCompHi;
  215. }
  216. if (lpIMC->lfFont.A.lfHeight > 0) {
  217. ptFont.y = lpIMC->lfFont.A.lfHeight;
  218. } else if (lpIMC->lfFont.A.lfHeight < 0) {
  219. ptFont.y = -lpIMC->lfFont.A.lfHeight;
  220. } else {
  221. ptFont.y = ptFont.x;
  222. }
  223. #ifdef IDEBUG
  224. _DebugOut(DEB_WARNING, "All positve, x - %d, y - %d",
  225. ptFont.x, ptFont.y);
  226. #endif
  227. // if the input char is too big, we don't need to consider so much
  228. if (ptFont.x > lpImeL->yCompHi * 8) {
  229. ptFont.x = lpImeL->yCompHi * 8;
  230. }
  231. if (ptFont.y > lpImeL->yCompHi * 8) {
  232. ptFont.y = lpImeL->yCompHi * 8;
  233. }
  234. if (ptFont.x < sImeG.xChiCharWi) {
  235. ptFont.x = sImeG.xChiCharWi;
  236. }
  237. if (ptFont.y < sImeG.yChiCharHi) {
  238. ptFont.y = sImeG.yChiCharHi;
  239. }
  240. #ifdef IDEBUG
  241. _DebugOut(DEB_WARNING, "Not too large or too samll, x - %d, y - %d",
  242. ptFont.x, ptFont.y);
  243. #endif
  244. // -450 to 450 index 0
  245. // 450 to 1350 index 1
  246. // 1350 to 2250 index 2
  247. // 2250 to 3150 index 3
  248. uEsc = (UINT)((lpIMC->lfFont.A.lfEscapement + 450) / 900 % 4);
  249. uRot = (UINT)((lpIMC->lfFont.A.lfOrientation + 450) / 900 % 4);
  250. // decide the input rectangle
  251. rcInputRect.left = lpptNew->x;
  252. rcInputRect.top = lpptNew->y;
  253. // build up an input rectangle from escapemment
  254. rcInputRect.right = rcInputRect.left + ptFont.x * ptInputEsc[uEsc].x;
  255. rcInputRect.bottom = rcInputRect.top + ptFont.y * ptInputEsc[uEsc].y;
  256. // be a normal rectangle, not a negative rectangle
  257. if (rcInputRect.left > rcInputRect.right) {
  258. LONG tmp;
  259. tmp = rcInputRect.left;
  260. rcInputRect.left = rcInputRect.right;
  261. rcInputRect.right = tmp;
  262. }
  263. if (rcInputRect.top > rcInputRect.bottom) {
  264. LONG tmp;
  265. tmp = rcInputRect.top;
  266. rcInputRect.top = rcInputRect.bottom;
  267. rcInputRect.bottom = tmp;
  268. }
  269. #ifdef IDEBUG
  270. _DebugOut(DEB_WARNING, "Input Rect, top - %d, left - %d, bottom %d, right - %d",
  271. rcInputRect.top, rcInputRect.left, rcInputRect.bottom, rcInputRect.right);
  272. #endif
  273. GetNearCaretPosition(
  274. #if defined(UNIIME)
  275. lpImeL,
  276. #endif
  277. &ptFont, uEsc, uRot, lpptNew, &ptNearCaret, NEAR_CARET_FIRST_TIME);
  278. // 1st, use the adjust point
  279. // build up the new suggest UI rectangle (composition window)
  280. rcUIRect.left = ptNearCaret.x;
  281. rcUIRect.top = ptNearCaret.y;
  282. rcUIRect.right = rcUIRect.left + lpImeL->xCompWi;
  283. rcUIRect.bottom = rcUIRect.top + lpImeL->yCompHi;
  284. #ifdef IDEBUG
  285. _DebugOut(DEB_WARNING, "Near caret UI Rect, top - %d, left - %d, bottom %d, right - %d",
  286. rcUIRect.top, rcUIRect.left, rcUIRect.bottom, rcUIRect.right);
  287. #endif
  288. ptCompWnd = ptOldNearCaret = ptNearCaret;
  289. // OK, no intersect between the near caret position and input char
  290. if (IntersectRect(&rcInterRect, &rcUIRect, &rcInputRect)) {
  291. } else if (CalcCandPos(
  292. #if defined(UNIIME)
  293. lpImeL,
  294. #endif
  295. lpIMC, &ptCompWnd)) {
  296. // can not fit the candidate window
  297. } else if (FitInLazyOperation(
  298. #if defined(UNIIME)
  299. lpImeL,
  300. #endif
  301. lpptOrg, &ptNearCaret, &rcInputRect, uEsc)) {
  302. #ifdef IDEBUG
  303. _DebugOut(DEB_WARNING, "Fit in lazy operation");
  304. #endif
  305. // happy ending!!!, don't chaqge position
  306. return (FALSE);
  307. } else {
  308. #ifdef IDEBUG
  309. _DebugOut(DEB_WARNING, "Go to adjust point");
  310. #endif
  311. *lpptOrg = ptNearCaret;
  312. // happy ending!!
  313. return (TRUE);
  314. }
  315. // unhappy case
  316. GetNearCaretPosition(
  317. #if defined(UNIIME)
  318. lpImeL,
  319. #endif
  320. &ptFont, uEsc, uRot, lpptNew, &ptNearCaret, 0);
  321. // build up the new suggest UI rectangle (composition window)
  322. rcUIRect.left = ptNearCaret.x;
  323. rcUIRect.top = ptNearCaret.y;
  324. rcUIRect.right = rcUIRect.left + lpImeL->xCompWi;
  325. rcUIRect.bottom = rcUIRect.top + lpImeL->yCompHi;
  326. #ifdef IDEBUG
  327. _DebugOut(DEB_WARNING, "Another NearCaret UI Rect, top - %d, left - %d, bottom %d, right - %d",
  328. rcUIRect.top, rcUIRect.left, rcUIRect.bottom, rcUIRect.right);
  329. #endif
  330. ptCompWnd = ptNearCaret;
  331. // OK, no intersect between the adjust position and input char
  332. if (IntersectRect(&rcInterRect, &rcUIRect, &rcInputRect)) {
  333. } else if (CalcCandPos(
  334. #if defined(UNIIME)
  335. lpImeL,
  336. #endif
  337. lpIMC, &ptCompWnd)) {
  338. // can not fit the candidate window
  339. } else if (FitInLazyOperation(
  340. #if defined(UNIIME)
  341. lpImeL,
  342. #endif
  343. lpptOrg, &ptNearCaret, &rcInputRect, uEsc)) {
  344. #ifdef IDEBUG
  345. _DebugOut(DEB_WARNING, "Fit in Another lazy operation");
  346. #endif
  347. // happy ending!!!, don't chaqge position
  348. return (FALSE);
  349. } else {
  350. #ifdef IDEBUG
  351. _DebugOut(DEB_WARNING, "Go to Another near caret point");
  352. #endif
  353. *lpptOrg = ptNearCaret;
  354. // happy ending!!
  355. return (TRUE);
  356. }
  357. // unhappy ending! :-(
  358. *lpptOrg = ptOldNearCaret;
  359. return (TRUE);
  360. }
  361. /**********************************************************************/
  362. /* SetCompPosition() */
  363. /**********************************************************************/
  364. void PASCAL SetCompPosition( // set the composition window position
  365. #if defined(UNIIME)
  366. LPIMEL lpImeL,
  367. #endif
  368. HWND hCompWnd,
  369. LPINPUTCONTEXT lpIMC)
  370. {
  371. POINT ptWnd;
  372. BOOL fChange = FALSE;
  373. HWND hCandWnd;
  374. if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
  375. return;
  376. }
  377. // the client coordinate position (0, 0) of composition window
  378. ptWnd.x = 0;
  379. ptWnd.y = 0;
  380. // convert to screen coordinates
  381. ClientToScreen(hCompWnd, &ptWnd);
  382. ptWnd.x -= lpImeL->cxCompBorder;
  383. ptWnd.y -= lpImeL->cyCompBorder;
  384. if (lpIMC->cfCompForm.dwStyle & CFS_FORCE_POSITION) {
  385. POINT ptNew; // new position of UI
  386. ptNew = lpIMC->cfCompForm.ptCurrentPos;
  387. ClientToScreen((HWND)lpIMC->hWnd, &ptNew);
  388. if (ptWnd.x != ptNew.x) {
  389. ptWnd.x = ptNew.x;
  390. fChange = TRUE;
  391. }
  392. if (ptWnd.y != ptNew.y) {
  393. ptWnd.y = ptNew.y;
  394. fChange = TRUE;
  395. }
  396. if (fChange) {
  397. ptWnd.x -= lpImeL->cxCompBorder;
  398. ptWnd.y -= lpImeL->cyCompBorder;
  399. }
  400. } else if (lpIMC->cfCompForm.dwStyle != CFS_DEFAULT) {
  401. // aplication tell us the position, we need to adjust
  402. POINT ptNew; // new position of UI
  403. ptNew = lpIMC->cfCompForm.ptCurrentPos;
  404. ClientToScreen((HWND)lpIMC->hWnd, &ptNew);
  405. fChange = AdjustCompPosition(
  406. #if defined(UNIIME)
  407. lpImeL,
  408. #endif
  409. lpIMC, &ptWnd, &ptNew);
  410. } else {
  411. POINT ptNew; // new position of UI
  412. RECT rcWorkArea;
  413. ptNew.x = lpIMC->ptStatusWndPos.x + lpImeL->xStatusWi + UI_MARGIN;
  414. if (ptNew.x + lpImeL->xCompWi > sImeG.rcWorkArea.right) {
  415. ptNew.x = lpIMC->ptStatusWndPos.x -
  416. lpImeL->xCompWi - lpImeL->cxCompBorder * 2 -
  417. UI_MARGIN;
  418. }
  419. #if 1 // MultiMonoitor
  420. rcWorkArea = ImeMonitorWorkAreaFromWindow(lpIMC->hWnd);
  421. #else
  422. rcWorkArea = sImeG.rcWorkArea;
  423. #endif
  424. ptNew.y = rcWorkArea.bottom - lpImeL->yCompHi - 2 * UI_MARGIN;
  425. if (ptWnd.x != ptNew.x) {
  426. ptWnd.x = ptNew.x;
  427. fChange = TRUE;
  428. }
  429. if (ptWnd.y != ptNew.y) {
  430. ptWnd.y = ptNew.y;
  431. fChange = TRUE;
  432. }
  433. if (fChange) {
  434. lpIMC->cfCompForm.ptCurrentPos = ptNew;
  435. ScreenToClient(lpIMC->hWnd, &lpIMC->cfCompForm.ptCurrentPos);
  436. }
  437. }
  438. if (!fChange) {
  439. return;
  440. }
  441. SetWindowPos(hCompWnd, NULL,
  442. ptWnd.x, ptWnd.y,
  443. 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
  444. if (lpIMC->cfCandForm[0].dwIndex == 0) {
  445. // application the candidate position by itself
  446. return;
  447. }
  448. hCandWnd = GetCandWnd(GetWindow(hCompWnd, GW_OWNER));
  449. if (!hCandWnd) {
  450. return;
  451. }
  452. // decide the position of candidate window by compoistion's position
  453. CalcCandPos(
  454. #if defined(UNIIME)
  455. lpImeL,
  456. #endif
  457. lpIMC, &ptWnd);
  458. ScreenToClient(lpIMC->hWnd, &ptWnd);
  459. lpIMC->cfCandForm[0].dwStyle = CFS_CANDIDATEPOS;
  460. lpIMC->cfCandForm[0].ptCurrentPos = ptWnd;
  461. if (!IsWindowVisible(hCandWnd)) {
  462. return;
  463. }
  464. PostMessage(hCandWnd, WM_IME_NOTIFY, IMN_SETCANDIDATEPOS, 0x0001);
  465. return;
  466. }
  467. /**********************************************************************/
  468. /* SetCompWindow() */
  469. /**********************************************************************/
  470. void PASCAL SetCompWindow( // set the position of composition window
  471. #if defined(UNIIME)
  472. LPIMEL lpImeL,
  473. #endif
  474. HWND hCompWnd)
  475. {
  476. HIMC hIMC;
  477. LPINPUTCONTEXT lpIMC;
  478. HWND hUIWnd;
  479. hUIWnd = GetWindow(hCompWnd, GW_OWNER);
  480. if (!hUIWnd) {
  481. return;
  482. }
  483. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  484. if (!hIMC) {
  485. return;
  486. }
  487. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  488. if (!lpIMC) {
  489. return;
  490. }
  491. SetCompPosition(
  492. #if defined(UNIIME)
  493. lpImeL,
  494. #endif
  495. hCompWnd, lpIMC);
  496. ImmUnlockIMC(hIMC);
  497. return;
  498. }
  499. /**********************************************************************/
  500. /* MoveDefaultCompPosition() */
  501. /**********************************************************************/
  502. void PASCAL MoveDefaultCompPosition( // the default comp position
  503. // need to near the caret
  504. #if defined(UNIIME)
  505. LPIMEL lpImeL,
  506. #endif
  507. HWND hUIWnd)
  508. {
  509. HIMC hIMC;
  510. LPINPUTCONTEXT lpIMC;
  511. HWND hCompWnd;
  512. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  513. if (!hIMC) {
  514. return;
  515. }
  516. hCompWnd = GetCompWnd(hUIWnd);
  517. if (!hCompWnd) {
  518. return;
  519. }
  520. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  521. if (!lpIMC) {
  522. return;
  523. }
  524. if (!(lpIMC->cfCompForm.dwStyle & CFS_FORCE_POSITION)) {
  525. SetCompPosition(
  526. #if defined(UNIIME)
  527. lpImeL,
  528. #endif
  529. hCompWnd, lpIMC);
  530. }
  531. ImmUnlockIMC(hIMC);
  532. return;
  533. }
  534. /**********************************************************************/
  535. /* ShowComp() */
  536. /**********************************************************************/
  537. void PASCAL ShowComp( // Show the composition window
  538. #if defined(UNIIME)
  539. LPIMEL lpImeL,
  540. #endif
  541. HWND hUIWnd,
  542. int nShowCompCmd)
  543. {
  544. HGLOBAL hUIPrivate;
  545. LPUIPRIV lpUIPrivate;
  546. // show or hid the UI window
  547. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  548. if (!hUIPrivate) {
  549. return;
  550. }
  551. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  552. if (!lpUIPrivate) {
  553. return;
  554. }
  555. if (lpUIPrivate->nShowCompCmd == nShowCompCmd) {
  556. goto SwCompNoChange;
  557. }
  558. if (nShowCompCmd == SW_HIDE) {
  559. lpUIPrivate->fdwSetContext &= ~(ISC_HIDE_COMP_WINDOW);
  560. }
  561. if (!lpUIPrivate->hCompWnd) {
  562. // not in show candidate window mode
  563. } else if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
  564. int nCurrShowState;
  565. lpUIPrivate->nShowCompCmd = nShowCompCmd;
  566. nCurrShowState = lpUIPrivate->nShowStatusCmd;
  567. nCurrShowState |= lpUIPrivate->nShowCandCmd;
  568. if (nCurrShowState == SW_HIDE) {
  569. // if other two are hide, the current show state is determined
  570. // by this composition section
  571. ShowWindow(lpUIPrivate->hCompWnd, lpUIPrivate->nShowCompCmd);
  572. } else {
  573. RECT rcRect;
  574. rcRect = lpImeL->rcCompText;
  575. // off by 1
  576. rcRect.right += 1;
  577. rcRect.bottom += 1;
  578. RedrawWindow(lpUIPrivate->hCompWnd, &rcRect, NULL,
  579. RDW_INVALIDATE);
  580. }
  581. } else {
  582. ShowWindow(lpUIPrivate->hCompWnd, nShowCompCmd);
  583. lpUIPrivate->nShowCompCmd = nShowCompCmd;
  584. }
  585. SwCompNoChange:
  586. GlobalUnlock(hUIPrivate);
  587. return;
  588. }
  589. /**********************************************************************/
  590. /* StartComp() */
  591. /**********************************************************************/
  592. void PASCAL StartComp(
  593. #if defined(UNIIME)
  594. LPINSTDATAL lpInstL,
  595. LPIMEL lpImeL,
  596. #endif
  597. HWND hUIWnd)
  598. {
  599. HIMC hIMC;
  600. HGLOBAL hUIPrivate;
  601. LPINPUTCONTEXT lpIMC;
  602. LPUIPRIV lpUIPrivate;
  603. LPPRIVCONTEXT lpImcP;
  604. DWORD fdwImeMsg;
  605. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  606. if (!hUIPrivate) { // Oh! Oh!
  607. return;
  608. }
  609. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  610. if (!hIMC) { // Oh! Oh!
  611. return;
  612. }
  613. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  614. if (!lpUIPrivate) { // can not draw composition window
  615. return;
  616. }
  617. lpUIPrivate->fdwSetContext |= ISC_SHOWUICOMPOSITIONWINDOW;
  618. // in the timing of the transition, we will wait
  619. if (lpUIPrivate->fdwSetContext & ISC_OFF_CARET_UI) {
  620. if (!(lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI)) {
  621. PostMessage(hUIWnd, WM_USER_UICHANGE, 0, 0);
  622. goto StartCompUnlockUIPriv;
  623. }
  624. } else {
  625. if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
  626. PostMessage(hUIWnd, WM_USER_UICHANGE, 0, 0);
  627. goto StartCompUnlockUIPriv;
  628. }
  629. }
  630. if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
  631. if (lpUIPrivate->hCompWnd) {
  632. } else if (lpUIPrivate->hStatusWnd) {
  633. lpUIPrivate->hCompWnd = lpUIPrivate->hStatusWnd;
  634. lpUIPrivate->nShowCompCmd = lpUIPrivate->nShowStatusCmd;
  635. } else if (lpUIPrivate->hCandWnd) {
  636. lpUIPrivate->hCompWnd = lpUIPrivate->hCandWnd;
  637. lpUIPrivate->nShowCompCmd = lpUIPrivate->nShowCandCmd;
  638. } else {
  639. }
  640. }
  641. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  642. if (!lpIMC) { // Oh! Oh!
  643. goto StartCompUnlockUIPriv;
  644. }
  645. fdwImeMsg = 0;
  646. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  647. if (lpImcP) {
  648. fdwImeMsg = lpImcP->fdwImeMsg;
  649. ImmUnlockIMCC(lpIMC->hPrivate);
  650. }
  651. if (!(fdwImeMsg & MSG_ALREADY_START)) {
  652. // Sometime the application call ImmNotifyIME to cancel the
  653. // composition before it process WM_IME_STARTCOMPOSITION.
  654. // We should avoid to process this kind of WM_IME_STARTCOMPOSITION.
  655. goto StartCompUnlockIMC;
  656. }
  657. if (lpUIPrivate->hCompWnd) {
  658. if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
  659. RECT rcRect;
  660. rcRect = lpImeL->rcCompText;
  661. // off by 1
  662. rcRect.right += 1;
  663. rcRect.bottom += 1;
  664. RedrawWindow(lpUIPrivate->hCompWnd, &rcRect, NULL,
  665. RDW_INVALIDATE);
  666. }
  667. } else {
  668. if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
  669. lpUIPrivate->hCompWnd = CreateWindowEx(
  670. WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME,
  671. lpImeL->szOffCaretClassName, NULL,
  672. WS_POPUP|WS_DISABLED,
  673. lpIMC->ptStatusWndPos.x, lpIMC->ptStatusWndPos.y,
  674. lpImeL->xCompWi, lpImeL->yCompHi,
  675. hUIWnd, (HMENU)NULL, lpInstL->hInst, NULL);
  676. if (lpUIPrivate->hSoftKbdWnd) {
  677. // insert soft keyboard in front of other UI
  678. SetWindowPos(lpUIPrivate->hCompWnd,
  679. lpUIPrivate->hSoftKbdWnd,
  680. 0, 0, 0, 0,
  681. SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
  682. }
  683. } else {
  684. POINT ptNew;
  685. ptNew = lpIMC->cfCompForm.ptCurrentPos;
  686. ClientToScreen((HWND)lpIMC->hWnd, &ptNew);
  687. lpUIPrivate->hCompWnd = CreateWindowEx(0,
  688. // WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME,
  689. lpImeL->szCompClassName, NULL,
  690. WS_POPUP|WS_DISABLED|WS_BORDER,
  691. ptNew.x, ptNew.y, lpImeL->xCompWi, lpImeL->yCompHi,
  692. hUIWnd, (HMENU)NULL, lpInstL->hInst, NULL);
  693. }
  694. SetWindowLong(lpUIPrivate->hCompWnd, UI_MOVE_OFFSET,
  695. WINDOW_NOT_DRAG);
  696. SetWindowLong(lpUIPrivate->hCompWnd, UI_MOVE_XY, lpImeL->nRevMaxKey);
  697. }
  698. if (!(lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI)) {
  699. // try to set the position of composition UI window near the caret
  700. SetCompPosition(
  701. #if defined(UNIIME)
  702. lpImeL,
  703. #endif
  704. lpUIPrivate->hCompWnd, lpIMC);
  705. }
  706. ShowComp(
  707. #if defined(UNIIME)
  708. lpImeL,
  709. #endif
  710. hUIWnd, SW_SHOWNOACTIVATE);
  711. StartCompUnlockIMC:
  712. ImmUnlockIMC(hIMC);
  713. StartCompUnlockUIPriv:
  714. GlobalUnlock(hUIPrivate);
  715. return;
  716. }
  717. /**********************************************************************/
  718. /* EndComp() */
  719. /**********************************************************************/
  720. void PASCAL EndComp(
  721. #if defined(UNIIME)
  722. LPIMEL lpImeL,
  723. #endif
  724. HWND hUIWnd)
  725. {
  726. ShowComp(
  727. #if defined(UNIIME)
  728. lpImeL,
  729. #endif
  730. hUIWnd, SW_HIDE);
  731. return;
  732. }
  733. /**********************************************************************/
  734. /* ChangeCompositionSize() */
  735. /**********************************************************************/
  736. void PASCAL ChangeCompositionSize(
  737. #if defined(UNIIME)
  738. LPIMEL lpImeL,
  739. #endif
  740. HWND hUIWnd)
  741. {
  742. HWND hCompWnd, hCandWnd;
  743. RECT rcWnd;
  744. UINT nMaxKey;
  745. HIMC hIMC;
  746. LPINPUTCONTEXT lpIMC;
  747. hCompWnd = GetCompWnd(hUIWnd);
  748. if (!hCompWnd) {
  749. return;
  750. }
  751. GetWindowRect(hCompWnd, &rcWnd);
  752. if ((rcWnd.right - rcWnd.left) != lpImeL->xCompWi) {
  753. } else if ((rcWnd.bottom - rcWnd.top) != lpImeL->yCompHi) {
  754. } else {
  755. return;
  756. }
  757. SetWindowPos(hCompWnd, NULL,
  758. 0, 0, lpImeL->xCompWi, lpImeL->yCompHi,
  759. SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
  760. if (lpImeL->nRevMaxKey >= lpImeL->nMaxKey) {
  761. nMaxKey = lpImeL->nRevMaxKey;
  762. } else {
  763. nMaxKey = lpImeL->nMaxKey;
  764. }
  765. SetWindowLong(hCompWnd, UI_MOVE_XY, nMaxKey);
  766. if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
  767. return;
  768. }
  769. hCandWnd = GetCandWnd(hUIWnd);
  770. if (!hCandWnd) {
  771. return;
  772. }
  773. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  774. if (!hIMC) {
  775. return;
  776. }
  777. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  778. if (!lpIMC) {
  779. return;
  780. }
  781. CalcCandPos(
  782. #if defined(UNIIME)
  783. lpImeL,
  784. #endif
  785. lpIMC, (LPPOINT)&rcWnd);
  786. ImmUnlockIMC(hIMC);
  787. SetWindowPos(hCandWnd, NULL,
  788. rcWnd.left, rcWnd.top,
  789. 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
  790. return;
  791. }
  792. /**********************************************************************/
  793. /* DestroyCompWindow() */
  794. /**********************************************************************/
  795. void PASCAL DestroyCompWindow( // destroy composition window
  796. HWND hCompWnd)
  797. {
  798. HGLOBAL hUIPrivate;
  799. LPUIPRIV lpUIPrivate;
  800. if (GetWindowLong(hCompWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
  801. // undo the drag border
  802. DrawDragBorder(hCompWnd,
  803. GetWindowLong(hCompWnd, UI_MOVE_XY),
  804. GetWindowLong(hCompWnd, UI_MOVE_OFFSET));
  805. }
  806. hUIPrivate = (HGLOBAL)GetWindowLongPtr(GetWindow(hCompWnd, GW_OWNER),
  807. IMMGWLP_PRIVATE);
  808. if (!hUIPrivate) { // Oh! Oh!
  809. return;
  810. }
  811. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  812. if (!lpUIPrivate) { // Oh! Oh!
  813. return;
  814. }
  815. lpUIPrivate->nShowCompCmd = SW_HIDE;
  816. lpUIPrivate->hCompWnd = (HWND)NULL;
  817. GlobalUnlock(hUIPrivate);
  818. return;
  819. }
  820. /**********************************************************************/
  821. /* CompSetCursor() */
  822. /**********************************************************************/
  823. void PASCAL CompSetCursor(
  824. HWND hCompWnd,
  825. LPARAM lParam)
  826. {
  827. POINT ptCursor;
  828. RECT rcWnd;
  829. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  830. if (GetWindowLong(hCompWnd, UI_MOVE_OFFSET) !=
  831. WINDOW_NOT_DRAG) {
  832. return;
  833. }
  834. if (HIWORD(lParam) != WM_LBUTTONDOWN) {
  835. return;
  836. }
  837. // start dragging
  838. SystemParametersInfo(SPI_GETWORKAREA, 0, &sImeG.rcWorkArea, 0);
  839. SetCapture(hCompWnd);
  840. GetCursorPos(&ptCursor);
  841. SetWindowLong(hCompWnd, UI_MOVE_XY,
  842. MAKELONG(ptCursor.x, ptCursor.y));
  843. GetWindowRect(hCompWnd, &rcWnd);
  844. SetWindowLong(hCompWnd, UI_MOVE_OFFSET,
  845. MAKELONG(ptCursor.x - rcWnd.left, ptCursor.y - rcWnd.top));
  846. DrawDragBorder(hCompWnd, MAKELONG(ptCursor.x, ptCursor.y),
  847. GetWindowLong(hCompWnd, UI_MOVE_OFFSET));
  848. return;
  849. }
  850. /**********************************************************************/
  851. /* CompButtonUp() */
  852. /**********************************************************************/
  853. BOOL PASCAL CompButtonUp( // finish drag, set comp window to this
  854. // position
  855. #if defined(UNIIME)
  856. LPIMEL lpImeL,
  857. #endif
  858. HWND hCompWnd)
  859. {
  860. LONG lTmpCursor, lTmpOffset;
  861. POINT pt;
  862. HWND hUIWnd;
  863. HIMC hIMC;
  864. LPINPUTCONTEXT lpIMC;
  865. RECT rcWorkArea;
  866. if (GetWindowLong(hCompWnd, UI_MOVE_OFFSET) == WINDOW_NOT_DRAG) {
  867. return (FALSE);
  868. }
  869. lTmpCursor = GetWindowLong(hCompWnd, UI_MOVE_XY);
  870. // calculate the org by the offset
  871. lTmpOffset = GetWindowLong(hCompWnd, UI_MOVE_OFFSET);
  872. pt.x = (*(LPPOINTS)&lTmpCursor).x - (*(LPPOINTS)&lTmpOffset).x;
  873. pt.y = (*(LPPOINTS)&lTmpCursor).y - (*(LPPOINTS)&lTmpOffset).y;
  874. DrawDragBorder(hCompWnd, lTmpCursor, lTmpOffset);
  875. SetWindowLong(hCompWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG);
  876. SetWindowLong(hCompWnd, UI_MOVE_XY, lpImeL->nRevMaxKey);
  877. ReleaseCapture();
  878. hUIWnd = GetWindow(hCompWnd, GW_OWNER);
  879. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  880. if (!hIMC) {
  881. return (FALSE);
  882. }
  883. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  884. if (!lpIMC) {
  885. return (FALSE);
  886. }
  887. #if 1 // MultiMonitor
  888. rcWorkArea = ImeMonitorWorkAreaFromWindow(lpIMC->hWnd);
  889. #else
  890. rcWorkArea = sImeG.rcWorkArea;
  891. #endif
  892. if (pt.x < rcWorkArea.left) {
  893. pt.x = rcWorkArea.left;
  894. } else if (pt.x + lpImeL->xCompWi > rcWorkArea.right) {
  895. pt.x = rcWorkArea.right - lpImeL->xCompWi;
  896. }
  897. if (pt.y < rcWorkArea.top) {
  898. pt.y = rcWorkArea.top;
  899. } else if (pt.y + lpImeL->yCompHi > rcWorkArea.bottom) {
  900. pt.y = rcWorkArea.bottom - lpImeL->yCompHi;
  901. }
  902. lpIMC->cfCompForm.dwStyle = CFS_FORCE_POSITION;
  903. lpIMC->cfCompForm.ptCurrentPos.x = pt.x + lpImeL->cxCompBorder;
  904. lpIMC->cfCompForm.ptCurrentPos.y = pt.y + lpImeL->cyCompBorder;
  905. ScreenToClient(lpIMC->hWnd, &lpIMC->cfCompForm.ptCurrentPos);
  906. ImmUnlockIMC(hIMC);
  907. // set composition window to the new poosition
  908. PostMessage(hCompWnd, WM_IME_NOTIFY, IMN_SETCOMPOSITIONWINDOW, 0);
  909. return (TRUE);
  910. }
  911. /**********************************************************************/
  912. /* PaintCompWindow() */
  913. /**********************************************************************/
  914. void PASCAL PaintCompWindow(
  915. #if defined(UNIIME)
  916. LPIMEL lpImeL,
  917. #endif
  918. HWND hUIWnd,
  919. HDC hDC)
  920. {
  921. HIMC hIMC;
  922. LPINPUTCONTEXT lpIMC;
  923. LPCOMPOSITIONSTRING lpCompStr;
  924. HGDIOBJ hOldFont;
  925. // RECT rcSunken;
  926. LOGFONT lfFont;
  927. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  928. if (!hIMC) {
  929. return;
  930. }
  931. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  932. if (!lpIMC) {
  933. return;
  934. }
  935. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  936. hOldFont = GetCurrentObject(hDC, OBJ_FONT);
  937. GetObject(hOldFont, sizeof(lfFont), &lfFont);
  938. if (sImeG.fDiffSysCharSet) {
  939. lfFont.lfCharSet = NATIVE_CHARSET;
  940. lfFont.lfFaceName[0] = TEXT('\0');
  941. }
  942. lfFont.lfWeight = FW_DONTCARE;
  943. SelectObject(hDC, CreateFontIndirect(&lfFont));
  944. // light gray background for normal case
  945. SetBkColor(hDC, RGB(0xC0, 0xC0, 0xC0));
  946. if (!lpCompStr) {
  947. goto UpdCompWndShowGuideLine;
  948. } else if (!lpCompStr->dwCompStrLen) {
  949. LPGUIDELINE lpGuideLine;
  950. UpdCompWndShowGuideLine:
  951. lpGuideLine = (LPGUIDELINE)ImmLockIMCC(lpIMC->hGuideLine);
  952. if (lpGuideLine) {
  953. BOOL fReverseConversion;
  954. LPCANDIDATELIST lpCandList;
  955. LPTSTR lpStr;
  956. UINT uStrLen;
  957. fReverseConversion = FALSE;
  958. if (lpGuideLine->dwLevel != GL_LEVEL_INFORMATION) {
  959. goto UpdCompWndUnlockGuideLine;
  960. } else if (lpGuideLine->dwIndex != GL_ID_REVERSECONVERSION) {
  961. goto UpdCompWndUnlockGuideLine;
  962. } else {
  963. }
  964. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpGuideLine +
  965. lpGuideLine->dwPrivateOffset);
  966. if (!lpCandList) {
  967. goto UpdCompWndUnlockGuideLine;
  968. } else if (!lpCandList->dwCount) {
  969. goto UpdCompWndUnlockGuideLine;
  970. } else {
  971. fReverseConversion = TRUE;
  972. }
  973. // green text for information
  974. SetTextColor(hDC, RGB(0x00, 0x80, 0x00));
  975. lpStr = (LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[0]);
  976. uStrLen = lstrlen(lpStr);
  977. ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
  978. ETO_OPAQUE, &lpImeL->rcCompText,
  979. lpStr, uStrLen, iDx);
  980. UpdCompWndUnlockGuideLine:
  981. ImmUnlockIMCC(lpIMC->hGuideLine);
  982. if (!fReverseConversion) {
  983. goto UpdCompWndNoString;
  984. }
  985. } else {
  986. UpdCompWndNoString:
  987. // no any information
  988. ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
  989. ETO_OPAQUE, &lpImeL->rcCompText,
  990. (LPTSTR)NULL, 0, NULL);
  991. }
  992. } else {
  993. ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
  994. ETO_OPAQUE, &lpImeL->rcCompText,
  995. (LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset),
  996. (UINT)lpCompStr->dwCompStrLen, iDx);
  997. if (lpCompStr->dwCompStrLen <= lpCompStr->dwCursorPos) {
  998. goto UpdCompWndUnselectObj;
  999. }
  1000. // there is error part
  1001. // red text for error
  1002. SetTextColor(hDC, RGB(0xFF, 0x00, 0x00));
  1003. // dark gray background for error
  1004. SetBkColor(hDC, RGB(0x80, 0x80, 0x80));
  1005. ExtTextOut(hDC, lpImeL->rcCompText.left +
  1006. lpCompStr->dwCursorPos * sImeG.xChiCharWi /
  1007. (sizeof(WCHAR) / sizeof(TCHAR)),
  1008. lpImeL->rcCompText.top,
  1009. ETO_OPAQUE, NULL,
  1010. (LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset +
  1011. lpCompStr->dwCursorPos * sizeof(TCHAR)),
  1012. (UINT)(lpCompStr->dwCompStrLen - lpCompStr->dwCursorPos), iDx);
  1013. }
  1014. UpdCompWndUnselectObj:
  1015. DeleteObject(SelectObject(hDC, hOldFont));
  1016. if (lpCompStr) {
  1017. ImmUnlockIMCC(lpIMC->hCompStr);
  1018. }
  1019. ImmUnlockIMC(hIMC);
  1020. #if 0
  1021. rcSunken = lpImeL->rcCompText;
  1022. rcSunken.left -= lpImeL->cxCompBorder;
  1023. rcSunken.top -= lpImeL->cyCompBorder;
  1024. rcSunken.right += lpImeL->cxCompBorder;
  1025. rcSunken.bottom += lpImeL->cyCompBorder;
  1026. DrawEdge(hDC, &rcSunken, BDR_SUNKENOUTER, BF_RECT);
  1027. #endif
  1028. return;
  1029. }
  1030. /**********************************************************************/
  1031. /* CompWndProc() / UniCompWndProc() */
  1032. /**********************************************************************/
  1033. // composition window proc
  1034. #if defined(UNIIME)
  1035. LRESULT WINAPI UniCompWndProc(
  1036. LPINSTDATAL lpInstL,
  1037. LPIMEL lpImeL,
  1038. #else
  1039. LRESULT CALLBACK CompWndProc(
  1040. #endif
  1041. HWND hCompWnd,
  1042. UINT uMsg,
  1043. WPARAM wParam,
  1044. LPARAM lParam)
  1045. {
  1046. switch (uMsg) {
  1047. case WM_DESTROY:
  1048. DestroyCompWindow(hCompWnd);
  1049. break;
  1050. case WM_SETCURSOR:
  1051. CompSetCursor(hCompWnd, lParam);
  1052. break;
  1053. case WM_MOUSEMOVE:
  1054. if (GetWindowLong(hCompWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
  1055. POINT ptCursor;
  1056. DrawDragBorder(hCompWnd,
  1057. GetWindowLong(hCompWnd, UI_MOVE_XY),
  1058. GetWindowLong(hCompWnd, UI_MOVE_OFFSET));
  1059. GetCursorPos(&ptCursor);
  1060. SetWindowLong(hCompWnd, UI_MOVE_XY,
  1061. MAKELONG(ptCursor.x, ptCursor.y));
  1062. DrawDragBorder(hCompWnd, MAKELONG(ptCursor.x, ptCursor.y),
  1063. GetWindowLong(hCompWnd, UI_MOVE_OFFSET));
  1064. } else {
  1065. return DefWindowProc(hCompWnd, uMsg, wParam, lParam);
  1066. }
  1067. break;
  1068. case WM_LBUTTONUP:
  1069. if (!CompButtonUp(
  1070. #if defined(UNIIME)
  1071. lpImeL,
  1072. #endif
  1073. hCompWnd)) {
  1074. return DefWindowProc(hCompWnd, uMsg, wParam, lParam);
  1075. }
  1076. break;
  1077. case WM_IME_NOTIFY:
  1078. if (wParam != IMN_SETCOMPOSITIONWINDOW) {
  1079. } else if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
  1080. } else {
  1081. SetCompWindow(
  1082. #if defined(UNIIME)
  1083. lpImeL,
  1084. #endif
  1085. hCompWnd);
  1086. }
  1087. break;
  1088. case WM_PAINT:
  1089. {
  1090. HDC hDC;
  1091. PAINTSTRUCT ps;
  1092. hDC = BeginPaint(hCompWnd, &ps);
  1093. PaintCompWindow(
  1094. #if defined(UNIIME)
  1095. lpImeL,
  1096. #endif
  1097. GetWindow(hCompWnd, GW_OWNER), hDC);
  1098. EndPaint(hCompWnd, &ps);
  1099. }
  1100. break;
  1101. case WM_MOUSEACTIVATE:
  1102. return (MA_NOACTIVATE);
  1103. default:
  1104. return DefWindowProc(hCompWnd, uMsg, wParam, lParam);
  1105. }
  1106. return (0L);
  1107. }
  1108. #endif