windows-nt/Source/XPSP1/NT/windows/feime/cht/candui.c
2020-09-26 16:20:57 +08:00

1743 lines
47 KiB
C

/*++
Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
Module Name:
CANDUI.c
++*/
#include <windows.h>
#include <immdev.h>
#include "imeattr.h"
#include "imedefs.h"
#include "imerc.h"
#if defined(UNIIME)
#include "uniime.h"
#endif
#if !defined(ROMANIME)
/**********************************************************************/
/* GetCandWnd */
/* Return Value : */
/* window handle of candidatte */
/**********************************************************************/
HWND PASCAL GetCandWnd(
HWND hUIWnd) // UI window
{
HGLOBAL hUIPrivate;
LPUIPRIV lpUIPrivate;
HWND hCandWnd;
hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
if (!hUIPrivate) { // can not darw candidate window
return (HWND)NULL;
}
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
if (!lpUIPrivate) { // can not draw candidate window
return (HWND)NULL;
}
hCandWnd = lpUIPrivate->hCandWnd;
GlobalUnlock(hUIPrivate);
return (hCandWnd);
}
/**********************************************************************/
/* CalcCandPos */
/**********************************************************************/
BOOL PASCAL CalcCandPos(
#if defined (UNIIME)
LPIMEL lpImeL,
#endif
LPINPUTCONTEXT lpIMC,
LPPOINT lpptWnd) // the composition window position
{
UINT uEsc;
POINT ptCurPos, ptNew;
BOOL fAdjust;
RECT rcWorkArea;
#if 1 // MultiMonitor support
rcWorkArea = ImeMonitorWorkAreaFromPoint(*lpptWnd);
#else
rcWorkArea = sImeG.rcWorkArea;
#endif
uEsc = (UINT)((lpIMC->lfFont.A.lfEscapement + 450) / 900 % 4);
ptCurPos = lpIMC->cfCompForm.ptCurrentPos;
ClientToScreen(lpIMC->hWnd, &ptCurPos);
fAdjust = FALSE;
if (uEsc == 0) {
ptNew.x = lpptWnd->x + lpImeL->xCompWi + UI_MARGIN * 2;
if (ptNew.x + lpImeL->xCandWi > rcWorkArea.right) {
// exceed screen width
ptNew.x = lpptWnd->x - lpImeL->xCandWi - UI_MARGIN * 2;
}
if (lpptWnd->y >= ptCurPos.y) {
ptNew.y = lpptWnd->y + lpImeL->cyCompBorder - lpImeL->cyCandBorder;
if (ptNew.y + lpImeL->yCandHi > rcWorkArea.bottom) {
// exceed screen high
ptNew.y = rcWorkArea.bottom - lpImeL->yCandHi;
}
} else {
ptNew.y = lpptWnd->y + lpImeL->yCompHi - lpImeL->yCandHi;
if (ptNew.y < rcWorkArea.top) {
ptNew.y = rcWorkArea.top;
}
}
} else if (uEsc == 1) {
if (lpptWnd->x >= ptCurPos.x) {
ptNew.x = lpptWnd->x + lpImeL->cxCompBorder -
lpImeL->cxCandBorder;
if (ptNew.x + lpImeL->xCandWi > rcWorkArea.right) {
// exceed screen width
ptNew.x = rcWorkArea.right - lpImeL->xCandWi;
fAdjust = TRUE;
}
} else {
ptNew.x = lpptWnd->x + lpImeL->xCompWi - lpImeL->xCandWi;
if (ptNew.x < rcWorkArea.left) {
// exceed screen width
ptNew.x = rcWorkArea.left;
fAdjust = TRUE;
}
}
ptNew.y = lpptWnd->y + lpImeL->yCompHi + UI_MARGIN * 2;
if (ptNew.y + lpImeL->yCandHi > rcWorkArea.bottom) {
// exceed screen high
ptNew.y = lpptWnd->y - lpImeL->yCandHi - UI_MARGIN * 2;
}
} else if (uEsc == 2) {
ptNew.x = lpptWnd->x - lpImeL->xCandWi - UI_MARGIN * 2;
if (ptNew.x < 0) {
ptNew.x = lpptWnd->x + lpImeL->xCompWi + UI_MARGIN * 2;
}
if (lpptWnd->y >= ptCurPos.y) {
ptNew.y = lpptWnd->y + lpImeL->cyCompBorder - lpImeL->cyCandBorder;
if (ptNew.y + lpImeL->yCandHi > rcWorkArea.bottom) {
// exceed screen high
ptNew.y = rcWorkArea.bottom - lpImeL->yCandHi;
}
} else {
ptNew.y = lpptWnd->y + lpImeL->yCompHi - lpImeL->yCandHi;
if (ptNew.y < rcWorkArea.top) {
ptNew.y = rcWorkArea.top;
}
}
} else {
if (lpptWnd->x >= ptCurPos.x) {
ptNew.x = lpptWnd->x + lpImeL->cxCompBorder -
lpImeL->cxCandBorder;
if (ptNew.x + lpImeL->xCandWi > rcWorkArea.right) {
// exceed screen width
ptNew.x = rcWorkArea.right - lpImeL->xCandWi;
fAdjust = TRUE;
}
} else {
ptNew.x = lpptWnd->x + lpImeL->xCompWi - lpImeL->xCandWi;
if (ptNew.x < rcWorkArea.left) {
// exceed screen width
ptNew.x = rcWorkArea.left;
fAdjust = TRUE;
}
}
ptNew.y = lpptWnd->y + lpImeL->yCompHi + UI_MARGIN * 2;
if (ptNew.y + lpImeL->yCandHi > rcWorkArea.bottom) {
// exceed screen high
ptNew.y = lpptWnd->y - lpImeL->yCandHi - UI_MARGIN * 2;
}
}
*lpptWnd = ptNew;
return (fAdjust);
}
/**********************************************************************/
/* AdjustCandBoundry */
/**********************************************************************/
void PASCAL AdjustCandBoundry(
#if defined (UNIIME)
LPIMEL lpImeL,
#endif
LPPOINT lpptCandWnd) // the position
{
RECT rcWorkArea;
#if 1 // MultiMonitor support
{
RECT rcCandWnd;
*(LPPOINT)&rcCandWnd = *(LPPOINT)lpptCandWnd;
rcCandWnd.right = rcCandWnd.left + lpImeL->xCandWi;
rcCandWnd.bottom = rcCandWnd.top + lpImeL->yCandHi;
rcWorkArea = ImeMonitorWorkAreaFromRect(&rcCandWnd);
}
#else
rcWorkArea = sImeG.rcWorkArea;
#endif
if (lpptCandWnd->x < rcWorkArea.left) {
lpptCandWnd->x = rcWorkArea.left;
} else if (lpptCandWnd->x + lpImeL->xCandWi > rcWorkArea.right) {
lpptCandWnd->x = rcWorkArea.right - lpImeL->xCandWi;
} else {
}
if (lpptCandWnd->y < rcWorkArea.top) {
lpptCandWnd->y = rcWorkArea.top;
} else if (lpptCandWnd->y + lpImeL->yCandHi > rcWorkArea.bottom) {
lpptCandWnd->y = rcWorkArea.bottom - lpImeL->yCandHi;
} else {
}
return;
}
/**********************************************************************/
/* FitInCandLazyOperation() */
/* Return Value : */
/* TRUE or FALSE */
/**********************************************************************/
BOOL PASCAL FitInCandLazyOperation( // fit in lazy operation or not
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
LPPOINT lpptOrg,
LPPOINT lpptNearCaret, // the suggested near caret position
LPRECT lprcInputRect,
UINT uEsc)
{
POINT ptDelta, ptTol;
RECT rcUIRect, rcInterRect;
ptDelta.x = lpptOrg->x - lpptNearCaret->x;
ptDelta.x = (ptDelta.x >= 0) ? ptDelta.x : -ptDelta.x;
ptTol.x = sImeG.iParaTol * ncUIEsc[uEsc].iParaFacX +
sImeG.iPerpTol * ncUIEsc[uEsc].iPerpFacX;
ptTol.x = (ptTol.x >= 0) ? ptTol.x : -ptTol.x;
if (ptDelta.x > ptTol.x) {
return (FALSE);
}
ptDelta.y = lpptOrg->y - lpptNearCaret->y;
ptDelta.y = (ptDelta.y >= 0) ? ptDelta.y : -ptDelta.y;
ptTol.y = sImeG.iParaTol * ncUIEsc[uEsc].iParaFacY +
sImeG.iPerpTol * ncUIEsc[uEsc].iPerpFacY;
ptTol.y = (ptTol.y >= 0) ? ptTol.y : -ptTol.y;
if (ptDelta.y > ptTol.y) {
return (FALSE);
}
// build up the UI rectangle (candidate window)
rcUIRect.left = lpptOrg->x;
rcUIRect.top = lpptOrg->y;
rcUIRect.right = rcUIRect.left + lpImeL->xCandWi;
rcUIRect.bottom = rcUIRect.top + lpImeL->yCandHi;
if (IntersectRect(&rcInterRect, &rcUIRect, lprcInputRect)) {
return (FALSE);
}
return (TRUE);
}
/**********************************************************************/
/* AdjustCandRectBoundry */
/**********************************************************************/
void PASCAL AdjustCandRectBoundry(
#if defined (UNIIME)
LPIMEL lpImeL,
#endif
LPINPUTCONTEXT lpIMC,
LPPOINT lpptOrg, // original candidate position
LPPOINT lpptCaret) // the caret position
{
RECT rcExclude, rcUIRect, rcInterSect;
UINT uEsc, uRot;
POINT ptCaret, ptOldNearCaret, ptFont;
// be a normal rectangle, not a negative rectangle
if (lpIMC->cfCandForm[0].rcArea.left > lpIMC->cfCandForm[0].rcArea.right) {
LONG tmp;
tmp = lpIMC->cfCandForm[0].rcArea.left;
lpIMC->cfCandForm[0].rcArea.left = lpIMC->cfCandForm[0].rcArea.right;
lpIMC->cfCandForm[0].rcArea.right = tmp;
}
if (lpIMC->cfCandForm[0].rcArea.top > lpIMC->cfCandForm[0].rcArea.bottom) {
LONG tmp;
tmp = lpIMC->cfCandForm[0].rcArea.top;
lpIMC->cfCandForm[0].rcArea.top = lpIMC->cfCandForm[0].rcArea.bottom;
lpIMC->cfCandForm[0].rcArea.bottom = tmp;
}
// translate from client coordinate to screen coordinate
rcExclude = lpIMC->cfCandForm[0].rcArea;
rcExclude.left += lpptCaret->x - lpIMC->cfCandForm[0].ptCurrentPos.x;
rcExclude.right += lpptCaret->x - lpIMC->cfCandForm[0].ptCurrentPos.x;
rcExclude.top += lpptCaret->y - lpIMC->cfCandForm[0].ptCurrentPos.y;
rcExclude.bottom += lpptCaret->y - lpIMC->cfCandForm[0].ptCurrentPos.y;
uEsc = (UINT)((lpIMC->lfFont.A.lfEscapement + 450) / 900 % 4);
uRot = (UINT)((lpIMC->lfFont.A.lfOrientation + 450) / 900 % 4);
if (uEsc == 0) {
ptCaret.x = lpptCaret->x;
ptCaret.y = rcExclude.top;
} else if (uEsc == 1) {
ptCaret.x = rcExclude.left;
ptCaret.y = lpptCaret->y;
} else if (uEsc == 2) {
ptCaret.x = lpptCaret->x;
ptCaret.y = rcExclude.bottom;
} else {
ptCaret.x = rcExclude.right;
ptCaret.y = lpptCaret->y;
}
ptFont.x = rcExclude.right - rcExclude.left;
ptFont.y = rcExclude.bottom - rcExclude.top;
// the first try
GetNearCaretPosition(
#if defined(UNIIME)
lpImeL,
#endif
&ptFont, uEsc, uRot, &ptCaret, &ptOldNearCaret,
NEAR_CARET_FIRST_TIME|NEAR_CARET_CANDIDATE);
AdjustCandBoundry(
#if defined(UNIIME)
lpImeL,
#endif
&ptOldNearCaret);
*(LPPOINT)&rcUIRect = ptOldNearCaret;
rcUIRect.right = rcUIRect.left + lpImeL->xCandWi;
rcUIRect.bottom = rcUIRect.top + lpImeL->yCandHi;
if (IntersectRect(&rcInterSect, &rcExclude, &rcUIRect)) {
} else if (FitInCandLazyOperation(
#if defined(UNIIME)
lpImeL,
#endif
lpptOrg, (LPPOINT)&rcUIRect, &rcExclude, uEsc)) {
*lpptCaret = *lpptOrg;
return;
} else {
*lpptCaret = *(LPPOINT)&rcUIRect;
return;
}
// the second try
GetNearCaretPosition(
#if defined(UNIIME)
lpImeL,
#endif
&ptFont, uEsc, uRot, &ptCaret, (LPPOINT)&rcUIRect,
NEAR_CARET_CANDIDATE);
AdjustCandBoundry(
#if defined(UNIIME)
lpImeL,
#endif
(LPPOINT)&rcUIRect);
rcUIRect.right = rcUIRect.left + lpImeL->xCandWi;
rcUIRect.bottom = rcUIRect.top + lpImeL->yCandHi;
if (IntersectRect(&rcInterSect, &rcExclude, &rcUIRect)) {
} else if (FitInCandLazyOperation(
#if defined(UNIIME)
lpImeL,
#endif
lpptOrg, (LPPOINT)&rcUIRect, &rcExclude, uEsc)) {
*lpptCaret = *lpptOrg;
return;
} else {
*lpptCaret = *(LPPOINT)&rcUIRect;
return;
}
// unhappy ending! :-(
*lpptCaret = ptOldNearCaret;
return;
}
/**********************************************************************/
/* SetCandPosition() */
/**********************************************************************/
LRESULT PASCAL SetCandPosition(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
HWND hCandWnd)
{
HWND hUIWnd;
HIMC hIMC;
LPINPUTCONTEXT lpIMC;
POINT ptWnd;
hUIWnd = GetWindow(hCandWnd, GW_OWNER);
hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
if (!hIMC) {
return (1L);
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) {
return (1L);
}
ptWnd = lpIMC->cfCandForm[0].ptCurrentPos;
ClientToScreen((HWND)lpIMC->hWnd, &ptWnd);
if (lpIMC->cfCandForm[0].dwStyle & CFS_FORCE_POSITION) {
} else if (lpIMC->cfCandForm[0].dwStyle == CFS_EXCLUDE) {
RECT rcCand;
GetWindowRect(hCandWnd, &rcCand);
AdjustCandRectBoundry(
#if defined(UNIIME)
lpImeL,
#endif
lpIMC, (LPPOINT)&rcCand, &ptWnd);
if (ptWnd.x != rcCand.left) {
} else if (ptWnd.y != rcCand.right) {
} else {
goto SetCandPosUnlockIMC;
}
} else if (lpIMC->cfCandForm[0].dwStyle == CFS_CANDIDATEPOS) {
HWND hCompWnd;
AdjustCandBoundry(
#if defined(UNIIME)
lpImeL,
#endif
&ptWnd);
if (lpIMC->cfCandForm[0].dwIndex == 0) {
} else if (!(hCompWnd = GetCompWnd(hUIWnd))) {
} else {
RECT rcComp, rcCand, rcInterSect;
GetWindowRect(hCompWnd, &rcComp);
*(LPPOINT)&rcCand = ptWnd;
rcCand.right = rcCand.left + lpImeL->xCandWi;
rcCand.bottom = rcCand.top + lpImeL->yCandHi;
if (IntersectRect(&rcInterSect, &rcComp, &rcCand)) {
ptWnd = *(LPPOINT)&rcComp;
CalcCandPos(
#if defined(UNIIME)
lpImeL,
#endif
lpIMC, &ptWnd);
}
}
} else if (lpIMC->cfCandForm[0].dwStyle == CFS_DEFAULT) {
HWND hCompWnd;
BOOL fUseCompWndPos;
hCompWnd = GetCompWnd(hUIWnd);
if (!hCompWnd) {
fUseCompWndPos = FALSE;
} else if (IsWindowVisible(hCompWnd)) {
fUseCompWndPos = TRUE;
} else {
fUseCompWndPos = FALSE;
}
if (fUseCompWndPos) {
ptWnd.x = 0;
ptWnd.y = 0;
ClientToScreen(hCompWnd, &ptWnd);
ptWnd.x -= lpImeL->cxCompBorder;
ptWnd.y -= lpImeL->cyCompBorder;
} else {
POINT ptNew;
ptWnd = lpIMC->cfCompForm.ptCurrentPos;
ClientToScreen((HWND)lpIMC->hWnd, &ptWnd);
ptWnd.x -= lpImeL->cxCompBorder;
ptWnd.y -= lpImeL->cyCompBorder;
ptNew = ptWnd;
// try to simulate the position of composition window
AdjustCompPosition(
#if defined(UNIIME)
lpImeL,
#endif
lpIMC, &ptWnd, &ptNew);
}
CalcCandPos(
#if defined(UNIIME)
lpImeL,
#endif
lpIMC, &ptWnd);
} else {
}
SetWindowPos(hCandWnd, NULL, ptWnd.x, ptWnd.y,
0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
SetCandPosUnlockIMC:
ImmUnlockIMC(hIMC);
return (0L);
}
/**********************************************************************/
/* ShowCand() */
/**********************************************************************/
void PASCAL ShowCand( // Show the candidate window
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
HWND hUIWnd,
int nShowCandCmd)
{
HGLOBAL hUIPrivate;
LPUIPRIV lpUIPrivate;
hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
if (!hUIPrivate) { // can not darw candidate window
return;
}
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
if (!lpUIPrivate) { // can not draw candidate window
return;
}
if (lpUIPrivate->nShowCandCmd == nShowCandCmd) {
goto SwCandNoChange;
}
if (nShowCandCmd == SW_HIDE) {
lpUIPrivate->fdwSetContext &= ~(ISC_HIDE_CAND_WINDOW);
}
if (!lpUIPrivate->hCandWnd) {
// not in show candidate window mode
} else if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
int nCurrShowState;
lpUIPrivate->nShowCandCmd = nShowCandCmd;
nCurrShowState = lpUIPrivate->nShowStatusCmd;
nCurrShowState |= lpUIPrivate->nShowCompCmd;
if (nCurrShowState == SW_HIDE) {
// if other two are hide, the current show state is determined
// by this candidate section
ShowWindow(lpUIPrivate->hCandWnd, nShowCandCmd);
} else {
RedrawWindow(lpUIPrivate->hCandWnd, NULL, NULL,
RDW_INVALIDATE|RDW_ERASE);
}
} else {
ShowWindow(lpUIPrivate->hCandWnd, nShowCandCmd);
lpUIPrivate->nShowCandCmd = nShowCandCmd;
}
SwCandNoChange:
GlobalUnlock(hUIPrivate);
return;
}
/**********************************************************************/
/* CandPageSizeDown */
/**********************************************************************/
void PASCAL CandPageSizeDown(
LPINPUTCONTEXT lpIMC)
{
DWORD dwSize;
LPCANDIDATEINFO lpCandInfo;
LPCANDIDATELIST lpCandList;
DWORD dwStart, dwEnd;
int nChars, iLen;
if (!lpIMC) {
return;
}
if (!lpIMC->hCandInfo) {
return;
}
lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
if (!lpCandInfo) {
return;
}
lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
lpCandInfo->dwOffset[0]);
dwStart = lpCandList->dwPageStart;
dwEnd = dwStart + CANDPERPAGE;
if (dwEnd > lpCandList->dwCount) {
dwEnd = lpCandList->dwCount;
}
dwSize = 0;
for (nChars = 0; dwStart < dwEnd; dwStart++, dwSize++) {
LPTSTR lpStr;
#ifdef UNICODE
LPTSTR lpTmpStr;
#endif
// for displaying digit
nChars++;
lpStr = (LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart]);
#ifdef UNICODE
iLen = 0;
for (lpTmpStr = lpStr; *lpTmpStr; lpTmpStr++) {
if (*lpTmpStr < 0x200) {
iLen += 1;
} else {
iLen += 2;
}
}
#else
iLen = lstrlen(lpStr);
#endif
#if defined(WINAR30)
if (!iLen) {
iLen = sizeof(WCHAR)/sizeof(TCHAR);
}
#endif
// buffer is not enough
if ((CANDPERPAGE * 3 - nChars) < iLen) {
if (!dwSize) {
dwSize = 1;
}
break;
}
nChars += iLen;
}
if (!dwSize) {
dwSize = CANDPERPAGE;
}
lpCandList->dwPageSize = dwSize;
ImmUnlockIMCC(lpIMC->hCandInfo);
return;
}
/**********************************************************************/
/* OpenCand */
/**********************************************************************/
void PASCAL OpenCand(
#if defined(UNIIME)
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#endif
HWND hUIWnd)
{
HGLOBAL hUIPrivate;
LPUIPRIV lpUIPrivate;
HIMC hIMC;
LPINPUTCONTEXT lpIMC;
LPPRIVCONTEXT lpImcP;
DWORD fdwImeMsg;
POINT ptWnd;
hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
if (!hUIPrivate) { // can not darw candidate window
return;
}
hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
if (!hIMC) {
return;
}
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
if (!lpUIPrivate) { // can not draw candidate window
return;
}
lpUIPrivate->fdwSetContext |= ISC_SHOWUICANDIDATEWINDOW;
// in the timing of the transition, we will wait
if (lpUIPrivate->fdwSetContext & ISC_OFF_CARET_UI) {
if (!(lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI)) {
PostMessage(hUIWnd, WM_USER_UICHANGE, 0, 0);
goto OpenCandUnlockUIPriv;
}
} else {
if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
PostMessage(hUIWnd, WM_USER_UICHANGE, 0, 0);
goto OpenCandUnlockUIPriv;
}
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) {
goto OpenCandUnlockUIPriv;
}
fdwImeMsg = 0;
lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
if (lpImcP) {
fdwImeMsg = lpImcP->fdwImeMsg;
ImmUnlockIMCC(lpIMC->hPrivate);
}
if (!(fdwImeMsg & MSG_ALREADY_OPEN)) {
// Sometime the application call ImmNotifyIME to cancel the
// composition before it process IMN_OPENCANDIDATE.
// We should avoid to process this kind of IMN_OPENCANDIDATE.
goto OpenCandUnlockIMC;
}
if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
if (lpUIPrivate->hCandWnd) {
} else if (lpUIPrivate->hStatusWnd) {
lpUIPrivate->hCandWnd = lpUIPrivate->hStatusWnd;
lpUIPrivate->nShowCandCmd = lpUIPrivate->nShowStatusCmd;
} else if (lpUIPrivate->hCompWnd) {
lpUIPrivate->hCandWnd = lpUIPrivate->hCompWnd;
lpUIPrivate->nShowCandCmd = lpUIPrivate->nShowCompCmd;
} else {
}
CandPageSizeDown(lpIMC);
ptWnd = lpIMC->ptStatusWndPos;
} else if (lpIMC->cfCandForm[0].dwIndex == 0) {
ptWnd = lpIMC->cfCandForm[0].ptCurrentPos;
ClientToScreen(lpIMC->hWnd, &ptWnd);
if (lpIMC->cfCandForm[0].dwStyle & CFS_FORCE_POSITION) {
} else if (lpIMC->cfCandForm[0].dwStyle == CFS_EXCLUDE) {
RECT rcCand;
if (lpUIPrivate->hCandWnd) {
GetWindowRect(lpUIPrivate->hCandWnd, &rcCand);
} else {
*(LPPOINT)&rcCand = ptWnd;
}
AdjustCandRectBoundry(
#if defined(UNIIME)
lpImeL,
#endif
lpIMC, (LPPOINT)&rcCand, &ptWnd);
} else if (lpIMC->cfCandForm[0].dwStyle == CFS_CANDIDATEPOS) {
AdjustCandBoundry(
#if defined(UNIIME)
lpImeL,
#endif
&ptWnd);
} else {
goto OpenCandDefault;
}
} else {
OpenCandDefault:
if (lpUIPrivate->nShowCompCmd != SW_HIDE) {
ptWnd.x = ptWnd.y = 0;
ClientToScreen(lpUIPrivate->hCompWnd, &ptWnd);
ptWnd.x -= lpImeL->cxCompBorder;
ptWnd.y -= lpImeL->cyCompBorder;
} else {
POINT ptNew;
ptWnd = lpIMC->cfCompForm.ptCurrentPos;
ClientToScreen(lpIMC->hWnd, &ptWnd);
ptWnd.x -= lpImeL->cxCompBorder;
ptWnd.y -= lpImeL->cyCompBorder;
ptNew = ptWnd;
// try to simulate the position of composition window
AdjustCompPosition(
#if defined(UNIIME)
lpImeL,
#endif
lpIMC, &ptWnd, &ptNew);
}
CalcCandPos(
#if defined(UNIIME)
lpImeL,
#endif
lpIMC, &ptWnd);
lpIMC->cfCandForm[0].dwStyle = CFS_CANDIDATEPOS;
lpIMC->cfCandForm[0].ptCurrentPos = ptWnd;
ScreenToClient(lpIMC->hWnd, &lpIMC->cfCandForm[0].ptCurrentPos);
}
if (lpUIPrivate->hCandWnd) {
if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
RECT rcRect;
rcRect = lpImeL->rcCandText;
// off by 1
rcRect.right += 1;
rcRect.bottom += 1;
InvalidateRect(lpUIPrivate->hCandWnd, &rcRect, FALSE);
rcRect = lpImeL->rcCandPrompt;
// off by 1
rcRect.right += 1;
rcRect.bottom += 1;
InvalidateRect(lpUIPrivate->hCandWnd, &rcRect, TRUE);
rcRect = lpImeL->rcCandPageText;
// off by 1
rcRect.right += 1;
rcRect.bottom += 1;
InvalidateRect(lpUIPrivate->hCandWnd, &rcRect, TRUE);
} else {
SetWindowPos(lpUIPrivate->hCandWnd, NULL,
ptWnd.x, ptWnd.y,
0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
}
} else {
if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
lpUIPrivate->hCandWnd = CreateWindowEx(
WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME,
lpImeL->szOffCaretClassName, NULL,
WS_POPUP|WS_DISABLED,
ptWnd.x, ptWnd.y,
lpImeL->xCandWi, lpImeL->yCandHi,
hUIWnd, (HMENU)NULL, lpInstL->hInst, NULL);
if (lpUIPrivate->hSoftKbdWnd) {
// insert soft keyboard in front of other UI
SetWindowPos(lpUIPrivate->hCandWnd,
lpUIPrivate->hSoftKbdWnd,
0, 0, 0, 0,
SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
}
} else {
lpUIPrivate->hCandWnd = CreateWindowEx(0,
// WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME,
lpImeL->szCandClassName, NULL,
WS_POPUP|WS_DISABLED|WS_BORDER,
ptWnd.x, ptWnd.y,
lpImeL->xCandWi, lpImeL->yCandHi,
hUIWnd, (HMENU)NULL, lpInstL->hInst, NULL);
}
SetWindowLong(lpUIPrivate->hCandWnd, UI_MOVE_OFFSET,
WINDOW_NOT_DRAG);
SetWindowLong(lpUIPrivate->hCandWnd, UI_MOVE_XY, 0L);
}
ShowCand(
#if defined(UNIIME)
lpImeL,
#endif
hUIWnd, SW_SHOWNOACTIVATE);
OpenCandUnlockIMC:
ImmUnlockIMC(hIMC);
OpenCandUnlockUIPriv:
GlobalUnlock(hUIPrivate);
return;
}
/**********************************************************************/
/* CloseCand */
/**********************************************************************/
void PASCAL CloseCand(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
HWND hUIWnd)
{
ShowCand(
#if defined(UNIIME)
lpImeL,
#endif
hUIWnd, SW_HIDE);
return;
}
/**********************************************************************/
/* CandPageSizeUp */
/**********************************************************************/
void PASCAL CandPageSizeUp(
HIMC hIMC,
LPINPUTCONTEXT lpIMC,
DWORD dwPrevPageStart)
{
DWORD dwSize;
LPCANDIDATEINFO lpCandInfo;
LPCANDIDATELIST lpCandList;
int iStart, iEnd;
int nChars, iLen;
if (!lpIMC) {
return;
}
if (!lpIMC->hCandInfo) {
return;
}
lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
if (!lpCandInfo) {
return;
}
lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
lpCandInfo->dwOffset[0]);
if (dwPrevPageStart) {
iStart = dwPrevPageStart - 1;
} else {
goto CandPageSizeUpUnlockCandInfo;
}
if (iStart > (CANDPERPAGE - 1)) {
iEnd = iStart - (CANDPERPAGE - 1);
} else {
iEnd = 0;
}
dwSize = 0;
for (nChars = 0; iStart >= iEnd; iStart--, dwSize++) {
LPTSTR lpStr;
#ifdef UNICODE
LPTSTR lpTmpStr;
#endif
// for displaying digit
nChars++;
lpStr = (LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[iStart]);
#ifdef UNICODE
iLen = 0;
for (lpTmpStr = lpStr; *lpTmpStr; lpTmpStr++) {
if (*lpTmpStr < 0x200) {
iLen += 1;
} else {
iLen += 2;
}
}
#else
iLen = lstrlen(lpStr);
#endif
#if defined(WINAR30)
if (!iLen) {
iLen = sizeof(WCHAR);
}
#endif
// buffer is not enough
if ((CANDPERPAGE * 3 - nChars) < iLen) {
if (!dwSize) {
dwSize = 1;
}
break;
}
nChars += iLen;
}
if (!dwSize) {
dwSize = CANDPERPAGE;
}
lpCandList->dwPageStart = lpCandList->dwSelection =
dwPrevPageStart - dwSize;
lpCandList->dwPageSize = dwSize;
CandPageSizeUpUnlockCandInfo:
ImmUnlockIMCC(lpIMC->hCandInfo);
return;
}
/**********************************************************************/
/* CandPageSize */
/**********************************************************************/
void PASCAL CandPageSize(
HWND hUIWnd,
BOOL fForward)
{
HGLOBAL hUIPrivate;
LPUIPRIV lpUIPrivate;
HIMC hIMC;
LPINPUTCONTEXT lpIMC;
LPPRIVCONTEXT lpImcP;
hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
if (!hUIPrivate) { // can not darw candidate window
return;
}
hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
if (!hIMC) {
return;
}
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
if (!lpUIPrivate) { // can not draw candidate window
return;
}
if (!(lpUIPrivate->fdwSetContext & ISC_SHOWUICANDIDATEWINDOW)) {
goto CandPageDownUnlockUIPriv;
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) {
goto CandPageDownUnlockUIPriv;
}
lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
if (!lpImcP) {
goto CandPageDownUnlockIMC;
}
if (fForward) {
CandPageSizeDown(lpIMC);
} else {
CandPageSizeUp(hIMC, lpIMC, lpImcP->dwPrevPageStart);
}
ImmUnlockIMCC(lpIMC->hPrivate);
CandPageDownUnlockIMC:
ImmUnlockIMC(hIMC);
CandPageDownUnlockUIPriv:
GlobalUnlock(hUIPrivate);
return;
}
/**********************************************************************/
/* DestroyCandWindow */
/**********************************************************************/
void PASCAL DestroyCandWindow(
HWND hCandWnd)
{
HGLOBAL hUIPrivate;
LPUIPRIV lpUIPrivate;
if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
// undo the drag border
DrawDragBorder(hCandWnd,
GetWindowLong(hCandWnd, UI_MOVE_XY),
GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
}
hUIPrivate = (HGLOBAL)GetWindowLongPtr(GetWindow(hCandWnd, GW_OWNER),
IMMGWLP_PRIVATE);
if (!hUIPrivate) { // can not darw candidate window
return;
}
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
if (!lpUIPrivate) { // can not draw candidate window
return;
}
lpUIPrivate->nShowCandCmd = SW_HIDE;
lpUIPrivate->hCandWnd = (HWND)NULL;
GlobalUnlock(hUIPrivate);
return;
}
/**********************************************************************/
/* MouseSelectCandStr() */
/**********************************************************************/
void PASCAL MouseSelectCandStr(
#if defined(UNIIME)
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#endif
HWND hCandWnd,
LPPOINT lpCursor)
{
HIMC hIMC;
LPINPUTCONTEXT lpIMC;
LPCANDIDATEINFO lpCandInfo;
LPCANDIDATELIST lpCandList;
DWORD dwValue;
hIMC = (HIMC)GetWindowLongPtr(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
if (!hIMC) {
return;
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) {
return;
}
if (!lpIMC->hCandInfo) {
ImmUnlockIMC(hIMC);
return;
}
lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
if (!lpCandInfo) {
ImmUnlockIMC(hIMC);
return;
}
dwValue = (lpCursor->y - lpImeL->rcCandText.top) / sImeG.yChiCharHi;
lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
lpCandInfo->dwOffset[0]);
dwValue = dwValue + lpCandList->dwPageStart;
if (dwValue >= lpCandList->dwCount) {
// invalid choice
MessageBeep((UINT)-1);
} else {
#if defined(UNIIME)
UniNotifyIME(lpInstL, lpImeL, hIMC, NI_SELECTCANDIDATESTR,
0, dwValue);
#else
NotifyIME(hIMC, NI_SELECTCANDIDATESTR, 0, dwValue);
#endif
}
ImmUnlockIMCC(lpIMC->hCandInfo);
ImmUnlockIMC(hIMC);
return;
}
/**********************************************************************/
/* CandSetCursor() */
/**********************************************************************/
void PASCAL CandSetCursor(
#if defined(UNIIME)
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#endif
HWND hCandWnd,
LPARAM lParam)
{
POINT ptCursor, ptSavCursor;
RECT rcWnd;
if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) !=
WINDOW_NOT_DRAG) {
SetCursor(LoadCursor(NULL, IDC_SIZEALL));
return;
}
GetCursorPos(&ptCursor);
ptSavCursor = ptCursor;
ScreenToClient(hCandWnd, &ptCursor);
if (PtInRect(&lpImeL->rcCandText, ptCursor)) {
SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(IDCR_HAND_CURSOR)));
if (HIWORD(lParam) == WM_LBUTTONDOWN) {
MouseSelectCandStr(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
hCandWnd, &ptCursor);
}
return;
} else if (PtInRect(&lpImeL->rcCandPageUp, ptCursor)) {
if (HIWORD(lParam) != WM_LBUTTONDOWN) {
SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(IDCR_HAND_CURSOR)));
return;
}
if (MouseSelectCandPage(
#if defined(UNIIME)
lpImeL,
#endif
hCandWnd, CHOOSE_PREVPAGE)) {
return;
}
SetCursor(LoadCursor(NULL, IDC_SIZEALL));
} else if (PtInRect(&lpImeL->rcCandPageDn, ptCursor)) {
if (HIWORD(lParam) != WM_LBUTTONDOWN) {
SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(IDCR_HAND_CURSOR)));
return;
}
if (MouseSelectCandPage(
#if defined(UNIIME)
lpImeL,
#endif
hCandWnd, CHOOSE_NEXTPAGE)) {
return;
}
SetCursor(LoadCursor(NULL, IDC_SIZEALL));
} else {
SetCursor(LoadCursor(NULL, IDC_SIZEALL));
if (HIWORD(lParam) == WM_LBUTTONDOWN) {
// start drag
SystemParametersInfo(SPI_GETWORKAREA, 0, &sImeG.rcWorkArea, 0);
} else {
return;
}
}
SetCapture(hCandWnd);
SetWindowLong(hCandWnd, UI_MOVE_XY,
MAKELONG(ptSavCursor.x, ptSavCursor.y));
GetWindowRect(hCandWnd, &rcWnd);
SetWindowLong(hCandWnd, UI_MOVE_OFFSET,
MAKELONG(ptSavCursor.x - rcWnd.left, ptSavCursor.y - rcWnd.top));
DrawDragBorder(hCandWnd, MAKELONG(ptSavCursor.x, ptSavCursor.y),
GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
return;
}
/**********************************************************************/
/* CandButtonUp() */
/**********************************************************************/
BOOL PASCAL CandButtonUp(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
HWND hCandWnd)
{
LONG lTmpCursor, lTmpOffset;
POINT pt;
HWND hUIWnd;
HIMC hIMC;
LPINPUTCONTEXT lpIMC;
if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) == WINDOW_NOT_DRAG) {
return (FALSE);
}
lTmpCursor = GetWindowLong(hCandWnd, UI_MOVE_XY);
// calculate the org by the offset
lTmpOffset = GetWindowLong(hCandWnd, UI_MOVE_OFFSET);
pt.x = (*(LPPOINTS)&lTmpCursor).x - (*(LPPOINTS)&lTmpOffset).x;
pt.y = (*(LPPOINTS)&lTmpCursor).y - (*(LPPOINTS)&lTmpOffset).y;
DrawDragBorder(hCandWnd, lTmpCursor, lTmpOffset);
SetWindowLong(hCandWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG);
ReleaseCapture();
hUIWnd = GetWindow(hCandWnd, GW_OWNER);
hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
if (!hIMC) {
return (FALSE);
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) {
return (FALSE);
}
AdjustCandBoundry(
#if defined(UNIIME)
lpImeL,
#endif
&pt);
ScreenToClient(lpIMC->hWnd, &pt);
lpIMC->cfCandForm[0].dwStyle = CFS_CANDIDATEPOS;
lpIMC->cfCandForm[0].ptCurrentPos = pt;
ImmUnlockIMC(hIMC);
PostMessage(hCandWnd, WM_IME_NOTIFY, IMN_SETCANDIDATEPOS, 0x0001);
return (TRUE);
}
/**********************************************************************/
/* PaintCandPage() */
/**********************************************************************/
void PASCAL PaintCandPage(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
HDC hDC,
UINT uCandMode,
LPCANDIDATELIST lpCandList)
{
HBITMAP hCandPromptBmp;
HBITMAP hPageUpBmp, hPageDnBmp, hOldBmp;
HDC hMemDC;
hMemDC = CreateCompatibleDC(hDC);
if ( hMemDC == NULL )
return;
if (uCandMode == CAND_PROMPT_PHRASE) {
hCandPromptBmp = LoadBitmap(hInst,
MAKEINTRESOURCE(IDBM_CAND_PROMPT_PHRASE));
#if defined(WINAR30)
} else if (uCandMode == CAND_PROMPT_QUICK_VIEW) {
hCandPromptBmp = LoadBitmap(hInst,
MAKEINTRESOURCE(IDBM_CAND_PROMPT_QUICK_VIEW));
#endif
} else {
hCandPromptBmp = LoadBitmap(hInst,
MAKEINTRESOURCE(IDBM_CAND_PROMPT_NORMAL));
}
if ( hCandPromptBmp == NULL )
{
DeleteDC(hMemDC);
return;
}
hOldBmp = SelectObject(hMemDC, hCandPromptBmp);
BitBlt(hDC, lpImeL->rcCandPrompt.left, lpImeL->rcCandPrompt.top,
lpImeL->rcCandPrompt.right - lpImeL->rcCandPrompt.left,
lpImeL->rcCandPrompt.bottom - lpImeL->rcCandPrompt.top,
hMemDC, 0, 0, SRCCOPY);
if (lpCandList->dwCount <= lpCandList->dwPageSize) {
goto PaintCandPageOvr;
}
if (lpCandList->dwPageStart > 0) {
hPageUpBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_PAGEUP_VERT));
} else {
hPageUpBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_NO_PAGEUP_VERT));
}
if ( hPageUpBmp == NULL )
{
goto PaintCandPageOvr;
}
if ((lpCandList->dwPageStart + lpCandList->dwPageSize) <
lpCandList->dwCount) {
hPageDnBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_PAGEDN_VERT));
} else {
hPageDnBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_NO_PAGEDN_VERT));
}
if ( hPageDnBmp == NULL )
{
DeleteObject(hPageUpBmp);
goto PaintCandPageOvr;
}
SelectObject(hMemDC, hPageUpBmp);
BitBlt(hDC, lpImeL->rcCandPageUp.left, lpImeL->rcCandPageUp.top,
lpImeL->rcCandPageUp.right - lpImeL->rcCandPageUp.left,
lpImeL->rcCandPageUp.bottom - lpImeL->rcCandPageUp.top,
hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hPageDnBmp);
BitBlt(hDC, lpImeL->rcCandPageDn.left, lpImeL->rcCandPageDn.top,
lpImeL->rcCandPageDn.right - lpImeL->rcCandPageDn.left,
lpImeL->rcCandPageDn.bottom - lpImeL->rcCandPageDn.top,
hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOldBmp);
DeleteObject(hPageUpBmp);
DeleteObject(hPageDnBmp);
PaintCandPageOvr:
SelectObject(hMemDC, hOldBmp);
DeleteDC(hMemDC);
DeleteObject(hCandPromptBmp);
return;
}
/**********************************************************************/
/* PaintCompWindow() */
/**********************************************************************/
void PASCAL PaintCandWindow(
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
HWND hCandWnd,
HDC hDC)
{
HIMC hIMC;
LPINPUTCONTEXT lpIMC;
LPCANDIDATEINFO lpCandInfo;
LPCANDIDATELIST lpCandList;
LPPRIVCONTEXT lpImcP;
HGDIOBJ hOldFont;
DWORD dwStart, dwEnd;
UINT uCandMode;
TCHAR szStrBuf[16];
int i;
RECT rcSunken;
LOGFONT lfFont;
hIMC = (HIMC)GetWindowLongPtr(GetWindow(hCandWnd, GW_OWNER), IMMGWLP_IMC);
if (!hIMC) {
return;
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) {
return;
}
rcSunken = lpImeL->rcCandText;
rcSunken.left -= lpImeL->cxCandMargin;
rcSunken.top -= lpImeL->cyCandMargin;
rcSunken.right += lpImeL->cxCandMargin;
rcSunken.bottom += lpImeL->cyCandMargin;
DrawEdge(hDC, &rcSunken, BDR_SUNKENOUTER, BF_RECT);
if (!lpIMC->hCandInfo) {
goto UpCandW2UnlockIMC;
}
if (!lpIMC->hPrivate) {
goto UpCandW2UnlockIMC;
}
lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo);
if (!lpCandInfo) {
goto UpCandW2UnlockIMC;
}
lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
if (!lpImcP) {
goto UpCandW2UnlockCandInfo;
}
hOldFont = GetCurrentObject(hDC, OBJ_FONT);
GetObject(hOldFont, sizeof(lfFont), &lfFont);
if (sImeG.fDiffSysCharSet) {
lfFont.lfCharSet = NATIVE_CHARSET;
lfFont.lfFaceName[0] = TEXT('\0');
}
lfFont.lfWeight = FW_DONTCARE;
SelectObject(hDC, CreateFontIndirect(&lfFont));
lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo +
lpCandInfo->dwOffset[0]);
dwStart = lpCandList->dwPageStart;
dwEnd = dwStart + lpCandList->dwPageSize;
if (dwEnd > lpCandList->dwCount) {
dwEnd = lpCandList->dwCount;
}
if (lpImcP->iImeState == CST_INIT) {
// phrase prediction
SetTextColor(hDC, RGB(0x00, 0x80, 0x00));
uCandMode = CAND_PROMPT_PHRASE;
#if defined(WINAR30)
} else if (lpImcP->iImeState != CST_CHOOSE) {
// quick key
SetTextColor(hDC, RGB(0x80, 0x00, 0x80));
uCandMode = CAND_PROMPT_QUICK_VIEW;
#endif
} else {
uCandMode = CAND_PROMPT_NORMAL;
}
PaintCandPage(
#if defined(UNIIME)
lpImeL,
#endif
hDC, uCandMode, lpCandList);
SetBkColor(hDC, RGB(0xC0, 0xC0, 0xC0));
ExtTextOut(hDC, lpImeL->rcCandText.left, lpImeL->rcCandText.top,
ETO_OPAQUE, &lpImeL->rcCandText, NULL, 0, NULL);
szStrBuf[0] = TEXT('1');
szStrBuf[1] = TEXT(':');
for (i = 0; dwStart < dwEnd; dwStart++, i++) {
LPTSTR lpStr;
int nCharsInOneStr;
int nHalfCharsInOneStr; // how many half width chars
// one full width char ==
// 2 half width chars
int nLimit; // the room left to the candidate window
#ifdef UNICODE
LPTSTR lpTmpStr;
int iDx[3 * CANDPERPAGE + 1];
#endif
lpStr = (LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart]);
// the candidate window width allow 7 + 1 full shape DBCS chars
// only 8 chars can accomendate the width of three bitmaps.
nLimit = 16;
szStrBuf[0] = szDigit[i + lpImeL->wCandStart];
#ifdef UNICODE
nCharsInOneStr = 0;
iDx[nCharsInOneStr++] = sImeG.xChiCharWi / 2;
iDx[nCharsInOneStr++] = sImeG.xChiCharWi - iDx[0];
nHalfCharsInOneStr = 2;
for (lpTmpStr = lpStr; *lpTmpStr; lpTmpStr++, nCharsInOneStr++) {
if (nHalfCharsInOneStr > nLimit) {
break;
} else if (*lpTmpStr < 0x0200) {
nHalfCharsInOneStr += 1;
iDx[nCharsInOneStr] = sImeG.xChiCharWi / 2;
} else {
nHalfCharsInOneStr += 2;
iDx[nCharsInOneStr] = sImeG.xChiCharWi;
}
}
#else
nHalfCharsInOneStr = nCharsInOneStr = lstrlen(lpStr) + 2;
#endif
if (nHalfCharsInOneStr <= nLimit) {
CopyMemory(&szStrBuf[2], lpStr,
(nCharsInOneStr - 2) * sizeof(TCHAR));
} else {
#ifdef UNICODE
if (lpStr[nCharsInOneStr - 2 - 2] < 0x0200) {
// we need more room to put ..
nCharsInOneStr -= 3;
} else {
nCharsInOneStr -= 2;
}
#else
nHalfCharsInOneStr = nCharsInOneStr = nLimit - 2;
#endif
CopyMemory(&szStrBuf[2], lpStr,
(nCharsInOneStr - 2) * sizeof(TCHAR));
#ifdef UNICODE
// unicode of ..
iDx[nCharsInOneStr] = sImeG.xChiCharWi;
szStrBuf[nCharsInOneStr++] = 0x2025;
#else
szStrBuf[nCharsInOneStr++] = '.';
szStrBuf[nCharsInOneStr++] = '.';
#endif
}
#if defined(WINAR30)
if (nCharsInOneStr <= 2) {
#ifdef UNICODE
// add unicode 0x25A1
*(LPWSTR)&szStrBuf[2] = 0x25A1;
iDx[2] = sImeG.xChiCharWi;
#else
// add big-5 0xA1BC
*(LPWSTR)&szStrBuf[2] = 0xBCA1;
#endif
nCharsInOneStr = 2 + sizeof(WCHAR) / sizeof(TCHAR);
}
#endif
ExtTextOut(hDC, lpImeL->rcCandText.left,
lpImeL->rcCandText.top + i * sImeG.yChiCharHi,
(UINT)0, NULL,
szStrBuf,
nCharsInOneStr, iDx);
}
DeleteObject(SelectObject(hDC, hOldFont));
ImmUnlockIMCC(lpIMC->hPrivate);
UpCandW2UnlockCandInfo:
ImmUnlockIMCC(lpIMC->hCandInfo);
UpCandW2UnlockIMC:
ImmUnlockIMC(hIMC);
return;
}
/**********************************************************************/
/* CandWndProc() */
/**********************************************************************/
#if defined(UNIIME)
LRESULT WINAPI UniCandWndProc(
LPINSTDATAL lpInstL,
LPIMEL lpImeL,
#else
LRESULT CALLBACK CandWndProc(
#endif
HWND hCandWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg) {
case WM_DESTROY:
DestroyCandWindow(hCandWnd);
break;
case WM_SETCURSOR:
CandSetCursor(
#if defined(UNIIME)
lpInstL, lpImeL,
#endif
hCandWnd, lParam);
break;
case WM_MOUSEMOVE:
if (GetWindowLong(hCandWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
POINT ptCursor;
DrawDragBorder(hCandWnd,
GetWindowLong(hCandWnd, UI_MOVE_XY),
GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
GetCursorPos(&ptCursor);
SetWindowLong(hCandWnd, UI_MOVE_XY,
MAKELONG(ptCursor.x, ptCursor.y));
DrawDragBorder(hCandWnd, MAKELONG(ptCursor.x, ptCursor.y),
GetWindowLong(hCandWnd, UI_MOVE_OFFSET));
} else {
return DefWindowProc(hCandWnd, uMsg, wParam, lParam);
}
break;
case WM_LBUTTONUP:
if (!CandButtonUp(
#if defined(UNIIME)
lpImeL,
#endif
hCandWnd)) {
return DefWindowProc(hCandWnd, uMsg, wParam, lParam);
}
break;
case WM_IME_NOTIFY:
if (wParam != IMN_SETCANDIDATEPOS) {
} else if (lpImeL->fdwModeConfig & MODE_CONFIG_OFF_CARET_UI) {
} else if (lParam & 0x0001) {
return SetCandPosition(
#if defined(UNIIME)
lpImeL,
#endif
hCandWnd);
} else {
}
break;
case WM_PAINT:
{
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hCandWnd, &ps);
PaintCandWindow(
#if defined(UNIIME)
lpImeL,
#endif
hCandWnd, hDC);
EndPaint(hCandWnd, &ps);
}
break;
case WM_MOUSEACTIVATE:
return (MA_NOACTIVATE);
default:
return DefWindowProc(hCandWnd, uMsg, wParam, lParam);
}
return (0L);
}
#endif