📄 compui.c
字号:
/*++
Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
Module Name:
compui.c
++*/
#include <windows.h>
#include <imm.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
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
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;
}
}
#ifdef MUL_MONITOR
rcWorkArea = ImeMonitorWorkAreaFromPoint(*lpptCaret);
#else
rcWorkArea = sImeG.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
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(
&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(
lpptOrg, &ptNearCaret, &rcInputRect, uEsc)) {
// happy ending!!!, don't change position
return (FALSE);
} else {
*lpptOrg = ptNearCaret;
// happy ending!!
return (TRUE);
}
// unhappy case
GetNearCaretPosition(
&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(
lpptOrg, &ptNearCaret, &rcInputRect, uEsc)) {
return (FALSE);
} else {
*lpptOrg = ptNearCaret;
return (TRUE);
}
*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;
#ifdef MUL_MONITOR
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -