WindowsXP-SP1/windows/feime/usa/toascii.c
2020-09-30 16:53:49 +02:00

628 lines
16 KiB
C

/*************************************************
* toascii.c *
* *
* Copyright (C) 1999 Microsoft Inc. *
* *
*************************************************/
#include <windows.h>
#include <immdev.h>
#include "imeattr.h"
#include "imedefs.h"
/**********************************************************************/
/* ProcessKey() */
/* Return Value: */
/* different state which input key will change IME to */
/**********************************************************************/
UINT PASCAL ProcessKey( // this key will cause the IME go to what state
WORD wCharCode,
UINT uVirtKey,
UINT uScanCode,
CONST LPBYTE lpbKeyState,
LPINPUTCONTEXT lpIMC,
LPPRIVCONTEXT lpImcP)
{
if (!lpIMC)
{
return (CST_INVALID);
}
if (!lpImcP)
{
return (CST_INVALID);
}
if (uVirtKey == VK_MENU)
{
//
// no ALT key
//
return (CST_INVALID);
}
else if (uScanCode & KF_ALTDOWN)
{
//
// no ALT-xx key
//
return (CST_INVALID);
}
else if (uVirtKey == VK_CONTROL)
{
//
// no CTRL key
//
return (CST_INVALID);
}
else if (lpbKeyState[VK_CONTROL] & 0x80)
{
//
// no CTRL-xx key
//
return (CST_INVALID);
}
else if (uVirtKey == VK_SHIFT)
{
//
// no SHIFT key
//
return (CST_INVALID);
}
else if (!lpIMC->fOpen)
{
//
// don't compose in close status
//
return (CST_INVALID);
}
else if (lpIMC->fdwConversion & IME_CMODE_NOCONVERSION)
{
//
// don't compose in no coversion status
//
return (CST_INVALID);
}
else if (lpIMC->fdwConversion & IME_CMODE_CHARCODE)
{
//
// not support
//
return (CST_INVALID);
}
if (uVirtKey >= VK_NUMPAD0 && uVirtKey <= VK_DIVIDE)
{
//
// A PM decision: all numpad should be past to app
//
return (CST_ALPHANUMERIC);
}
if (!(lpIMC->fdwConversion & IME_CMODE_NATIVE))
{
return (CST_INVALID);
}
else if (!(lpbKeyState[VK_SHIFT] & 0x80))
{
//
// need more check for IME_CMODE_NATIVE
//
}
else if (wCharCode < ' ' && wCharCode > '~')
{
return (CST_INVALID);
}
//
// need more check for IME_CMODE_NATIVE
//
if (wCharCode >= ' ' && wCharCode <= 'z')
{
wCharCode = bUpper[wCharCode - ' '];
}
if (uVirtKey == VK_ESCAPE)
{
register LPGUIDELINE lpGuideLine;
register UINT iImeState;
if (lpImcP->fdwImeMsg & MSG_ALREADY_START)
{
return (CST_INPUT);
}
lpGuideLine = ImmLockIMCC(lpIMC->hGuideLine);
if (!lpGuideLine)
{
return (CST_INVALID);
}
else if (lpGuideLine->dwLevel == GL_LEVEL_NOGUIDELINE)
{
iImeState = CST_INVALID;
}
else
{
//
// need this key to clean information string or guideline state
//
iImeState = CST_INPUT;
}
ImmUnlockIMCC(lpIMC->hGuideLine);
return (iImeState);
}
else if (uVirtKey == VK_BACK)
{
if (lpImcP->fdwImeMsg & MSG_ALREADY_START)
{
return (CST_INPUT);
}
else
{
return (CST_INVALID);
}
}
//
// check finalize char
//
if (wCharCode == ' ' && lpImcP->iImeState == CST_INIT)
{
return (CST_INVALID);
}
else if (lpImeL->fCompChar[(wCharCode - ' ') >> 4] &
fMask[wCharCode & 0x000F])
{
return (CST_INPUT);
}
else if (wCharCode >= 'G' && wCharCode <= 'Z' ||
wCharCode >= 'g' && wCharCode <= 'z')
{
//
// PM decision says we should not send these letters to input
// to avoid confusing users. We special handle this case by
// introducing CST_BLOCKINPUT flag.
//
return (CST_BLOCKINPUT);
}
return (CST_INVALID);
}
/**********************************************************************/
/* ImeProcessKey() / UniImeProcessKey() */
/* Return Value: */
/* TRUE - successful, FALSE - failure */
/**********************************************************************/
// if this key is need by IME?
BOOL WINAPI ImeProcessKey(
HIMC hIMC,
UINT uVirtKey,
LPARAM lParam,
CONST LPBYTE lpbKeyState)
{
LPINPUTCONTEXT lpIMC;
LPPRIVCONTEXT lpImcP;
BYTE szAscii[4];
int nChars;
BOOL fRet;
//
// can't compose in NULL hIMC
//
if (!hIMC)
{
return (FALSE);
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC)
{
return (FALSE);
}
lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
if (!lpImcP)
{
ImmUnlockIMC(hIMC);
return (FALSE);
}
nChars = ToAscii(uVirtKey, HIWORD(lParam), lpbKeyState, (LPVOID)szAscii, 0);
if (!nChars)
{
szAscii[0] = 0;
}
if (ProcessKey( (WORD)szAscii[0],
uVirtKey,
HIWORD(lParam),
lpbKeyState,
lpIMC,
lpImcP) == CST_INVALID)
{
fRet = FALSE;
}
else
{
fRet = TRUE;
}
ImmUnlockIMCC(lpIMC->hPrivate);
ImmUnlockIMC(hIMC);
return (fRet);
}
/**********************************************************************/
/* TranslateToAscii() */
/* Translates the key input to WM_CHAR as keyboard drivers does */
/* */
/* Return Value: */
/* the number of translated chars */
/**********************************************************************/
UINT PASCAL TranslateToAscii(
UINT uScanCode,
LPTRANSMSG lpTransMsg,
WORD wCharCode)
{
if (wCharCode)
{
//
// one char code
//
lpTransMsg->message = WM_CHAR;
lpTransMsg->wParam = wCharCode;
lpTransMsg->lParam = (uScanCode << 16) | 1UL;
return (1);
}
//
// no char code case
//
return (0);
}
/**********************************************************************/
/* TranslateImeMessage() */
/* Return Value: */
/* the number of translated messages */
/**********************************************************************/
UINT PASCAL TranslateImeMessage(
LPTRANSMSGLIST lpTransBuf,
LPINPUTCONTEXT lpIMC,
LPPRIVCONTEXT lpImcP)
{
UINT uNumMsg;
UINT i;
BOOL bLockMsgBuf;
LPTRANSMSG lpTransMsg;
uNumMsg = 0;
bLockMsgBuf = FALSE;
for (i = 0; i < 2; i++)
{
if (lpImcP->fdwImeMsg & MSG_IMN_COMPOSITIONSIZE)
{
if (!i)
{
uNumMsg++;
}
else
{
lpTransMsg->message = WM_IME_NOTIFY;
lpTransMsg->wParam = IMN_PRIVATE;
lpTransMsg->lParam = IMN_PRIVATE_COMPOSITION_SIZE;
lpTransMsg += 1;
}
}
if (lpImcP->fdwImeMsg & MSG_START_COMPOSITION)
{
if (!(lpImcP->fdwImeMsg & MSG_ALREADY_START))
{
if (!i)
{
uNumMsg++;
}
else
{
lpTransMsg->message = WM_IME_STARTCOMPOSITION;
lpTransMsg->wParam = 0;
lpTransMsg->lParam = 0;
lpTransMsg += 1;
lpImcP->fdwImeMsg |= MSG_ALREADY_START;
}
}
}
if (lpImcP->fdwImeMsg & MSG_IMN_COMPOSITIONPOS)
{
if (!i)
{
uNumMsg++;
}
else
{
lpTransMsg->message = WM_IME_NOTIFY;
lpTransMsg->wParam = IMN_SETCOMPOSITIONWINDOW;
lpTransMsg->lParam = 0;
lpTransMsg += 1;
}
}
if (lpImcP->fdwImeMsg & MSG_COMPOSITION)
{
if (!i)
{
uNumMsg++;
}
else
{
lpTransMsg->message = WM_IME_COMPOSITION;
lpTransMsg->wParam = lpImcP->dwCompChar;
lpTransMsg->lParam = lpImcP->fdwGcsFlag;
lpTransMsg += 1;
}
}
if (lpImcP->fdwImeMsg & MSG_GUIDELINE)
{
if (!i)
{
uNumMsg++;
}
else
{
lpTransMsg->message = WM_IME_NOTIFY;
lpTransMsg->wParam = IMN_GUIDELINE;
lpTransMsg->lParam = 0;
lpTransMsg += 1;
}
}
if (lpImcP->fdwImeMsg & MSG_IMN_PAGEUP)
{
if (!i)
{
uNumMsg++;
}
else
{
lpTransMsg->message = WM_IME_NOTIFY;
lpTransMsg->wParam = IMN_PRIVATE;
lpTransMsg->lParam = IMN_PRIVATE_PAGEUP;
lpTransMsg += 1;
}
}
if (lpImcP->fdwImeMsg & MSG_END_COMPOSITION)
{
if (lpImcP->fdwImeMsg & MSG_ALREADY_START)
{
if (!i)
{
uNumMsg++;
}
else
{
lpTransMsg->message = WM_IME_ENDCOMPOSITION;
lpTransMsg->wParam = 0;
lpTransMsg->lParam = 0;
lpTransMsg += 1;
lpImcP->fdwImeMsg &= ~(MSG_ALREADY_START);
}
}
}
if (lpImcP->fdwImeMsg & MSG_IMN_TOGGLE_UI)
{
if (!i)
{
uNumMsg++;
}
else
{
lpTransMsg->message = WM_IME_NOTIFY;
lpTransMsg->wParam = IMN_PRIVATE;
lpTransMsg->lParam = IMN_PRIVATE_TOGGLE_UI;
lpTransMsg += 1;
}
}
if (!i)
{
HIMCC hMem;
if (!uNumMsg)
{
return (uNumMsg);
}
if (lpImcP->fdwImeMsg & MSG_IN_IMETOASCIIEX)
{
UINT uNumMsgLimit;
// ++ for the start position of buffer to strore the messages
uNumMsgLimit = lpTransBuf->uMsgCount;
if (uNumMsg <= uNumMsgLimit)
{
lpTransMsg = lpTransBuf->TransMsg;
continue;
}
}
// we need to use message buffer
if (!lpIMC->hMsgBuf)
{
lpIMC->hMsgBuf = ImmCreateIMCC(uNumMsg * sizeof(TRANSMSG));
lpIMC->dwNumMsgBuf = 0;
}
else if (hMem = ImmReSizeIMCC(lpIMC->hMsgBuf,
(lpIMC->dwNumMsgBuf + uNumMsg) * sizeof(TRANSMSG)))
{
if (hMem != lpIMC->hMsgBuf)
{
ImmDestroyIMCC(lpIMC->hMsgBuf);
lpIMC->hMsgBuf = hMem;
}
}
else
{
return (0);
}
lpTransMsg = (LPTRANSMSG)ImmLockIMCC(lpIMC->hMsgBuf);
if (!lpTransMsg)
{
return (0);
}
lpTransMsg += lpIMC->dwNumMsgBuf;
bLockMsgBuf = TRUE;
}
else
{
if (bLockMsgBuf)
{
ImmUnlockIMCC(lpIMC->hMsgBuf);
}
}
}
return (uNumMsg);
}
/**********************************************************************/
/* ImeToAsciiEx() / UniImeToAsciiex() */
/* Return Value: */
/* the number of translated message */
/**********************************************************************/
UINT WINAPI ImeToAsciiEx(
UINT uVirtKey,
UINT uScanCode,
CONST LPBYTE lpbKeyState,
LPTRANSMSGLIST lpTransBuf,
UINT fuState,
HIMC hIMC)
{
WORD wCharCode;
LPINPUTCONTEXT lpIMC;
LPCOMPOSITIONSTRING lpCompStr;
LPGUIDELINE lpGuideLine;
LPPRIVCONTEXT lpImcP;
UINT uNumMsg;
int iRet;
wCharCode = HIWORD(uVirtKey);
uVirtKey = LOBYTE(uVirtKey);
if (!hIMC)
{
return TranslateToAscii(uScanCode,
&lpTransBuf->TransMsg[0],
wCharCode);
}
lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
if (!lpIMC)
{
return TranslateToAscii(uScanCode,
&lpTransBuf->TransMsg[0],
wCharCode);
}
lpImcP = (LPPRIVCONTEXT)ImmLockIMCC(lpIMC->hPrivate);
if (!lpImcP)
{
ImmUnlockIMC(hIMC);
return TranslateToAscii(uScanCode,
&lpTransBuf->TransMsg[0],
wCharCode);
}
// Now all composition realated information already pass to app
// a brand new start
lpImcP->fdwImeMsg = lpImcP->fdwImeMsg & (MSG_STATIC_STATE) |
MSG_IN_IMETOASCIIEX;
iRet = ProcessKey(wCharCode,
uVirtKey,
uScanCode,
lpbKeyState,
lpIMC,
lpImcP);
if (iRet == CST_ALPHABET)
{
// A-Z convert to a-z, a-z convert to A-Z
wCharCode ^= 0x20;
iRet = CST_ALPHANUMERIC;
}
if (iRet == CST_ALPHANUMERIC)
{
uNumMsg = TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
uNumMsg += TranslateToAscii(uScanCode,
&lpTransBuf->TransMsg[uNumMsg],
wCharCode);
}
else if (iRet == CST_INPUT)
{
lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
lpGuideLine = (LPGUIDELINE)ImmLockIMCC(lpIMC->hGuideLine);
CompWord(wCharCode, hIMC, lpIMC, lpCompStr, lpGuideLine, lpImcP);
if (lpGuideLine)
{
ImmUnlockIMCC(lpIMC->hGuideLine);
}
if (lpCompStr)
{
ImmUnlockIMCC(lpIMC->hCompStr);
}
uNumMsg = TranslateImeMessage(lpTransBuf, lpIMC, lpImcP);
}
else if (iRet == CST_BLOCKINPUT)
{
//
// This codepoint should be blocked. We don't compose it for IME.
// Nor do we pass it to normal input. Instead, we beep.
//
MessageBeep(-1);
uNumMsg = 0;
}
else
{
uNumMsg = TranslateToAscii(uScanCode,
&lpTransBuf->TransMsg[0],
wCharCode);
}
lpImcP->fdwImeMsg &= (MSG_STATIC_STATE);
lpImcP->fdwGcsFlag = 0;
ImmUnlockIMCC(lpIMC->hPrivate);
ImmUnlockIMC(hIMC);
return (uNumMsg);
}