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.

1721 lines
51 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. candui.c
  5. ++*/
  6. #include <windows.h>
  7. #include <immdev.h>
  8. #include <imedefs.h>
  9. /**********************************************************************/
  10. /* GetCandWnd */
  11. /* Return Value : */
  12. /* window handle of candidatte */
  13. /**********************************************************************/
  14. HWND PASCAL GetCandWnd(
  15. HWND hUIWnd) // UI window
  16. {
  17. HGLOBAL hUIPrivate;
  18. LPUIPRIV lpUIPrivate;
  19. HWND hCandWnd;
  20. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  21. if (!hUIPrivate) { // can not darw candidate window
  22. return (HWND)NULL;
  23. }
  24. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  25. if (!lpUIPrivate) { // can not draw candidate window
  26. return (HWND)NULL;
  27. }
  28. hCandWnd = lpUIPrivate->hCandWnd;
  29. GlobalUnlock(hUIPrivate);
  30. return (hCandWnd);
  31. }
  32. void PASCAL CalcCandPos(
  33. HIMC hIMC,
  34. HWND hUIWnd,
  35. LPPOINT lpptWnd) // the composition window position
  36. {
  37. POINT ptNew, ptSTWPos;
  38. RECT rcWorkArea;
  39. #ifdef MUL_MONITOR
  40. rcWorkArea = ImeMonitorWorkAreaFromPoint(*lpptWnd);
  41. #else
  42. rcWorkArea = sImeG.rcWorkArea;
  43. #endif
  44. ptNew.x = lpptWnd->x + lpImeL->xCompWi + UI_MARGIN;
  45. if (ptNew.x + sImeG.xCandWi > rcWorkArea.right) {
  46. // exceed screen width
  47. ptNew.x = lpptWnd->x - sImeG.xCandWi - UI_MARGIN;
  48. }
  49. ptNew.y = lpptWnd->y + lpImeL->cyCompBorder - sImeG.cyCandBorder;
  50. if (ptNew.y + sImeG.yCandHi > rcWorkArea.bottom) {
  51. // exceed screen high
  52. ptNew.y = rcWorkArea.bottom - sImeG.yCandHi;
  53. }
  54. if(!sImeG.IC_Trace) {
  55. HWND hCompWnd;
  56. ImmGetStatusWindowPos(hIMC, (LPPOINT)&ptSTWPos);
  57. hCompWnd = GetCompWnd(hUIWnd);
  58. if (hCompWnd) {
  59. ptNew.x = ptSTWPos.x + sImeG.xStatusWi + lpImeL->xCompWi + 2 * UI_MARGIN;
  60. if((ptSTWPos.x + sImeG.xStatusWi + sImeG.xCandWi + lpImeL->xCompWi + 2 * UI_MARGIN)>
  61. rcWorkArea.right) {
  62. if (ptSTWPos.x >= (sImeG.xCandWi + lpImeL->xCompWi + 2 * UI_MARGIN)) {
  63. ptNew.x = ptSTWPos.x - lpImeL->xCompWi - sImeG.xCandWi - 2 * UI_MARGIN;
  64. } else {
  65. ptNew.x = ptSTWPos.x + sImeG.xStatusWi + UI_MARGIN;
  66. }
  67. }
  68. ptNew.y = ptSTWPos.y + lpImeL->cyCompBorder - sImeG.cyCandBorder;
  69. if (ptNew.y + sImeG.yCandHi > rcWorkArea.bottom) {
  70. ptNew.y = rcWorkArea.bottom - sImeG.yCandHi;
  71. }
  72. } else {
  73. ptNew.x = ptSTWPos.x + sImeG.xStatusWi + UI_MARGIN;
  74. if(((ptSTWPos.x + sImeG.xStatusWi + sImeG.xCandWi + UI_MARGIN)>=
  75. rcWorkArea.right)
  76. && (ptSTWPos.x >= sImeG.xCandWi + UI_MARGIN)) {
  77. ptNew.x = ptSTWPos.x - sImeG.xCandWi - UI_MARGIN;
  78. }
  79. ptNew.y = ptSTWPos.y + lpImeL->cyCompBorder - sImeG.cyCandBorder;
  80. if (ptNew.y + sImeG.yCandHi > rcWorkArea.bottom) {
  81. ptNew.y = rcWorkArea.bottom - sImeG.yCandHi;
  82. }
  83. }
  84. }
  85. lpptWnd->x = ptNew.x;
  86. lpptWnd->y = ptNew.y;
  87. return;
  88. }
  89. /**********************************************************************/
  90. /* AdjustCandPos */
  91. /**********************************************************************/
  92. void AdjustCandPos(
  93. HIMC hIMC,
  94. LPPOINT lpptWnd) // the composition window position
  95. {
  96. LPINPUTCONTEXT lpIMC;
  97. LONG ptFontHi;
  98. UINT uEsc;
  99. RECT rcWorkArea;
  100. #ifdef MUL_MONITOR
  101. rcWorkArea = ImeMonitorWorkAreaFromPoint(*lpptWnd);
  102. #else
  103. rcWorkArea = sImeG.rcWorkArea;
  104. #endif
  105. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  106. if (!lpIMC) {
  107. return;
  108. }
  109. if (lpIMC->lfFont.A.lfHeight > 0) {
  110. ptFontHi = lpIMC->lfFont.A.lfHeight;
  111. } else if (lpIMC->lfFont.A.lfWidth == 0) {
  112. ptFontHi = lpImeL->yCompHi;
  113. } else {
  114. ptFontHi = -lpIMC->lfFont.A.lfHeight;
  115. }
  116. if (ptFontHi > lpImeL->yCompHi * 8) {
  117. ptFontHi = lpImeL->yCompHi * 8;
  118. }
  119. if (ptFontHi < sImeG.yChiCharHi) {
  120. ptFontHi = sImeG.yChiCharHi;
  121. }
  122. // -450 to 450 index 0
  123. // 450 to 1350 index 1
  124. // 1350 to 2250 index 2
  125. // 2250 to 3150 index 3
  126. uEsc = (UINT)((lpIMC->lfFont.A.lfEscapement + 450) / 900 % 4);
  127. // find the location after IME do an adjustment
  128. ptFontHi = ptFontHi * ptInputEsc[uEsc].y;
  129. if(lpptWnd->y + ptFontHi + sImeG.yCandHi <= rcWorkArea.bottom) {
  130. lpptWnd->y += ptFontHi;
  131. } else {
  132. lpptWnd->y -= (ptFontHi + sImeG.yCandHi);
  133. }
  134. ImmUnlockIMC(hIMC);
  135. return;
  136. }
  137. /**********************************************************************/
  138. /* AdjustCandRectBoundry */
  139. /**********************************************************************/
  140. void PASCAL AdjustCandRectBoundry(
  141. LPINPUTCONTEXT lpIMC,
  142. LPPOINT lpptCandWnd) // the caret position
  143. {
  144. RECT rcExclude, rcUIRect, rcInterSect;
  145. UINT uEsc;
  146. RECT rcWorkArea;
  147. #ifdef MUL_MONITOR
  148. {
  149. RECT rcCandWnd;
  150. *(LPPOINT)&rcCandWnd = *(LPPOINT)lpptCandWnd;
  151. rcCandWnd.right = rcCandWnd.left + sImeG.xCandWi;
  152. rcCandWnd.bottom = rcCandWnd.top + sImeG.yCandHi;
  153. rcWorkArea = ImeMonitorWorkAreaFromRect(&rcCandWnd);
  154. }
  155. #else
  156. rcWorkArea = sImeG.rcWorkArea;
  157. #endif
  158. // be a normal rectangle, not a negative rectangle
  159. if (lpIMC->cfCandForm[0].rcArea.left > lpIMC->cfCandForm[0].rcArea.right) {
  160. LONG tmp;
  161. tmp = lpIMC->cfCandForm[0].rcArea.left;
  162. lpIMC->cfCandForm[0].rcArea.left = lpIMC->cfCandForm[0].rcArea.right;
  163. lpIMC->cfCandForm[0].rcArea.right = tmp;
  164. }
  165. if (lpIMC->cfCandForm[0].rcArea.top > lpIMC->cfCandForm[0].rcArea.bottom) {
  166. LONG tmp;
  167. tmp = lpIMC->cfCandForm[0].rcArea.top;
  168. lpIMC->cfCandForm[0].rcArea.top = lpIMC->cfCandForm[0].rcArea.bottom;
  169. lpIMC->cfCandForm[0].rcArea.bottom = tmp;
  170. }
  171. // translate from client coordinate to screen coordinate
  172. rcExclude = lpIMC->cfCandForm[0].rcArea;
  173. rcExclude.left += lpptCandWnd->x - lpIMC->cfCandForm[0].ptCurrentPos.x;
  174. rcExclude.right += lpptCandWnd->x - lpIMC->cfCandForm[0].ptCurrentPos.x;
  175. rcExclude.top += lpptCandWnd->y - lpIMC->cfCandForm[0].ptCurrentPos.y;
  176. rcExclude.bottom += lpptCandWnd->y - lpIMC->cfCandForm[0].ptCurrentPos.y;
  177. // if original point is OK, we use it
  178. *(LPPOINT)&rcUIRect = *lpptCandWnd;
  179. if (rcUIRect.left < rcWorkArea.left) {
  180. rcUIRect.left = rcWorkArea.left;
  181. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  182. rcUIRect.left = rcWorkArea.right - sImeG.xCandWi;
  183. } else {
  184. }
  185. if (rcUIRect.top < rcWorkArea.top) {
  186. rcUIRect.top = rcWorkArea.top;
  187. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.bottom) {
  188. rcUIRect.top = rcWorkArea.bottom - sImeG.yCandHi;
  189. } else {
  190. }
  191. rcUIRect.right = rcUIRect.left + sImeG.xCandWi;
  192. rcUIRect.bottom = rcUIRect.top + sImeG.yCandHi;
  193. if (!IntersectRect(&rcInterSect, &rcExclude, &rcUIRect)) {
  194. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  195. return;
  196. }
  197. uEsc = (UINT)((lpIMC->lfFont.A.lfEscapement + 450) / 900 % 4);
  198. if (uEsc & 0x0001) {
  199. // 900 & 2700 we need change x coordinate
  200. if (ptInputEsc[uEsc].x > 0) {
  201. rcUIRect.left = rcExclude.right;
  202. } else {
  203. rcUIRect.left = rcExclude.left - sImeG.xCandWi;
  204. }
  205. } else {
  206. // 0 & 1800 we do not change x coordinate
  207. rcUIRect.left = lpptCandWnd->x;
  208. }
  209. if (rcUIRect.left < rcWorkArea.left) {
  210. rcUIRect.left = rcWorkArea.left;
  211. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  212. rcUIRect.left = rcWorkArea.right - sImeG.xCandWi;
  213. } else {
  214. }
  215. if (uEsc & 0x0001) {
  216. // 900 & 2700 we do not change y coordinate
  217. rcUIRect.top = lpptCandWnd->y;
  218. } else {
  219. // 0 & 1800 we need change y coordinate
  220. if (ptInputEsc[uEsc].y > 0) {
  221. rcUIRect.top = rcExclude.bottom;
  222. } else {
  223. rcUIRect.top = rcExclude.top - sImeG.yCandHi;
  224. }
  225. }
  226. if (rcUIRect.top < rcWorkArea.top) {
  227. rcUIRect.top = rcWorkArea.top;
  228. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.bottom) {
  229. rcUIRect.top = rcWorkArea.bottom - sImeG.yCandHi;
  230. } else {
  231. }
  232. rcUIRect.right = rcUIRect.left + sImeG.xCandWi;
  233. rcUIRect.bottom = rcUIRect.top + sImeG.yCandHi;
  234. // the candidate window not overlapped with exclude rectangle
  235. // so we found a position
  236. if (!IntersectRect(&rcInterSect, &rcExclude, &rcUIRect)) {
  237. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  238. return;
  239. }
  240. // adjust according to
  241. *(LPPOINT)&rcUIRect = *lpptCandWnd;
  242. if (uEsc & 0x0001) {
  243. // 900 & 2700 we prefer adjust x
  244. if (ptInputEsc[uEsc].x > 0) {
  245. rcUIRect.left = rcExclude.right;
  246. } else {
  247. rcUIRect.left = rcExclude.left - sImeG.xCandWi;
  248. }
  249. if (rcUIRect.left < rcWorkArea.left) {
  250. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  251. } else {
  252. if (rcUIRect.top < rcWorkArea.top) {
  253. rcUIRect.top = rcWorkArea.top;
  254. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.bottom) {
  255. rcUIRect.top = rcWorkArea.bottom - sImeG.yCandHi;
  256. }
  257. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  258. return;
  259. }
  260. // negative try
  261. if (ptInputEsc[uEsc].x > 0) {
  262. rcUIRect.left = rcExclude.left - sImeG.xCandWi;
  263. } else {
  264. rcUIRect.left = rcExclude.right;
  265. }
  266. if (rcUIRect.left < rcWorkArea.left) {
  267. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  268. } else {
  269. if (rcUIRect.top < rcWorkArea.top) {
  270. rcUIRect.top = rcWorkArea.top;
  271. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.bottom) {
  272. rcUIRect.top = rcWorkArea.bottom - sImeG.yCandHi;
  273. }
  274. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  275. return;
  276. }
  277. // negative try failure again, we use positive plus display adjust
  278. if (ptInputEsc[uEsc].x > 0) {
  279. rcUIRect.left = rcExclude.right;
  280. } else {
  281. rcUIRect.left = rcExclude.left - sImeG.xCandWi;
  282. }
  283. if (rcUIRect.left < rcWorkArea.left) {
  284. rcUIRect.left = rcWorkArea.left;
  285. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  286. rcUIRect.left = rcWorkArea.right - sImeG.xCandWi;
  287. }
  288. if (rcUIRect.top < rcWorkArea.top) {
  289. rcUIRect.top = rcWorkArea.top;
  290. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.bottom) {
  291. rcUIRect.top = rcWorkArea.bottom - sImeG.yCandHi;
  292. }
  293. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  294. } else {
  295. // 0 & 1800 we prefer adjust y
  296. if (ptInputEsc[uEsc].y > 0) {
  297. rcUIRect.top = rcExclude.bottom;
  298. } else {
  299. rcUIRect.top = rcExclude.top - sImeG.yCandHi;
  300. }
  301. if (rcUIRect.top < rcWorkArea.top) {
  302. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.bottom) {
  303. } else {
  304. if (rcUIRect.left < rcWorkArea.left) {
  305. rcUIRect.left = rcWorkArea.left;
  306. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  307. rcUIRect.left = rcWorkArea.right - sImeG.xCandWi;
  308. }
  309. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  310. return;
  311. }
  312. // negative try
  313. if (ptInputEsc[uEsc].y > 0) {
  314. rcUIRect.top = rcExclude.top - sImeG.yCandHi;
  315. } else {
  316. rcUIRect.top = rcExclude.bottom;
  317. }
  318. if (rcUIRect.top < rcWorkArea.top) {
  319. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.right) {
  320. } else {
  321. if (rcUIRect.left < rcWorkArea.left) {
  322. rcUIRect.left = rcWorkArea.left;
  323. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  324. rcUIRect.left = rcWorkArea.right - sImeG.xCandWi;
  325. }
  326. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  327. return;
  328. }
  329. // negative try failure again, we use positive plus display adjust
  330. if (ptInputEsc[uEsc].y > 0) {
  331. rcUIRect.top = rcExclude.bottom;
  332. } else {
  333. rcUIRect.top = rcExclude.top - sImeG.yCandHi;
  334. }
  335. if (rcUIRect.left < rcWorkArea.left) {
  336. rcUIRect.left = rcWorkArea.left;
  337. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  338. rcUIRect.left = rcWorkArea.right - sImeG.xCandWi;
  339. }
  340. if (rcUIRect.top < rcWorkArea.top) {
  341. rcUIRect.top = rcWorkArea.top;
  342. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.bottom) {
  343. rcUIRect.top = rcWorkArea.bottom - sImeG.yCandHi;
  344. }
  345. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  346. }
  347. return;
  348. }
  349. /**********************************************************************/
  350. /* AdjustCandBoundry */
  351. /**********************************************************************/
  352. void PASCAL AdjustCandBoundry(
  353. LPPOINT lpptCandWnd) // the position
  354. {
  355. RECT rcWorkArea;
  356. #ifdef MUL_MONITOR
  357. {
  358. RECT rcCandWnd;
  359. *(LPPOINT)&rcCandWnd = *(LPPOINT)lpptCandWnd;
  360. rcCandWnd.right = rcCandWnd.left + sImeG.xCandWi;
  361. rcCandWnd.bottom = rcCandWnd.top + sImeG.yCandHi;
  362. rcWorkArea = ImeMonitorWorkAreaFromRect(&rcCandWnd);
  363. }
  364. #else
  365. rcWorkArea = sImeG.rcWorkArea;
  366. #endif
  367. if (lpptCandWnd->x < rcWorkArea.left) {
  368. lpptCandWnd->x = rcWorkArea.left;
  369. } else if (lpptCandWnd->x + sImeG.xCandWi > rcWorkArea.right) {
  370. lpptCandWnd->x = rcWorkArea.right - sImeG.xCandWi;
  371. }
  372. if (lpptCandWnd->y < rcWorkArea.top) {
  373. lpptCandWnd->y = rcWorkArea.top;
  374. } else if (lpptCandWnd->y + sImeG.yCandHi > rcWorkArea.bottom) {
  375. lpptCandWnd->y = rcWorkArea.bottom - sImeG.yCandHi;
  376. }
  377. return;
  378. }
  379. /**********************************************************************/
  380. /* SetCandPosition() */
  381. /**********************************************************************/
  382. LRESULT PASCAL SetCandPosition(
  383. HWND hCandWnd)
  384. {
  385. HWND hUIWnd;
  386. HIMC hIMC;
  387. LPINPUTCONTEXT lpIMC;
  388. POINT ptNew;
  389. hUIWnd = GetWindow(hCandWnd, GW_OWNER);
  390. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  391. if (!hIMC) {
  392. return (1L);
  393. }
  394. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  395. if (!lpIMC) {
  396. return (1L);
  397. }
  398. ptNew = lpIMC->cfCandForm[0].ptCurrentPos;
  399. ClientToScreen((HWND)lpIMC->hWnd, &ptNew);
  400. if (lpIMC->cfCandForm[0].dwStyle & CFS_FORCE_POSITION) {
  401. } else if (lpIMC->cfCandForm[0].dwStyle == CFS_CANDIDATEPOS) {
  402. AdjustCandBoundry(&ptNew);
  403. } else if (lpIMC->cfCandForm[0].dwStyle == CFS_EXCLUDE) {
  404. if(!sImeG.IC_Trace) {
  405. CalcCandPos(hIMC, hUIWnd, &ptNew);
  406. }
  407. AdjustCandBoundry(&ptNew);
  408. }
  409. SetWindowPos(hCandWnd, NULL, ptNew.x, ptNew.y,
  410. 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
  411. ImmUnlockIMC(hIMC);
  412. return (0L);
  413. }
  414. /**********************************************************************/
  415. /* ShowCand() */
  416. /**********************************************************************/
  417. void PASCAL ShowCand( // Show the candidate window
  418. HWND hUIWnd,
  419. int nShowCandCmd)
  420. {
  421. HGLOBAL hUIPrivate;
  422. LPUIPRIV lpUIPrivate;
  423. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  424. if (!hUIPrivate) { // can not darw candidate window
  425. return;
  426. }
  427. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  428. if (!lpUIPrivate) { // can not draw candidate window
  429. return;
  430. }
  431. if (lpUIPrivate->nShowCandCmd == nShowCandCmd) {
  432. goto SwCandNoChange;
  433. }
  434. if (nShowCandCmd == SW_HIDE) {
  435. lpUIPrivate->fdwSetContext &= ~(ISC_HIDE_CAND_WINDOW);
  436. }
  437. if (!lpUIPrivate->hCandWnd) {
  438. // not in show candidate window mode
  439. } else if (lpUIPrivate->nShowCandCmd == nShowCandCmd) {
  440. } else {
  441. if(nShowCandCmd == SW_HIDE) {
  442. uOpenCand = 0;
  443. } else {
  444. HIMC hIMC;
  445. POINT ptSTWPos;
  446. int Comp_CandWndLen;
  447. RECT rcWorkArea;
  448. uOpenCand = 1;
  449. // reset status window for LINE_UI(FIX_UI)
  450. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  451. if (!hIMC) {
  452. goto ShowCand;
  453. }
  454. ImmGetStatusWindowPos(hIMC, (LPPOINT)&ptSTWPos);
  455. #ifdef MUL_MONITOR
  456. rcWorkArea = ImeMonitorWorkAreaFromPoint(ptSTWPos);
  457. #else
  458. rcWorkArea = sImeG.rcWorkArea;
  459. #endif
  460. Comp_CandWndLen = 0;
  461. if(uOpenCand) {
  462. Comp_CandWndLen += sImeG.xCandWi + UI_MARGIN;
  463. if(uStartComp) {
  464. Comp_CandWndLen += lpImeL->xCompWi + UI_MARGIN;
  465. }
  466. if(ptSTWPos.x + sImeG.xStatusWi + Comp_CandWndLen > rcWorkArea.right) {
  467. PostMessage(GetCompWnd(hUIWnd),
  468. WM_IME_NOTIFY,
  469. IMN_SETCOMPOSITIONWINDOW,
  470. 0);
  471. }
  472. }
  473. }
  474. ShowCand:
  475. ShowWindow(lpUIPrivate->hCandWnd, nShowCandCmd);
  476. lpUIPrivate->nShowCandCmd = nShowCandCmd;
  477. }
  478. SwCandNoChange:
  479. GlobalUnlock(hUIPrivate);
  480. return;
  481. }
  482. /**********************************************************************/
  483. /* OpenCand */
  484. /**********************************************************************/
  485. void PASCAL OpenCand(
  486. HWND hUIWnd)
  487. {
  488. HGLOBAL hUIPrivate;
  489. LPUIPRIV lpUIPrivate;
  490. HIMC hIMC;
  491. LPINPUTCONTEXT lpIMC;
  492. POINT ptWnd;
  493. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  494. if (!hUIPrivate) { // can not darw candidate window
  495. return;
  496. }
  497. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  498. if (!lpUIPrivate) { // can not draw candidate window
  499. return;
  500. }
  501. lpUIPrivate->fdwSetContext |= ISC_SHOWUICANDIDATEWINDOW;
  502. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  503. if (!hIMC) {
  504. goto OpenCandUnlockUIPriv;
  505. }
  506. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  507. if (!lpIMC) {
  508. goto OpenCandUnlockUIPriv;
  509. }
  510. if (lpIMC->cfCandForm[0].dwIndex == 0) {
  511. ptWnd = lpIMC->cfCandForm[0].ptCurrentPos;
  512. ClientToScreen(lpIMC->hWnd, &ptWnd);
  513. if (lpIMC->cfCandForm[0].dwStyle & CFS_FORCE_POSITION) {
  514. } else if (lpIMC->cfCandForm[0].dwStyle == CFS_EXCLUDE) {
  515. POINT ptCaret;
  516. AdjustCandBoundry(&ptWnd);
  517. if((!sImeG.IC_Trace) || (!GetCaretPos(&ptCaret))) {
  518. if(GetCompWnd(hUIWnd)) {
  519. ptWnd.x = ptWnd.y = 0;
  520. ClientToScreen(lpIMC->hWnd, &ptWnd);
  521. ptWnd.x -= lpImeL->cxCompBorder + 1;
  522. ptWnd.y -= lpImeL->cyCompBorder + 1;
  523. } else {
  524. ptWnd.x = lpImeL->cxCompBorder + 1;
  525. ptWnd.y = lpImeL->cyCompBorder + 1;
  526. }
  527. CalcCandPos(hIMC, hUIWnd, &ptWnd);
  528. lpIMC->cfCandForm[0].dwStyle |= CFS_CANDIDATEPOS;
  529. lpIMC->cfCandForm[0].ptCurrentPos = ptWnd;
  530. ScreenToClient(lpIMC->hWnd, &lpIMC->cfCandForm[0].ptCurrentPos);
  531. } else {
  532. AdjustCandPos(hIMC, &ptWnd);
  533. }
  534. } else if (lpIMC->cfCandForm[0].dwStyle == CFS_CANDIDATEPOS) {
  535. AdjustCandBoundry(&ptWnd);
  536. } else {
  537. if (lpUIPrivate->nShowCompCmd != SW_HIDE) {
  538. ptWnd.x = ptWnd.y = 0;
  539. ClientToScreen(lpUIPrivate->hCompWnd, &ptWnd);
  540. } else {
  541. ptWnd = lpIMC->cfCompForm.ptCurrentPos;
  542. ClientToScreen(lpIMC->hWnd, &ptWnd);
  543. }
  544. ptWnd.x -= lpImeL->cxCompBorder + 1;
  545. ptWnd.y -= lpImeL->cyCompBorder + 1;
  546. CalcCandPos(hIMC, hUIWnd, &ptWnd);
  547. lpIMC->cfCandForm[0].dwStyle |= CFS_CANDIDATEPOS;
  548. lpIMC->cfCandForm[0].ptCurrentPos = ptWnd;
  549. ScreenToClient(lpIMC->hWnd, &lpIMC->cfCandForm[0].ptCurrentPos);
  550. }
  551. } else {
  552. // make cand windows trace comp window !
  553. if (lpUIPrivate->nShowCompCmd != SW_HIDE) {
  554. ptWnd.x = ptWnd.y = 0;
  555. ClientToScreen(lpUIPrivate->hCompWnd, &ptWnd);
  556. } else {
  557. ptWnd = lpIMC->cfCompForm.ptCurrentPos;
  558. ClientToScreen(lpIMC->hWnd, &ptWnd);
  559. }
  560. ptWnd.x -= lpImeL->cxCompBorder + 1;
  561. ptWnd.y -= lpImeL->cyCompBorder + 1;
  562. CalcCandPos(hIMC, hUIWnd, &ptWnd);
  563. lpIMC->cfCandForm[0].dwStyle |= CFS_CANDIDATEPOS;
  564. lpIMC->cfCandForm[0].ptCurrentPos = ptWnd;
  565. ScreenToClient(lpIMC->hWnd, &lpIMC->cfCandForm[0].ptCurrentPos);
  566. }
  567. ImmUnlockIMC(hIMC);
  568. if (lpUIPrivate->hCandWnd) {
  569. SetWindowPos(lpUIPrivate->hCandWnd,
  570. NULL,
  571. ptWnd.x,
  572. ptWnd.y,
  573. 0,
  574. 0,
  575. SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
  576. } else {
  577. lpUIPrivate->hCandWnd = CreateWindowEx(
  578. WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME,
  579. szCandClassName,
  580. NULL,
  581. WS_POPUP|WS_DISABLED,
  582. ptWnd.x,
  583. ptWnd.y,
  584. sImeG.xCandWi,
  585. sImeG.yCandHi,
  586. hUIWnd,
  587. (HMENU)NULL,
  588. hInst,
  589. NULL);
  590. SetWindowLong(lpUIPrivate->hCandWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG);
  591. SetWindowLong(lpUIPrivate->hCandWnd, UI_MOVE_XY, 0L);
  592. }
  593. ShowCand(hUIWnd, SW_SHOWNOACTIVATE);
  594. OpenCandUnlockUIPriv:
  595. GlobalUnlock(hUIPrivate);
  596. return;
  597. }
  598. /**********************************************************************/
  599. /* CloseCand */
  600. /**********************************************************************/
  601. void PASCAL CloseCand(
  602. HWND hUIWnd)
  603. {
  604. uOpenCand = 0;
  605. ShowCand(hUIWnd, SW_HIDE);
  606. return;
  607. }
  608. /**********************************************************************/
  609. /* DestroyCandWindow */
  610. /**********************************************************************/
  611. void PASCAL DestroyCandWindow(
  612. HWND hCandWnd)
  613. {
  614. HGLOBAL hUIPrivate;
  615. LPUIPRIV lpUIPrivate;
  616. if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
  617. // undo the drag border
  618. DrawDragBorder(hCandWnd,
  619. GetWindowLong(hCandWnd, UI_MOVE_XY),
  620. GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
  621. }
  622. hUIPrivate = (HGLOBAL)GetWindowLongPtr(GetWindow(hCandWnd, GW_OWNER),
  623. IMMGWLP_PRIVATE);
  624. if (!hUIPrivate) { // can not darw candidate window
  625. return;
  626. }
  627. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  628. if (!lpUIPrivate) { // can not draw candidate window
  629. return;
  630. }
  631. lpUIPrivate->nShowCandCmd = SW_HIDE;
  632. lpUIPrivate->hCandWnd = (HWND)NULL;
  633. GlobalUnlock(hUIPrivate);
  634. return;
  635. }
  636. /**********************************************************************/
  637. /* MouseSelectCandStr() */
  638. /**********************************************************************/
  639. void PASCAL MouseSelectCandStr(
  640. HWND hCandWnd,
  641. LPPOINT lpCursor)
  642. {
  643. HIMC hIMC;
  644. LPINPUTCONTEXT lpIMC;
  645. LPCANDIDATEINFO lpCandInfo;
  646. LPCANDIDATELIST lpCandList;
  647. DWORD dwValue;
  648. hIMC = (HIMC)GetWindowLongPtr(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
  649. if (!hIMC) {
  650. return;
  651. }
  652. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  653. if (!lpIMC) {
  654. return;
  655. }
  656. if (!lpIMC->hCandInfo) {
  657. ImmUnlockIMC(hIMC);
  658. return;
  659. }
  660. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  661. if (!lpCandInfo) {
  662. ImmUnlockIMC(hIMC);
  663. return;
  664. }
  665. dwValue = (lpCursor->y - sImeG.rcCandText.top) / sImeG.yChiCharHi;
  666. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  667. lpCandInfo->dwOffset[0]);
  668. dwValue = dwValue + lpCandList->dwSelection /
  669. lpCandList->dwPageSize * lpCandList->dwPageSize;
  670. if (dwValue >= lpCandList->dwCount) {
  671. // invalid choice
  672. MessageBeep((UINT)-1);
  673. } else {
  674. NotifyIME(hIMC, NI_SELECTCANDIDATESTR, 0, dwValue);
  675. }
  676. ImmUnlockIMCC(lpIMC->hCandInfo);
  677. ImmUnlockIMC(hIMC);
  678. return;
  679. }
  680. /**********************************************************************/
  681. /* CandPageDownUP() */
  682. /**********************************************************************/
  683. void PASCAL CandPageDownUP(
  684. HWND hCandWnd,
  685. UINT uCandDownUp)
  686. {
  687. HIMC hIMC;
  688. LPINPUTCONTEXT lpIMC;
  689. LPPRIVCONTEXT lpImcP;
  690. LPCANDIDATEINFO lpCandInfo;
  691. LPCANDIDATELIST lpCandList;
  692. HDC hDC;
  693. HBITMAP hCandHpBmp, hCandUpBmp, hCandDpBmp, hCandEpBmp;
  694. HBITMAP hOldBmp;
  695. HDC hMemDC;
  696. // change candlist
  697. hIMC = (HIMC)GetWindowLongPtr(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
  698. if (!hIMC) {
  699. return;
  700. }
  701. // get lpIMC
  702. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  703. if (!lpIMC) {
  704. return;
  705. }
  706. // get lpImcP
  707. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  708. if (!lpImcP) {
  709. return;
  710. }
  711. // get lpCandInfo
  712. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  713. if (!lpCandInfo) {
  714. return;
  715. }
  716. // get lpCandList and init dwCount & dwSelection
  717. lpCandList = (LPCANDIDATELIST)
  718. ((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[0]);
  719. switch(uCandDownUp) {
  720. case uCandHome:
  721. ChooseCand(0x24, lpIMC, lpCandInfo, lpImcP);
  722. NotifyIME(hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  723. break;
  724. case uCandUp:
  725. ChooseCand('-', lpIMC, lpCandInfo, lpImcP);
  726. NotifyIME(hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  727. break;
  728. case uCandDown:
  729. ChooseCand('=', lpIMC, lpCandInfo, lpImcP);
  730. NotifyIME(hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  731. break;
  732. case uCandEnd:
  733. ChooseCand(0x23, lpIMC, lpCandInfo, lpImcP);
  734. NotifyIME(hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  735. break;
  736. default:
  737. break;
  738. }
  739. ImmUnlockIMCC(lpIMC->hPrivate);
  740. ImmUnlockIMCC(lpIMC->hCandInfo);
  741. ImmUnlockIMC(hIMC);
  742. // draw button down
  743. hDC = GetDC(hCandWnd);
  744. if ( hDC == NULL )
  745. return;
  746. hMemDC = CreateCompatibleDC(hDC);
  747. if ( hMemDC == NULL )
  748. {
  749. ReleaseDC(hCandWnd, hDC);
  750. return;
  751. }
  752. hOldBmp = NULL;
  753. switch(uCandDownUp) {
  754. case uCandHome:
  755. hCandHpBmp = LoadBitmap(hInst, TEXT("CandHp"));
  756. if ( hCandHpBmp != NULL)
  757. {
  758. hOldBmp = SelectObject(hMemDC, hCandHpBmp);
  759. BitBlt(hDC, sImeG.rcCandBTH.left, sImeG.rcCandBTH.top,
  760. sImeG.rcCandBTH.right - sImeG.rcCandBTH.left,
  761. STATUS_DIM_Y,
  762. hMemDC, 0, 0, SRCCOPY);
  763. DeleteObject(hCandHpBmp);
  764. }
  765. break;
  766. case uCandUp:
  767. hCandUpBmp = LoadBitmap(hInst, TEXT("CandUp"));
  768. if ( hCandUpBmp != NULL )
  769. {
  770. hOldBmp = SelectObject(hMemDC, hCandUpBmp);
  771. BitBlt(hDC, sImeG.rcCandBTU.left, sImeG.rcCandBTU.top,
  772. sImeG.rcCandBTU.right - sImeG.rcCandBTU.left,
  773. STATUS_DIM_Y,
  774. hMemDC, 0, 0, SRCCOPY);
  775. DeleteObject(hCandUpBmp);
  776. }
  777. break;
  778. case uCandDown:
  779. hCandDpBmp = LoadBitmap(hInst, TEXT("CandDp"));
  780. if ( hCandDpBmp != NULL)
  781. {
  782. hOldBmp = SelectObject(hMemDC, hCandDpBmp);
  783. BitBlt(hDC, sImeG.rcCandBTD.left, sImeG.rcCandBTD.top,
  784. sImeG.rcCandBTD.right - sImeG.rcCandBTD.left,
  785. STATUS_DIM_Y,
  786. hMemDC, 0, 0, SRCCOPY);
  787. DeleteObject(hCandDpBmp);
  788. }
  789. break;
  790. case uCandEnd:
  791. hCandEpBmp = LoadBitmap(hInst, TEXT("CandEp"));
  792. if ( hCandEpBmp != NULL)
  793. {
  794. hOldBmp = SelectObject(hMemDC, hCandEpBmp);
  795. BitBlt(hDC, sImeG.rcCandBTE.left, sImeG.rcCandBTE.top,
  796. sImeG.rcCandBTE.right - sImeG.rcCandBTE.left,
  797. STATUS_DIM_Y,
  798. hMemDC, 0, 0, SRCCOPY);
  799. DeleteObject(hCandEpBmp);
  800. }
  801. break;
  802. default:
  803. break;
  804. }
  805. if ( hOldBmp != NULL)
  806. SelectObject(hMemDC, hOldBmp);
  807. DeleteDC(hMemDC);
  808. ReleaseDC(hCandWnd, hDC);
  809. return;
  810. }
  811. /**********************************************************************/
  812. /* CandSetCursor() */
  813. /**********************************************************************/
  814. void PASCAL CandSetCursor(
  815. HWND hCandWnd,
  816. LPARAM lParam)
  817. {
  818. POINT ptCursor;
  819. RECT rcWnd;
  820. if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) !=
  821. WINDOW_NOT_DRAG) {
  822. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  823. return;
  824. }
  825. if (HIWORD(lParam) == WM_LBUTTONDOWN) {
  826. SystemParametersInfo(SPI_GETWORKAREA, 0, &sImeG.rcWorkArea, 0);
  827. GetCursorPos(&ptCursor);
  828. ScreenToClient(hCandWnd, &ptCursor);
  829. if (PtInRect(&sImeG.rcCandText, ptCursor)
  830. && sImeG.IC_Trace) {
  831. SetCursor(LoadCursor(hInst, szHandCursor));
  832. MouseSelectCandStr(hCandWnd, &ptCursor);
  833. return;
  834. } else if (PtInRect(&sImeG.rcCandBTH, ptCursor)) {
  835. CandPageDownUP(hCandWnd, uCandHome);
  836. return;
  837. } else if (PtInRect(&sImeG.rcCandBTU, ptCursor)) {
  838. CandPageDownUP(hCandWnd, uCandUp);
  839. return;
  840. } else if (PtInRect(&sImeG.rcCandBTD, ptCursor)) {
  841. CandPageDownUP(hCandWnd, uCandDown);
  842. return;
  843. } else if (PtInRect(&sImeG.rcCandBTE, ptCursor)) {
  844. CandPageDownUP(hCandWnd, uCandEnd);
  845. return;
  846. } else {
  847. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  848. }
  849. } else if (HIWORD(lParam) == WM_LBUTTONUP) {
  850. HDC hDC;
  851. HBITMAP hCandHBmp, hCandUBmp, hCandDBmp, hCandEBmp;
  852. HBITMAP hOldBmp;
  853. HDC hMemDC;
  854. hDC = GetDC(hCandWnd);
  855. hMemDC = CreateCompatibleDC(hDC);
  856. if ( hMemDC )
  857. {
  858. hCandHBmp = LoadBitmap(hInst, TEXT("CandH"));
  859. if ( hCandHBmp )
  860. {
  861. hOldBmp = SelectObject(hMemDC, hCandHBmp);
  862. BitBlt(hDC, sImeG.rcCandBTH.left, sImeG.rcCandBTH.top,
  863. sImeG.rcCandBTH.right - sImeG.rcCandBTH.left,
  864. STATUS_DIM_Y,
  865. hMemDC, 0, 0, SRCCOPY);
  866. SelectObject(hMemDC, hOldBmp);
  867. DeleteObject(hCandHBmp);
  868. }
  869. hCandUBmp = LoadBitmap(hInst, TEXT("CandU"));
  870. if ( hCandUBmp )
  871. {
  872. hOldBmp=SelectObject(hMemDC, hCandUBmp);
  873. BitBlt(hDC, sImeG.rcCandBTU.left, sImeG.rcCandBTU.top,
  874. sImeG.rcCandBTU.right - sImeG.rcCandBTU.left,
  875. STATUS_DIM_Y,
  876. hMemDC, 0, 0, SRCCOPY);
  877. SelectObject(hMemDC, hOldBmp);
  878. DeleteObject(hCandUBmp);
  879. }
  880. hCandDBmp = LoadBitmap(hInst, TEXT("CandD"));
  881. if ( hCandDBmp )
  882. {
  883. hOldBmp=SelectObject(hMemDC, hCandDBmp);
  884. BitBlt(hDC, sImeG.rcCandBTD.left, sImeG.rcCandBTD.top,
  885. sImeG.rcCandBTD.right - sImeG.rcCandBTD.left,
  886. STATUS_DIM_Y,
  887. hMemDC, 0, 0, SRCCOPY);
  888. SelectObject(hMemDC, hOldBmp);
  889. DeleteObject(hCandDBmp);
  890. }
  891. hCandEBmp = LoadBitmap(hInst, TEXT("CandE"));
  892. if ( hCandEBmp )
  893. {
  894. hOldBmp=SelectObject(hMemDC, hCandEBmp);
  895. BitBlt(hDC, sImeG.rcCandBTE.left, sImeG.rcCandBTE.top,
  896. sImeG.rcCandBTE.right - sImeG.rcCandBTE.left,
  897. STATUS_DIM_Y,
  898. hMemDC, 0, 0, SRCCOPY);
  899. SelectObject(hMemDC, hOldBmp);
  900. DeleteObject(hCandEBmp);
  901. }
  902. DeleteDC(hMemDC);
  903. }
  904. ReleaseDC(hCandWnd, hDC);
  905. return;
  906. } else {
  907. SystemParametersInfo(SPI_GETWORKAREA, 0, &sImeG.rcWorkArea, 0);
  908. GetCursorPos(&ptCursor);
  909. ScreenToClient(hCandWnd, &ptCursor);
  910. if (PtInRect(&sImeG.rcCandText, ptCursor)) {
  911. SetCursor(LoadCursor(hInst, szHandCursor));
  912. return;
  913. } else if (PtInRect(&sImeG.rcCandBTH, ptCursor)) {
  914. SetCursor(LoadCursor(hInst, szHandCursor));
  915. } else if (PtInRect(&sImeG.rcCandBTU, ptCursor)) {
  916. SetCursor(LoadCursor(hInst, szHandCursor));
  917. } else if (PtInRect(&sImeG.rcCandBTD, ptCursor)) {
  918. SetCursor(LoadCursor(hInst, szHandCursor));
  919. } else if (PtInRect(&sImeG.rcCandBTE, ptCursor)) {
  920. SetCursor(LoadCursor(hInst, szHandCursor));
  921. } else {
  922. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  923. }
  924. return;
  925. }
  926. SetCapture(hCandWnd);
  927. GetCursorPos(&ptCursor);
  928. SetWindowLong(hCandWnd, UI_MOVE_XY,
  929. MAKELONG(ptCursor.x, ptCursor.y));
  930. GetWindowRect(hCandWnd, &rcWnd);
  931. SetWindowLong(hCandWnd, UI_MOVE_OFFSET,
  932. MAKELONG(ptCursor.x - rcWnd.left, ptCursor.y - rcWnd.top));
  933. DrawDragBorder(hCandWnd, MAKELONG(ptCursor.x, ptCursor.y),
  934. GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
  935. return;
  936. }
  937. /**********************************************************************/
  938. /* CandButtonUp() */
  939. /**********************************************************************/
  940. BOOL PASCAL CandButtonUp(
  941. HWND hCandWnd)
  942. {
  943. LONG lTmpCursor, lTmpOffset;
  944. POINT pt;
  945. HWND hUIWnd;
  946. HIMC hIMC;
  947. LPINPUTCONTEXT lpIMC;
  948. if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) == WINDOW_NOT_DRAG) {
  949. return (FALSE);
  950. }
  951. lTmpCursor = GetWindowLong(hCandWnd, UI_MOVE_XY);
  952. // calculate the org by the offset
  953. lTmpOffset = GetWindowLong(hCandWnd, UI_MOVE_OFFSET);
  954. pt.x = (*(LPPOINTS)&lTmpCursor).x - (*(LPPOINTS)&lTmpOffset).x;
  955. pt.y = (*(LPPOINTS)&lTmpCursor).y - (*(LPPOINTS)&lTmpOffset).y;
  956. DrawDragBorder(hCandWnd, lTmpCursor, lTmpOffset);
  957. SetWindowLong(hCandWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG);
  958. ReleaseCapture();
  959. hUIWnd = GetWindow(hCandWnd, GW_OWNER);
  960. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  961. if (!hIMC) {
  962. return (FALSE);
  963. }
  964. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  965. if (!lpIMC) {
  966. return (FALSE);
  967. }
  968. AdjustCandBoundry(&pt);
  969. ScreenToClient(lpIMC->hWnd, &pt);
  970. lpIMC->cfCandForm[0].dwStyle |= CFS_CANDIDATEPOS;
  971. lpIMC->cfCandForm[0].ptCurrentPos = pt;
  972. ImmUnlockIMC(hIMC);
  973. PostMessage(hCandWnd, WM_IME_NOTIFY, IMN_SETCANDIDATEPOS, 0x0001);
  974. return (TRUE);
  975. }
  976. /**********************************************************************/
  977. /* UpdateCandWindow() */
  978. /**********************************************************************/
  979. void PASCAL PaintCandWindow(
  980. HWND hCandWnd,
  981. HDC hDC)
  982. {
  983. HIMC hIMC;
  984. LPINPUTCONTEXT lpIMC;
  985. LPCANDIDATEINFO lpCandInfo;
  986. LPCANDIDATELIST lpCandList;
  987. LPPRIVCONTEXT lpImcP;
  988. HGDIOBJ hOldFont;
  989. DWORD dwStart, dwEnd;
  990. TCHAR szStrBuf[2 * MAXSTRLEN * sizeof(WCHAR) / sizeof(TCHAR) + 1];
  991. int i;
  992. HBITMAP hCandIconBmp, hCandInfBmp;
  993. HBITMAP hOldBmp, hCandHBmp, hCandUBmp, hCandDBmp, hCandEBmp;
  994. HDC hMemDC;
  995. hIMC = (HIMC)GetWindowLongPtr(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
  996. if (!hIMC) {
  997. return;
  998. }
  999. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  1000. if (!lpIMC) {
  1001. return;
  1002. }
  1003. if (!lpIMC->hCandInfo) {
  1004. goto UpCandW2UnlockIMC;
  1005. }
  1006. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  1007. if (!lpCandInfo) {
  1008. goto UpCandW2UnlockIMC;
  1009. }
  1010. if (!lpIMC->hPrivate) {
  1011. goto UpCandW2UnlockCandInfo;
  1012. }
  1013. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  1014. if (!lpImcP) {
  1015. goto UpCandW2UnlockCandInfo;
  1016. }
  1017. // set font
  1018. if (sImeG.fDiffSysCharSet) {
  1019. LOGFONT lfFont;
  1020. ZeroMemory(&lfFont, sizeof(lfFont));
  1021. hOldFont = GetCurrentObject(hDC, OBJ_FONT);
  1022. lfFont.lfHeight = -MulDiv(12, GetDeviceCaps(hDC, LOGPIXELSY), 72);
  1023. lfFont.lfCharSet = NATIVE_CHARSET;
  1024. lstrcpy(lfFont.lfFaceName, TEXT("Simsun"));
  1025. SelectObject(hDC, CreateFontIndirect(&lfFont));
  1026. }
  1027. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  1028. lpCandInfo->dwOffset[0]);
  1029. dwStart = lpCandList->dwSelection;
  1030. dwEnd = dwStart + lpCandList->dwPageSize;
  1031. if (dwEnd > lpCandList->dwCount) {
  1032. dwEnd = lpCandList->dwCount;
  1033. }
  1034. // draw CandWnd Layout
  1035. if (sImeG.IC_Trace) {
  1036. RECT rcWnd;
  1037. GetClientRect(hCandWnd, &rcWnd);
  1038. DrawConcaveRect(hDC,
  1039. rcWnd.left,
  1040. rcWnd.top + UI_CANDINF,
  1041. rcWnd.right - 1,
  1042. rcWnd.bottom - 1);
  1043. } else {
  1044. RECT rcWnd;
  1045. GetClientRect(hCandWnd, &rcWnd);
  1046. DrawConcaveRect(hDC,
  1047. sImeG.rcCandText.left - 1,
  1048. rcWnd.top,
  1049. sImeG.rcCandText.right + 1,
  1050. rcWnd.bottom - 1);
  1051. }
  1052. SetTextColor(hDC, RGB(0x00, 0x00, 0x00));
  1053. SetBkColor(hDC, RGB(0xC0, 0xC0, 0xC0));
  1054. if (sImeG.IC_Trace) {
  1055. ExtTextOut(hDC, sImeG.rcCandText.left, sImeG.rcCandText.top,
  1056. ETO_OPAQUE, &sImeG.rcCandText, NULL, 0, NULL);
  1057. szStrBuf[0] = TEXT('1');
  1058. szStrBuf[1] = TEXT(':');
  1059. for (i = 0; dwStart < dwEnd; dwStart++, i++) {
  1060. int iLen;
  1061. iLen = 0;
  1062. szStrBuf[0] = szDigit[i + CAND_START];
  1063. #if defined(COMBO_IME)
  1064. if(sImeL.dwRegImeIndex == INDEX_GB || sImeL.dwRegImeIndex == INDEX_GBK){
  1065. iLen = lstrlen((LPTSTR)((LPBYTE)lpCandList +
  1066. lpCandList->dwOffset[dwStart]));
  1067. if (iLen > 10 * 2 / sizeof(TCHAR)) {
  1068. iLen = 10 * 2 / sizeof(TCHAR);
  1069. CopyMemory(&szStrBuf[2],
  1070. ((LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart])),
  1071. (iLen - 2) * sizeof(TCHAR));
  1072. // maybe not good for UNICODE
  1073. szStrBuf[iLen] = TEXT('.');
  1074. szStrBuf[iLen+1] = TEXT('.');
  1075. szStrBuf[iLen+2] = TEXT('\0');
  1076. } else {
  1077. CopyMemory(&szStrBuf[2],
  1078. (LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart]),
  1079. iLen*sizeof(TCHAR));
  1080. }
  1081. }else if(sImeL.dwRegImeIndex == INDEX_UNICODE){
  1082. WORD wCode;
  1083. wCode = *(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart]);
  1084. #ifdef UNICODE
  1085. szStrBuf[2]= wCode;
  1086. szStrBuf[3]=TEXT('\0');
  1087. #else
  1088. szStrBuf[2]= LOBYTE(wCode);
  1089. szStrBuf[3]= HIBYTE(wCode);
  1090. szStrBuf[4]=TEXT('\0');
  1091. #endif
  1092. iLen = 2/sizeof(TCHAR);
  1093. }
  1094. #else
  1095. iLen = lstrlen((LPTSTR)((LPBYTE)lpCandList +
  1096. lpCandList->dwOffset[dwStart]));
  1097. if (iLen > 10 * 2 / sizeof(TCHAR)) {
  1098. iLen = 10 * 2 / sizeof(TCHAR);
  1099. CopyMemory(&szStrBuf[2],
  1100. ((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart]),
  1101. (iLen - 2) * sizeof(TCHAR));
  1102. szStrBuf[iLen] = TEXT('.');
  1103. szStrBuf[iLen+1] = TEXT('.');
  1104. szStrBuf[iLen+2] = TEXT('\0');
  1105. } else {
  1106. CopyMemory(&szStrBuf[2],
  1107. ((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart]),
  1108. iLen*sizeof(TCHAR));
  1109. }
  1110. #endif //COMBO_IME
  1111. ExtTextOut(hDC, sImeG.rcCandText.left,
  1112. sImeG.rcCandText.top + i * sImeG.yChiCharHi,
  1113. (UINT)0, NULL,
  1114. szStrBuf,
  1115. iLen + 2, NULL);
  1116. // QW/GB info
  1117. {
  1118. int iMyLen;
  1119. WORD wCode, wGB;
  1120. TCHAR AbSeq[5];
  1121. TCHAR GbSeq[5];
  1122. TCHAR szMyStrBuf[12 * sizeof(WCHAR) / sizeof(TCHAR)];
  1123. RECT GBARInfo;
  1124. #ifdef UNICODE
  1125. wCode = *(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart]);
  1126. AbSeq[0] = wCode;
  1127. AbSeq[1] = TEXT('\0');
  1128. // change the CP_ACP to 936, so that it can work under Multilingul Env.
  1129. WideCharToMultiByte(NATIVE_ANSI_CP, WC_COMPOSITECHECK, AbSeq, 1, (BYTE*)GbSeq, sizeof(GbSeq), NULL, NULL);
  1130. wGB = HIBYTE(GbSeq[0]) | (LOBYTE(GbSeq[0]) << 8);
  1131. wsprintf (GbSeq,TEXT("%04lx"),wGB); // get GB string
  1132. wGB -= 0xa0a0;
  1133. wsprintf (AbSeq,TEXT("%02d%02d"),HIBYTE(wGB),LOBYTE(wGB));
  1134. #else
  1135. wCode = *(LPUNAWORD)((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart]);
  1136. MultiByteToWideChar(CP_ACP, NULL, &wCode, 2, &wGB, 1);
  1137. wCode = HIBYTE(wCode) | (LOBYTE(wCode) << 8);
  1138. wsprintf (GbSeq,"%04lx",wCode); // get GB string
  1139. wCode -= 0xa0a0;
  1140. wsprintf (AbSeq,"%02d%02d",HIBYTE(wCode),LOBYTE(wCode));
  1141. #endif
  1142. // if (lpImcP->fdwGB & IME_SELECT_GB) {
  1143. #if defined(COMBO_IME)
  1144. switch(sImeL.dwRegImeIndex){
  1145. case INDEX_GB:
  1146. lstrcpy (szMyStrBuf,TEXT("("));
  1147. lstrcat (szMyStrBuf,GbSeq);
  1148. lstrcat (szMyStrBuf,TEXT(", "));
  1149. lstrcat (szMyStrBuf,AbSeq);
  1150. lstrcat (szMyStrBuf,TEXT(")"));
  1151. iMyLen = 12;
  1152. break;
  1153. case INDEX_GBK:
  1154. lstrcpy (szMyStrBuf,TEXT(" "));
  1155. lstrcat (szMyStrBuf,TEXT("("));
  1156. lstrcat (szMyStrBuf,GbSeq);
  1157. lstrcat (szMyStrBuf,TEXT(")"));
  1158. iMyLen = 10;
  1159. break;
  1160. case INDEX_UNICODE: //adjust code display info
  1161. lstrcpy (szMyStrBuf,TEXT("("));
  1162. lstrcat (szMyStrBuf,GbSeq);
  1163. lstrcat (szMyStrBuf,TEXT(", "));
  1164. wsprintf (AbSeq,TEXT("%04lx"),wCode);
  1165. lstrcat (szMyStrBuf, AbSeq);
  1166. lstrcat (szMyStrBuf,TEXT(")"));
  1167. iMyLen = lstrlen(szMyStrBuf);
  1168. break;
  1169. }
  1170. #else //COMBO_IME
  1171. #ifdef GB
  1172. lstrcpy (szMyStrBuf,TEXT("("));
  1173. lstrcat (szMyStrBuf,GbSeq);
  1174. lstrcat (szMyStrBuf,TEXT(", "));
  1175. lstrcat (szMyStrBuf,AbSeq);
  1176. lstrcat (szMyStrBuf,TEXT(")"));
  1177. iMyLen = 12;
  1178. #else
  1179. lstrcpy (szMyStrBuf,TEXT(" "));
  1180. lstrcat (szMyStrBuf,TEXT("("));
  1181. lstrcat (szMyStrBuf,GbSeq);
  1182. lstrcat (szMyStrBuf,TEXT(")"));
  1183. iMyLen = 10;
  1184. #endif //GB
  1185. #endif //COMBO_IME
  1186. GBARInfo.top = sImeG.rcCandText.top + i * sImeG.yChiCharHi;
  1187. GBARInfo.left = sImeG.rcCandText.left;
  1188. GBARInfo.right = sImeG.rcCandText.right;
  1189. GBARInfo.bottom = sImeG.rcCandText.bottom;
  1190. DrawText(hDC, szMyStrBuf, lstrlen(szMyStrBuf),
  1191. &GBARInfo, DT_RIGHT | DT_SINGLELINE);
  1192. }
  1193. }
  1194. } else {
  1195. int nX;
  1196. ExtTextOut(hDC, sImeG.rcCandText.left, sImeG.rcCandText.top + 1,
  1197. ETO_OPAQUE, &sImeG.rcCandText, NULL, 0, NULL);
  1198. nX = 0;
  1199. for (i = 0; dwStart < dwEnd; dwStart++, i++) {
  1200. int iLen;
  1201. int j, k;
  1202. TCHAR AnsiStr[MAXCODE+1];
  1203. SIZE StrSize;
  1204. // display numbers
  1205. AnsiStr[0] = szDigit[i + CAND_START];
  1206. AnsiStr[1] = TEXT(':');
  1207. AnsiStr[2] = 0;
  1208. ExtTextOut(hDC, sImeG.rcCandText.left + nX,
  1209. sImeG.rcCandText.top + 1,
  1210. ETO_CLIPPED, &sImeG.rcCandText,
  1211. AnsiStr,
  1212. lstrlen(AnsiStr), NULL);
  1213. if(!GetTextExtentPoint(hDC, (LPCTSTR)AnsiStr, lstrlen(AnsiStr), &StrSize))
  1214. memset(&StrSize, 0, sizeof(SIZE));
  1215. nX += StrSize.cx;
  1216. // display chinese word and code
  1217. iLen = lstrlen((LPTSTR)((LPBYTE)lpCandList +
  1218. lpCandList->dwOffset[dwStart]));
  1219. CopyMemory(szStrBuf,
  1220. ((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart]),
  1221. iLen*sizeof(TCHAR));
  1222. for(j=0; j<iLen; j++) {
  1223. #ifdef UNICODE
  1224. if(szStrBuf[j] > 0x100) {
  1225. #else
  1226. if(szStrBuf[j] & 0x80) {
  1227. #endif
  1228. j++;
  1229. continue;
  1230. }
  1231. break;
  1232. }
  1233. k = j-1;
  1234. for(j=0; j<iLen - k; j++) {
  1235. AnsiStr[j] = szStrBuf[j+k];
  1236. }
  1237. AnsiStr[j] = 0;
  1238. szStrBuf[k] = 0;
  1239. ExtTextOut(hDC, sImeG.rcCandText.left + nX,
  1240. sImeG.rcCandText.top + 1,
  1241. ETO_CLIPPED, &sImeG.rcCandText,
  1242. szStrBuf,
  1243. lstrlen(szStrBuf), NULL);
  1244. if(!GetTextExtentPoint(hDC, (LPCTSTR)szStrBuf, lstrlen(szStrBuf), &StrSize))
  1245. memset(&StrSize, 0, sizeof(SIZE));
  1246. nX += StrSize.cx;
  1247. ExtTextOut(hDC, sImeG.rcCandText.left + nX,
  1248. sImeG.rcCandText.top + 1,
  1249. ETO_CLIPPED, &sImeG.rcCandText,
  1250. AnsiStr,
  1251. lstrlen(AnsiStr), NULL);
  1252. if(!GetTextExtentPoint(hDC, (LPCTSTR)AnsiStr, lstrlen(AnsiStr), &StrSize))
  1253. memset(&StrSize, 0, sizeof(SIZE));
  1254. nX += StrSize.cx;
  1255. }
  1256. }
  1257. // load all bitmap
  1258. if (sImeG.IC_Trace) {
  1259. hCandInfBmp = LoadBitmap(hInst, TEXT("Candinf"));
  1260. } else {
  1261. hCandInfBmp = NULL;
  1262. }
  1263. hMemDC = CreateCompatibleDC(hDC);
  1264. if ( hMemDC != NULL )
  1265. {
  1266. hCandIconBmp = LoadBitmap(hInst, TEXT("CandSel"));
  1267. if ( hCandIconBmp )
  1268. {
  1269. hOldBmp = SelectObject(hMemDC, hCandIconBmp);
  1270. BitBlt(hDC, sImeG.rcCandIcon.left, sImeG.rcCandIcon.top,
  1271. sImeG.rcCandIcon.right - sImeG.rcCandIcon.left,
  1272. STATUS_DIM_Y,
  1273. hMemDC, 0, 0, SRCCOPY);
  1274. SelectObject(hMemDC, hOldBmp);
  1275. DeleteObject(hCandIconBmp);
  1276. }
  1277. if(hCandInfBmp) {
  1278. hOldBmp = SelectObject(hMemDC, hCandInfBmp);
  1279. BitBlt(hDC, sImeG.rcCandInf.left, sImeG.rcCandInf.top,
  1280. sImeG.rcCandInf.right - sImeG.rcCandInf.left,
  1281. STATUS_DIM_Y,
  1282. hMemDC, 0, 0, SRCCOPY);
  1283. SelectObject(hMemDC, hOldBmp);
  1284. }
  1285. hCandHBmp = LoadBitmap(hInst, TEXT("CandH"));
  1286. if ( hCandHBmp )
  1287. {
  1288. hOldBmp = SelectObject(hMemDC, hCandHBmp);
  1289. BitBlt(hDC, sImeG.rcCandBTH.left, sImeG.rcCandBTH.top,
  1290. sImeG.rcCandBTH.right - sImeG.rcCandBTH.left,
  1291. STATUS_DIM_Y,
  1292. hMemDC, 0, 0, SRCCOPY);
  1293. SelectObject(hMemDC, hOldBmp);
  1294. DeleteObject(hCandHBmp);
  1295. }
  1296. hCandUBmp = LoadBitmap(hInst, TEXT("CandU"));
  1297. if ( hCandUBmp )
  1298. {
  1299. hOldBmp = SelectObject(hMemDC, hCandUBmp);
  1300. BitBlt(hDC, sImeG.rcCandBTU.left, sImeG.rcCandBTU.top,
  1301. sImeG.rcCandBTU.right - sImeG.rcCandBTU.left,
  1302. STATUS_DIM_Y,
  1303. hMemDC, 0, 0, SRCCOPY);
  1304. SelectObject(hMemDC, hOldBmp);
  1305. DeleteObject(hCandUBmp);
  1306. }
  1307. hCandDBmp = LoadBitmap(hInst, TEXT("CandD"));
  1308. if ( hCandDBmp )
  1309. {
  1310. hOldBmp = SelectObject(hMemDC, hCandDBmp);
  1311. BitBlt(hDC, sImeG.rcCandBTD.left, sImeG.rcCandBTD.top,
  1312. sImeG.rcCandBTD.right - sImeG.rcCandBTD.left,
  1313. STATUS_DIM_Y,
  1314. hMemDC, 0, 0, SRCCOPY);
  1315. SelectObject(hMemDC, hOldBmp);
  1316. DeleteObject(hCandDBmp);
  1317. }
  1318. hCandEBmp = LoadBitmap(hInst, TEXT("CandE"));
  1319. if ( hCandEBmp )
  1320. {
  1321. hOldBmp = SelectObject(hMemDC, hCandEBmp);
  1322. BitBlt(hDC, sImeG.rcCandBTE.left, sImeG.rcCandBTE.top,
  1323. sImeG.rcCandBTE.right - sImeG.rcCandBTE.left,
  1324. STATUS_DIM_Y,
  1325. hMemDC, 0, 0, SRCCOPY);
  1326. SelectObject(hMemDC, hOldBmp);
  1327. DeleteObject(hCandEBmp);
  1328. }
  1329. DeleteDC(hMemDC);
  1330. }
  1331. if ( hCandInfBmp )
  1332. DeleteObject(hCandInfBmp);
  1333. if (sImeG.fDiffSysCharSet) {
  1334. DeleteObject(SelectObject(hDC, hOldFont));
  1335. }
  1336. ImmUnlockIMCC(lpIMC->hPrivate);
  1337. UpCandW2UnlockCandInfo:
  1338. ImmUnlockIMCC(lpIMC->hCandInfo);
  1339. UpCandW2UnlockIMC:
  1340. ImmUnlockIMC(hIMC);
  1341. return;
  1342. }
  1343. /**********************************************************************/
  1344. /* CandWndProc() */
  1345. /**********************************************************************/
  1346. LRESULT CALLBACK CandWndProc(
  1347. HWND hCandWnd,
  1348. UINT uMsg,
  1349. WPARAM wParam,
  1350. LPARAM lParam)
  1351. {
  1352. switch (uMsg) {
  1353. case WM_DESTROY:
  1354. DestroyCandWindow(hCandWnd);
  1355. break;
  1356. case WM_SETCURSOR:
  1357. CandSetCursor(hCandWnd, lParam);
  1358. break;
  1359. case WM_MOUSEMOVE:
  1360. if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
  1361. POINT ptCursor;
  1362. DrawDragBorder(hCandWnd,
  1363. GetWindowLong(hCandWnd, UI_MOVE_XY),
  1364. GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
  1365. GetCursorPos(&ptCursor);
  1366. SetWindowLong(hCandWnd, UI_MOVE_XY,
  1367. MAKELONG(ptCursor.x, ptCursor.y));
  1368. DrawDragBorder(hCandWnd, MAKELONG(ptCursor.x, ptCursor.y),
  1369. GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
  1370. } else {
  1371. return DefWindowProc(hCandWnd, uMsg, wParam, lParam);
  1372. }
  1373. break;
  1374. case WM_LBUTTONUP:
  1375. if (!CandButtonUp(hCandWnd)) {
  1376. return DefWindowProc(hCandWnd, uMsg, wParam, lParam);
  1377. }
  1378. break;
  1379. case WM_IME_NOTIFY:
  1380. if (wParam == IMN_SETCANDIDATEPOS) {
  1381. return SetCandPosition(hCandWnd);
  1382. }
  1383. break;
  1384. case WM_PAINT:
  1385. {
  1386. HDC hDC;
  1387. PAINTSTRUCT ps;
  1388. hDC = BeginPaint(hCandWnd, &ps);
  1389. PaintCandWindow(hCandWnd, hDC);
  1390. EndPaint(hCandWnd, &ps);
  1391. }
  1392. break;
  1393. case WM_MOUSEACTIVATE:
  1394. return (MA_NOACTIVATE);
  1395. default:
  1396. return DefWindowProc(hCandWnd, uMsg, wParam, lParam);
  1397. }
  1398. return (0L);
  1399. }