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.

1535 lines
47 KiB

  1. /*++
  2. Copyright (c) 1995-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. #if 1 // MultiMonitor support
  40. rcWorkArea = ImeMonitorWorkAreaFromPoint(*lpptWnd);
  41. #else
  42. rcWorkArea = 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(!MBIndex.IMEChara[0].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. #if 1 // MultiMonitor support
  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. #if 1 // MultiMonitor support
  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. } else {
  257. }
  258. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  259. return;
  260. }
  261. // negative try
  262. if (ptInputEsc[uEsc].x > 0) {
  263. rcUIRect.left = rcExclude.left - sImeG.xCandWi;
  264. } else {
  265. rcUIRect.left = rcExclude.right;
  266. }
  267. if (rcUIRect.left < rcWorkArea.left) {
  268. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  269. } else {
  270. if (rcUIRect.top < rcWorkArea.top) {
  271. rcUIRect.top = rcWorkArea.top;
  272. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.bottom) {
  273. rcUIRect.top = rcWorkArea.bottom - sImeG.yCandHi;
  274. } else {
  275. }
  276. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  277. return;
  278. }
  279. // negative try failure again, we use positive plus display adjust
  280. if (ptInputEsc[uEsc].x > 0) {
  281. rcUIRect.left = rcExclude.right;
  282. } else {
  283. rcUIRect.left = rcExclude.left - sImeG.xCandWi;
  284. }
  285. if (rcUIRect.left < rcWorkArea.left) {
  286. rcUIRect.left = rcWorkArea.left;
  287. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  288. rcUIRect.left = rcWorkArea.right - sImeG.xCandWi;
  289. } else {
  290. }
  291. if (rcUIRect.top < rcWorkArea.top) {
  292. rcUIRect.top = rcWorkArea.top;
  293. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.bottom) {
  294. rcUIRect.top = rcWorkArea.bottom - sImeG.yCandHi;
  295. } else {
  296. }
  297. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  298. } else {
  299. // 0 & 1800 we prefer adjust y
  300. if (ptInputEsc[uEsc].y > 0) {
  301. rcUIRect.top = rcExclude.bottom;
  302. } else {
  303. rcUIRect.top = rcExclude.top - sImeG.yCandHi;
  304. }
  305. if (rcUIRect.top < rcWorkArea.top) {
  306. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.bottom) {
  307. } else {
  308. if (rcUIRect.left < rcWorkArea.left) {
  309. rcUIRect.left = rcWorkArea.left;
  310. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  311. rcUIRect.left = rcWorkArea.right - sImeG.xCandWi;
  312. } else {
  313. }
  314. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  315. return;
  316. }
  317. // negative try
  318. if (ptInputEsc[uEsc].y > 0) {
  319. rcUIRect.top = rcExclude.top - sImeG.yCandHi;
  320. } else {
  321. rcUIRect.top = rcExclude.bottom;
  322. }
  323. if (rcUIRect.top < rcWorkArea.top) {
  324. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.right) {
  325. } else {
  326. if (rcUIRect.left < rcWorkArea.left) {
  327. rcUIRect.left = rcWorkArea.left;
  328. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  329. rcUIRect.left = rcWorkArea.right - sImeG.xCandWi;
  330. } else {
  331. }
  332. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  333. return;
  334. }
  335. // negative try failure again, we use positive plus display adjust
  336. if (ptInputEsc[uEsc].y > 0) {
  337. rcUIRect.top = rcExclude.bottom;
  338. } else {
  339. rcUIRect.top = rcExclude.top - sImeG.yCandHi;
  340. }
  341. if (rcUIRect.left < rcWorkArea.left) {
  342. rcUIRect.left = rcWorkArea.left;
  343. } else if (rcUIRect.left + sImeG.xCandWi > rcWorkArea.right) {
  344. rcUIRect.left = rcWorkArea.right - sImeG.xCandWi;
  345. } else {
  346. }
  347. if (rcUIRect.top < rcWorkArea.top) {
  348. rcUIRect.top = rcWorkArea.top;
  349. } else if (rcUIRect.top + sImeG.yCandHi > rcWorkArea.bottom) {
  350. rcUIRect.top = rcWorkArea.bottom - sImeG.yCandHi;
  351. } else {
  352. }
  353. *lpptCandWnd = *(LPPOINT)&rcUIRect;
  354. }
  355. return;
  356. }
  357. /**********************************************************************/
  358. /* AdjustCandBoundry */
  359. /**********************************************************************/
  360. void PASCAL AdjustCandBoundry(
  361. LPPOINT lpptCandWnd) // the position
  362. {
  363. RECT rcWorkArea;
  364. #if 1 // MultiMonitor support
  365. {
  366. RECT rcCandWnd;
  367. *(LPPOINT)&rcCandWnd = *(LPPOINT)lpptCandWnd;
  368. rcCandWnd.right = rcCandWnd.left + sImeG.xCandWi;
  369. rcCandWnd.bottom = rcCandWnd.top + sImeG.yCandHi;
  370. rcWorkArea = ImeMonitorWorkAreaFromRect(&rcCandWnd);
  371. }
  372. #else
  373. rcWorkArea = sImeG.rcWorkArea;
  374. #endif
  375. if (lpptCandWnd->x < rcWorkArea.left) {
  376. lpptCandWnd->x = rcWorkArea.left;
  377. } else if (lpptCandWnd->x + sImeG.xCandWi > rcWorkArea.right) {
  378. lpptCandWnd->x = rcWorkArea.right - sImeG.xCandWi;
  379. }
  380. if (lpptCandWnd->y < rcWorkArea.top) {
  381. lpptCandWnd->y = rcWorkArea.top;
  382. } else if (lpptCandWnd->y + sImeG.yCandHi > rcWorkArea.bottom) {
  383. lpptCandWnd->y = rcWorkArea.bottom - sImeG.yCandHi;
  384. }
  385. return;
  386. }
  387. /**********************************************************************/
  388. /* SetCandPosition() */
  389. /**********************************************************************/
  390. LRESULT PASCAL SetCandPosition(
  391. HWND hCandWnd)
  392. {
  393. HWND hUIWnd;
  394. HIMC hIMC;
  395. LPINPUTCONTEXT lpIMC;
  396. POINT ptNew;
  397. hUIWnd = GetWindow(hCandWnd, GW_OWNER);
  398. if (!hUIWnd) {
  399. return(1L);
  400. }
  401. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  402. if (!hIMC) {
  403. return (1L);
  404. }
  405. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  406. if (!lpIMC) {
  407. return (1L);
  408. }
  409. ptNew = lpIMC->cfCandForm[0].ptCurrentPos;
  410. ClientToScreen((HWND)lpIMC->hWnd, &ptNew);
  411. if (lpIMC->cfCandForm[0].dwStyle & CFS_FORCE_POSITION) {
  412. } else if (lpIMC->cfCandForm[0].dwStyle == CFS_CANDIDATEPOS) {
  413. AdjustCandBoundry(&ptNew);
  414. } else if (lpIMC->cfCandForm[0].dwStyle == CFS_EXCLUDE) {
  415. if(!MBIndex.IMEChara[0].IC_Trace) {
  416. CalcCandPos(hIMC, hUIWnd, &ptNew);
  417. }
  418. AdjustCandBoundry(&ptNew);
  419. }
  420. SetWindowPos(hCandWnd, NULL, ptNew.x, ptNew.y,
  421. 0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
  422. ImmUnlockIMC(hIMC);
  423. return (0L);
  424. }
  425. /**********************************************************************/
  426. /* ShowCand() */
  427. /**********************************************************************/
  428. void PASCAL ShowCand( // Show the candidate window
  429. HWND hUIWnd,
  430. int nShowCandCmd)
  431. {
  432. HGLOBAL hUIPrivate;
  433. LPUIPRIV lpUIPrivate;
  434. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  435. if (!hUIPrivate) { // can not darw candidate window
  436. return;
  437. }
  438. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  439. if (!lpUIPrivate) { // can not draw candidate window
  440. return;
  441. }
  442. // add 10.9
  443. if (lpUIPrivate->nShowCandCmd == nShowCandCmd) {
  444. goto SwCandNoChange;
  445. }
  446. if (nShowCandCmd == SW_HIDE) {
  447. lpUIPrivate->fdwSetContext &= ~(ISC_HIDE_CAND_WINDOW);
  448. }
  449. if (!lpUIPrivate->hCandWnd) {
  450. // not in show candidate window mode
  451. } else if (lpUIPrivate->nShowCandCmd != nShowCandCmd) {
  452. if(nShowCandCmd == SW_HIDE) {
  453. uOpenCand = 0;
  454. } else {
  455. HIMC hIMC;
  456. POINT ptSTWPos;
  457. int Comp_CandWndLen;
  458. uOpenCand = 1;
  459. // reset status window for LINE_UI(FIX_UI)
  460. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  461. if (!hIMC) {
  462. goto ShowCand;
  463. }
  464. ImmGetStatusWindowPos(hIMC, (LPPOINT)&ptSTWPos);
  465. Comp_CandWndLen = 0;
  466. if(uOpenCand) {
  467. Comp_CandWndLen += sImeG.xCandWi + UI_MARGIN;
  468. if(uStartComp) {
  469. Comp_CandWndLen += lpImeL->xCompWi + UI_MARGIN;
  470. }
  471. if(ptSTWPos.x + sImeG.xStatusWi + Comp_CandWndLen > sImeG.rcWorkArea.right) {
  472. PostMessage(GetCompWnd(hUIWnd), WM_IME_NOTIFY, IMN_SETCOMPOSITIONWINDOW, 0);
  473. }
  474. }
  475. }
  476. ShowCand:
  477. ShowWindow(lpUIPrivate->hCandWnd, nShowCandCmd);
  478. lpUIPrivate->nShowCandCmd = nShowCandCmd;
  479. }
  480. SwCandNoChange:
  481. GlobalUnlock(hUIPrivate);
  482. return;
  483. }
  484. /**********************************************************************/
  485. /* OpenCand */
  486. /**********************************************************************/
  487. void PASCAL OpenCand(
  488. HWND hUIWnd)
  489. {
  490. HGLOBAL hUIPrivate;
  491. LPUIPRIV lpUIPrivate;
  492. HIMC hIMC;
  493. LPINPUTCONTEXT lpIMC;
  494. POINT ptWnd;
  495. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  496. if (!hUIPrivate) { // can not darw candidate window
  497. return;
  498. }
  499. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  500. if (!lpUIPrivate) { // can not draw candidate window
  501. return;
  502. }
  503. lpUIPrivate->fdwSetContext |= ISC_SHOWUICANDIDATEWINDOW;
  504. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  505. if (!hIMC) {
  506. goto OpenCandUnlockUIPriv;
  507. }
  508. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  509. if (!lpIMC) {
  510. goto OpenCandUnlockUIPriv;
  511. }
  512. if (lpIMC->cfCandForm[0].dwIndex == 0) {
  513. ptWnd = lpIMC->cfCandForm[0].ptCurrentPos;
  514. ClientToScreen(lpIMC->hWnd, &ptWnd);
  515. if (lpIMC->cfCandForm[0].dwStyle & CFS_FORCE_POSITION) {
  516. } else if (lpIMC->cfCandForm[0].dwStyle == CFS_EXCLUDE) {
  517. POINT ptCaret;
  518. AdjustCandBoundry(&ptWnd);
  519. if((!MBIndex.IMEChara[0].IC_Trace)
  520. || (!GetCaretPos(&ptCaret))) {
  521. if(GetCompWnd(hUIWnd)) {
  522. ptWnd.x = ptWnd.y = 0;
  523. // ptWnd = lpIMC->cfCompForm.ptCurrentPos;
  524. ClientToScreen(lpIMC->hWnd, &ptWnd);
  525. ptWnd.x -= lpImeL->cxCompBorder + 1;
  526. ptWnd.y -= lpImeL->cyCompBorder + 1;
  527. } else {
  528. ptWnd.x = lpImeL->cxCompBorder + 1;
  529. ptWnd.y = lpImeL->cyCompBorder + 1;
  530. }
  531. CalcCandPos(hIMC, hUIWnd, &ptWnd);
  532. lpIMC->cfCandForm[0].dwStyle |= CFS_CANDIDATEPOS;
  533. lpIMC->cfCandForm[0].ptCurrentPos = ptWnd;
  534. ScreenToClient(lpIMC->hWnd, &lpIMC->cfCandForm[0].ptCurrentPos);
  535. } else {
  536. AdjustCandPos(hIMC, &ptWnd);
  537. }
  538. } else if (lpIMC->cfCandForm[0].dwStyle == CFS_CANDIDATEPOS) {
  539. AdjustCandBoundry(&ptWnd);
  540. } else {
  541. if (lpUIPrivate->nShowCompCmd != SW_HIDE) {
  542. ptWnd.x = ptWnd.y = 0;
  543. ClientToScreen(lpUIPrivate->hCompWnd, &ptWnd);
  544. } else {
  545. ptWnd = lpIMC->cfCompForm.ptCurrentPos;
  546. ClientToScreen(lpIMC->hWnd, &ptWnd);
  547. }
  548. ptWnd.x -= lpImeL->cxCompBorder + 1;
  549. ptWnd.y -= lpImeL->cyCompBorder + 1;
  550. CalcCandPos(hIMC, hUIWnd, &ptWnd);
  551. lpIMC->cfCandForm[0].dwStyle |= CFS_CANDIDATEPOS;
  552. lpIMC->cfCandForm[0].ptCurrentPos = ptWnd;
  553. ScreenToClient(lpIMC->hWnd, &lpIMC->cfCandForm[0].ptCurrentPos);
  554. }
  555. } else {
  556. // make cand windows trace comp window !
  557. if (lpUIPrivate->nShowCompCmd != SW_HIDE) {
  558. ptWnd.x = ptWnd.y = 0;
  559. ClientToScreen(lpUIPrivate->hCompWnd, &ptWnd);
  560. } else {
  561. ptWnd = lpIMC->cfCompForm.ptCurrentPos;
  562. ClientToScreen(lpIMC->hWnd, &ptWnd);
  563. }
  564. ptWnd.x -= lpImeL->cxCompBorder + 1;
  565. ptWnd.y -= lpImeL->cyCompBorder + 1;
  566. CalcCandPos(hIMC, hUIWnd, &ptWnd);
  567. lpIMC->cfCandForm[0].dwStyle |= CFS_CANDIDATEPOS;
  568. lpIMC->cfCandForm[0].ptCurrentPos = ptWnd;
  569. ScreenToClient(lpIMC->hWnd, &lpIMC->cfCandForm[0].ptCurrentPos);
  570. }
  571. ImmUnlockIMC(hIMC);
  572. if (lpUIPrivate->hCandWnd) {
  573. SetWindowPos(lpUIPrivate->hCandWnd, NULL,
  574. ptWnd.x, ptWnd.y,
  575. 0, 0, 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. if ( lpUIPrivate->hCandWnd )
  591. {
  592. SetWindowLong(lpUIPrivate->hCandWnd, UI_MOVE_OFFSET,WINDOW_NOT_DRAG);
  593. SetWindowLong(lpUIPrivate->hCandWnd, UI_MOVE_XY, 0L);
  594. }
  595. }
  596. ShowCand(hUIWnd, SW_SHOWNOACTIVATE);
  597. OpenCandUnlockUIPriv:
  598. GlobalUnlock(hUIPrivate);
  599. return;
  600. }
  601. /**********************************************************************/
  602. /* CloseCand */
  603. /**********************************************************************/
  604. void PASCAL CloseCand(
  605. HWND hUIWnd)
  606. {
  607. ShowCand(hUIWnd, SW_HIDE);
  608. return;
  609. }
  610. /**********************************************************************/
  611. /* DestroyCandWindow */
  612. /**********************************************************************/
  613. void PASCAL DestroyCandWindow(
  614. HWND hCandWnd)
  615. {
  616. HGLOBAL hUIPrivate;
  617. LPUIPRIV lpUIPrivate;
  618. if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
  619. // undo the drag border
  620. DrawDragBorder(hCandWnd,
  621. GetWindowLong(hCandWnd, UI_MOVE_XY),
  622. GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
  623. }
  624. hUIPrivate = (HGLOBAL)GetWindowLongPtr(GetWindow(hCandWnd, GW_OWNER),
  625. IMMGWLP_PRIVATE);
  626. if (!hUIPrivate) { // can not darw candidate window
  627. return;
  628. }
  629. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  630. if (!lpUIPrivate) { // can not draw candidate window
  631. return;
  632. }
  633. lpUIPrivate->nShowCandCmd = SW_HIDE;
  634. lpUIPrivate->hCandWnd = (HWND)NULL;
  635. GlobalUnlock(hUIPrivate);
  636. return;
  637. }
  638. /**********************************************************************/
  639. /* MouseSelectCandStr() */
  640. /**********************************************************************/
  641. void PASCAL MouseSelectCandStr(
  642. HWND hCandWnd,
  643. LPPOINT lpCursor)
  644. {
  645. HIMC hIMC;
  646. LPINPUTCONTEXT lpIMC;
  647. LPCANDIDATEINFO lpCandInfo;
  648. LPCANDIDATELIST lpCandList;
  649. DWORD dwValue;
  650. hIMC = (HIMC)GetWindowLongPtr(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
  651. if (!hIMC) {
  652. return;
  653. }
  654. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  655. if (!lpIMC) {
  656. return;
  657. }
  658. if (!lpIMC->hCandInfo) {
  659. ImmUnlockIMC(hIMC);
  660. return;
  661. }
  662. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  663. if (!lpCandInfo) {
  664. ImmUnlockIMC(hIMC);
  665. return;
  666. }
  667. dwValue = (lpCursor->y - sImeG.rcCandText.top) / sImeG.yChiCharHi;
  668. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  669. lpCandInfo->dwOffset[0]);
  670. dwValue = dwValue + lpCandList->dwSelection /
  671. lpCandList->dwPageSize * lpCandList->dwPageSize;
  672. if (dwValue >= lpCandList->dwCount) {
  673. // invalid choice
  674. MessageBeep((UINT)-1);
  675. } else {
  676. NotifyIME(hIMC, NI_SELECTCANDIDATESTR, 0, dwValue);
  677. }
  678. ImmUnlockIMCC(lpIMC->hCandInfo);
  679. ImmUnlockIMC(hIMC);
  680. return;
  681. }
  682. /**********************************************************************/
  683. /* CandPageDownUP() */
  684. /**********************************************************************/
  685. void PASCAL CandPageDownUP(
  686. HWND hCandWnd,
  687. UINT uCandDownUp)
  688. {
  689. HIMC hIMC;
  690. LPINPUTCONTEXT lpIMC;
  691. LPPRIVCONTEXT lpImcP;
  692. LPCANDIDATEINFO lpCandInfo;
  693. LPCANDIDATELIST lpCandList;
  694. HDC hDC;
  695. HBITMAP hCandHpBmp, hCandUpBmp, hCandDpBmp, hCandEpBmp;
  696. HBITMAP hOldBmp;
  697. HDC hMemDC;
  698. // change candlist
  699. hIMC = (HIMC)GetWindowLongPtr(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
  700. if (!hIMC) {
  701. return;
  702. }
  703. // get lpIMC
  704. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  705. if (!lpIMC) {
  706. return;
  707. }
  708. // get lpImcP
  709. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  710. if (!lpImcP) {
  711. return;
  712. }
  713. // get lpCandInfo
  714. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  715. if (!lpCandInfo) {
  716. return;
  717. }
  718. // get lpCandList and init dwCount & dwSelection
  719. lpCandList = (LPCANDIDATELIST)
  720. ((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[0]);
  721. switch(uCandDownUp) {
  722. case uCandHome:
  723. EngChCand(NULL, lpCandList, lpImcP, lpIMC, 0x24);
  724. NotifyIME(hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  725. break;
  726. case uCandUp:
  727. EngChCand(NULL, lpCandList, lpImcP, lpIMC, 0x21);
  728. NotifyIME(hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  729. break;
  730. case uCandDown:
  731. //EngChCand(NULL, lpCandList, lpImcP, lpIMC, '=');
  732. EngChCand(NULL, lpCandList, lpImcP, lpIMC, 0x22);
  733. NotifyIME(hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  734. break;
  735. case uCandEnd:
  736. EngChCand(NULL, lpCandList, lpImcP, lpIMC, 0x23);
  737. NotifyIME(hIMC, NI_CHANGECANDIDATELIST, 0, 0);
  738. break;
  739. default:
  740. break;
  741. }
  742. ImmUnlockIMCC(lpIMC->hPrivate);
  743. ImmUnlockIMCC(lpIMC->hCandInfo);
  744. ImmUnlockIMC(hIMC);
  745. // draw button down
  746. hDC = GetDC(hCandWnd);
  747. hCandHpBmp = LoadBitmap(hInst, TEXT("CandHp"));
  748. hCandUpBmp = LoadBitmap(hInst, TEXT("CandUp"));
  749. hCandDpBmp = LoadBitmap(hInst, TEXT("CandDp"));
  750. hCandEpBmp = LoadBitmap(hInst, TEXT("CandEp"));
  751. hMemDC = CreateCompatibleDC(hDC);
  752. switch(uCandDownUp) {
  753. case uCandHome:
  754. hOldBmp = SelectObject(hMemDC, hCandHpBmp);
  755. BitBlt(hDC, sImeG.rcCandBTH.left, sImeG.rcCandBTH.top,
  756. sImeG.rcCandBTH.right - sImeG.rcCandBTH.left,
  757. STATUS_DIM_Y,
  758. hMemDC, 0, 0, SRCCOPY);
  759. break;
  760. case uCandUp:
  761. hOldBmp = SelectObject(hMemDC, hCandUpBmp);
  762. BitBlt(hDC, sImeG.rcCandBTU.left, sImeG.rcCandBTU.top,
  763. sImeG.rcCandBTU.right - sImeG.rcCandBTU.left,
  764. STATUS_DIM_Y,
  765. hMemDC, 0, 0, SRCCOPY);
  766. break;
  767. case uCandDown:
  768. hOldBmp = SelectObject(hMemDC, hCandDpBmp);
  769. BitBlt(hDC, sImeG.rcCandBTD.left, sImeG.rcCandBTD.top,
  770. sImeG.rcCandBTD.right - sImeG.rcCandBTD.left,
  771. STATUS_DIM_Y,
  772. hMemDC, 0, 0, SRCCOPY);
  773. break;
  774. case uCandEnd:
  775. hOldBmp = SelectObject(hMemDC, hCandEpBmp);
  776. BitBlt(hDC, sImeG.rcCandBTE.left, sImeG.rcCandBTE.top,
  777. sImeG.rcCandBTE.right - sImeG.rcCandBTE.left,
  778. STATUS_DIM_Y,
  779. hMemDC, 0, 0, SRCCOPY);
  780. break;
  781. default:
  782. break;
  783. }
  784. SelectObject(hMemDC, hOldBmp);
  785. DeleteDC(hMemDC);
  786. DeleteObject(hCandEpBmp);
  787. DeleteObject(hCandDpBmp);
  788. DeleteObject(hCandUpBmp);
  789. DeleteObject(hCandHpBmp);
  790. ReleaseDC(hCandWnd, hDC);
  791. return;
  792. }
  793. /**********************************************************************/
  794. /* CandSetCursor() */
  795. /**********************************************************************/
  796. void PASCAL CandSetCursor(
  797. HWND hCandWnd,
  798. LPARAM lParam)
  799. {
  800. POINT ptCursor;
  801. RECT rcWnd;
  802. if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) !=
  803. WINDOW_NOT_DRAG) {
  804. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  805. return;
  806. }
  807. if (HIWORD(lParam) == WM_LBUTTONDOWN) {
  808. SystemParametersInfo(SPI_GETWORKAREA, 0, &sImeG.rcWorkArea, 0);
  809. GetCursorPos(&ptCursor);
  810. ScreenToClient(hCandWnd, &ptCursor);
  811. if (PtInRect(&sImeG.rcCandText, ptCursor)
  812. && MBIndex.IMEChara[0].IC_Trace) {
  813. SetCursor(LoadCursor(hInst, szHandCursor));
  814. MouseSelectCandStr(hCandWnd, &ptCursor);
  815. return;
  816. } else if (PtInRect(&sImeG.rcCandBTH, ptCursor)) {
  817. CandPageDownUP(hCandWnd, uCandHome);
  818. return;
  819. } else if (PtInRect(&sImeG.rcCandBTU, ptCursor)) {
  820. CandPageDownUP(hCandWnd, uCandUp);
  821. return;
  822. } else if (PtInRect(&sImeG.rcCandBTD, ptCursor)) {
  823. CandPageDownUP(hCandWnd, uCandDown);
  824. return;
  825. } else if (PtInRect(&sImeG.rcCandBTE, ptCursor)) {
  826. CandPageDownUP(hCandWnd, uCandEnd);
  827. return;
  828. } else {
  829. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  830. }
  831. } else if (HIWORD(lParam) == WM_LBUTTONUP) {
  832. HDC hDC;
  833. HBITMAP hCandHBmp, hCandUBmp, hCandDBmp, hCandEBmp;
  834. HBITMAP hOldBmp;
  835. HDC hMemDC;
  836. hDC = GetDC(hCandWnd);
  837. hCandHBmp = LoadBitmap(hInst, TEXT("CandH"));
  838. hCandUBmp = LoadBitmap(hInst, TEXT("CandU"));
  839. hCandDBmp = LoadBitmap(hInst, TEXT("CandD"));
  840. hCandEBmp = LoadBitmap(hInst, TEXT("CandE"));
  841. hMemDC = CreateCompatibleDC(hDC);
  842. hOldBmp = SelectObject(hMemDC, hCandHBmp);
  843. BitBlt(hDC, sImeG.rcCandBTH.left, sImeG.rcCandBTH.top,
  844. sImeG.rcCandBTH.right - sImeG.rcCandBTH.left,
  845. STATUS_DIM_Y,
  846. hMemDC, 0, 0, SRCCOPY);
  847. SelectObject(hMemDC, hCandUBmp);
  848. BitBlt(hDC, sImeG.rcCandBTU.left, sImeG.rcCandBTU.top,
  849. sImeG.rcCandBTU.right - sImeG.rcCandBTU.left,
  850. STATUS_DIM_Y,
  851. hMemDC, 0, 0, SRCCOPY);
  852. SelectObject(hMemDC, hCandDBmp);
  853. BitBlt(hDC, sImeG.rcCandBTD.left, sImeG.rcCandBTD.top,
  854. sImeG.rcCandBTD.right - sImeG.rcCandBTD.left,
  855. STATUS_DIM_Y,
  856. hMemDC, 0, 0, SRCCOPY);
  857. SelectObject(hMemDC, hCandEBmp);
  858. BitBlt(hDC, sImeG.rcCandBTE.left, sImeG.rcCandBTE.top,
  859. sImeG.rcCandBTE.right - sImeG.rcCandBTE.left,
  860. STATUS_DIM_Y,
  861. hMemDC, 0, 0, SRCCOPY);
  862. SelectObject(hMemDC, hOldBmp);
  863. DeleteObject(hCandEBmp);
  864. DeleteObject(hCandDBmp);
  865. DeleteObject(hCandUBmp);
  866. DeleteObject(hCandEBmp);
  867. DeleteDC(hMemDC);
  868. ReleaseDC(hCandWnd, hDC);
  869. return;
  870. } else {
  871. SystemParametersInfo(SPI_GETWORKAREA, 0, &sImeG.rcWorkArea, 0);
  872. GetCursorPos(&ptCursor);
  873. ScreenToClient(hCandWnd, &ptCursor);
  874. if (PtInRect(&sImeG.rcCandText, ptCursor)) {
  875. SetCursor(LoadCursor(hInst, szHandCursor));
  876. return;
  877. } else if (PtInRect(&sImeG.rcCandBTH, ptCursor)) {
  878. SetCursor(LoadCursor(hInst, szHandCursor));
  879. } else if (PtInRect(&sImeG.rcCandBTU, ptCursor)) {
  880. SetCursor(LoadCursor(hInst, szHandCursor));
  881. } else if (PtInRect(&sImeG.rcCandBTD, ptCursor)) {
  882. SetCursor(LoadCursor(hInst, szHandCursor));
  883. } else if (PtInRect(&sImeG.rcCandBTE, ptCursor)) {
  884. SetCursor(LoadCursor(hInst, szHandCursor));
  885. } else {
  886. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  887. }
  888. return;
  889. }
  890. SetCapture(hCandWnd);
  891. GetCursorPos(&ptCursor);
  892. SetWindowLong(hCandWnd, UI_MOVE_XY,
  893. MAKELONG(ptCursor.x, ptCursor.y));
  894. GetWindowRect(hCandWnd, &rcWnd);
  895. SetWindowLong(hCandWnd, UI_MOVE_OFFSET,
  896. MAKELONG(ptCursor.x - rcWnd.left, ptCursor.y - rcWnd.top));
  897. DrawDragBorder(hCandWnd, MAKELONG(ptCursor.x, ptCursor.y),
  898. GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
  899. return;
  900. }
  901. /**********************************************************************/
  902. /* CandButtonUp() */
  903. /**********************************************************************/
  904. BOOL PASCAL CandButtonUp(
  905. HWND hCandWnd)
  906. {
  907. LONG lTmpCursor, lTmpOffset;
  908. POINT pt;
  909. HWND hUIWnd;
  910. HIMC hIMC;
  911. LPINPUTCONTEXT lpIMC;
  912. if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) == WINDOW_NOT_DRAG) {
  913. return (FALSE);
  914. }
  915. lTmpCursor = GetWindowLong(hCandWnd, UI_MOVE_XY);
  916. // calculate the org by the offset
  917. lTmpOffset = GetWindowLong(hCandWnd, UI_MOVE_OFFSET);
  918. pt.x = (*(LPPOINTS)&lTmpCursor).x - (*(LPPOINTS)&lTmpOffset).x;
  919. pt.y = (*(LPPOINTS)&lTmpCursor).y - (*(LPPOINTS)&lTmpOffset).y;
  920. DrawDragBorder(hCandWnd, lTmpCursor, lTmpOffset);
  921. SetWindowLong(hCandWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG);
  922. ReleaseCapture();
  923. hUIWnd = GetWindow(hCandWnd, GW_OWNER);
  924. if (!hUIWnd) {
  925. return (FALSE);
  926. }
  927. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  928. if (!hIMC) {
  929. return (FALSE);
  930. }
  931. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  932. if (!lpIMC) {
  933. return (FALSE);
  934. }
  935. AdjustCandBoundry(&pt);
  936. ScreenToClient(lpIMC->hWnd, &pt);
  937. lpIMC->cfCandForm[0].dwStyle |= CFS_CANDIDATEPOS;
  938. lpIMC->cfCandForm[0].ptCurrentPos = pt;
  939. ImmUnlockIMC(hIMC);
  940. PostMessage(hCandWnd, WM_IME_NOTIFY, IMN_SETCANDIDATEPOS, 0x0001);
  941. return (TRUE);
  942. }
  943. /**********************************************************************/
  944. /* UpdateCandWindow() */
  945. /**********************************************************************/
  946. //void PASCAL UpdateCandWindow2(
  947. void PASCAL PaintCandWindow(
  948. HWND hCandWnd,
  949. HDC hDC)
  950. {
  951. HIMC hIMC;
  952. LPINPUTCONTEXT lpIMC;
  953. LPCANDIDATEINFO lpCandInfo;
  954. LPCANDIDATELIST lpCandList;
  955. LPPRIVCONTEXT lpImcP;
  956. HGDIOBJ hOldFont;
  957. DWORD dwStart, dwEnd;
  958. TCHAR szStrBuf[2 * MAXSTRLEN * sizeof(WCHAR) / sizeof(TCHAR) + 1];
  959. int i;
  960. HBITMAP hCandIconBmp, hCandInfBmp;
  961. HBITMAP hOldBmp, hCandHBmp, hCandUBmp, hCandDBmp, hCandEBmp;
  962. HDC hMemDC;
  963. LOGFONT lfFont;
  964. hIMC = (HIMC)GetWindowLongPtr(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
  965. if (!hIMC) {
  966. return;
  967. }
  968. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  969. if (!lpIMC) {
  970. return;
  971. }
  972. if (!lpIMC->hCandInfo) {
  973. goto UpCandW2UnlockIMC;
  974. }
  975. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  976. if (!lpCandInfo) {
  977. goto UpCandW2UnlockIMC;
  978. }
  979. if (!lpIMC->hPrivate) {
  980. goto UpCandW2UnlockCandInfo;
  981. }
  982. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  983. if (!lpImcP) {
  984. goto UpCandW2UnlockCandInfo;
  985. }
  986. // set font
  987. if (sImeG.fDiffSysCharSet) {
  988. LOGFONT lfFont;
  989. ZeroMemory(&lfFont, sizeof(lfFont));
  990. hOldFont = GetCurrentObject(hDC, OBJ_FONT);
  991. lfFont.lfHeight = -MulDiv(12, GetDeviceCaps(hDC, LOGPIXELSY), 72);
  992. lfFont.lfCharSet = NATIVE_CHARSET;
  993. lstrcpy(lfFont.lfFaceName, TEXT("Simsun"));
  994. SelectObject(hDC, CreateFontIndirect(&lfFont));
  995. }
  996. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  997. lpCandInfo->dwOffset[0]);
  998. dwStart = lpCandList->dwSelection;
  999. dwEnd = dwStart + lpCandList->dwPageSize;
  1000. if (dwEnd > lpCandList->dwCount) {
  1001. dwEnd = lpCandList->dwCount;
  1002. }
  1003. // draw CandWnd Layout
  1004. if (MBIndex.IMEChara[0].IC_Trace) {
  1005. RECT rcWnd;
  1006. GetClientRect(hCandWnd, &rcWnd);
  1007. DrawConcaveRect(hDC,
  1008. rcWnd.left,
  1009. rcWnd.top + UI_CANDINF,
  1010. rcWnd.right - 1,
  1011. rcWnd.bottom - 1);
  1012. } else {
  1013. RECT rcWnd;
  1014. GetClientRect(hCandWnd, &rcWnd);
  1015. DrawConcaveRect(hDC,
  1016. sImeG.rcCandText.left - 1,
  1017. rcWnd.top,
  1018. sImeG.rcCandText.right + 1,
  1019. rcWnd.bottom - 1);
  1020. }
  1021. if(lpImcP->PrivateArea.Comp_Status.dwSTLX) {
  1022. SetTextColor(hDC, RGB(0x00, 0x00, 0x255));
  1023. } else if(lpImcP->PrivateArea.Comp_Status.dwSTMULCODE) {
  1024. SetTextColor(hDC, RGB(0x80, 0x00, 0x00));
  1025. } else {
  1026. SetTextColor(hDC, RGB(0x00, 0x00, 0x00));
  1027. }
  1028. SetBkColor(hDC, RGB(0xC0, 0xC0, 0xC0));
  1029. if (MBIndex.IMEChara[0].IC_Trace) {
  1030. ExtTextOut(hDC, sImeG.rcCandText.left, sImeG.rcCandText.top,
  1031. ETO_OPAQUE, &sImeG.rcCandText, NULL, 0, NULL);
  1032. szStrBuf[0] = TEXT('1');
  1033. szStrBuf[1] = TEXT(':');
  1034. for (i = 0; dwStart < dwEnd; dwStart++, i++) {
  1035. int iLen;
  1036. szStrBuf[0] = szDigit[i + CAND_START];
  1037. iLen = lstrlen((LPTSTR)((LPBYTE)lpCandList +
  1038. lpCandList->dwOffset[dwStart]));
  1039. #ifdef KEYSTICKER
  1040. {
  1041. LPTSTR p;
  1042. BOOL fMap;
  1043. TCHAR mapbuf[MAXSTRLEN];
  1044. int j,k,l;
  1045. ZeroMemory(mapbuf, MAXSTRLEN*sizeof(TCHAR));
  1046. p=(LPTSTR)((LPBYTE)lpCandList +lpCandList->dwOffset[dwStart]);
  1047. fMap=FALSE;
  1048. if(MBIndex.IMEChara[0].IC_CTC) {
  1049. for(l=0; l<iLen; l++){
  1050. if(IsUsedCode(p[l], NULL)){
  1051. fMap=TRUE;
  1052. break;
  1053. }else{
  1054. l = l + 2 - sizeof(TCHAR);
  1055. continue;
  1056. }
  1057. }
  1058. if(fMap && l<iLen){
  1059. lstrcpyn(mapbuf, (LPTSTR)((LPBYTE)lpCandList
  1060. +lpCandList->dwOffset[dwStart]), l*sizeof(TCHAR));
  1061. k=l;
  1062. mapbuf[l++] = TEXT('(');
  1063. j=0;
  1064. while(IsUsedCode(p[k++], NULL))
  1065. j++;
  1066. MapSticker((LPTSTR)p+l-1, &mapbuf[l], j);
  1067. lstrcat(mapbuf, TEXT(")"));
  1068. iLen = lstrlen(mapbuf);
  1069. }else{
  1070. lstrcpy(mapbuf,(LPTSTR)((LPBYTE)lpCandList
  1071. +lpCandList->dwOffset[dwStart]));
  1072. }
  1073. }else{
  1074. lstrcpy(mapbuf,(LPTSTR)((LPBYTE)lpCandList
  1075. +lpCandList->dwOffset[dwStart]));
  1076. }
  1077. // according to init.c, 11 DBCS char
  1078. if (iLen > 14 * 2 / sizeof(TCHAR)) {
  1079. iLen = 14 * 2 / sizeof(TCHAR);
  1080. CopyMemory(&szStrBuf[2],mapbuf,
  1081. (iLen - 2) * sizeof(TCHAR));
  1082. // maybe not good for UNICODE
  1083. szStrBuf[iLen] = TEXT('.');
  1084. szStrBuf[iLen+1] = TEXT('.');
  1085. szStrBuf[iLen+2] = TEXT('\0');
  1086. } else {
  1087. CopyMemory(&szStrBuf[2],mapbuf,iLen*sizeof(TCHAR));
  1088. }
  1089. }
  1090. #else
  1091. // according to init.c, 11 DBCS char
  1092. if (iLen > 14 * 2 / sizeof(TCHAR)) {
  1093. iLen = 14 * 2 / sizeof(TCHAR);
  1094. CopyMemory(&szStrBuf[2],
  1095. ((LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart])),
  1096. (iLen - 2) * sizeof(TCHAR));
  1097. // maybe not good for UNICODE
  1098. szStrBuf[iLen] = TEXT('.');
  1099. szStrBuf[iLen+1] = TEXT('.');
  1100. szStrBuf[iLen+2] = TEXT('\0');
  1101. } else {
  1102. CopyMemory(&szStrBuf[2],
  1103. ((LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart])),
  1104. iLen*sizeof(TCHAR));
  1105. }
  1106. #endif //KEYSTICKER
  1107. ExtTextOut(hDC, sImeG.rcCandText.left,
  1108. sImeG.rcCandText.top + i * sImeG.yChiCharHi,
  1109. (UINT) 0, NULL,
  1110. szStrBuf,
  1111. iLen+2, NULL);
  1112. }
  1113. } else {
  1114. int nX;
  1115. ExtTextOut(hDC, sImeG.rcCandText.left, sImeG.rcCandText.top + 1,
  1116. ETO_OPAQUE, &sImeG.rcCandText, NULL, 0, NULL);
  1117. nX = 0;
  1118. for (i = 0; dwStart < dwEnd; dwStart++, i++) {
  1119. int iLen;
  1120. SIZE StrSize;
  1121. // display numbers
  1122. szStrBuf[0] = szDigit[i + CAND_START];
  1123. szStrBuf[1] = TEXT(':');
  1124. // display chinese word and code
  1125. iLen = lstrlen((LPTSTR)((LPBYTE)lpCandList +
  1126. lpCandList->dwOffset[dwStart]));
  1127. CopyMemory((LPTSTR)&(szStrBuf[2]),
  1128. (LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart]),
  1129. iLen*sizeof(TCHAR));
  1130. szStrBuf[iLen+2] = TEXT(' ');
  1131. szStrBuf[iLen+2+1] = TEXT('\0');
  1132. ExtTextOut(hDC, sImeG.rcCandText.left + nX,
  1133. sImeG.rcCandText.top + 1,
  1134. ETO_CLIPPED, &sImeG.rcCandText,
  1135. szStrBuf,
  1136. lstrlen(szStrBuf), NULL);
  1137. if(!GetTextExtentPoint(hDC, (LPCTSTR)szStrBuf, lstrlen(szStrBuf), &StrSize))
  1138. memset(&StrSize, 0, sizeof(SIZE));
  1139. nX += StrSize.cx;
  1140. }
  1141. }
  1142. // load all bitmap
  1143. if (MBIndex.IMEChara[0].IC_Trace) {
  1144. WORD NumCode, wFlg;
  1145. SetTextColor(hDC, RGB(0x00, 0x00, 0x00));
  1146. SetBkColor(hDC, RGB(0xC0, 0xC0, 0xC0));
  1147. NumCode = 0x0030;
  1148. for(wFlg=0; wFlg<10; wFlg++, NumCode++)
  1149. if(IsUsedCode(NumCode, lpImcP)) break;
  1150. if(wFlg == 10) {
  1151. hCandInfBmp = LoadBitmap(hInst, TEXT("Candinf1"));
  1152. } else {
  1153. hCandInfBmp = LoadBitmap(hInst, TEXT("Candinf2"));
  1154. }
  1155. } else {
  1156. hCandInfBmp = NULL;
  1157. }
  1158. hCandHBmp = LoadBitmap(hInst, TEXT("CandH"));
  1159. hCandUBmp = LoadBitmap(hInst, TEXT("CandU"));
  1160. hCandDBmp = LoadBitmap(hInst, TEXT("CandD"));
  1161. hCandEBmp = LoadBitmap(hInst, TEXT("CandE"));
  1162. if (lpImcP->PrivateArea.Comp_Status.dwSTLX) {
  1163. hCandIconBmp = LoadBitmap(hInst, TEXT("CandLX"));
  1164. } else if (lpImcP->PrivateArea.Comp_Status.dwSTMULCODE) {
  1165. hCandIconBmp = LoadBitmap(hInst, TEXT("CandMult"));
  1166. } else {
  1167. hCandIconBmp = LoadBitmap(hInst, TEXT("CandSel"));
  1168. }
  1169. hMemDC = CreateCompatibleDC(hDC);
  1170. hOldBmp = SelectObject(hMemDC, hCandIconBmp);
  1171. BitBlt(hDC, sImeG.rcCandIcon.left, sImeG.rcCandIcon.top,
  1172. sImeG.rcCandIcon.right - sImeG.rcCandIcon.left,
  1173. STATUS_DIM_Y,
  1174. hMemDC, 0, 0, SRCCOPY);
  1175. if(hCandInfBmp) {
  1176. SelectObject(hMemDC, hCandInfBmp);
  1177. BitBlt(hDC, sImeG.rcCandInf.left, sImeG.rcCandInf.top,
  1178. sImeG.rcCandInf.right - sImeG.rcCandInf.left,
  1179. STATUS_DIM_Y,
  1180. hMemDC, 0, 0, SRCCOPY);
  1181. }
  1182. SelectObject(hMemDC, hCandHBmp);
  1183. BitBlt(hDC, sImeG.rcCandBTH.left, sImeG.rcCandBTH.top,
  1184. sImeG.rcCandBTH.right - sImeG.rcCandBTH.left,
  1185. STATUS_DIM_Y,
  1186. hMemDC, 0, 0, SRCCOPY);
  1187. SelectObject(hMemDC, hCandUBmp);
  1188. BitBlt(hDC, sImeG.rcCandBTU.left, sImeG.rcCandBTU.top,
  1189. sImeG.rcCandBTU.right - sImeG.rcCandBTU.left,
  1190. STATUS_DIM_Y,
  1191. hMemDC, 0, 0, SRCCOPY);
  1192. SelectObject(hMemDC, hCandDBmp);
  1193. BitBlt(hDC, sImeG.rcCandBTD.left, sImeG.rcCandBTD.top,
  1194. sImeG.rcCandBTD.right - sImeG.rcCandBTD.left,
  1195. STATUS_DIM_Y,
  1196. hMemDC, 0, 0, SRCCOPY);
  1197. SelectObject(hMemDC, hCandEBmp);
  1198. BitBlt(hDC, sImeG.rcCandBTE.left, sImeG.rcCandBTE.top,
  1199. sImeG.rcCandBTE.right - sImeG.rcCandBTE.left,
  1200. STATUS_DIM_Y,
  1201. hMemDC, 0, 0, SRCCOPY);
  1202. SelectObject(hMemDC, hOldBmp);
  1203. DeleteDC(hMemDC);
  1204. DeleteObject(hCandIconBmp);
  1205. DeleteObject(hCandEBmp);
  1206. DeleteObject(hCandDBmp);
  1207. DeleteObject(hCandUBmp);
  1208. DeleteObject(hCandHBmp);
  1209. DeleteObject(hCandInfBmp);
  1210. if (sImeG.fDiffSysCharSet) {
  1211. DeleteObject(SelectObject(hDC, hOldFont));
  1212. }
  1213. ImmUnlockIMCC(lpIMC->hPrivate);
  1214. UpCandW2UnlockCandInfo:
  1215. ImmUnlockIMCC(lpIMC->hCandInfo);
  1216. UpCandW2UnlockIMC:
  1217. ImmUnlockIMC(hIMC);
  1218. return;
  1219. }
  1220. /**********************************************************************/
  1221. /* CandWndProc() */
  1222. /**********************************************************************/
  1223. LRESULT CALLBACK CandWndProc(
  1224. HWND hCandWnd,
  1225. UINT uMsg,
  1226. WPARAM wParam,
  1227. LPARAM lParam)
  1228. {
  1229. switch (uMsg) {
  1230. case WM_DESTROY:
  1231. DestroyCandWindow(hCandWnd);
  1232. break;
  1233. case WM_SETCURSOR:
  1234. CandSetCursor(hCandWnd, lParam);
  1235. break;
  1236. case WM_MOUSEMOVE:
  1237. if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
  1238. POINT ptCursor;
  1239. DrawDragBorder(hCandWnd,
  1240. GetWindowLong(hCandWnd, UI_MOVE_XY),
  1241. GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
  1242. GetCursorPos(&ptCursor);
  1243. SetWindowLong(hCandWnd, UI_MOVE_XY,
  1244. MAKELONG(ptCursor.x, ptCursor.y));
  1245. DrawDragBorder(hCandWnd, MAKELONG(ptCursor.x, ptCursor.y),
  1246. GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
  1247. } else {
  1248. return DefWindowProc(hCandWnd, uMsg, wParam, lParam);
  1249. }
  1250. break;
  1251. case WM_LBUTTONUP:
  1252. if (!CandButtonUp(hCandWnd)) {
  1253. return DefWindowProc(hCandWnd, uMsg, wParam, lParam);
  1254. }
  1255. break;
  1256. case WM_IME_NOTIFY:
  1257. if (wParam == IMN_SETCANDIDATEPOS) {
  1258. return SetCandPosition(hCandWnd);
  1259. }
  1260. break;
  1261. case WM_PAINT:
  1262. {
  1263. HDC hDC;
  1264. PAINTSTRUCT ps;
  1265. hDC = BeginPaint(hCandWnd, &ps);
  1266. PaintCandWindow(hCandWnd, hDC);
  1267. EndPaint(hCandWnd, &ps);
  1268. }
  1269. break;
  1270. case WM_MOUSEACTIVATE:
  1271. return (MA_NOACTIVATE);
  1272. default:
  1273. return DefWindowProc(hCandWnd, uMsg, wParam, lParam);
  1274. }
  1275. return (0L);
  1276. }