/*++ Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved Module Name: CANDUI.c ++*/ #include #include #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