/*++ Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved Module Name: OFFCARET.C ++*/ #include #include #include "imeattr.h" #include "imedefs.h" #include "imerc.h" #if defined(UNIIME) #include "uniime.h" #endif /**********************************************************************/ /* DestroyOffCaretWindow() */ /**********************************************************************/ void PASCAL DestroyOffCaretWindow( // destroy composition window HWND hOffCaretWnd) { HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; if (GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) { // undo the drag border DrawDragBorder(hOffCaretWnd, GetWindowLong(hOffCaretWnd, UI_MOVE_XY), GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET)); } hUIPrivate = (HGLOBAL)GetWindowLongPtr(GetWindow(hOffCaretWnd, GW_OWNER), IMMGWLP_PRIVATE); if (!hUIPrivate) { return; } lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); if (!lpUIPrivate) { return; } #if !defined(ROMANIME) lpUIPrivate->nShowCompCmd = lpUIPrivate->nShowCandCmd = SW_HIDE; #endif lpUIPrivate->nShowStatusCmd = SW_HIDE; #if !defined(ROMANIME) lpUIPrivate->hCompWnd = lpUIPrivate->hCandWnd = NULL; #endif lpUIPrivate->hStatusWnd = NULL; GlobalUnlock(hUIPrivate); return; } #if !defined(ROMANIME) /**********************************************************************/ /* MouseSelectOffCaretCandStr() */ /**********************************************************************/ BOOL PASCAL MouseSelectOffCaretCandStr( #if defined(UNIIME) LPINSTDATAL lpInstL, LPIMEL lpImeL, #endif HWND hOffCaretWnd, LPPOINT lpCursor) { BOOL fRet; HWND hUIWnd; HIMC hIMC; LPINPUTCONTEXT lpIMC; HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; LPCANDIDATEINFO lpCandInfo; LPCANDIDATELIST lpCandList; DWORD dwValue, dwLimit; UINT nMouseChars, nChars; fRet = FALSE; hUIWnd = GetWindow(hOffCaretWnd, GW_OWNER); hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC); if (!hIMC) { return (fRet); } hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE); if (!hUIPrivate) { return (fRet); } lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC); if (!lpIMC) { return (fRet); } if (!lpIMC->hCandInfo) { goto MouseSelOffCaretCandStrUnlockIMC; } lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); if (!lpUIPrivate) { goto MouseSelOffCaretCandStrUnlockIMC; } dwValue = lpUIPrivate->nShowCandCmd; GlobalUnlock(hUIPrivate); if (dwValue == SW_HIDE) { // may application draw the UI or currently is not in candidate list goto MouseSelOffCaretCandStrUnlockIMC; } // we can select candidate fRet = TRUE; lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo); if (!lpCandInfo) { goto MouseSelOffCaretCandStrUnlockIMC; } nMouseChars = (lpCursor->x - lpImeL->rcCandText.left) * 2 / sImeG.xChiCharWi; lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[0]); dwValue = lpCandList->dwPageStart; // process one page dwLimit = dwValue + lpCandList->dwPageSize; if (dwLimit > lpCandList->dwCount) { dwLimit = lpCandList->dwCount; } for (nChars = 0; dwValue < dwLimit; dwValue++) { UINT uStrLen; #ifdef UNICODE LPTSTR lpTmpStr; #endif #ifdef UNICODE // this is not a real string length just an approximate char width uStrLen = 0; lpTmpStr = (LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[dwValue]); for (; *lpTmpStr; lpTmpStr++) { if (*lpTmpStr < 0x0200) { uStrLen += 1; } else { uStrLen += 2; } } #else uStrLen = lstrlen((LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[dwValue])); #endif #if defined(WINAR30) if (!uStrLen) { uStrLen = sizeof(WCHAR); } #endif // + 1 for the '1' '2' '3' .... nChars += uStrLen + 1; if (nMouseChars < nChars) { #if defined(UNIIME) UniNotifyIME(lpInstL, lpImeL, hIMC, NI_SELECTCANDIDATESTR, 0, dwValue); #else NotifyIME(hIMC, NI_SELECTCANDIDATESTR, 0, dwValue); #endif break; } } ImmUnlockIMCC(lpIMC->hCandInfo); if (nMouseChars >= nChars) { // invalid choice MessageBeep((UINT)-1); } MouseSelOffCaretCandStrUnlockIMC: ImmUnlockIMC(hIMC); return (fRet); } /**********************************************************************/ /* MouseSelectCandPage() */ /**********************************************************************/ BOOL PASCAL MouseSelectCandPage( #if defined(UNIIME) LPIMEL lpImeL, #endif HWND hCandWnd, WORD wCharCode) { BOOL fRet; HWND hUIWnd; HIMC hIMC; LPINPUTCONTEXT lpIMC; HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; LPCANDIDATEINFO lpCandInfo; LPPRIVCONTEXT lpImcP; fRet = FALSE; hUIWnd = GetWindow(hCandWnd, GW_OWNER); hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC); if (!hIMC) { return (fRet); } hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE); if (!hUIPrivate) { return (fRet); } lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC); if (!lpIMC) { return (fRet); } if (!lpIMC->hCandInfo) { goto MouseSelCandPageUnlockIMC; } if (!lpIMC->hPrivate) { goto MouseSelCandPageUnlockIMC; } lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); if (!lpUIPrivate) { goto MouseSelCandPageUnlockIMC; } if (lpUIPrivate->nShowCandCmd == SW_HIDE) { // may application draw the UI or currently is not in candidate list goto MouseSelCandPageUnlockIMC; } // we can select candidate fRet = TRUE; lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo); if (!lpCandInfo) { goto MouseSelCandPageUnlockUIPriv; } lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate); if (!lpImcP) { goto MouseSelCandPageUnlockCandInfo; } ChooseCand( #if defined(UNIIME) NULL, lpImeL, #endif wCharCode, hIMC, lpIMC, lpCandInfo, lpImcP); GenerateMessage(hIMC, lpIMC, lpImcP); ImmUnlockIMCC(lpIMC->hPrivate); MouseSelCandPageUnlockCandInfo: ImmUnlockIMCC(lpIMC->hCandInfo); MouseSelCandPageUnlockUIPriv: GlobalUnlock(hUIPrivate); MouseSelCandPageUnlockIMC: ImmUnlockIMC(hIMC); return (fRet); } #endif /**********************************************************************/ /* OffCaretSetCursor() */ /**********************************************************************/ void PASCAL OffCaretSetCursor( #if defined(UNIIME) LPINSTDATAL lpInstL, LPIMEL lpImeL, #endif HWND hOffCaretWnd, LPARAM lParam) { POINT ptCursor, ptSavCursor; RECT rcWnd; if (GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) { SetCursor(LoadCursor(NULL, IDC_SIZEALL)); return; } GetCursorPos(&ptCursor); ptSavCursor = ptCursor; ScreenToClient(hOffCaretWnd, &ptCursor); if (PtInRect(&lpImeL->rcStatusText, ptCursor)) { SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(IDCR_HAND_CURSOR))); if (HIWORD(lParam) == WM_LBUTTONDOWN) { HWND hStatusWnd; SystemParametersInfo(SPI_GETWORKAREA, 0, &sImeG.rcWorkArea, 0); hStatusWnd = GetStatusWnd(GetWindow(hOffCaretWnd, GW_OWNER)); if (hStatusWnd) { SetStatus( #if defined(UNIIME) lpImeL, #endif hStatusWnd, &ptCursor); return; } else { SetCursor(LoadCursor(NULL, IDC_SIZEALL)); } } else if (HIWORD(lParam) == WM_RBUTTONUP) { static BOOL fImeConfigure = FALSE; HWND hUIWnd, hStatusWnd; // prevent recursive if (fImeConfigure) { // configuration already bring up return; } hUIWnd = GetWindow(hOffCaretWnd, GW_OWNER); hStatusWnd = GetStatusWnd(hUIWnd); if (!hStatusWnd) { return; } fImeConfigure = TRUE; ContextMenu( #if defined(UNIIME) lpInstL, lpImeL, #endif hStatusWnd, ptSavCursor.x, ptSavCursor.y); fImeConfigure = FALSE; return; } else { return; } #if !defined(ROMANIME) } else if (PtInRect(&lpImeL->rcCandText, ptCursor)) { if (HIWORD(lParam) != WM_LBUTTONDOWN) { SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(IDCR_HAND_CURSOR))); return; } if (MouseSelectOffCaretCandStr( #if defined(UNIIME) lpInstL, lpImeL, #endif hOffCaretWnd, &ptCursor)) { return; } SetCursor(LoadCursor(NULL, IDC_SIZEALL)); #if defined(WINAR30) } else if (PtInRect(&lpImeL->rcCompText, ptCursor)) { SetCursor(LoadCursor(NULL, IDC_SIZEALL)); if (HIWORD(lParam) != WM_LBUTTONDOWN) { return; } #endif } 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 hOffCaretWnd, CHOOSE_PREVPAGE)) { return; } SetCursor(LoadCursor(NULL, IDC_SIZEALL)); } else if (PtInRect(&lpImeL->rcCandHome, ptCursor)) { if (HIWORD(lParam) != WM_LBUTTONDOWN) { SetCursor(LoadCursor(hInst, MAKEINTRESOURCE(IDCR_HAND_CURSOR))); return; } if (MouseSelectCandPage( #if defined(UNIIME) lpImeL, #endif hOffCaretWnd, CHOOSE_HOME)) { 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 hOffCaretWnd, CHOOSE_NEXTPAGE)) { return; } SetCursor(LoadCursor(NULL, IDC_SIZEALL)); #endif } else { SetCursor(LoadCursor(NULL, IDC_SIZEALL)); if (HIWORD(lParam) != WM_LBUTTONDOWN) { return; } } SetCapture(hOffCaretWnd); SetWindowLong(hOffCaretWnd, UI_MOVE_XY, MAKELONG(ptSavCursor.x, ptSavCursor.y)); GetWindowRect(hOffCaretWnd, &rcWnd); SetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET, MAKELONG(ptSavCursor.x - rcWnd.left, ptSavCursor.y - rcWnd.top)); DrawDragBorder(hOffCaretWnd, MAKELONG(ptSavCursor.x, ptSavCursor.y), GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET)); return; } /**********************************************************************/ /* PaintOffCaretStatus() */ /**********************************************************************/ void PASCAL PaintOffCaretStatus( #if defined(UNIIME) LPINSTDATAL lpInstL, LPIMEL lpImeL, #endif HWND hOffCaretWnd, HDC hDC) { HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; hUIPrivate = (HGLOBAL)GetWindowLongPtr(GetWindow(hOffCaretWnd, GW_OWNER), IMMGWLP_PRIVATE); if (!hUIPrivate) { return; } lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); if (!lpUIPrivate) { return; } if (lpUIPrivate->fdwSetContext & ISC_OPEN_STATUS_WINDOW) { PaintStatusWindow( #if defined(UNIIME) lpInstL, lpImeL, #endif hOffCaretWnd, hDC); } GlobalUnlock(hUIPrivate); return; } #if !defined(ROMANIME) /**********************************************************************/ /* PaintOffCaretCandPage() */ /**********************************************************************/ void PASCAL PaintOffCaretCandPage( #if defined(UNIIME) LPIMEL lpImeL, #endif HDC hDC, UINT uCandMode, LPCANDIDATELIST lpCandList) { HBITMAP hCandPromptBmp; HBITMAP hPageUpBmp, hHomeBmp, 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 PaintOffCaretCandPageOvr; } if (lpCandList->dwPageStart > 0) { hPageUpBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_PAGEUP_HORIZ)); } else { hPageUpBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_NO_PAGEUP_HORIZ)); } if ( hPageUpBmp == NULL ) { goto PaintOffCaretCandPageOvr; } if (lpCandList->dwPageStart > 0) { hHomeBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_HOME_HORIZ)); } else { hHomeBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_NO_HOME_HORIZ)); } if ( hHomeBmp == NULL ) { DeleteObject(hPageUpBmp); goto PaintOffCaretCandPageOvr; } if ((lpCandList->dwPageStart + lpCandList->dwPageSize) < lpCandList->dwCount) { hPageDnBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_PAGEDN_HORIZ)); } else { hPageDnBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDBM_NO_PAGEDN_HORIZ)); } if ( hPageDnBmp == NULL ) { DeleteObject(hPageUpBmp); DeleteObject(hHomeBmp); goto PaintOffCaretCandPageOvr; } 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, hHomeBmp); BitBlt(hDC, lpImeL->rcCandHome.left, lpImeL->rcCandHome.top, lpImeL->rcCandHome.right - lpImeL->rcCandHome.left, lpImeL->rcCandHome.bottom - lpImeL->rcCandHome.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(hHomeBmp); DeleteObject(hPageDnBmp); PaintOffCaretCandPageOvr: SelectObject(hMemDC, hOldBmp); DeleteDC(hMemDC); DeleteObject(hCandPromptBmp); return; } /**********************************************************************/ /* PaintOffCaretComposition() */ /**********************************************************************/ void PASCAL PaintOffCaretComposition( #if defined(UNIIME) LPIMEL lpImeL, #endif HWND hOffCaretWnd, HDC hDC) { HWND hUIWnd; HIMC hIMC; LPINPUTCONTEXT lpIMC; HGLOBAL hUIPrivate; LPUIPRIV lpUIPrivate; LPPRIVCONTEXT lpImcP; HGDIOBJ hOldFont; LPTSTR lpStr; RECT rcSunken; LOGFONT lfFont; HFONT hNewFont; hUIWnd = GetWindow(hOffCaretWnd, GW_OWNER); hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC); if (!hIMC) { return; } hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE); if (!hUIPrivate) { return; } lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC); if (!lpIMC) { return; } lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate); if (!lpUIPrivate) { goto PaintOffCaretCompUnlockIMC; } rcSunken = lpImeL->rcCompText; rcSunken.left -= lpImeL->cxCompBorder; rcSunken.top -= lpImeL->cyCompBorder; rcSunken.right += lpImeL->cxCompBorder; rcSunken.bottom += lpImeL->cyCompBorder; DrawEdge(hDC, &rcSunken, BDR_SUNKENOUTER, BF_RECT); 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; hNewFont = CreateFontIndirect(&lfFont); if ( hNewFont != NULL ) { SelectObject(hDC, (HGDIOBJ)hNewFont); } else { // return error GlobalUnlock(hUIPrivate); ImmUnlockIMC(hIMC); return; } #if defined(WINAR30) 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); #endif // light gray background SetBkColor(hDC, RGB(0xC0, 0xC0, 0xC0)); if (lpUIPrivate->nShowCandCmd != SW_HIDE) { LPCANDIDATEINFO lpCandInfo; LPCANDIDATELIST lpCandList; BOOL fCandidate; DWORD dwStart, dwEnd; UINT uCandMode; int i, nChars, nHalfChars; TCHAR szStrBuf[CANDPERPAGE * 3 + 1]; #ifdef UNICODE int iDx[CANDPERPAGE * 3 + 1]; #endif fCandidate = FALSE; if (!lpIMC->hCandInfo) { goto PaintOffCaretCompChkCandInfo; } lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpIMC->hCandInfo); if (!lpCandInfo) { goto PaintOffCaretCompChkCandInfo; } if (!lpCandInfo->dwCount) { goto PaintOffCaretCompUnlockCandInfo; } lpCandList = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[0]); if (!lpCandList->dwCount) { goto PaintOffCaretCompUnlockCandInfo; } dwStart = lpCandList->dwPageStart; dwEnd = dwStart + lpCandList->dwPageSize; if (dwEnd > lpCandList->dwCount) { dwEnd = lpCandList->dwCount; } fCandidate = TRUE; lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate); if (!lpImcP) { uCandMode = CAND_PROMPT_NORMAL; } else 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; } if (lpImcP) { ImmUnlockIMCC(lpIMC->hPrivate); } PaintOffCaretCandPage( #if defined(UNIIME) lpImeL, #endif hDC, uCandMode, lpCandList); for (i = 0, nChars = 0, nHalfChars = 0; dwStart < dwEnd; dwStart++, i++) { 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; #endif lpStr = (LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[dwStart]); nLimit = CANDPERPAGE * 3 - nHalfChars; if (nLimit <= 1) { break; } szStrBuf[nChars] = szDigit[i + lpImeL->wCandStart]; #ifdef UNICODE // the digit for select candidate iDx[nChars] = sImeG.xChiCharWi / 2; nCharsInOneStr = nHalfCharsInOneStr = 1; #if defined(WINAR30) //1996/12/12 iDx[nChars + nCharsInOneStr] = sImeG.xChiCharWi; #endif for (lpTmpStr = lpStr; *lpTmpStr; lpTmpStr++, nCharsInOneStr++) { if (nHalfCharsInOneStr > nLimit) { break; } else if (*lpTmpStr < 0x0200) { nHalfCharsInOneStr += 1; iDx[nChars + nCharsInOneStr] = sImeG.xChiCharWi / 2; } else { nHalfCharsInOneStr += 2; iDx[nChars + nCharsInOneStr] = sImeG.xChiCharWi; } } #else nHalfCharsInOneStr = nCharsInOneStr = lstrlen(lpStr) + 1; #endif if (nHalfCharsInOneStr <= nLimit) { // the room is enough, nChars + 1 for "1", "2", "3", ... CopyMemory(&szStrBuf[nChars + 1], lpStr, (nCharsInOneStr - 1) * sizeof(TCHAR)); } else if (i) { break; } else { #ifdef UNICODE if (lpStr[nCharsInOneStr - 2 - 1] < 0x0200) { // we need more room to put ".." nCharsInOneStr -= 2; } else { nCharsInOneStr -= 1; } #else nHalfCharsInOneStr = nCharsInOneStr = nLimit - 2; #endif // nChars + 1 for "1", "2", "3", ... CopyMemory(&szStrBuf[nChars + 1], lpStr, (nCharsInOneStr - 1) * sizeof(TCHAR)); #ifdef UNICODE // unicode of .. iDx[nChars + nCharsInOneStr] = sImeG.xChiCharWi; szStrBuf[nChars + nCharsInOneStr++] = 0x2025; #else szStrBuf[nChars + nCharsInOneStr++] = '.'; szStrBuf[nChars + nCharsInOneStr++] = '.'; #endif } #if defined(WINAR30) if (nCharsInOneStr <= 1) { #ifdef UNICODE // add unicode 0x25A1 *(LPWSTR)&szStrBuf[nChars +1] = 0x25A1; #else // add big-5 0xA1BC *(LPWSTR)&szStrBuf[nChars +1] = 0xBCA1; #endif nCharsInOneStr =1+ sizeof(WCHAR) / sizeof(TCHAR); } #endif nChars += nCharsInOneStr; nHalfChars += nHalfCharsInOneStr; if (nHalfCharsInOneStr >= nLimit) { break; } } ExtTextOut(hDC, lpImeL->rcCandText.left, lpImeL->rcCandText.top, ETO_OPAQUE, &lpImeL->rcCandText, szStrBuf, nChars, iDx); PaintOffCaretCompUnlockCandInfo: ImmUnlockIMCC(lpIMC->hCandInfo); PaintOffCaretCompChkCandInfo: if (fCandidate) { #if !defined(WINAR30) goto PaintOffCaretCompUnlockUIPriv; #else } else { goto PaintOffCaretCandNone; #endif } #if defined(WINAR30) } else { PaintOffCaretCandNone: ExtTextOut(hDC, lpImeL->rcCandText.left, lpImeL->rcCandText.top, ETO_OPAQUE, &lpImeL->rcCandText, (LPTSTR)NULL, 0, NULL); #endif } // the composition window has daul function 1. composition window // 2. guideline so we need more check on ISC_xxx flags if (lpUIPrivate->nShowCompCmd == SW_HIDE) { goto PaintOffCaretCompNone; } else if (lpUIPrivate->fdwSetContext & ISC_SHOWUICOMPOSITIONWINDOW) { LPCOMPOSITIONSTRING lpCompStr; DWORD dwCompStrLen; if (!lpIMC->hCompStr) { goto PaintOffCaretCompGuideLine; } lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr); if (!lpCompStr) { goto PaintOffCaretCompGuideLine; } dwCompStrLen = lpCompStr->dwCompStrLen; if (!lpCompStr->dwCompStrLen) { goto PaintOffCaretCompUnlockCompStr; } // black text for compistion string SetTextColor(hDC, RGB(0x00, 0x00, 0x00)); ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top, ETO_OPAQUE, &lpImeL->rcCompText, (LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset), lpCompStr->dwCompStrLen, iDx); if (lpCompStr->dwCompStrLen <= lpCompStr->dwCursorPos) { goto PaintOffCaretCompUnlockCompStr; } // there is error part // red text for error SetTextColor(hDC, RGB(0xFF, 0x00, 0x00)); // dark gray background for error SetBkColor(hDC, RGB(0x80, 0x80, 0x80)); ExtTextOut(hDC, lpImeL->rcCompText.left + lpCompStr->dwCursorPos * sImeG.xChiCharWi / (sizeof(WCHAR) / sizeof(TCHAR)), lpImeL->rcCompText.top, ETO_OPAQUE, NULL, (LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset + lpCompStr->dwCursorPos), (lpCompStr->dwCompStrLen - lpCompStr->dwCursorPos), iDx); PaintOffCaretCompUnlockCompStr: ImmUnlockIMCC(lpIMC->hCompStr); if (!dwCompStrLen) { goto PaintOffCaretCompGuideLine; } } else if (lpUIPrivate->fdwSetContext & ISC_SHOWUIGUIDELINE) { LPGUIDELINE lpGuideLine; BOOL fGuideLine; LPCANDIDATELIST lpCandList; UINT uStrLen; PaintOffCaretCompGuideLine: if (!lpIMC->hGuideLine) { goto PaintOffCaretCompNone; } lpGuideLine = (LPGUIDELINE)ImmLockIMCC(lpIMC->hGuideLine); if (!lpGuideLine) { goto PaintOffCaretCompNone; } fGuideLine = FALSE; if (lpGuideLine->dwLevel != GL_LEVEL_INFORMATION) { goto PaintOffCaretCompUnlockGuideLine; } else if (lpGuideLine->dwIndex != GL_ID_REVERSECONVERSION) { goto PaintOffCaretCompUnlockGuideLine; } else { } lpCandList = (LPCANDIDATELIST)((LPBYTE)lpGuideLine + lpGuideLine->dwPrivateOffset); if (!lpCandList) { goto PaintOffCaretCompUnlockGuideLine; } else if (!lpCandList->dwCount) { goto PaintOffCaretCompUnlockGuideLine; } else { fGuideLine = TRUE; } // green text for information SetTextColor(hDC, RGB(0x00, 0x80, 0x00)); lpStr = (LPTSTR)((LPBYTE)lpCandList + lpCandList->dwOffset[0]); uStrLen = lstrlen(lpStr); ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top, ETO_OPAQUE, &lpImeL->rcCompText, lpStr, uStrLen, iDx); PaintOffCaretCompUnlockGuideLine: ImmUnlockIMCC(lpIMC->hGuideLine); if (!fGuideLine) { goto PaintOffCaretCompNone; } } else { PaintOffCaretCompNone: ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top, ETO_OPAQUE, &lpImeL->rcCompText, (LPTSTR)NULL, 0, NULL); } DeleteObject(SelectObject(hDC, hOldFont)); #if !defined(WINAR30) PaintOffCaretCompUnlockUIPriv: #endif GlobalUnlock(hUIPrivate); PaintOffCaretCompUnlockIMC: ImmUnlockIMC(hIMC); return; } #endif /**********************************************************************/ /* OffCaretWndProc() / UniOffCaretWndProc() */ /**********************************************************************/ #if defined(UNIIME) LRESULT WINAPI UniOffCaretWndProc( LPINSTDATAL lpInstL, LPIMEL lpImeL, #else LRESULT CALLBACK OffCaretWndProc( #endif HWND hOffCaretWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: DestroyOffCaretWindow(hOffCaretWnd); break; case WM_SETCURSOR: OffCaretSetCursor( #if defined(UNIIME) lpInstL, lpImeL, #endif hOffCaretWnd, lParam); break; case WM_MOUSEMOVE: if (GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) { POINT ptCursor; DrawDragBorder(hOffCaretWnd, GetWindowLong(hOffCaretWnd, UI_MOVE_XY), GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET)); GetCursorPos(&ptCursor); SetWindowLong(hOffCaretWnd, UI_MOVE_XY, MAKELONG(ptCursor.x, ptCursor.y)); DrawDragBorder(hOffCaretWnd, MAKELONG(ptCursor.x, ptCursor.y), GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET)); } else { return DefWindowProc(hOffCaretWnd, uMsg, wParam, lParam); } break; case WM_LBUTTONUP: if (GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) { LONG lTmpCursor, lTmpOffset; POINT ptCursor; HWND hUIWnd; lTmpCursor = GetWindowLong(hOffCaretWnd, UI_MOVE_XY); // calculate the org by the offset lTmpOffset = GetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET); DrawDragBorder(hOffCaretWnd, lTmpCursor, lTmpOffset); ptCursor.x = (*(LPPOINTS)&lTmpCursor).x - (*(LPPOINTS)&lTmpOffset).x; ptCursor.y = (*(LPPOINTS)&lTmpCursor).y - (*(LPPOINTS)&lTmpOffset).y; SetWindowLong(hOffCaretWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG); ReleaseCapture(); AdjustStatusBoundary( #if defined(UNIIME) lpImeL, #endif &ptCursor); hUIWnd = GetWindow(hOffCaretWnd, GW_OWNER); ImmSetStatusWindowPos((HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC), &ptCursor); } else { return DefWindowProc(hOffCaretWnd, uMsg, wParam, lParam); } break; case WM_IME_NOTIFY: if (wParam == IMN_SETSTATUSWINDOWPOS) { SetStatusWindowPos( #if defined(UNIIME) lpImeL, #endif hOffCaretWnd); } break; case WM_PAINT: { HDC hDC; PAINTSTRUCT ps; hDC = BeginPaint(hOffCaretWnd, &ps); PaintOffCaretStatus( #if defined(UNIIME) lpInstL, lpImeL, #endif hOffCaretWnd, hDC); #if !defined(ROMANIME) PaintOffCaretComposition( #if defined(UNIIME) lpImeL, #endif hOffCaretWnd, hDC); #endif EndPaint(hOffCaretWnd, &ps); } break; case WM_MOUSEACTIVATE: return (MA_NOACTIVATE); default: return DefWindowProc(hOffCaretWnd, uMsg, wParam, lParam); } return (0L); }