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.

1192 lines
37 KiB

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