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.

1152 lines
31 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. OFFCARET.C
  5. ++*/
  6. #include <windows.h>
  7. #include <immdev.h>
  8. #include "imeattr.h"
  9. #include "imedefs.h"
  10. #include "imerc.h"
  11. #if defined(UNIIME)
  12. #include "uniime.h"
  13. #endif
  14. /**********************************************************************/
  15. /* DestroyOffCaretWindow() */
  16. /**********************************************************************/
  17. void PASCAL DestroyOffCaretWindow( // destroy composition window
  18. HWND hOffCaretWnd)
  19. {
  20. HGLOBAL hUIPrivate;
  21. LPUIPRIV lpUIPrivate;
  22. if (GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
  23. // undo the drag border
  24. DrawDragBorder(hOffCaretWnd,
  25. GetWindowLong(hOffCaretWnd, UI_MOVE_XY),
  26. GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET));
  27. }
  28. hUIPrivate = (HGLOBAL)GetWindowLongPtr(GetWindow(hOffCaretWnd, GW_OWNER),
  29. IMMGWLP_PRIVATE);
  30. if (!hUIPrivate) {
  31. return;
  32. }
  33. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  34. if (!lpUIPrivate) {
  35. return;
  36. }
  37. #if !defined(ROMANIME)
  38. lpUIPrivate->nShowCompCmd = lpUIPrivate->nShowCandCmd = SW_HIDE;
  39. #endif
  40. lpUIPrivate->nShowStatusCmd = SW_HIDE;
  41. #if !defined(ROMANIME)
  42. lpUIPrivate->hCompWnd = lpUIPrivate->hCandWnd = NULL;
  43. #endif
  44. lpUIPrivate->hStatusWnd = NULL;
  45. GlobalUnlock(hUIPrivate);
  46. return;
  47. }
  48. #if !defined(ROMANIME)
  49. /**********************************************************************/
  50. /* MouseSelectOffCaretCandStr() */
  51. /**********************************************************************/
  52. BOOL PASCAL MouseSelectOffCaretCandStr(
  53. #if defined(UNIIME)
  54. LPINSTDATAL lpInstL,
  55. LPIMEL lpImeL,
  56. #endif
  57. HWND hOffCaretWnd,
  58. LPPOINT lpCursor)
  59. {
  60. BOOL fRet;
  61. HWND hUIWnd;
  62. HIMC hIMC;
  63. LPINPUTCONTEXT lpIMC;
  64. HGLOBAL hUIPrivate;
  65. LPUIPRIV lpUIPrivate;
  66. LPCANDIDATEINFO lpCandInfo;
  67. LPCANDIDATELIST lpCandList;
  68. DWORD dwValue, dwLimit;
  69. UINT nMouseChars, nChars;
  70. fRet = FALSE;
  71. hUIWnd = GetWindow(hOffCaretWnd, GW_OWNER);
  72. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  73. if (!hIMC) {
  74. return (fRet);
  75. }
  76. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  77. if (!hUIPrivate) {
  78. return (fRet);
  79. }
  80. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  81. if (!lpIMC) {
  82. return (fRet);
  83. }
  84. if (!lpIMC->hCandInfo) {
  85. goto MouseSelOffCaretCandStrUnlockIMC;
  86. }
  87. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  88. if (!lpUIPrivate) {
  89. goto MouseSelOffCaretCandStrUnlockIMC;
  90. }
  91. dwValue = lpUIPrivate->nShowCandCmd;
  92. GlobalUnlock(hUIPrivate);
  93. if (dwValue == SW_HIDE) {
  94. // may application draw the UI or currently is not in candidate list
  95. goto MouseSelOffCaretCandStrUnlockIMC;
  96. }
  97. // we can select candidate
  98. fRet = TRUE;
  99. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  100. if (!lpCandInfo) {
  101. goto MouseSelOffCaretCandStrUnlockIMC;
  102. }
  103. nMouseChars = (lpCursor->x - lpImeL->rcCandText.left) * 2 /
  104. sImeG.xChiCharWi;
  105. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  106. lpCandInfo->dwOffset[0]);
  107. dwValue = lpCandList->dwPageStart;
  108. // process one page
  109. dwLimit = dwValue + lpCandList->dwPageSize;
  110. if (dwLimit > lpCandList->dwCount) {
  111. dwLimit = lpCandList->dwCount;
  112. }
  113. for (nChars = 0; dwValue < dwLimit; dwValue++) {
  114. UINT uStrLen;
  115. #ifdef UNICODE
  116. LPTSTR lpTmpStr;
  117. #endif
  118. #ifdef UNICODE
  119. // this is not a real string length just an approximate char width
  120. uStrLen = 0;
  121. lpTmpStr = (LPTSTR)((LPBYTE)lpCandList +
  122. lpCandList->dwOffset[dwValue]);
  123. for (; *lpTmpStr; lpTmpStr++) {
  124. if (*lpTmpStr < 0x0200) {
  125. uStrLen += 1;
  126. } else {
  127. uStrLen += 2;
  128. }
  129. }
  130. #else
  131. uStrLen = lstrlen((LPTSTR)((LPBYTE)lpCandList +
  132. lpCandList->dwOffset[dwValue]));
  133. #endif
  134. #if defined(WINAR30)
  135. if (!uStrLen) {
  136. uStrLen = sizeof(WCHAR);
  137. }
  138. #endif
  139. // + 1 for the '1' '2' '3' ....
  140. nChars += uStrLen + 1;
  141. if (nMouseChars < nChars) {
  142. #if defined(UNIIME)
  143. UniNotifyIME(lpInstL, lpImeL, hIMC, NI_SELECTCANDIDATESTR, 0,
  144. dwValue);
  145. #else
  146. NotifyIME(hIMC, NI_SELECTCANDIDATESTR, 0, dwValue);
  147. #endif
  148. break;
  149. }
  150. }
  151. ImmUnlockIMCC(lpIMC->hCandInfo);
  152. if (nMouseChars >= nChars) {
  153. // invalid choice
  154. MessageBeep((UINT)-1);
  155. }
  156. MouseSelOffCaretCandStrUnlockIMC:
  157. ImmUnlockIMC(hIMC);
  158. return (fRet);
  159. }
  160. /**********************************************************************/
  161. /* MouseSelectCandPage() */
  162. /**********************************************************************/
  163. BOOL PASCAL MouseSelectCandPage(
  164. #if defined(UNIIME)
  165. LPIMEL lpImeL,
  166. #endif
  167. HWND hCandWnd,
  168. WORD wCharCode)
  169. {
  170. BOOL fRet;
  171. HWND hUIWnd;
  172. HIMC hIMC;
  173. LPINPUTCONTEXT lpIMC;
  174. HGLOBAL hUIPrivate;
  175. LPUIPRIV lpUIPrivate;
  176. LPCANDIDATEINFO lpCandInfo;
  177. LPPRIVCONTEXT lpImcP;
  178. fRet = FALSE;
  179. hUIWnd = GetWindow(hCandWnd, GW_OWNER);
  180. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  181. if (!hIMC) {
  182. return (fRet);
  183. }
  184. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  185. if (!hUIPrivate) {
  186. return (fRet);
  187. }
  188. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  189. if (!lpIMC) {
  190. return (fRet);
  191. }
  192. if (!lpIMC->hCandInfo) {
  193. goto MouseSelCandPageUnlockIMC;
  194. }
  195. if (!lpIMC->hPrivate) {
  196. goto MouseSelCandPageUnlockIMC;
  197. }
  198. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  199. if (!lpUIPrivate) {
  200. goto MouseSelCandPageUnlockIMC;
  201. }
  202. if (lpUIPrivate->nShowCandCmd == SW_HIDE) {
  203. // may application draw the UI or currently is not in candidate list
  204. goto MouseSelCandPageUnlockIMC;
  205. }
  206. // we can select candidate
  207. fRet = TRUE;
  208. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  209. if (!lpCandInfo) {
  210. goto MouseSelCandPageUnlockUIPriv;
  211. }
  212. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  213. if (!lpImcP) {
  214. goto MouseSelCandPageUnlockCandInfo;
  215. }
  216. ChooseCand(
  217. #if defined(UNIIME)
  218. NULL, lpImeL,
  219. #endif
  220. wCharCode, hIMC, lpIMC, lpCandInfo, lpImcP);
  221. GenerateMessage(hIMC, lpIMC, lpImcP);
  222. ImmUnlockIMCC(lpIMC->hPrivate);
  223. MouseSelCandPageUnlockCandInfo:
  224. ImmUnlockIMCC(lpIMC->hCandInfo);
  225. MouseSelCandPageUnlockUIPriv:
  226. GlobalUnlock(hUIPrivate);
  227. MouseSelCandPageUnlockIMC:
  228. ImmUnlockIMC(hIMC);
  229. return (fRet);
  230. }
  231. #endif
  232. /**********************************************************************/
  233. /* OffCaretSetCursor() */
  234. /**********************************************************************/
  235. void PASCAL OffCaretSetCursor(
  236. #if defined(UNIIME)
  237. LPINSTDATAL lpInstL,
  238. LPIMEL lpImeL,
  239. #endif
  240. HWND hOffCaretWnd,
  241. LPARAM lParam)
  242. {
  243. POINT ptCursor, ptSavCursor;
  244. RECT rcWnd;
  245. if (GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
  246. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  247. return;
  248. }
  249. GetCursorPos(&ptCursor);
  250. ptSavCursor = ptCursor;
  251. ScreenToClient(hOffCaretWnd, &ptCursor);
  252. if (PtInRect(&lpImeL->rcStatusText, ptCursor)) {
  253. SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(IDCR_HAND_CURSOR)));
  254. if (HIWORD(lParam) == WM_LBUTTONDOWN) {
  255. HWND hStatusWnd;
  256. SystemParametersInfo(SPI_GETWORKAREA, 0, &sImeG.rcWorkArea, 0);
  257. hStatusWnd = GetStatusWnd(GetWindow(hOffCaretWnd, GW_OWNER));
  258. if (hStatusWnd) {
  259. SetStatus(
  260. #if defined(UNIIME)
  261. lpImeL,
  262. #endif
  263. hStatusWnd, &ptCursor);
  264. return;
  265. } else {
  266. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  267. }
  268. } else if (HIWORD(lParam) == WM_RBUTTONUP) {
  269. static BOOL fImeConfigure = FALSE;
  270. HWND hUIWnd, hStatusWnd;
  271. // prevent recursive
  272. if (fImeConfigure) {
  273. // configuration already bring up
  274. return;
  275. }
  276. hUIWnd = GetWindow(hOffCaretWnd, GW_OWNER);
  277. hStatusWnd = GetStatusWnd(hUIWnd);
  278. if (!hStatusWnd) {
  279. return;
  280. }
  281. fImeConfigure = TRUE;
  282. ContextMenu(
  283. #if defined(UNIIME)
  284. lpInstL, lpImeL,
  285. #endif
  286. hStatusWnd, ptSavCursor.x, ptSavCursor.y);
  287. fImeConfigure = FALSE;
  288. return;
  289. } else {
  290. return;
  291. }
  292. #if !defined(ROMANIME)
  293. } else if (PtInRect(&lpImeL->rcCandText, ptCursor)) {
  294. if (HIWORD(lParam) != WM_LBUTTONDOWN) {
  295. SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(IDCR_HAND_CURSOR)));
  296. return;
  297. }
  298. if (MouseSelectOffCaretCandStr(
  299. #if defined(UNIIME)
  300. lpInstL, lpImeL,
  301. #endif
  302. hOffCaretWnd, &ptCursor)) {
  303. return;
  304. }
  305. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  306. #if defined(WINAR30)
  307. } else if (PtInRect(&lpImeL->rcCompText, ptCursor)) {
  308. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  309. if (HIWORD(lParam) != WM_LBUTTONDOWN) {
  310. return;
  311. }
  312. #endif
  313. } else if (PtInRect(&lpImeL->rcCandPageUp, ptCursor)) {
  314. if (HIWORD(lParam) != WM_LBUTTONDOWN) {
  315. SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(IDCR_HAND_CURSOR)));
  316. return;
  317. }
  318. if (MouseSelectCandPage(
  319. #if defined(UNIIME)
  320. lpImeL,
  321. #endif
  322. hOffCaretWnd, CHOOSE_PREVPAGE)) {
  323. return;
  324. }
  325. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  326. } else if (PtInRect(&lpImeL->rcCandHome, ptCursor)) {
  327. if (HIWORD(lParam) != WM_LBUTTONDOWN) {
  328. SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(IDCR_HAND_CURSOR)));
  329. return;
  330. }
  331. if (MouseSelectCandPage(
  332. #if defined(UNIIME)
  333. lpImeL,
  334. #endif
  335. hOffCaretWnd, CHOOSE_HOME)) {
  336. return;
  337. }
  338. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  339. } else if (PtInRect(&lpImeL->rcCandPageDn, ptCursor)) {
  340. if (HIWORD(lParam) != WM_LBUTTONDOWN) {
  341. SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(IDCR_HAND_CURSOR)));
  342. return;
  343. }
  344. if (MouseSelectCandPage(
  345. #if defined(UNIIME)
  346. lpImeL,
  347. #endif
  348. hOffCaretWnd, CHOOSE_NEXTPAGE)) {
  349. return;
  350. }
  351. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  352. #endif
  353. } else {
  354. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  355. if (HIWORD(lParam) != WM_LBUTTONDOWN) {
  356. return;
  357. }
  358. }
  359. SetCapture(hOffCaretWnd);
  360. SetWindowLong(hOffCaretWnd, UI_MOVE_XY,
  361. MAKELONG(ptSavCursor.x, ptSavCursor.y));
  362. GetWindowRect(hOffCaretWnd, &rcWnd);
  363. SetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET,
  364. MAKELONG(ptSavCursor.x - rcWnd.left, ptSavCursor.y - rcWnd.top));
  365. DrawDragBorder(hOffCaretWnd, MAKELONG(ptSavCursor.x, ptSavCursor.y),
  366. GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET));
  367. return;
  368. }
  369. /**********************************************************************/
  370. /* PaintOffCaretStatus() */
  371. /**********************************************************************/
  372. void PASCAL PaintOffCaretStatus(
  373. #if defined(UNIIME)
  374. LPINSTDATAL lpInstL,
  375. LPIMEL lpImeL,
  376. #endif
  377. HWND hOffCaretWnd,
  378. HDC hDC)
  379. {
  380. HGLOBAL hUIPrivate;
  381. LPUIPRIV lpUIPrivate;
  382. hUIPrivate = (HGLOBAL)GetWindowLongPtr(GetWindow(hOffCaretWnd, GW_OWNER),
  383. IMMGWLP_PRIVATE);
  384. if (!hUIPrivate) {
  385. return;
  386. }
  387. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  388. if (!lpUIPrivate) {
  389. return;
  390. }
  391. if (lpUIPrivate->fdwSetContext & ISC_OPEN_STATUS_WINDOW) {
  392. PaintStatusWindow(
  393. #if defined(UNIIME)
  394. lpInstL, lpImeL,
  395. #endif
  396. hOffCaretWnd, hDC);
  397. }
  398. GlobalUnlock(hUIPrivate);
  399. return;
  400. }
  401. #if !defined(ROMANIME)
  402. /**********************************************************************/
  403. /* PaintOffCaretCandPage() */
  404. /**********************************************************************/
  405. void PASCAL PaintOffCaretCandPage(
  406. #if defined(UNIIME)
  407. LPIMEL lpImeL,
  408. #endif
  409. HDC hDC,
  410. UINT uCandMode,
  411. LPCANDIDATELIST lpCandList)
  412. {
  413. HBITMAP hCandPromptBmp;
  414. HBITMAP hPageUpBmp, hHomeBmp, hPageDnBmp, hOldBmp;
  415. HDC hMemDC;
  416. hMemDC = CreateCompatibleDC(hDC);
  417. if ( hMemDC == NULL )
  418. {
  419. return;
  420. }
  421. if (uCandMode == CAND_PROMPT_PHRASE) {
  422. hCandPromptBmp = LoadBitmap(hInst,
  423. MAKEINTRESOURCE(IDBM_CAND_PROMPT_PHRASE));
  424. #if defined(WINAR30)
  425. } else if (uCandMode == CAND_PROMPT_QUICK_VIEW) {
  426. hCandPromptBmp = LoadBitmap(hInst,
  427. MAKEINTRESOURCE(IDBM_CAND_PROMPT_QUICK_VIEW));
  428. #endif
  429. } else {
  430. hCandPromptBmp = LoadBitmap(hInst,
  431. MAKEINTRESOURCE(IDBM_CAND_PROMPT_NORMAL));
  432. }
  433. if ( hCandPromptBmp == NULL )
  434. {
  435. DeleteDC(hMemDC);
  436. return;
  437. }
  438. hOldBmp = SelectObject(hMemDC, hCandPromptBmp);
  439. BitBlt(hDC, lpImeL->rcCandPrompt.left, lpImeL->rcCandPrompt.top,
  440. lpImeL->rcCandPrompt.right - lpImeL->rcCandPrompt.left,
  441. lpImeL->rcCandPrompt.bottom - lpImeL->rcCandPrompt.top,
  442. hMemDC, 0, 0, SRCCOPY);
  443. if (lpCandList->dwCount <= lpCandList->dwPageSize) {
  444. goto PaintOffCaretCandPageOvr;
  445. }
  446. if (lpCandList->dwPageStart > 0) {
  447. hPageUpBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_PAGEUP_HORIZ));
  448. } else {
  449. hPageUpBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_NO_PAGEUP_HORIZ));
  450. }
  451. if ( hPageUpBmp == NULL )
  452. {
  453. goto PaintOffCaretCandPageOvr;
  454. }
  455. if (lpCandList->dwPageStart > 0) {
  456. hHomeBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_HOME_HORIZ));
  457. } else {
  458. hHomeBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_NO_HOME_HORIZ));
  459. }
  460. if ( hHomeBmp == NULL )
  461. {
  462. DeleteObject(hPageUpBmp);
  463. goto PaintOffCaretCandPageOvr;
  464. }
  465. if ((lpCandList->dwPageStart + lpCandList->dwPageSize) <
  466. lpCandList->dwCount) {
  467. hPageDnBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_PAGEDN_HORIZ));
  468. } else {
  469. hPageDnBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_NO_PAGEDN_HORIZ));
  470. }
  471. if ( hPageDnBmp == NULL )
  472. {
  473. DeleteObject(hPageUpBmp);
  474. DeleteObject(hHomeBmp);
  475. goto PaintOffCaretCandPageOvr;
  476. }
  477. SelectObject(hMemDC, hPageUpBmp);
  478. BitBlt(hDC, lpImeL->rcCandPageUp.left, lpImeL->rcCandPageUp.top,
  479. lpImeL->rcCandPageUp.right - lpImeL->rcCandPageUp.left,
  480. lpImeL->rcCandPageUp.bottom - lpImeL->rcCandPageUp.top,
  481. hMemDC, 0, 0, SRCCOPY);
  482. SelectObject(hMemDC, hHomeBmp);
  483. BitBlt(hDC, lpImeL->rcCandHome.left, lpImeL->rcCandHome.top,
  484. lpImeL->rcCandHome.right - lpImeL->rcCandHome.left,
  485. lpImeL->rcCandHome.bottom - lpImeL->rcCandHome.top,
  486. hMemDC, 0, 0, SRCCOPY);
  487. SelectObject(hMemDC, hPageDnBmp);
  488. BitBlt(hDC, lpImeL->rcCandPageDn.left, lpImeL->rcCandPageDn.top,
  489. lpImeL->rcCandPageDn.right - lpImeL->rcCandPageDn.left,
  490. lpImeL->rcCandPageDn.bottom - lpImeL->rcCandPageDn.top,
  491. hMemDC, 0, 0, SRCCOPY);
  492. SelectObject(hMemDC, hOldBmp);
  493. DeleteObject(hPageUpBmp);
  494. DeleteObject(hHomeBmp);
  495. DeleteObject(hPageDnBmp);
  496. PaintOffCaretCandPageOvr:
  497. SelectObject(hMemDC, hOldBmp);
  498. DeleteDC(hMemDC);
  499. DeleteObject(hCandPromptBmp);
  500. return;
  501. }
  502. /**********************************************************************/
  503. /* PaintOffCaretComposition() */
  504. /**********************************************************************/
  505. void PASCAL PaintOffCaretComposition(
  506. #if defined(UNIIME)
  507. LPIMEL lpImeL,
  508. #endif
  509. HWND hOffCaretWnd,
  510. HDC hDC)
  511. {
  512. HWND hUIWnd;
  513. HIMC hIMC;
  514. LPINPUTCONTEXT lpIMC;
  515. HGLOBAL hUIPrivate;
  516. LPUIPRIV lpUIPrivate;
  517. LPPRIVCONTEXT lpImcP;
  518. HGDIOBJ hOldFont;
  519. LPTSTR lpStr;
  520. RECT rcSunken;
  521. LOGFONT lfFont;
  522. HFONT hNewFont;
  523. hUIWnd = GetWindow(hOffCaretWnd, GW_OWNER);
  524. hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
  525. if (!hIMC) {
  526. return;
  527. }
  528. hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
  529. if (!hUIPrivate) {
  530. return;
  531. }
  532. lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
  533. if (!lpIMC) {
  534. return;
  535. }
  536. lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
  537. if (!lpUIPrivate) {
  538. goto PaintOffCaretCompUnlockIMC;
  539. }
  540. rcSunken = lpImeL->rcCompText;
  541. rcSunken.left -= lpImeL->cxCompBorder;
  542. rcSunken.top -= lpImeL->cyCompBorder;
  543. rcSunken.right += lpImeL->cxCompBorder;
  544. rcSunken.bottom += lpImeL->cyCompBorder;
  545. DrawEdge(hDC, &rcSunken, BDR_SUNKENOUTER, BF_RECT);
  546. hOldFont = GetCurrentObject(hDC, OBJ_FONT);
  547. GetObject(hOldFont, sizeof(lfFont), &lfFont);
  548. if (sImeG.fDiffSysCharSet) {
  549. lfFont.lfCharSet = NATIVE_CHARSET;
  550. lfFont.lfFaceName[0] = TEXT('\0');
  551. }
  552. lfFont.lfWeight = FW_DONTCARE;
  553. hNewFont = CreateFontIndirect(&lfFont);
  554. if ( hNewFont != NULL )
  555. {
  556. SelectObject(hDC, (HGDIOBJ)hNewFont);
  557. }
  558. else
  559. {
  560. // return error
  561. GlobalUnlock(hUIPrivate);
  562. ImmUnlockIMC(hIMC);
  563. return;
  564. }
  565. #if defined(WINAR30)
  566. rcSunken = lpImeL->rcCandText;
  567. rcSunken.left -= lpImeL->cxCandMargin;
  568. rcSunken.top -= lpImeL->cyCandMargin;
  569. rcSunken.right += lpImeL->cxCandMargin;
  570. rcSunken.bottom += lpImeL->cyCandMargin;
  571. DrawEdge(hDC, &rcSunken, BDR_SUNKENOUTER, BF_RECT);
  572. #endif
  573. // light gray background
  574. SetBkColor(hDC, RGB(0xC0, 0xC0, 0xC0));
  575. if (lpUIPrivate->nShowCandCmd != SW_HIDE) {
  576. LPCANDIDATEINFO lpCandInfo;
  577. LPCANDIDATELIST lpCandList;
  578. BOOL fCandidate;
  579. DWORD dwStart, dwEnd;
  580. UINT uCandMode;
  581. int i, nChars, nHalfChars;
  582. TCHAR szStrBuf[CANDPERPAGE * 3 + 1];
  583. #ifdef UNICODE
  584. int iDx[CANDPERPAGE * 3 + 1];
  585. #endif
  586. fCandidate = FALSE;
  587. if (!lpIMC->hCandInfo) {
  588. goto PaintOffCaretCompChkCandInfo;
  589. }
  590. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
  591. if (!lpCandInfo) {
  592. goto PaintOffCaretCompChkCandInfo;
  593. }
  594. if (!lpCandInfo->dwCount) {
  595. goto PaintOffCaretCompUnlockCandInfo;
  596. }
  597. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
  598. lpCandInfo->dwOffset[0]);
  599. if (!lpCandList->dwCount) {
  600. goto PaintOffCaretCompUnlockCandInfo;
  601. }
  602. dwStart = lpCandList->dwPageStart;
  603. dwEnd = dwStart + lpCandList->dwPageSize;
  604. if (dwEnd > lpCandList->dwCount) {
  605. dwEnd = lpCandList->dwCount;
  606. }
  607. fCandidate = TRUE;
  608. lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
  609. if (!lpImcP) {
  610. uCandMode = CAND_PROMPT_NORMAL;
  611. } else if (lpImcP->iImeState == CST_INIT) {
  612. // phrase prediction
  613. SetTextColor(hDC, RGB(0x00, 0x80, 0x00));
  614. uCandMode = CAND_PROMPT_PHRASE;
  615. #if defined(WINAR30)
  616. } else if (lpImcP->iImeState != CST_CHOOSE) {
  617. // quick key
  618. SetTextColor(hDC, RGB(0x80, 0x00, 0x80));
  619. uCandMode = CAND_PROMPT_QUICK_VIEW;
  620. #endif
  621. } else {
  622. uCandMode = CAND_PROMPT_NORMAL;
  623. }
  624. if (lpImcP) {
  625. ImmUnlockIMCC(lpIMC->hPrivate);
  626. }
  627. PaintOffCaretCandPage(
  628. #if defined(UNIIME)
  629. lpImeL,
  630. #endif
  631. hDC, uCandMode, lpCandList);
  632. for (i = 0, nChars = 0, nHalfChars = 0; dwStart < dwEnd;
  633. dwStart++, i++) {
  634. int nCharsInOneStr;
  635. int nHalfCharsInOneStr; // how many half width chars
  636. // one full width char ==
  637. // 2 half width chars
  638. int nLimit; // the room left to the candidate window
  639. #ifdef UNICODE
  640. LPTSTR lpTmpStr;
  641. #endif
  642. lpStr = (LPTSTR)((LPBYTE)lpCandList +
  643. lpCandList->dwOffset[dwStart]);
  644. nLimit = CANDPERPAGE * 3 - nHalfChars;
  645. if (nLimit <= 1) {
  646. break;
  647. }
  648. szStrBuf[nChars] = szDigit[i + lpImeL->wCandStart];
  649. #ifdef UNICODE
  650. // the digit for select candidate
  651. iDx[nChars] = sImeG.xChiCharWi / 2;
  652. nCharsInOneStr = nHalfCharsInOneStr = 1;
  653. #if defined(WINAR30) //1996/12/12
  654. iDx[nChars + nCharsInOneStr] = sImeG.xChiCharWi;
  655. #endif
  656. for (lpTmpStr = lpStr; *lpTmpStr; lpTmpStr++, nCharsInOneStr++) {
  657. if (nHalfCharsInOneStr > nLimit) {
  658. break;
  659. } else if (*lpTmpStr < 0x0200) {
  660. nHalfCharsInOneStr += 1;
  661. iDx[nChars + nCharsInOneStr] = sImeG.xChiCharWi / 2;
  662. } else {
  663. nHalfCharsInOneStr += 2;
  664. iDx[nChars + nCharsInOneStr] = sImeG.xChiCharWi;
  665. }
  666. }
  667. #else
  668. nHalfCharsInOneStr = nCharsInOneStr = lstrlen(lpStr) + 1;
  669. #endif
  670. if (nHalfCharsInOneStr <= nLimit) {
  671. // the room is enough, nChars + 1 for "1", "2", "3", ...
  672. CopyMemory(&szStrBuf[nChars + 1], lpStr,
  673. (nCharsInOneStr - 1) * sizeof(TCHAR));
  674. } else if (i) {
  675. break;
  676. } else {
  677. #ifdef UNICODE
  678. if (lpStr[nCharsInOneStr - 2 - 1] < 0x0200) {
  679. // we need more room to put ".."
  680. nCharsInOneStr -= 2;
  681. } else {
  682. nCharsInOneStr -= 1;
  683. }
  684. #else
  685. nHalfCharsInOneStr = nCharsInOneStr = nLimit - 2;
  686. #endif
  687. // nChars + 1 for "1", "2", "3", ...
  688. CopyMemory(&szStrBuf[nChars + 1], lpStr,
  689. (nCharsInOneStr - 1) * sizeof(TCHAR));
  690. #ifdef UNICODE
  691. // unicode of ..
  692. iDx[nChars + nCharsInOneStr] = sImeG.xChiCharWi;
  693. szStrBuf[nChars + nCharsInOneStr++] = 0x2025;
  694. #else
  695. szStrBuf[nChars + nCharsInOneStr++] = '.';
  696. szStrBuf[nChars + nCharsInOneStr++] = '.';
  697. #endif
  698. }
  699. #if defined(WINAR30)
  700. if (nCharsInOneStr <= 1) {
  701. #ifdef UNICODE
  702. // add unicode 0x25A1
  703. *(LPWSTR)&szStrBuf[nChars +1] = 0x25A1;
  704. #else
  705. // add big-5 0xA1BC
  706. *(LPWSTR)&szStrBuf[nChars +1] = 0xBCA1;
  707. #endif
  708. nCharsInOneStr =1+ sizeof(WCHAR) / sizeof(TCHAR);
  709. }
  710. #endif
  711. nChars += nCharsInOneStr;
  712. nHalfChars += nHalfCharsInOneStr;
  713. if (nHalfCharsInOneStr >= nLimit) {
  714. break;
  715. }
  716. }
  717. ExtTextOut(hDC, lpImeL->rcCandText.left, lpImeL->rcCandText.top,
  718. ETO_OPAQUE, &lpImeL->rcCandText,
  719. szStrBuf, nChars, iDx);
  720. PaintOffCaretCompUnlockCandInfo:
  721. ImmUnlockIMCC(lpIMC->hCandInfo);
  722. PaintOffCaretCompChkCandInfo:
  723. if (fCandidate) {
  724. #if !defined(WINAR30)
  725. goto PaintOffCaretCompUnlockUIPriv;
  726. #else
  727. } else {
  728. goto PaintOffCaretCandNone;
  729. #endif
  730. }
  731. #if defined(WINAR30)
  732. } else {
  733. PaintOffCaretCandNone:
  734. ExtTextOut(hDC, lpImeL->rcCandText.left, lpImeL->rcCandText.top,
  735. ETO_OPAQUE, &lpImeL->rcCandText, (LPTSTR)NULL, 0, NULL);
  736. #endif
  737. }
  738. // the composition window has daul function 1. composition window
  739. // 2. guideline so we need more check on ISC_xxx flags
  740. if (lpUIPrivate->nShowCompCmd == SW_HIDE) {
  741. goto PaintOffCaretCompNone;
  742. } else if (lpUIPrivate->fdwSetContext & ISC_SHOWUICOMPOSITIONWINDOW) {
  743. LPCOMPOSITIONSTRING lpCompStr;
  744. DWORD dwCompStrLen;
  745. if (!lpIMC->hCompStr) {
  746. goto PaintOffCaretCompGuideLine;
  747. }
  748. lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
  749. if (!lpCompStr) {
  750. goto PaintOffCaretCompGuideLine;
  751. }
  752. dwCompStrLen = lpCompStr->dwCompStrLen;
  753. if (!lpCompStr->dwCompStrLen) {
  754. goto PaintOffCaretCompUnlockCompStr;
  755. }
  756. // black text for compistion string
  757. SetTextColor(hDC, RGB(0x00, 0x00, 0x00));
  758. ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
  759. ETO_OPAQUE, &lpImeL->rcCompText,
  760. (LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset),
  761. lpCompStr->dwCompStrLen, iDx);
  762. if (lpCompStr->dwCompStrLen <= lpCompStr->dwCursorPos) {
  763. goto PaintOffCaretCompUnlockCompStr;
  764. }
  765. // there is error part
  766. // red text for error
  767. SetTextColor(hDC, RGB(0xFF, 0x00, 0x00));
  768. // dark gray background for error
  769. SetBkColor(hDC, RGB(0x80, 0x80, 0x80));
  770. ExtTextOut(hDC, lpImeL->rcCompText.left +
  771. lpCompStr->dwCursorPos * sImeG.xChiCharWi /
  772. (sizeof(WCHAR) / sizeof(TCHAR)),
  773. lpImeL->rcCompText.top,
  774. ETO_OPAQUE, NULL,
  775. (LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset +
  776. lpCompStr->dwCursorPos),
  777. (lpCompStr->dwCompStrLen - lpCompStr->dwCursorPos), iDx);
  778. PaintOffCaretCompUnlockCompStr:
  779. ImmUnlockIMCC(lpIMC->hCompStr);
  780. if (!dwCompStrLen) {
  781. goto PaintOffCaretCompGuideLine;
  782. }
  783. } else if (lpUIPrivate->fdwSetContext & ISC_SHOWUIGUIDELINE) {
  784. LPGUIDELINE lpGuideLine;
  785. BOOL fGuideLine;
  786. LPCANDIDATELIST lpCandList;
  787. UINT uStrLen;
  788. PaintOffCaretCompGuideLine:
  789. if (!lpIMC->hGuideLine) {
  790. goto PaintOffCaretCompNone;
  791. }
  792. lpGuideLine = (LPGUIDELINE)ImmLockIMCC(lpIMC->hGuideLine);
  793. if (!lpGuideLine) {
  794. goto PaintOffCaretCompNone;
  795. }
  796. fGuideLine = FALSE;
  797. if (lpGuideLine->dwLevel != GL_LEVEL_INFORMATION) {
  798. goto PaintOffCaretCompUnlockGuideLine;
  799. } else if (lpGuideLine->dwIndex != GL_ID_REVERSECONVERSION) {
  800. goto PaintOffCaretCompUnlockGuideLine;
  801. } else {
  802. }
  803. lpCandList = (LPCANDIDATELIST)((LPBYTE)lpGuideLine +
  804. lpGuideLine->dwPrivateOffset);
  805. if (!lpCandList) {
  806. goto PaintOffCaretCompUnlockGuideLine;
  807. } else if (!lpCandList->dwCount) {
  808. goto PaintOffCaretCompUnlockGuideLine;
  809. } else {
  810. fGuideLine = TRUE;
  811. }
  812. // green text for information
  813. SetTextColor(hDC, RGB(0x00, 0x80, 0x00));
  814. lpStr = (LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[0]);
  815. uStrLen = lstrlen(lpStr);
  816. ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
  817. ETO_OPAQUE, &lpImeL->rcCompText, lpStr, uStrLen, iDx);
  818. PaintOffCaretCompUnlockGuideLine:
  819. ImmUnlockIMCC(lpIMC->hGuideLine);
  820. if (!fGuideLine) {
  821. goto PaintOffCaretCompNone;
  822. }
  823. } else {
  824. PaintOffCaretCompNone:
  825. ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
  826. ETO_OPAQUE, &lpImeL->rcCompText, (LPTSTR)NULL, 0, NULL);
  827. }
  828. DeleteObject(SelectObject(hDC, hOldFont));
  829. #if !defined(WINAR30)
  830. PaintOffCaretCompUnlockUIPriv:
  831. #endif
  832. GlobalUnlock(hUIPrivate);
  833. PaintOffCaretCompUnlockIMC:
  834. ImmUnlockIMC(hIMC);
  835. return;
  836. }
  837. #endif
  838. /**********************************************************************/
  839. /* OffCaretWndProc() / UniOffCaretWndProc() */
  840. /**********************************************************************/
  841. #if defined(UNIIME)
  842. LRESULT WINAPI UniOffCaretWndProc(
  843. LPINSTDATAL lpInstL,
  844. LPIMEL lpImeL,
  845. #else
  846. LRESULT CALLBACK OffCaretWndProc(
  847. #endif
  848. HWND hOffCaretWnd,
  849. UINT uMsg,
  850. WPARAM wParam,
  851. LPARAM lParam)
  852. {
  853. switch (uMsg) {
  854. case WM_DESTROY:
  855. DestroyOffCaretWindow(hOffCaretWnd);
  856. break;
  857. case WM_SETCURSOR:
  858. OffCaretSetCursor(
  859. #if defined(UNIIME)
  860. lpInstL, lpImeL,
  861. #endif
  862. hOffCaretWnd, lParam);
  863. break;
  864. case WM_MOUSEMOVE:
  865. if (GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
  866. POINT ptCursor;
  867. DrawDragBorder(hOffCaretWnd,
  868. GetWindowLong(hOffCaretWnd, UI_MOVE_XY),
  869. GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET));
  870. GetCursorPos(&ptCursor);
  871. SetWindowLong(hOffCaretWnd, UI_MOVE_XY,
  872. MAKELONG(ptCursor.x, ptCursor.y));
  873. DrawDragBorder(hOffCaretWnd, MAKELONG(ptCursor.x, ptCursor.y),
  874. GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET));
  875. } else {
  876. return DefWindowProc(hOffCaretWnd, uMsg, wParam, lParam);
  877. }
  878. break;
  879. case WM_LBUTTONUP:
  880. if (GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
  881. LONG lTmpCursor, lTmpOffset;
  882. POINT ptCursor;
  883. HWND hUIWnd;
  884. lTmpCursor = GetWindowLong(hOffCaretWnd, UI_MOVE_XY);
  885. // calculate the org by the offset
  886. lTmpOffset = GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET);
  887. DrawDragBorder(hOffCaretWnd, lTmpCursor, lTmpOffset);
  888. ptCursor.x = (*(LPPOINTS)&lTmpCursor).x - (*(LPPOINTS)&lTmpOffset).x;
  889. ptCursor.y = (*(LPPOINTS)&lTmpCursor).y - (*(LPPOINTS)&lTmpOffset).y;
  890. SetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG);
  891. ReleaseCapture();
  892. AdjustStatusBoundary(
  893. #if defined(UNIIME)
  894. lpImeL,
  895. #endif
  896. &ptCursor);
  897. hUIWnd = GetWindow(hOffCaretWnd, GW_OWNER);
  898. ImmSetStatusWindowPos((HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC),
  899. &ptCursor);
  900. } else {
  901. return DefWindowProc(hOffCaretWnd, uMsg, wParam, lParam);
  902. }
  903. break;
  904. case WM_IME_NOTIFY:
  905. if (wParam == IMN_SETSTATUSWINDOWPOS) {
  906. SetStatusWindowPos(
  907. #if defined(UNIIME)
  908. lpImeL,
  909. #endif
  910. hOffCaretWnd);
  911. }
  912. break;
  913. case WM_PAINT:
  914. {
  915. HDC hDC;
  916. PAINTSTRUCT ps;
  917. hDC = BeginPaint(hOffCaretWnd, &ps);
  918. PaintOffCaretStatus(
  919. #if defined(UNIIME)
  920. lpInstL, lpImeL,
  921. #endif
  922. hOffCaretWnd, hDC);
  923. #if !defined(ROMANIME)
  924. PaintOffCaretComposition(
  925. #if defined(UNIIME)
  926. lpImeL,
  927. #endif
  928. hOffCaretWnd, hDC);
  929. #endif
  930. EndPaint(hOffCaretWnd, &ps);
  931. }
  932. break;
  933. case WM_MOUSEACTIVATE:
  934. return (MA_NOACTIVATE);
  935. default:
  936. return DefWindowProc(hOffCaretWnd, uMsg, wParam, lParam);
  937. }
  938. return (0L);
  939. }