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

1193 lines
36 KiB
C

/*++
Copyright (c) 1995-1999 Microsoft Corporation, All Rights Reserved
Module Name:
COMPUI.C
++*/
#include <windows.h>
#include <immdev.h>
#include "imedefs.h"
#include <regstr.h>
/**********************************************************************/
/* GetCompWnd */
/* Return Value : */
/* window handle of composition */
/**********************************************************************/
HWND PASCAL GetCompWnd(
HWND hUIWnd) // UI window
{
HGLOBAL hUIPrivate;
LPUIPRIV lpUIPrivate;
HWND hCompWnd;
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;
}
hCompWnd = lpUIPrivate->hCompWnd;
GlobalUnlock(hUIPrivate);
return (hCompWnd);
}
/**********************************************************************/
/* FitInLazyOperation() */
/* Return Value : */
/* TRUE or FALSE */
/**********************************************************************/
BOOL PASCAL FitInLazyOperation( // 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 (composition window)
rcUIRect.left = lpptOrg->x;
rcUIRect.top = lpptOrg->y;
rcUIRect.right = rcUIRect.left + lpImeL->xCompWi;
rcUIRect.bottom = rcUIRect.top + lpImeL->yCompHi;
if (IntersectRect(&rcInterRect, &rcUIRect, lprcInputRect)) {
return (FALSE);
}
return (TRUE);
}
/**********************************************************************/
/* GetNearCaretPosition() */
/**********************************************************************/
void PASCAL GetNearCaretPosition( // decide a near caret position according
// to the caret position
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
LPPOINT lpptFont,
UINT uEsc,
UINT uRot,
LPPOINT lpptCaret,
LPPOINT lpptNearCaret,
BOOL fFlags)
{
LONG lFontSize;
LONG xWidthUI, yHeightUI, xBorder, yBorder;
RECT rcWorkArea;
if ((uEsc + uRot) & 0x0001) {
lFontSize = lpptFont->x;
} else {
lFontSize = lpptFont->y;
}
xWidthUI = lpImeL->xCompWi;
yHeightUI = lpImeL->yCompHi;
xBorder = lpImeL->cxCompBorder;
yBorder = lpImeL->cyCompBorder;
if (fFlags & NEAR_CARET_FIRST_TIME) {
lpptNearCaret->x = lpptCaret->x +
lFontSize * ncUIEsc[uEsc].iLogFontFacX +
sImeG.iPara * ncUIEsc[uEsc].iParaFacX +
sImeG.iPerp * ncUIEsc[uEsc].iPerpFacX;
if (ptInputEsc[uEsc].x >= 0) {
lpptNearCaret->x += xBorder * 2;
} else {
lpptNearCaret->x -= xWidthUI - xBorder * 2;
}
lpptNearCaret->y = lpptCaret->y +
lFontSize * ncUIEsc[uEsc].iLogFontFacY +
sImeG.iPara * ncUIEsc[uEsc].iParaFacY +
sImeG.iPerp * ncUIEsc[uEsc].iPerpFacY;
if (ptInputEsc[uEsc].y >= 0) {
lpptNearCaret->y += yBorder * 2;
} else {
lpptNearCaret->y -= yHeightUI - yBorder * 2;
}
} else {
lpptNearCaret->x = lpptCaret->x +
lFontSize * ncAltUIEsc[uEsc].iLogFontFacX +
sImeG.iPara * ncAltUIEsc[uEsc].iParaFacX +
sImeG.iPerp * ncAltUIEsc[uEsc].iPerpFacX;
if (ptAltInputEsc[uEsc].x >= 0) {
lpptNearCaret->x += xBorder * 2;
} else {
lpptNearCaret->x -= xWidthUI - xBorder * 2;
}
lpptNearCaret->y = lpptCaret->y +
lFontSize * ncAltUIEsc[uEsc].iLogFontFacY +
sImeG.iPara * ncAltUIEsc[uEsc].iParaFacY +
sImeG.iPerp * ncAltUIEsc[uEsc].iPerpFacY;
if (ptAltInputEsc[uEsc].y >= 0) {
lpptNearCaret->y += yBorder * 2;
} else {
lpptNearCaret->y -= yHeightUI - yBorder * 2;
}
}
#if 1 // MultiMonitor
rcWorkArea = ImeMonitorWorkAreaFromPoint(*lpptCaret);
#else
rcWorkArea = rcWorkArea;
#endif
if (lpptNearCaret->x < rcWorkArea.left) {
lpptNearCaret->x = rcWorkArea.left;
} else if (lpptNearCaret->x + xWidthUI > rcWorkArea.right) {
lpptNearCaret->x = rcWorkArea.right - xWidthUI;
}
if (lpptNearCaret->y < rcWorkArea.top) {
lpptNearCaret->y = rcWorkArea.top;
} else if (lpptNearCaret->y + yHeightUI > rcWorkArea.bottom) {
lpptNearCaret->y = rcWorkArea.bottom - yHeightUI;
}
return;
}
/**********************************************************************/
/* AdjustCompPosition() */
/* Return Value : */
/* the position of composition window is changed or not */
/**********************************************************************/
BOOL PASCAL AdjustCompPosition( // IME adjust position according to
// composition form
#if defined(UNIIME)
LPIMEL lpImeL,
#endif
LPINPUTCONTEXT lpIMC,
LPPOINT lpptOrg, // original composition window
// and final position
LPPOINT lpptNew) // new expect position
{
POINT ptNearCaret, ptOldNearCaret;
UINT uEsc, uRot;
RECT rcUIRect, rcInputRect, rcInterRect;
POINT ptFont;
// we need to adjust according to font attribute
if (lpIMC->lfFont.A.lfWidth > 0) {
ptFont.x = lpIMC->lfFont.A.lfWidth * 2;
} else if (lpIMC->lfFont.A.lfWidth < 0) {
ptFont.x = -lpIMC->lfFont.A.lfWidth * 2;
} else if (lpIMC->lfFont.A.lfHeight > 0) {
ptFont.x = lpIMC->lfFont.A.lfHeight;
} else if (lpIMC->lfFont.A.lfHeight < 0) {
ptFont.x = -lpIMC->lfFont.A.lfHeight;
} else {
ptFont.x = lpImeL->yCompHi;
}
if (lpIMC->lfFont.A.lfHeight > 0) {
ptFont.y = lpIMC->lfFont.A.lfHeight;
} else if (lpIMC->lfFont.A.lfHeight < 0) {
ptFont.y = -lpIMC->lfFont.A.lfHeight;
} else {
ptFont.y = ptFont.x;
}
// if the input char is too big, we don't need to consider so much
if (ptFont.x > lpImeL->yCompHi * 8) {
ptFont.x = lpImeL->yCompHi * 8;
}
if (ptFont.y > lpImeL->yCompHi * 8) {
ptFont.y = lpImeL->yCompHi * 8;
}
if (ptFont.x < sImeG.xChiCharWi) {
ptFont.x = sImeG.xChiCharWi;
}
if (ptFont.y < sImeG.yChiCharHi) {
ptFont.y = sImeG.yChiCharHi;
}
// -450 to 450 index 0
// 450 to 1350 index 1
// 1350 to 2250 index 2
// 2250 to 3150 index 3
uEsc = (UINT)((lpIMC->lfFont.A.lfEscapement + 450) / 900 % 4);
uRot = (UINT)((lpIMC->lfFont.A.lfOrientation + 450) / 900 % 4);
// decide the input rectangle
rcInputRect.left = lpptNew->x;
rcInputRect.top = lpptNew->y;
// build up an input rectangle from escapemment
rcInputRect.right = rcInputRect.left + ptFont.x * ptInputEsc[uEsc].x;
rcInputRect.bottom = rcInputRect.top + ptFont.y * ptInputEsc[uEsc].y;
// be a normal rectangle, not a negative rectangle
if (rcInputRect.left > rcInputRect.right) {
LONG tmp;
tmp = rcInputRect.left;
rcInputRect.left = rcInputRect.right;
rcInputRect.right = tmp;
}
if (rcInputRect.top > rcInputRect.bottom) {
LONG tmp;
tmp = rcInputRect.top;
rcInputRect.top = rcInputRect.bottom;
rcInputRect.bottom = tmp;
}
GetNearCaretPosition(
#if defined(UNIIME)
lpImeL,
#endif
&ptFont, uEsc, uRot, lpptNew, &ptNearCaret, NEAR_CARET_FIRST_TIME);
// 1st, use the adjust point
// build up the new suggest UI rectangle (composition window)
rcUIRect.left = ptNearCaret.x;
rcUIRect.top = ptNearCaret.y;
rcUIRect.right = rcUIRect.left + lpImeL->xCompWi;
rcUIRect.bottom = rcUIRect.top + lpImeL->yCompHi;
ptOldNearCaret = ptNearCaret;
// OK, no intersect between the near caret position and input char
if (IntersectRect(&rcInterRect, &rcUIRect, &rcInputRect)) {
} else if (FitInLazyOperation(
#if defined(UNIIME)
lpImeL,
#endif
lpptOrg, &ptNearCaret, &rcInputRect, uEsc)) {
// happy ending!!!, don't chaqge position
return (FALSE);
} else {
*lpptOrg = ptNearCaret;
// happy ending!!
return (TRUE);
}
// unhappy case
GetNearCaretPosition(
#if defined(UNIIME)
lpImeL,
#endif
&ptFont, uEsc, uRot, lpptNew, &ptNearCaret, 0);
// build up the new suggest UI rectangle (composition window)
rcUIRect.left = ptNearCaret.x;
rcUIRect.top = ptNearCaret.y;
rcUIRect.right = rcUIRect.left + lpImeL->xCompWi;
rcUIRect.bottom = rcUIRect.top + lpImeL->yCompHi;
// OK, no intersect between the adjust position and input char
if (IntersectRect(&rcInterRect, &rcUIRect, &rcInputRect)) {
} else if (FitInLazyOperation(
#if defined(UNIIME)
lpImeL,
#endif
lpptOrg, &ptNearCaret, &rcInputRect, uEsc)) {
// happy ending!!!, don't chaqge position
return (FALSE);
} else {
*lpptOrg = ptNearCaret;
// happy ending!!
return (TRUE);
}
// unhappy ending! :-(
*lpptOrg = ptOldNearCaret;
return (TRUE);
}
/**********************************************************************/
/* SetCompPosition() */
/**********************************************************************/
void PASCAL SetCompPosition( // set the composition window position
HWND hCompWnd,
HIMC hIMC,
LPINPUTCONTEXT lpIMC)
{
POINT ptWnd;
POINT ptSTWPos;
HWND hCandWnd;
BOOL fChange = FALSE;
RECT rcWorkArea;
#if 1 // MultiMonoitor
rcWorkArea = ImeMonitorWorkAreaFromWindow(lpIMC->hWnd);
#else
rcWorkArea = sImeG.rcWorkArea;
#endif
// the client coordinate position (0, 0) of composition window
ptWnd.x = 0;
ptWnd.y = 0;
// convert to screen coordinates
ClientToScreen(hCompWnd, &ptWnd);
ptWnd.x -= lpImeL->cxCompBorder;
ptWnd.y -= lpImeL->cyCompBorder;
if (!MBIndex.IMEChara[0].IC_Trace) {
int Comp_CandWndLen;
ImmGetStatusWindowPos(hIMC, (LPPOINT)&ptSTWPos);
// reset status window for LINE_UI(FIX_UI)
Comp_CandWndLen = 0;
if(uStartComp) {
Comp_CandWndLen += lpImeL->xCompWi + UI_MARGIN;
if(uOpenCand) {
Comp_CandWndLen += sImeG.xCandWi + UI_MARGIN;
}
if(ptSTWPos.x + sImeG.xStatusWi + Comp_CandWndLen > rcWorkArea.right) {
ptSTWPos.x = rcWorkArea.right - sImeG.xStatusWi - Comp_CandWndLen;
}
SetWindowPos(GetStatusWnd(GetWindow(hCompWnd, GW_OWNER)), NULL,
(int)ptSTWPos.x, (int)ptSTWPos.y,
0, 0, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOSIZE|SWP_NOZORDER);
ImmSetStatusWindowPos(hIMC, (LPPOINT)&ptSTWPos);
}
ptWnd.x = ptSTWPos.x + sImeG.xStatusWi + UI_MARGIN;
ptWnd.y = ptSTWPos.y;
lpIMC->cfCompForm.ptCurrentPos = ptWnd;
ScreenToClient(lpIMC->hWnd, &lpIMC->cfCompForm.ptCurrentPos);
fChange = TRUE;
} else if (lpIMC->cfCompForm.dwStyle & CFS_FORCE_POSITION) {
POINT ptNew; // new position of UI
ptNew.x = lpIMC->cfCompForm.ptCurrentPos.x;
ptNew.y = lpIMC->cfCompForm.ptCurrentPos.y;
ClientToScreen((HWND)lpIMC->hWnd, &ptNew);
if (ptWnd.x != ptNew.x) {
ptWnd.x = ptNew.x;
fChange = TRUE;
}
if (ptWnd.y != ptNew.y) {
ptWnd.y = ptNew.y;
fChange = TRUE;
}
if (fChange) {
ptWnd.x -= lpImeL->cxCompBorder;
ptWnd.y -= lpImeL->cyCompBorder;
}
} else if (lpIMC->cfCompForm.dwStyle != CFS_DEFAULT) {
POINT ptNew; // new position of UI
ptNew.x = lpIMC->cfCompForm.ptCurrentPos.x;
ptNew.y = lpIMC->cfCompForm.ptCurrentPos.y;
ClientToScreen((HWND)lpIMC->hWnd, &ptNew);
fChange = AdjustCompPosition(lpIMC, &ptWnd, &ptNew);
} else {
POINT ptNew; // new position of UI
ImmGetStatusWindowPos(hIMC, (LPPOINT)&ptSTWPos);
ptNew.x = ptSTWPos.x + sImeG.xStatusWi + UI_MARGIN;
if((ptSTWPos.x + sImeG.xStatusWi + sImeG.xCandWi + lpImeL->xCompWi + 2 * UI_MARGIN) >=
rcWorkArea.right) {
ptNew.x = ptSTWPos.x - lpImeL->xCompWi - UI_MARGIN;
}
ptNew.y = ptSTWPos.y;
if (ptWnd.x != ptNew.x) {
ptWnd.x = ptNew.x;
fChange = TRUE;
}
if (ptWnd.y != ptNew.y) {
ptWnd.y = ptNew.y;
fChange = TRUE;
}
if (fChange) {
lpIMC->cfCompForm.ptCurrentPos = ptNew;
ScreenToClient(lpIMC->hWnd, &lpIMC->cfCompForm.ptCurrentPos);
}
}
if (!fChange) {
return;
}
SetWindowPos(hCompWnd, NULL,
ptWnd.x, ptWnd.y,
0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
hCandWnd = GetCandWnd(GetWindow(hCompWnd, GW_OWNER));
if (!hCandWnd) {
return;
}
// decide the position of candidate window by UI's position
CalcCandPos(hIMC, GetWindow(hCompWnd, GW_OWNER), &ptWnd);
ScreenToClient(lpIMC->hWnd, &ptWnd);
lpIMC->cfCandForm[0].dwStyle = CFS_CANDIDATEPOS;
lpIMC->cfCandForm[0].ptCurrentPos = ptWnd;
if (!IsWindowVisible(hCandWnd)) {
return;
}
PostMessage(hCandWnd, WM_IME_NOTIFY, IMN_SETCANDIDATEPOS, 0x0001);
return;
}
/**********************************************************************/
/* SetCompWindow() */
/**********************************************************************/
void PASCAL SetCompWindow( // set the position of composition window
HWND hCompWnd)
{
HIMC hIMC;
LPINPUTCONTEXT lpIMC;
HWND hUIWnd;
hUIWnd = GetWindow(hCompWnd, GW_OWNER);
if (!hUIWnd) {
return;
}
hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
if (!hIMC) {
return;
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) {
return;
}
SetCompPosition(hCompWnd, hIMC, lpIMC);
ImmUnlockIMC(hIMC);
return;
}
/**********************************************************************/
/* MoveDefaultCompPosition() */
/**********************************************************************/
void PASCAL MoveDefaultCompPosition( // the default comp position
// need to near the caret
HWND hUIWnd)
{
HIMC hIMC;
LPINPUTCONTEXT lpIMC;
HWND hCompWnd;
hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
if (!hIMC) {
return;
}
hCompWnd = GetCompWnd(hUIWnd);
if (!hCompWnd) {
return;
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) {
return;
}
if (!(lpIMC->cfCompForm.dwStyle & CFS_FORCE_POSITION)) {
SetCompPosition(hCompWnd, hIMC, lpIMC);
}
ImmUnlockIMC(hIMC);
return;
}
/**********************************************************************/
/* ShowComp() */
/**********************************************************************/
void PASCAL ShowComp( // Show the composition window
HWND hUIWnd,
int nShowCompCmd)
{
HGLOBAL hUIPrivate;
LPUIPRIV lpUIPrivate;
// show or hid the UI window
hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
if (!hUIPrivate) {
return;
}
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
if (!lpUIPrivate) {
return;
}
if (lpUIPrivate->nShowCompCmd == nShowCompCmd) {
goto SwCompNoChange;
}
if (nShowCompCmd == SW_HIDE) {
lpUIPrivate->fdwSetContext &= ~(ISC_HIDE_COMP_WINDOW);
}
if (!lpUIPrivate->hCompWnd) {
// not in show candidate window mode
} else {
if(nShowCompCmd == SW_HIDE) {
uStartComp = 0;
} else {
uStartComp = 1;
}
ShowWindow(lpUIPrivate->hCompWnd, nShowCompCmd);
lpUIPrivate->nShowCompCmd = nShowCompCmd;
}
SwCompNoChange:
GlobalUnlock(hUIPrivate);
return;
}
/**********************************************************************/
/* StartComp() */
/**********************************************************************/
void PASCAL StartComp(
HWND hUIWnd)
{
HIMC hIMC;
HGLOBAL hUIPrivate;
LPINPUTCONTEXT lpIMC;
LPUIPRIV lpUIPrivate;
hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
if (!hIMC) { // Oh! Oh!
return;
}
hUIPrivate = (HGLOBAL)GetWindowLongPtr(hUIWnd, IMMGWLP_PRIVATE);
if (!hUIPrivate) { // Oh! Oh!
return;
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) { // Oh! Oh!
return;
}
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
if (!lpUIPrivate) { // can not draw composition window
ImmUnlockIMC(hIMC);
return;
}
lpUIPrivate->fdwSetContext |= ISC_SHOWUICOMPOSITIONWINDOW;
if(!lpUIPrivate->hCompWnd) {
lpUIPrivate->hCompWnd = CreateWindowEx(
WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME,
szCompClassName,
NULL,
WS_POPUP|WS_DISABLED,
0,
0,
lpImeL->xCompWi,
lpImeL->yCompHi,
hUIWnd,
(HMENU)NULL,
hInst,
NULL);
SetWindowLong(lpUIPrivate->hCompWnd, UI_MOVE_OFFSET,WINDOW_NOT_DRAG);
SetWindowLong(lpUIPrivate->hCompWnd, UI_MOVE_XY, lpImeL->nMaxKey);
}
uStartComp = 1;
// try to set the position of composition UI window near the caret
SetCompPosition(lpUIPrivate->hCompWnd, hIMC, lpIMC);
ImmUnlockIMC(hIMC);
ShowComp(hUIWnd, SW_SHOWNOACTIVATE);
GlobalUnlock(hUIPrivate);
return;
}
/**********************************************************************/
/* EndComp() */
/**********************************************************************/
void PASCAL EndComp(
HWND hUIWnd)
{
ShowComp(hUIWnd, SW_HIDE);
return;
}
/**********************************************************************/
/* DestroyCompWindow() */
/**********************************************************************/
void PASCAL DestroyCompWindow( // destroy composition window
HWND hCompWnd)
{
HGLOBAL hUIPrivate;
LPUIPRIV lpUIPrivate;
if (GetWindowLong(hCompWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
// undo the drag border
DrawDragBorder(hCompWnd,
GetWindowLong(hCompWnd, UI_MOVE_XY),
GetWindowLong(hCompWnd, UI_MOVE_OFFSET));
}
hUIPrivate = (HGLOBAL)GetWindowLongPtr(GetWindow(hCompWnd, GW_OWNER),
IMMGWLP_PRIVATE);
if (!hUIPrivate) { // Oh! Oh!
return;
}
lpUIPrivate = (LPUIPRIV)GlobalLock(hUIPrivate);
if (!lpUIPrivate) { // Oh! Oh!
return;
}
lpUIPrivate->nShowCompCmd = SW_HIDE;
lpUIPrivate->hCompWnd = (HWND)NULL;
GlobalUnlock(hUIPrivate);
return;
}
/**********************************************************************/
/* CompSetCursor() */
/**********************************************************************/
void PASCAL CompSetCursor(
HWND hCompWnd,
LPARAM lParam)
{
POINT ptCursor;
RECT rcWnd;
SetCursor(LoadCursor(NULL, IDC_SIZEALL));
if (GetWindowLong(hCompWnd, UI_MOVE_OFFSET) !=
WINDOW_NOT_DRAG) {
return;
}
if (HIWORD(lParam) != WM_LBUTTONDOWN) {
return;
}
// start dragging
SystemParametersInfo(SPI_GETWORKAREA, 0, &sImeG.rcWorkArea, 0);
SetCapture(hCompWnd);
GetCursorPos(&ptCursor);
SetWindowLong(hCompWnd, UI_MOVE_XY,
MAKELONG(ptCursor.x, ptCursor.y));
GetWindowRect(hCompWnd, &rcWnd);
SetWindowLong(hCompWnd, UI_MOVE_OFFSET,
MAKELONG(ptCursor.x - rcWnd.left, ptCursor.y - rcWnd.top));
DrawDragBorder(hCompWnd, MAKELONG(ptCursor.x, ptCursor.y),
GetWindowLong(hCompWnd, UI_MOVE_OFFSET));
return;
}
/**********************************************************************/
/* CompButtonUp() */
/**********************************************************************/
BOOL PASCAL CompButtonUp( // finish drag, set comp window to this
// position
HWND hCompWnd)
{
LONG lTmpCursor, lTmpOffset;
POINT pt;
HWND hUIWnd;
HIMC hIMC;
LPINPUTCONTEXT lpIMC;
RECT rcWorkArea;
if (GetWindowLong(hCompWnd, UI_MOVE_OFFSET) == WINDOW_NOT_DRAG) {
return (FALSE);
}
lTmpCursor = GetWindowLong(hCompWnd, UI_MOVE_XY);
// calculate the org by the offset
lTmpOffset = GetWindowLong(hCompWnd, UI_MOVE_OFFSET);
pt.x = (*(LPPOINTS)&lTmpCursor).x - (*(LPPOINTS)&lTmpOffset).x;
pt.y = (*(LPPOINTS)&lTmpCursor).y - (*(LPPOINTS)&lTmpOffset).y;
DrawDragBorder(hCompWnd, lTmpCursor, lTmpOffset);
SetWindowLong(hCompWnd, UI_MOVE_OFFSET, WINDOW_NOT_DRAG);
SetWindowLong(hCompWnd, UI_MOVE_XY, lpImeL->nMaxKey);
ReleaseCapture();
hUIWnd = GetWindow(hCompWnd, GW_OWNER);
if (!hUIWnd) {
return (FALSE);
}
hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
if (!hIMC) {
return (FALSE);
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) {
return (FALSE);
}
#if 1 // MultiMonoitor
rcWorkArea = ImeMonitorWorkAreaFromWindow(lpIMC->hWnd);
#else
rcWorkArea = sImeG.rcWorkArea;
#endif
if (pt.x < rcWorkArea.left) {
pt.x = rcWorkArea.left;
} else if (pt.x + lpImeL->xCompWi > rcWorkArea.right) {
pt.x = rcWorkArea.right - lpImeL->xCompWi;
}
if (pt.y < rcWorkArea.top) {
pt.y = rcWorkArea.top;
} else if (pt.y + lpImeL->yCompHi > rcWorkArea.bottom) {
pt.y = rcWorkArea.bottom - lpImeL->yCompHi;
}
lpIMC->cfCompForm.dwStyle = CFS_FORCE_POSITION;
lpIMC->cfCompForm.ptCurrentPos.x = pt.x + lpImeL->cxCompBorder;
lpIMC->cfCompForm.ptCurrentPos.y = pt.y + lpImeL->cyCompBorder;
ScreenToClient(lpIMC->hWnd, &lpIMC->cfCompForm.ptCurrentPos);
ImmUnlockIMC(hIMC);
// set composition window to the new poosition
PostMessage(hCompWnd, WM_IME_NOTIFY, IMN_SETCOMPOSITIONWINDOW, 0);
return (TRUE);
}
#ifdef KEYSTICKER
//**********************************************************************
//IndexKeySticker(int)
//**********************************************************************
int IndexKeySticker(TCHAR index)
{
int i;
for(i=0; i<INDEXNUM; i++){
if(KeyIndexTbl[i] == index){
return i;
}
}
return (-1);
}
//**********************************************************************
//MapSticker(LPCTSTR, LPTSTR, int)
//**********************************************************************
void MapSticker(
LPCTSTR ReadingStr,
LPTSTR szStickerLayout,
int len)
{
int i,j,k;
for(i=0,k=0;i<len;i++){
j = IndexKeySticker(ReadingStr[i]);
//memcpy(&szStickerLayout[i*2], MapKeyStickerTbl[j], 2);
if(j>=0){
memcpy(&szStickerLayout[k], MapKeyStickerTbl[j], 2);
k+=2/sizeof(TCHAR);
}else{
szStickerLayout[k] = ReadingStr[i];
k++;
}
}
}
#endif //KEYSTICKER
/**********************************************************************/
/* PaintCompWindow() */
/**********************************************************************/
void PASCAL PaintCompWindow(
HWND hUIWnd,
HWND hCompWnd,
HDC hDC)
{
HIMC hIMC;
LPINPUTCONTEXT lpIMC;
HGDIOBJ hOldFont;
LPCOMPOSITIONSTRING lpCompStr;
LPGUIDELINE lpGuideLine;
BOOL fShowString;
LPCTSTR lpStr;
hIMC = (HIMC)GetWindowLongPtr(hUIWnd, IMMGWLP_IMC);
if (!hIMC) {
return;
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC) {
return;
}
if (sImeG.fDiffSysCharSet) {
LOGFONT lfFont;
ZeroMemory(&lfFont, sizeof(lfFont));
hOldFont = GetCurrentObject(hDC, OBJ_FONT);
lfFont.lfHeight = -MulDiv(12, GetDeviceCaps(hDC, LOGPIXELSY), 72);
lfFont.lfCharSet = NATIVE_CHARSET;
lstrcpy(lfFont.lfFaceName, TEXT("Simsun"));
SelectObject(hDC, CreateFontIndirect(&lfFont));
}
lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
if(!lpCompStr){
return;
}
lpGuideLine = (LPGUIDELINE)ImmLockIMCC(lpIMC->hGuideLine);
if(!lpGuideLine){
return;
}
// draw CompWnd Layout
{
RECT rcWnd;
GetClientRect(hCompWnd, &rcWnd);
DrawConcaveRect(hDC,
rcWnd.left,
rcWnd.top,
rcWnd.right - 1,
rcWnd.bottom - 1);
}
SetBkColor(hDC, RGB(0xC0, 0xC0, 0xC0));
fShowString = (BOOL) 0;
if (!lpGuideLine) {
} else if (lpGuideLine->dwLevel == GL_LEVEL_NOGUIDELINE) {
} else if (!lpGuideLine->dwStrLen) {
if (lpGuideLine->dwLevel == GL_LEVEL_ERROR) {
fShowString |= IME_STR_ERROR;
}
} else {
// if there is information string, we will show the information
// string
if (lpGuideLine->dwLevel == GL_LEVEL_ERROR) {
// red text for error
SetTextColor(hDC, RGB(0xFF, 0, 0));
// light gray background for error
SetBkColor(hDC, RGB(0x80, 0x80, 0x80));
}
lpStr = (LPCTSTR)((LPBYTE)lpGuideLine + lpGuideLine->dwStrOffset);
ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
ETO_OPAQUE, &lpImeL->rcCompText,
lpStr, (UINT)lpGuideLine->dwStrLen, NULL);
fShowString |= IME_STR_SHOWED;
}
if (fShowString & IME_STR_SHOWED) {
// already show it, don't need to show
} else if (lpCompStr->dwCompStrLen > 0) {
#ifdef KEYSTICKER
{
TCHAR szStickerLayout[MAXCODE*2/sizeof(TCHAR)];
memset(szStickerLayout, 0,MAXCODE*2);
MapSticker((LPTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset),
szStickerLayout,lpCompStr->dwCompStrLen);
ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
ETO_OPAQUE, &lpImeL->rcCompText,
(LPTSTR)NULL, (int)NULL, NULL);
DrawText(hDC, (LPTSTR)szStickerLayout,
(int)lstrlen(szStickerLayout), &lpImeL->rcCompText,
DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
#else
ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
ETO_OPAQUE, &lpImeL->rcCompText,
(LPTSTR)NULL, (int) 0, NULL);
lpStr = (LPCTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset);
DrawText(hDC, lpStr, (int)lpCompStr->dwCompStrLen, &lpImeL->rcCompText,
DT_LEFT | DT_VCENTER | DT_SINGLELINE);
#endif //KEYSTICKER
if (fShowString & IME_STR_ERROR) {
// red text for error
//SetTextColor(hDC, RGB(0xFF, 0, 0));
// light gray background for error
SetBkColor(hDC, RGB(0x80, 0x80, 0x80));
lpStr = (LPCTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset + lpCompStr->dwCursorPos);
ExtTextOut(hDC, lpImeL->rcCompText.left +
lpCompStr->dwCursorPos * sImeG.xChiCharWi/ 2,
lpImeL->rcCompText.top,
ETO_CLIPPED, &lpImeL->rcCompText,
lpStr, (UINT)lpCompStr->dwCompStrLen - lpCompStr->dwCursorPos, NULL);
} else if (lpCompStr->dwCursorPos < lpCompStr->dwCompStrLen) {
// light gray background for cursor start
SetBkColor(hDC, RGB(0x80, 0x80, 0x80));
lpStr = (LPCTSTR)((LPBYTE)lpCompStr + lpCompStr->dwCompStrOffset + lpCompStr->dwCursorPos);
ExtTextOut(hDC, lpImeL->rcCompText.left +
lpCompStr->dwCursorPos * sImeG.xChiCharWi/ 2,
lpImeL->rcCompText.top,
ETO_CLIPPED, &lpImeL->rcCompText,
lpStr, (UINT)lpCompStr->dwCompStrLen - lpCompStr->dwCursorPos, NULL);
} else {
}
} else {
// CHP
// Display stand code for reference
#ifdef FUSSYMODE
if (MBIndex.IMEChara[0].IC_FCSR && MBIndex.IMEChara[0].IC_FCTS){
if (MBIndex.IsFussyCharFlag)
{
LPCANDIDATELIST lpRevCandList;
LPPRIVCONTEXT lpImcP;
MBIndex.IsFussyCharFlag = 0;
lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
if (lpImcP) {
if(lpImcP->hRevCandList){
lpRevCandList = (LPCANDIDATELIST)GlobalLock((HGLOBAL)lpImcP->hRevCandList);
if (lpRevCandList != NULL && lpRevCandList->dwCount) {
// Red text for correction
SetTextColor(hDC, RGB(0xc0, 0x00, 0x00));
SetBkColor(hDC, RGB(0xc0, 0xc0, 0xc0));
lpStr = (LPCTSTR)((LPBYTE)lpRevCandList + lpRevCandList->dwOffset[0]);
ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
ETO_OPAQUE, &lpImeL->rcCompText,
lpStr, (int)lstrlen(lpStr), NULL);
//MessageBox(NULL,TEXT("OK"),TEXT("Mydebug"),MB_OK);
GlobalFree((HGLOBAL)lpImcP->hRevCandList);
lpImcP->hRevCandList = (HIMCC)NULL;
}
}
}
else
{
ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
ETO_OPAQUE, &lpImeL->rcCompText,
(LPTSTR)NULL, 0, NULL);
}
ImmUnlockIMCC(lpIMC->hPrivate);
}
else
ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
ETO_OPAQUE, &lpImeL->rcCompText,
(LPTSTR)NULL, 0, NULL);
}
else
#endif
#ifdef CROSSREF
{
LPCANDIDATELIST lpRevCandList;
LPPRIVCONTEXT lpImcP;
lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
if (lpImcP) {
if(lpImcP->hRevCandList){
lpRevCandList = (LPCANDIDATELIST)GlobalLock((HGLOBAL)lpImcP->hRevCandList);
if (lpRevCandList != NULL && lpRevCandList->dwCount) {
// green text for information
SetTextColor(hDC, RGB(0x00, 0x80, 0x00));
SetBkColor(hDC, RGB(0xc0, 0xc0, 0xc0));
lpStr = (LPCTSTR)((LPBYTE)lpRevCandList + lpRevCandList->dwOffset[0]);
ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
ETO_OPAQUE, &lpImeL->rcCompText,
lpStr, (int)lstrlen(lpStr), NULL);
GlobalFree((HGLOBAL)lpImcP->hRevCandList);
lpImcP->hRevCandList = (HIMCC)NULL;
goto CrossCodeFinish;
}
}
}
ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
ETO_OPAQUE, &lpImeL->rcCompText,
(LPTSTR)NULL, 0, NULL);
CrossCodeFinish:
ImmUnlockIMCC(lpIMC->hPrivate);
}
#else
ExtTextOut(hDC, lpImeL->rcCompText.left, lpImeL->rcCompText.top,
ETO_OPAQUE, &lpImeL->rcCompText,
(LPTSTR)NULL, 0, NULL);
#endif
}
if (sImeG.fDiffSysCharSet) {
DeleteObject(SelectObject(hDC, hOldFont));
}
ImmUnlockIMCC(lpIMC->hGuideLine);
ImmUnlockIMCC(lpIMC->hCompStr);
ImmUnlockIMC(hIMC);
return;
}
/**********************************************************************/
/* UpdateCompWindow() */
/**********************************************************************/
void PASCAL UpdateCompWindow(
HWND hUIWnd)
{
HWND hCompWnd;
HDC hDC;
hCompWnd = GetCompWnd(hUIWnd);
hDC = GetDC(hCompWnd);
PaintCompWindow(hUIWnd, hCompWnd, hDC);
ReleaseDC(hCompWnd, hDC);
}
/**********************************************************************/
/* CompWndProc() */
/**********************************************************************/
LRESULT CALLBACK CompWndProc( // composition window proc
HWND hCompWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg) {
case WM_DESTROY:
DestroyCompWindow(hCompWnd);
break;
case WM_SETCURSOR:
CompSetCursor(hCompWnd, lParam);
break;
case WM_MOUSEMOVE:
if (GetWindowLong(hCompWnd, UI_MOVE_OFFSET) != WINDOW_NOT_DRAG) {
POINT ptCursor;
DrawDragBorder(hCompWnd,
GetWindowLong(hCompWnd, UI_MOVE_XY),
GetWindowLong(hCompWnd, UI_MOVE_OFFSET));
GetCursorPos(&ptCursor);
SetWindowLong(hCompWnd, UI_MOVE_XY,
MAKELONG(ptCursor.x, ptCursor.y));
DrawDragBorder(hCompWnd, MAKELONG(ptCursor.x, ptCursor.y),
GetWindowLong(hCompWnd, UI_MOVE_OFFSET));
} else {
return DefWindowProc(hCompWnd, uMsg, wParam, lParam);
}
break;
case WM_LBUTTONUP:
if (!CompButtonUp(hCompWnd)) {
return DefWindowProc(hCompWnd, uMsg, wParam, lParam);
}
break;
case WM_IME_NOTIFY:
if (wParam == IMN_SETCOMPOSITIONWINDOW) {
SetCompWindow(hCompWnd);
}
break;
case WM_PAINT:
{
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hCompWnd, &ps);
PaintCompWindow(GetWindow(hCompWnd, GW_OWNER), hCompWnd, hDC);
EndPaint(hCompWnd, &ps);
}
break;
case WM_MOUSEACTIVATE:
return (MA_NOACTIVATE);
default:
return DefWindowProc(hCompWnd, uMsg, wParam, lParam);
}
return (0L);
}