mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2948 lines
82 KiB
2948 lines
82 KiB
/**************************************************************************\
|
|
* Module Name: ctxtinfo.c
|
|
*
|
|
* Copyright (c) Microsoft Corp. 1985-1996 All Rights Reserved
|
|
*
|
|
* Get/set routines of various Input context information for imm32.dll
|
|
*
|
|
* History:
|
|
* 26-Feb-1996 wkwok
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCompositionStringA
|
|
*
|
|
* Query composition string information specified by dwIndex.
|
|
*
|
|
* History:
|
|
* 28-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
LONG WINAPI ImmGetCompositionStringA(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPVOID lpBuf,
|
|
DWORD dwBufLen)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
PCOMPOSITIONSTRING pCompStr;
|
|
BOOL fAnsi;
|
|
LONG lRet = 0;
|
|
|
|
if (dwBufLen != 0 && lpBuf == NULL) {
|
|
RIPMSG0(RIP_WARNING, "ImmGetCompositionStringW: NULL lpBuf.");
|
|
return lRet;
|
|
}
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmGetCompositionStringA: Invalid hImc %lx.", hImc);
|
|
return lRet;
|
|
}
|
|
|
|
fAnsi = !TestICF(pClientImc, IMCF_UNICODE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (pInputContext == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCompositionStringA: Lock hImc %lx failed.", hImc);
|
|
return lRet;
|
|
}
|
|
|
|
pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr);
|
|
if (pCompStr == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCompositionStringA: Lock hCompStr %x failed",
|
|
pInputContext->hCompStr);
|
|
ImmUnlockIMC(hImc);
|
|
return lRet;
|
|
}
|
|
|
|
lRet = InternalGetCompositionStringA(pCompStr, dwIndex,
|
|
lpBuf, dwBufLen, fAnsi);
|
|
|
|
ImmUnlockIMCC(pInputContext->hCompStr);
|
|
ImmUnlockIMC(hImc);
|
|
|
|
return lRet;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCompositionStringA
|
|
*
|
|
* Query composition string information specified by dwIndex.
|
|
*
|
|
* History:
|
|
* 28-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
LONG WINAPI ImmGetCompositionStringW(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPVOID lpBuf,
|
|
DWORD dwBufLen)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
PCOMPOSITIONSTRING pCompStr;
|
|
BOOL fAnsi;
|
|
LONG lRet = 0;
|
|
|
|
if (dwBufLen != 0 && lpBuf == NULL) {
|
|
RIPMSG0(RIP_WARNING, "ImmGetCompositionStringW: NULL lpBuf.");
|
|
return lRet;
|
|
}
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmGetCompositionStringW: Invalid hImc %lx.", hImc);
|
|
return lRet;
|
|
}
|
|
|
|
fAnsi = !TestICF(pClientImc, IMCF_UNICODE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (pInputContext == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCompositionStringW: Lock hImc %lx failed.", hImc);
|
|
return lRet;
|
|
}
|
|
|
|
pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr);
|
|
if (pCompStr == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCompositionStringA: Lock hCompStr %x failed",
|
|
pInputContext->hCompStr);
|
|
ImmUnlockIMC(hImc);
|
|
return lRet;
|
|
}
|
|
|
|
lRet = InternalGetCompositionStringW(pCompStr, dwIndex,
|
|
lpBuf, dwBufLen, fAnsi);
|
|
|
|
ImmUnlockIMCC(pInputContext->hCompStr);
|
|
ImmUnlockIMC(hImc);
|
|
|
|
return lRet;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmSetCompositionStringA
|
|
*
|
|
* Set composition string information specified by dwIndex.
|
|
*
|
|
* History:
|
|
* 28-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmSetCompositionStringA(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPCVOID lpComp,
|
|
DWORD dwCompLen,
|
|
LPCVOID lpRead,
|
|
DWORD dwReadLen)
|
|
{
|
|
return ImmSetCompositionStringWorker(hImc, dwIndex, lpComp,
|
|
dwCompLen, lpRead, dwReadLen, TRUE);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmSetCompositionStringA
|
|
*
|
|
* Set composition string information specified by dwIndex.
|
|
*
|
|
* History:
|
|
* 28-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmSetCompositionStringW(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPCVOID lpComp,
|
|
DWORD dwCompLen,
|
|
LPCVOID lpRead,
|
|
DWORD dwReadLen)
|
|
{
|
|
return ImmSetCompositionStringWorker(hImc, dwIndex, lpComp,
|
|
dwCompLen, lpRead, dwReadLen, FALSE);
|
|
}
|
|
|
|
|
|
LONG CompositionString(
|
|
HIMC hImc,
|
|
PINPUTCONTEXT *ppInputContext,
|
|
PCOMPOSITIONSTRING *ppCompStr)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
PCOMPOSITIONSTRING pCompStr;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "CompositionString: Lock hImc %lx failed.", hImc);
|
|
return (LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
if (!pInputContext->hCompStr) {
|
|
ImmUnlockIMC(hImc);
|
|
return (LONG)IMM_ERROR_NODATA;
|
|
}
|
|
|
|
pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr);
|
|
if (!pCompStr) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"CompositionString: Lock hCompStr %lx failed.", pInputContext->hCompStr);
|
|
ImmUnlockIMC(hImc);
|
|
return (LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
if (pCompStr->dwSize < sizeof(COMPOSITIONSTRING)) {
|
|
RIPMSG0(RIP_WARNING, "CompositionString: no composition string.");
|
|
ImmUnlockIMCC(pInputContext->hCompStr);
|
|
ImmUnlockIMC(hImc);
|
|
return (LONG)IMM_ERROR_NODATA;
|
|
}
|
|
|
|
*ppInputContext = pInputContext;
|
|
*ppCompStr = pCompStr;
|
|
|
|
return (1);
|
|
}
|
|
|
|
|
|
BOOL CheckAttribute(
|
|
LPBYTE lpComp, // the attr from apps
|
|
DWORD dwCompLen, // the attr length from apps
|
|
LPBYTE lpAttr, // the attr from IMC
|
|
DWORD dwAttrLen, // the attr length from IMC
|
|
LPDWORD lpClause, // the clause from IMC
|
|
DWORD dwClauseLen) // the clause length from IMC
|
|
{
|
|
DWORD dwCnt;
|
|
DWORD dwBound;
|
|
BYTE bAttr;
|
|
|
|
if (!lpClause) {
|
|
RIPMSG0(RIP_WARNING, "CheckAttribute: no Clause. Pass it to IME.");
|
|
return (TRUE);
|
|
}
|
|
|
|
if (!lpAttr) {
|
|
RIPMSG0(RIP_WARNING, "CheckAttribute: no Attr. Not pass it to IME.");
|
|
return (FALSE);
|
|
}
|
|
|
|
if (dwCompLen != dwAttrLen) {
|
|
RIPMSG0(RIP_WARNING, "CheckAttribute: wrong length. Not pass it to IME.");
|
|
return (FALSE);
|
|
}
|
|
|
|
/*
|
|
* The attr. of chars of one clause have to be same.
|
|
*/
|
|
while (*lpClause < dwCompLen) {
|
|
dwBound = *(lpClause+1) - *lpClause;
|
|
bAttr = *lpComp++;
|
|
for (dwCnt = 1; dwCnt < dwBound; dwCnt++)
|
|
if (bAttr != *lpComp++) {
|
|
RIPMSG0(RIP_WARNING,
|
|
"CheckAttribute: mismatch clause att. Not Pass it to IME");
|
|
return (FALSE);
|
|
}
|
|
lpClause++;
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
BOOL CheckClause(
|
|
LPDWORD lpComp, // the clause from apps
|
|
DWORD dwCompLen, // the clause length from apps
|
|
LPDWORD lpClause, // the clause from IMC
|
|
DWORD dwClauseLen) // the clause length from IMC
|
|
{
|
|
UINT nCnt;
|
|
INT diff = 0;
|
|
|
|
if (!dwClauseLen || !dwCompLen) {
|
|
RIPMSG0(RIP_WARNING, "CheckClause: no Clause. Not Pass it to IME.");
|
|
return (FALSE);
|
|
}
|
|
|
|
if (*lpComp || *lpClause) {
|
|
RIPMSG0(RIP_WARNING, "CheckClause: lpClause[0] have to be ZERO.");
|
|
return (FALSE);
|
|
}
|
|
|
|
for (nCnt = 0; nCnt < (UINT)(dwClauseLen/4); nCnt++)
|
|
{
|
|
if (*lpComp++ != *lpClause++)
|
|
{
|
|
diff++;
|
|
if (dwCompLen > dwClauseLen)
|
|
lpClause--;
|
|
if (dwCompLen < dwClauseLen)
|
|
lpComp--;
|
|
}
|
|
if (diff > 1)
|
|
return (FALSE);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
LPBYTE InternalSCS_SETSTR(
|
|
LPCVOID lpCompRead,
|
|
DWORD dwCompReadLen,
|
|
LPVOID *lplpNewCompRead,
|
|
DWORD *lpdwNewCompReadLen,
|
|
BOOL fAnsi)
|
|
{
|
|
LPBYTE lpBufRet;
|
|
DWORD dwBufSize;
|
|
LPSTR lpBufA;
|
|
LPWSTR lpBufW;
|
|
INT i;
|
|
BOOL bUDC;
|
|
|
|
if (lpCompRead == NULL || dwCompReadLen == 0)
|
|
return NULL;
|
|
|
|
dwBufSize = dwCompReadLen * sizeof(WCHAR) * 2;
|
|
|
|
lpBufRet = ImmLocalAlloc(0, dwBufSize);
|
|
if (lpBufRet == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalSCS_SETSTR: memory failure.");
|
|
return NULL;
|
|
}
|
|
|
|
lpBufW = (LPWSTR)lpBufRet;
|
|
lpBufA = (LPSTR)(lpBufW + dwCompReadLen);
|
|
|
|
if (fAnsi) {
|
|
|
|
RtlCopyMemory(lpBufA, lpCompRead, dwCompReadLen);
|
|
|
|
i = MultiByteToWideChar(CP_ACP,
|
|
(DWORD)MB_PRECOMPOSED,
|
|
(LPSTR)lpBufA, // src
|
|
(INT)dwCompReadLen,
|
|
(LPWSTR)lpBufW, // dest
|
|
(INT)dwCompReadLen);
|
|
|
|
*lplpNewCompRead = lpBufW;
|
|
*lpdwNewCompReadLen = (DWORD)(i * sizeof(WCHAR));
|
|
}
|
|
else {
|
|
|
|
RtlCopyMemory(lpBufW, lpCompRead, dwCompReadLen);
|
|
|
|
i = WideCharToMultiByte(CP_ACP,
|
|
(DWORD)0,
|
|
lpBufW, // src
|
|
(INT)dwCompReadLen/sizeof(WCHAR),
|
|
(LPSTR)lpBufA, // dest
|
|
(INT)dwCompReadLen,
|
|
(LPSTR)NULL,
|
|
(LPBOOL)&bUDC);
|
|
|
|
*lplpNewCompRead = lpBufA;
|
|
*lpdwNewCompReadLen = (DWORD)(i * sizeof(CHAR));
|
|
}
|
|
|
|
return lpBufRet;
|
|
}
|
|
|
|
|
|
LPBYTE InternalSCS_CHANGEATTR(
|
|
HIMC hImc,
|
|
LPCVOID lpCompRead,
|
|
DWORD dwCompReadLen,
|
|
DWORD dwIndex,
|
|
LPVOID *lplpNewCompRead,
|
|
DWORD *lpdwNewCompReadLen,
|
|
BOOL fAnsi)
|
|
{
|
|
LPBYTE lpBufRet;
|
|
LPBYTE lpAttr, lpAttrA, lpAttrW;
|
|
DWORD dwBufLenA, dwBufLenW;
|
|
LPSTR lpStrBufA, lpBufA;
|
|
LPWSTR lpStrBufW, lpBufW;
|
|
CHAR c;
|
|
WCHAR wc;
|
|
ULONG MultiByteSize;
|
|
|
|
if (lpCompRead == NULL || dwCompReadLen == 0)
|
|
return NULL;
|
|
|
|
if (fAnsi) {
|
|
|
|
dwBufLenA = ImmGetCompositionStringA(hImc, dwIndex, NULL, 0);
|
|
|
|
lpStrBufA = ImmLocalAlloc(0, dwBufLenA);
|
|
if (lpStrBufA == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure.");
|
|
return NULL;
|
|
}
|
|
|
|
ImmGetCompositionStringA(hImc, dwIndex, lpStrBufA, dwBufLenA);
|
|
|
|
lpBufRet = ImmLocalAlloc(0, dwBufLenA);
|
|
if (lpBufRet == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure.");
|
|
ImmLocalFree(lpStrBufA);
|
|
return NULL;
|
|
}
|
|
|
|
lpBufA = lpStrBufA;
|
|
lpAttrA = (LPBYTE)lpCompRead;
|
|
lpAttr = lpBufRet;
|
|
|
|
while (dwBufLenA != 0 && (c=*lpBufA++) != 0) {
|
|
if (IsDBCSLeadByte(c)) {
|
|
if (dwBufLenA >= 2) {
|
|
*lpAttr++ = *lpAttrA++;
|
|
dwBufLenA--;
|
|
} else {
|
|
*lpAttr++ = *lpAttrA;
|
|
}
|
|
lpBufA++;
|
|
} else {
|
|
*lpAttr++ = *lpAttrA;
|
|
}
|
|
lpAttrA++;
|
|
dwBufLenA--;
|
|
}
|
|
|
|
ImmLocalFree(lpStrBufA);
|
|
}
|
|
else {
|
|
|
|
dwBufLenW = ImmGetCompositionStringW(hImc, dwIndex, NULL, 0);
|
|
|
|
lpStrBufW = ImmLocalAlloc(0, dwBufLenW);
|
|
if (lpStrBufW == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure.");
|
|
return NULL;
|
|
}
|
|
|
|
ImmGetCompositionStringW(hImc, dwIndex, lpStrBufW, dwBufLenW);
|
|
|
|
lpBufRet = ImmLocalAlloc(0, dwBufLenW);
|
|
if (lpBufRet == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure.");
|
|
ImmLocalFree(lpStrBufW);
|
|
return NULL;
|
|
}
|
|
|
|
lpBufW = lpStrBufW;
|
|
lpAttrW = (LPBYTE)lpCompRead;
|
|
lpAttr = lpBufRet;
|
|
|
|
while (dwBufLenW != 0 && (wc=*lpBufW++) != L'\0') {
|
|
RtlUnicodeToMultiByteSize(&MultiByteSize, &wc, sizeof(WCHAR));
|
|
if (MultiByteSize == 2) {
|
|
*lpAttr++ = *lpAttrW;
|
|
}
|
|
*lpAttr++ = *lpAttrW++;
|
|
dwBufLenW -= sizeof(WCHAR);
|
|
}
|
|
|
|
ImmLocalFree(lpStrBufW);
|
|
}
|
|
|
|
*lplpNewCompRead = lpBufRet;
|
|
*lpdwNewCompReadLen = (DWORD)(lpAttr - (PBYTE)lpBufRet);
|
|
|
|
return lpBufRet;
|
|
}
|
|
|
|
|
|
LPBYTE InternalSCS_CHANGECLAUSE(
|
|
HIMC hImc,
|
|
LPCVOID lpCompRead,
|
|
DWORD dwCompReadLen,
|
|
DWORD dwIndex,
|
|
LPDWORD *lplpNewCompRead,
|
|
DWORD *lpdwNewCompReadLen,
|
|
BOOL fAnsi)
|
|
{
|
|
LPDWORD lpdw, lpNewdw, lpBufRet;
|
|
DWORD dwBufLenA, dwBufLenW;
|
|
LPSTR lpStrBufA;
|
|
LPWSTR lpStrBufW;
|
|
INT i;
|
|
|
|
if (lpCompRead == NULL || dwCompReadLen == 0)
|
|
return NULL;
|
|
|
|
lpdw = (LPDWORD)lpCompRead;
|
|
|
|
lpBufRet = ImmLocalAlloc(0, dwCompReadLen);
|
|
if (lpBufRet == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalSCS_CHANGECLAUSE: memory failure.");
|
|
return NULL;
|
|
}
|
|
|
|
if (fAnsi) {
|
|
|
|
dwBufLenA = ImmGetCompositionStringA(hImc, dwIndex, NULL, 0);
|
|
|
|
lpStrBufA = ImmLocalAlloc(0, dwBufLenA);
|
|
if (lpStrBufA == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalSCS_CHANGECLAUSE: memory failure.");
|
|
ImmLocalFree(lpBufRet);
|
|
return NULL;
|
|
}
|
|
|
|
ImmGetCompositionStringA(hImc, dwIndex, lpStrBufA, dwBufLenA);
|
|
}
|
|
else {
|
|
|
|
dwBufLenW = ImmGetCompositionStringW(hImc, dwIndex, NULL, 0);
|
|
|
|
lpStrBufW = ImmLocalAlloc(0, dwBufLenW);
|
|
if (lpStrBufW == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalSCS_CHANGECLAUSE: memory failure.");
|
|
ImmLocalFree(lpBufRet);
|
|
return NULL;
|
|
}
|
|
|
|
ImmGetCompositionStringW(hImc, dwIndex, lpStrBufW, dwBufLenW);
|
|
}
|
|
|
|
*lplpNewCompRead = lpNewdw = lpBufRet;
|
|
*lpdwNewCompReadLen = dwCompReadLen;
|
|
|
|
for (i = 0; i < (INT)(dwCompReadLen / sizeof(DWORD)); i++) {
|
|
*lpNewdw++ = fAnsi ? CalcCharacterPositionAtoW(*lpdw++, lpStrBufA)
|
|
: CalcCharacterPositionWtoA(*lpdw++, lpStrBufW);
|
|
}
|
|
|
|
return (LPBYTE)lpBufRet;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmSetCompositionStringWorker
|
|
*
|
|
* Worker function of ImmSetCompositionStringA/ImmSetCompositionStringW
|
|
*
|
|
* History:
|
|
* 28-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL ImmSetCompositionStringWorker(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPCVOID lpComp,
|
|
DWORD dwCompLen,
|
|
LPCVOID lpRead,
|
|
DWORD dwReadLen,
|
|
BOOL fAnsi)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
PCOMPOSITIONSTRING pCompStr;
|
|
DWORD dwThreadId;
|
|
PIMEDPI pImeDpi;
|
|
LPBYTE lpCompBuf, lpReadBuf;
|
|
LPBYTE lpNewComp, lpNewRead;
|
|
DWORD dwNewCompLen, dwNewReadLen;
|
|
BOOL fRet = FALSE;
|
|
|
|
dwThreadId = GetInputContextThread(hImc);
|
|
if (dwThreadId == 0) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmSetCompositionString: GetInputContextThread(%lx) failed.", hImc);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
pImeDpi = ImmLockImeDpi(GetKeyboardLayout(dwThreadId));
|
|
if (pImeDpi == NULL)
|
|
return FALSE;
|
|
|
|
lpCompBuf = lpReadBuf = NULL;
|
|
|
|
/*
|
|
* Check if we need ANSI/Unicode conversion
|
|
*/
|
|
if (( fAnsi && !(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)) ||
|
|
(!fAnsi && (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))) {
|
|
/*
|
|
* No A/W conversion needed.
|
|
*/
|
|
goto start_scs;
|
|
}
|
|
|
|
switch (dwIndex) {
|
|
case SCS_SETSTR:
|
|
if ( lpComp &&
|
|
(lpCompBuf = InternalSCS_SETSTR(lpComp, dwCompLen,
|
|
&lpNewComp, &dwNewCompLen, fAnsi)) == NULL)
|
|
goto end_scs;
|
|
if ( lpRead &&
|
|
(lpReadBuf = InternalSCS_SETSTR(lpRead, dwReadLen,
|
|
&lpNewRead, &dwNewReadLen, fAnsi)) == NULL)
|
|
goto end_scs;
|
|
break;
|
|
|
|
case SCS_CHANGEATTR:
|
|
if ( lpComp &&
|
|
(lpCompBuf = InternalSCS_CHANGEATTR(
|
|
hImc, lpComp, dwCompLen, GCS_COMPSTR,
|
|
&lpNewComp, &dwNewCompLen, fAnsi)) == NULL)
|
|
goto end_scs;
|
|
if ( lpRead &&
|
|
(lpReadBuf = InternalSCS_CHANGEATTR(
|
|
hImc, lpRead, dwReadLen, GCS_COMPREADSTR,
|
|
&lpNewRead, &dwNewReadLen, fAnsi)) == NULL)
|
|
goto end_scs;
|
|
break;
|
|
|
|
case SCS_CHANGECLAUSE:
|
|
if ( lpComp &&
|
|
(lpCompBuf = InternalSCS_CHANGECLAUSE(
|
|
hImc, lpComp, dwCompLen, GCS_COMPSTR,
|
|
(LPDWORD *)&lpNewComp, &dwNewCompLen, fAnsi)) == NULL)
|
|
goto end_scs;
|
|
if ( lpRead &&
|
|
(lpReadBuf = InternalSCS_CHANGECLAUSE(
|
|
hImc, lpRead, dwReadLen, GCS_COMPREADSTR,
|
|
(LPDWORD *)&lpNewRead, &dwNewReadLen, fAnsi)) == NULL)
|
|
goto end_scs;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (lpCompBuf != NULL) {
|
|
lpComp = lpNewComp;
|
|
dwCompLen = dwNewCompLen;
|
|
}
|
|
|
|
if (lpReadBuf != NULL) {
|
|
lpRead = lpNewRead;
|
|
dwReadLen = dwNewReadLen;
|
|
}
|
|
|
|
start_scs:
|
|
|
|
if (CompositionString(hImc, &pInputContext, &pCompStr) <= 0)
|
|
goto end_scs;
|
|
|
|
switch (dwIndex)
|
|
{
|
|
case SCS_SETSTR:
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
case SCS_CHANGEATTR:
|
|
if ( lpComp &&
|
|
!CheckAttribute((LPBYTE)lpComp, dwCompLen,
|
|
(LPBYTE)((LPBYTE)pCompStr + pCompStr->dwCompAttrOffset),
|
|
pCompStr->dwCompAttrLen,
|
|
(LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompClauseOffset),
|
|
pCompStr->dwCompClauseLen)) break;
|
|
|
|
if ( lpRead &&
|
|
!CheckAttribute((LPBYTE)lpRead, dwReadLen,
|
|
(LPBYTE)((LPBYTE)pCompStr + pCompStr->dwCompReadAttrOffset),
|
|
pCompStr->dwCompReadAttrLen,
|
|
(LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompReadClauseOffset),
|
|
pCompStr->dwCompReadClauseLen)) break;
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
case SCS_CHANGECLAUSE:
|
|
if ( lpComp &&
|
|
!CheckClause((LPDWORD)lpComp, dwCompLen,
|
|
(LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompClauseOffset),
|
|
pCompStr->dwCompClauseLen)) break;
|
|
if ( lpRead &&
|
|
!CheckClause((LPDWORD)lpRead, dwReadLen,
|
|
(LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompReadClauseOffset),
|
|
pCompStr->dwCompReadClauseLen)) break;
|
|
fRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
ImmUnlockIMCC(pInputContext->hCompStr);
|
|
ImmUnlockIMC(hImc);
|
|
|
|
end_scs:
|
|
|
|
if (fRet) {
|
|
fRet = (*pImeDpi->pfn.ImeSetCompositionString)(hImc, dwIndex,
|
|
lpComp, dwCompLen, lpRead, dwReadLen);
|
|
}
|
|
|
|
if (lpCompBuf != NULL)
|
|
ImmLocalFree(lpCompBuf);
|
|
if (lpReadBuf != NULL)
|
|
ImmLocalFree(lpReadBuf);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return (fRet);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCandidateListCountA
|
|
*
|
|
* Query the byte count and list count to receive all candidate list.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD WINAPI ImmGetCandidateListCountA(
|
|
HIMC hImc,
|
|
LPDWORD lpdwListCount) // the buffer pointer for list count
|
|
{
|
|
return ImmGetCandidateListCountWorker(hImc, lpdwListCount, TRUE);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCandidateListCountW
|
|
*
|
|
* Query the byte count and list count to receive all candidate list.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD WINAPI ImmGetCandidateListCountW(
|
|
HIMC hImc,
|
|
LPDWORD lpdwListCount) // the buffer pointer for list count
|
|
{
|
|
return ImmGetCandidateListCountWorker(hImc, lpdwListCount, FALSE);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCandidateListCountWorker
|
|
*
|
|
* Worker function of ImmGetCandidateListCountA/ImmGetCandidateListCountW.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD ImmGetCandidateListCountWorker(
|
|
HIMC hImc,
|
|
LPDWORD lpdwListCount,
|
|
BOOL fAnsi)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
LPCANDIDATEINFO lpCandInfo;
|
|
DWORD dwRet = 0;
|
|
INT i;
|
|
|
|
if (lpdwListCount) {
|
|
*lpdwListCount = 0;
|
|
} else {
|
|
RIPMSG0(RIP_WARNING, "ImmGetCandidateListCount: NULL lpdwListCount.");
|
|
return dwRet;
|
|
}
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCandidateListCount: Invalid hImc %lx.", hImc);
|
|
goto GetCandListCntExit;
|
|
}
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (pInputContext == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCandidateListCount: Lock hImc %lx failed.", hImc);
|
|
goto GetCandListCntUnlockClientImc;
|
|
}
|
|
|
|
lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(pInputContext->hCandInfo);
|
|
if (!lpCandInfo) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmGetCandidateListCount: Lock hCandInfo %x failed.",
|
|
pInputContext->hCandInfo);
|
|
goto GetCandListCntUnlockIMC;
|
|
}
|
|
|
|
if (lpCandInfo->dwSize < sizeof(CANDIDATEINFO)) {
|
|
RIPMSG0(RIP_WARNING, "ImmGetCandidateListCount: no candidate list.");
|
|
goto GetCandListCntUnlockIMC;
|
|
}
|
|
|
|
*lpdwListCount = lpCandInfo->dwCount;
|
|
|
|
if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) {
|
|
LPCANDIDATELIST lpCandListW;
|
|
|
|
dwRet = DWORD_ALIGN(sizeof(CANDIDATEINFO))
|
|
+ DWORD_ALIGN(lpCandInfo->dwPrivateSize);
|
|
|
|
for (i = 0; i < (INT)lpCandInfo->dwCount; i++) {
|
|
lpCandListW = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[i]);
|
|
dwRet += InternalGetCandidateListWtoA(lpCandListW, NULL, 0);
|
|
}
|
|
}
|
|
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
|
|
LPCANDIDATELIST lpCandListA;
|
|
|
|
dwRet = DWORD_ALIGN(sizeof(CANDIDATEINFO))
|
|
+ DWORD_ALIGN(lpCandInfo->dwPrivateSize);
|
|
|
|
for (i = 0; i < (INT)lpCandInfo->dwCount; i++) {
|
|
lpCandListA = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[i]);
|
|
dwRet += InternalGetCandidateListAtoW(lpCandListA, NULL, 0);
|
|
}
|
|
}
|
|
else {
|
|
dwRet = lpCandInfo->dwSize;
|
|
}
|
|
|
|
ImmUnlockIMCC(pInputContext->hCandInfo);
|
|
|
|
GetCandListCntUnlockIMC:
|
|
ImmUnlockIMC(hImc);
|
|
|
|
GetCandListCntUnlockClientImc:
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
GetCandListCntExit:
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCandidateListA
|
|
*
|
|
* Gets the candidate list information specified by dwIndex.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD WINAPI ImmGetCandidateListA(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPCANDIDATELIST lpCandList,
|
|
DWORD dwBufLen)
|
|
{
|
|
return ImmGetCandidateListWorker(hImc, dwIndex,
|
|
lpCandList, dwBufLen, TRUE);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCandidateListW
|
|
*
|
|
* Gets the candidate list information specified by dwIndex.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD WINAPI ImmGetCandidateListW(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPCANDIDATELIST lpCandList,
|
|
DWORD dwBufLen)
|
|
{
|
|
return ImmGetCandidateListWorker(hImc, dwIndex,
|
|
lpCandList, dwBufLen, FALSE);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCandidateListWorker
|
|
*
|
|
* Worker function of ImmGetCandidateListA/ImmGetCandidateListW.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD ImmGetCandidateListWorker(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPCANDIDATELIST lpCandList,
|
|
DWORD dwBufLen,
|
|
BOOL fAnsi)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
LPCANDIDATEINFO lpCandInfo;
|
|
LPCANDIDATELIST lpCandListTemp;
|
|
DWORD dwBufLenTemp;
|
|
DWORD dwRet = 0;
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCandidateList: Invalid hImc %lx.", hImc);
|
|
goto GetCandListExit;
|
|
}
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (pInputContext == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCandidateList: Lock hImc %lx failed.", hImc);
|
|
goto GetCandListUnlockClientImc;
|
|
}
|
|
|
|
lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(pInputContext->hCandInfo);
|
|
if (!lpCandInfo) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCandidateList: Lock hCandInfo %x failed",
|
|
pInputContext->hCandInfo);
|
|
goto GetCandListUnlockIMC;
|
|
}
|
|
|
|
if (lpCandInfo->dwSize < sizeof(CANDIDATEINFO)) {
|
|
RIPMSG0(RIP_WARNING, "ImmGetCandidateList: no candidate list.");
|
|
goto GetCandListUnlockIMCC;
|
|
}
|
|
|
|
/*
|
|
* invalid access
|
|
*/
|
|
if (dwIndex >= lpCandInfo->dwCount) {
|
|
RIPMSG0(RIP_WARNING, "ImmGetCandidateList: dwIndex >= lpCandInfo->dwCount.");
|
|
goto GetCandListUnlockIMCC;
|
|
}
|
|
|
|
lpCandListTemp = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[dwIndex]);
|
|
|
|
if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) {
|
|
/*
|
|
* ANSI Caller with an Unicode hImc.
|
|
*/
|
|
dwBufLenTemp = InternalGetCandidateListWtoA(lpCandListTemp, NULL, 0);
|
|
}
|
|
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
|
|
/*
|
|
* Unicode Caller with an ANSI hImc.
|
|
*/
|
|
dwBufLenTemp = InternalGetCandidateListAtoW(lpCandListTemp, NULL, 0);
|
|
}
|
|
else {
|
|
/*
|
|
* No conversion required.
|
|
*/
|
|
dwBufLenTemp = lpCandListTemp->dwSize;
|
|
}
|
|
|
|
/*
|
|
* Query buffer size or early exit on error
|
|
*/
|
|
if (dwBufLen == 0 || dwBufLenTemp == 0) {
|
|
dwRet = dwBufLenTemp;
|
|
}
|
|
else if (!lpCandList) {
|
|
RIPMSG0(RIP_WARNING, "ImmGetCandidateList: Null lpCandList.");
|
|
}
|
|
else if (dwBufLen < dwBufLenTemp) {
|
|
RIPMSG2(RIP_WARNING, "ImmGetCandidateList: dwBufLen = %d too small, require = %d.",
|
|
dwBufLen, dwBufLenTemp);
|
|
} else {
|
|
if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) {
|
|
dwRet = InternalGetCandidateListWtoA(lpCandListTemp, lpCandList, dwBufLenTemp);
|
|
}
|
|
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
|
|
dwRet = InternalGetCandidateListAtoW(lpCandListTemp, lpCandList, dwBufLenTemp);
|
|
}
|
|
else {
|
|
RtlCopyMemory((LPBYTE)lpCandList, (LPBYTE)lpCandListTemp, dwBufLenTemp);
|
|
dwRet = dwBufLenTemp;
|
|
}
|
|
}
|
|
|
|
GetCandListUnlockIMCC:
|
|
ImmUnlockIMCC(pInputContext->hCandInfo);
|
|
|
|
GetCandListUnlockIMC:
|
|
ImmUnlockIMC(hImc);
|
|
|
|
GetCandListUnlockClientImc:
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
GetCandListExit:
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetGuideLineA
|
|
*
|
|
* Gets the guide line information reported by the IME.
|
|
*
|
|
* History:
|
|
* 26-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD WINAPI ImmGetGuideLineA(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPSTR lpszBuf,
|
|
DWORD dwBufLen)
|
|
{
|
|
return ImmGetGuideLineWorker(hImc, dwIndex,
|
|
(LPBYTE)lpszBuf, dwBufLen, TRUE);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetGuideLineW
|
|
*
|
|
* Gets the guide line information reported by the IME.
|
|
*
|
|
* History:
|
|
* 26-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD WINAPI ImmGetGuideLineW(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPWSTR lpwszBuf,
|
|
DWORD dwBufLen)
|
|
{
|
|
return ImmGetGuideLineWorker(hImc, dwIndex,
|
|
(LPBYTE)lpwszBuf, dwBufLen, FALSE);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetGuideLineWorker
|
|
*
|
|
* Worker function of ImmGetGuideLineA/ImmGetGuideLineW.
|
|
*
|
|
* History:
|
|
* 26-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD ImmGetGuideLineWorker(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPBYTE lpBuf,
|
|
DWORD dwBufLen,
|
|
BOOL fAnsi)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
LPGUIDELINE lpGuideLine;
|
|
LPBYTE lpBufTemp;
|
|
DWORD dwRet = 0;
|
|
DWORD dwBufLenNeeded;
|
|
BOOL bUDC;
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetGuideLine: Invalid hImc %lx.", hImc);
|
|
goto GetGuideLineExit;
|
|
}
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (pInputContext == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetGuideLine: Lock hImc %lx failed.", hImc);
|
|
goto GetGuideLineUnlockClientImc;
|
|
}
|
|
|
|
lpGuideLine = (LPGUIDELINE)ImmLockIMCC(pInputContext->hGuideLine);
|
|
if (!lpGuideLine) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetGuideLine: Lock hGuideLine %lx failed.",
|
|
pInputContext->hGuideLine);
|
|
goto GetGuideLineUnlockIMC;
|
|
}
|
|
|
|
switch (dwIndex) {
|
|
case GGL_LEVEL:
|
|
dwRet = lpGuideLine->dwLevel;
|
|
break;
|
|
|
|
case GGL_INDEX:
|
|
dwRet = lpGuideLine->dwIndex;
|
|
break;
|
|
|
|
case GGL_STRING:
|
|
|
|
lpBufTemp = (LPBYTE)lpGuideLine + lpGuideLine->dwStrOffset;
|
|
|
|
/*
|
|
* Calculate the required buffer length.
|
|
*/
|
|
if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) {
|
|
dwBufLenNeeded = WideCharToMultiByte(CP_ACP,
|
|
(DWORD)0,
|
|
(LPWSTR)lpBufTemp,
|
|
(INT)lpGuideLine->dwStrLen,
|
|
(LPSTR)NULL,
|
|
(INT)0,
|
|
(LPSTR)NULL,
|
|
(LPBOOL)&bUDC);
|
|
}
|
|
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
|
|
dwBufLenNeeded = MultiByteToWideChar(CP_ACP,
|
|
(DWORD)MB_PRECOMPOSED,
|
|
(LPSTR)lpBufTemp,
|
|
(INT)lpGuideLine->dwStrLen,
|
|
(LPWSTR)NULL,
|
|
(INT)0);
|
|
dwBufLenNeeded *= sizeof(WCHAR);
|
|
}
|
|
else {
|
|
dwBufLenNeeded = lpGuideLine->dwStrLen;
|
|
/*
|
|
* The dwStrLen records the strlen and not the byte count.
|
|
*/
|
|
if (TestICF(pClientImc, IMCF_UNICODE))
|
|
dwBufLenNeeded *= sizeof(WCHAR);
|
|
}
|
|
|
|
/*
|
|
* Query GuideLine string size only or early exit on error
|
|
*/
|
|
if (dwBufLen == 0 || dwBufLenNeeded == 0) {
|
|
dwRet = dwBufLenNeeded;
|
|
goto GetGuideLineUnlockIMCC;
|
|
}
|
|
|
|
if (lpBuf == NULL || dwBufLen < dwBufLenNeeded)
|
|
goto GetGuideLineUnlockIMCC;
|
|
|
|
if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) {
|
|
dwRet = WideCharToMultiByte(CP_ACP,
|
|
(DWORD)0,
|
|
(LPWSTR)lpBufTemp,
|
|
(INT)lpGuideLine->dwStrLen,
|
|
(LPSTR)lpBuf,
|
|
(INT)dwBufLen,
|
|
(LPSTR)NULL,
|
|
(LPBOOL)&bUDC);
|
|
}
|
|
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
|
|
dwRet = MultiByteToWideChar(CP_ACP,
|
|
(DWORD)MB_PRECOMPOSED,
|
|
(LPSTR)lpBufTemp,
|
|
(INT)lpGuideLine->dwStrLen,
|
|
(LPWSTR)lpBuf,
|
|
(INT)dwBufLen/sizeof(WCHAR));
|
|
dwRet *= sizeof(WCHAR);
|
|
}
|
|
else {
|
|
RtlCopyMemory(lpBuf, lpBufTemp, dwBufLenNeeded);
|
|
dwRet = dwBufLenNeeded;
|
|
}
|
|
|
|
break;
|
|
|
|
case GGL_PRIVATE:
|
|
|
|
lpBufTemp = (LPBYTE)lpGuideLine + lpGuideLine->dwPrivateOffset;
|
|
|
|
/*
|
|
* The dwPrivateOffset is an offset to a CANDIDATELIST when
|
|
* lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION. Do conversion
|
|
* for this case only.
|
|
*/
|
|
if (fAnsi && TestICF(pClientImc, IMCF_UNICODE) &&
|
|
lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) {
|
|
dwBufLenNeeded = InternalGetCandidateListWtoA(
|
|
(LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)NULL, 0);
|
|
}
|
|
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE) &&
|
|
lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) {
|
|
dwBufLenNeeded = InternalGetCandidateListAtoW(
|
|
(LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)NULL, 0);
|
|
}
|
|
else {
|
|
dwBufLenNeeded = lpGuideLine->dwPrivateSize;
|
|
}
|
|
|
|
/*
|
|
* Query dwPrivateSize size only or early exit on error
|
|
*/
|
|
if (dwBufLen == 0 || dwBufLenNeeded == 0) {
|
|
dwRet = dwBufLenNeeded;
|
|
goto GetGuideLineUnlockIMCC;
|
|
}
|
|
|
|
if (lpBuf == NULL || dwBufLen < dwBufLenNeeded)
|
|
goto GetGuideLineUnlockIMCC;
|
|
|
|
if (fAnsi && TestICF(pClientImc, IMCF_UNICODE) &&
|
|
lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) {
|
|
dwRet = InternalGetCandidateListWtoA(
|
|
(LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)lpBuf, dwBufLenNeeded);
|
|
}
|
|
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE) &&
|
|
lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) {
|
|
dwRet = InternalGetCandidateListAtoW(
|
|
(LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)lpBuf, dwBufLenNeeded);
|
|
}
|
|
else {
|
|
RtlCopyMemory(lpBuf, lpBufTemp, dwBufLenNeeded);
|
|
dwRet = dwBufLenNeeded;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
GetGuideLineUnlockIMCC:
|
|
ImmUnlockIMCC(pInputContext->hGuideLine);
|
|
|
|
GetGuideLineUnlockIMC:
|
|
ImmUnlockIMC(hImc);
|
|
|
|
GetGuideLineUnlockClientImc:
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
GetGuideLineExit:
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetConversionStatus
|
|
*
|
|
* Gets current conversion status.
|
|
*
|
|
* History:
|
|
* 26-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmGetConversionStatus( // Get the conversion status
|
|
HIMC hImc,
|
|
LPDWORD lpfdwConversion,
|
|
LPDWORD lpfdwSentence)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (pInputContext == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetConversionStatus: Lock hImc %lx failed", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
*lpfdwConversion = pInputContext->fdwConversion;
|
|
*lpfdwSentence = pInputContext->fdwSentence;
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmSetConversionStatus
|
|
*
|
|
* Sets current conversion status.
|
|
*
|
|
* History:
|
|
* 26-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmSetConversionStatus(
|
|
HIMC hImc,
|
|
DWORD fdwConversion,
|
|
DWORD fdwSentence)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
DWORD fdwOldConversion;
|
|
DWORD fdwOldSentence;
|
|
BOOL fConvModeChg;
|
|
BOOL fSentenceChg;
|
|
HWND hWnd;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (pInputContext == NULL) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmSetConversionStatus: Lock hImc %lx failed", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
fConvModeChg = FALSE;
|
|
fSentenceChg = FALSE;
|
|
|
|
if (pInputContext->fdwConversion != fdwConversion) {
|
|
if ((fdwConversion & IME_CMODE_LANGUAGE) == IME_CMODE_KATAKANA) {
|
|
RIPMSG0(RIP_WARNING, "ImmSetConversionStatus: wrong fdwConversion");
|
|
}
|
|
fdwOldConversion = pInputContext->fdwConversion;
|
|
pInputContext->fdwConversion = fdwConversion;
|
|
fConvModeChg = TRUE;
|
|
}
|
|
|
|
if (pInputContext->fdwSentence != fdwSentence) {
|
|
fdwOldSentence = pInputContext->fdwSentence;
|
|
pInputContext->fdwSentence = fdwSentence;
|
|
fSentenceChg = TRUE;
|
|
}
|
|
|
|
hWnd = pInputContext->hWnd;
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
#ifdef LATER
|
|
// Do uNumLangVKey and uNumVKey checking later.
|
|
#endif
|
|
|
|
/*
|
|
* inform IME and UI about the conversion mode changes.
|
|
*/
|
|
if (fConvModeChg) {
|
|
MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, fdwOldConversion,
|
|
IMC_SETCONVERSIONMODE, IMN_SETCONVERSIONMODE, 0L);
|
|
}
|
|
|
|
/*
|
|
* inform IME and UI about the sentence mode changes.
|
|
*/
|
|
if (fSentenceChg) {
|
|
MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, fdwOldSentence,
|
|
IMC_SETSENTENCEMODE, IMN_SETSENTENCEMODE, 0L);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetOpenStatus
|
|
*
|
|
* Gets the open or close status of the IME.
|
|
*
|
|
* History:
|
|
* 26-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmGetOpenStatus(
|
|
HIMC hImc)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
BOOL fOpen;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetOpenStatus: Lock hImc %lx failed", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
fOpen = pInputContext->fOpen;
|
|
ImmUnlockIMC(hImc);
|
|
|
|
return (fOpen);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmSetOpenStatus
|
|
*
|
|
* Opens or closes the IME.
|
|
*
|
|
* History:
|
|
* 26-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmSetOpenStatus(
|
|
HIMC hImc,
|
|
BOOL fOpen)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
HWND hWnd;
|
|
BOOL fOpenChg = FALSE;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmSetOpenStatus: Lock hImc %lx failed", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pInputContext->fOpen != fOpen) {
|
|
fOpenChg = TRUE;
|
|
pInputContext->fOpen = fOpen;
|
|
}
|
|
|
|
hWnd = (HWND)pInputContext->hWnd;
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
/*
|
|
* inform IME and UI about the conversion mode changes.
|
|
*/
|
|
if (fOpenChg) {
|
|
MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, (DWORD)0,
|
|
IMC_SETOPENSTATUS, IMN_SETOPENSTATUS, 0L);
|
|
|
|
if (hWnd)
|
|
SendMessage(hWnd, WM_IME_SYSTEM, IMS_SETOPENSTATUS, 0L);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCompositionFontA
|
|
*
|
|
* Opens or closes the IME.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmGetCompositionFontA(
|
|
HIMC hImc,
|
|
LPLOGFONTA lpLogFontA)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
LOGFONTW LogFontW;
|
|
BOOL fUnicode, fRet;
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCompositionFontA: Invalid hImc %lx.", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
fUnicode = TestICF(pClientImc, IMCF_UNICODE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (pInputContext == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCompositionFontA: Lock hImc %lx failed.", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
if (fUnicode) {
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
if (ImmGetCompositionFontW(hImc, &LogFontW)) {
|
|
LFontWtoLFontA(&LogFontW, lpLogFontA);
|
|
return (TRUE);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if ((pInputContext->fdwInit & INIT_LOGFONT) == INIT_LOGFONT) {
|
|
*lpLogFontA = pInputContext->lfFont.A;
|
|
fRet = TRUE;
|
|
}
|
|
else {
|
|
fRet = FALSE;
|
|
}
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCompositionFontW
|
|
*
|
|
* Opens or closes the IME.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmGetCompositionFontW(
|
|
HIMC hImc,
|
|
LPLOGFONTW lpLogFontW)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
LOGFONTA LogFontA;
|
|
BOOL fUnicode, fRet;
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCompositionFontW: Invalid hImc %lx.", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
fUnicode = TestICF(pClientImc, IMCF_UNICODE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCompositionFontW: Lock hImc %lx failed.", hImc);
|
|
return (FALSE);
|
|
}
|
|
|
|
if (!fUnicode) {
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
if (ImmGetCompositionFontA(hImc, &LogFontA)) {
|
|
LFontAtoLFontW(&LogFontA, lpLogFontW);
|
|
return (TRUE);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if ((pInputContext->fdwInit & INIT_LOGFONT) == INIT_LOGFONT) {
|
|
*lpLogFontW = pInputContext->lfFont.W;
|
|
fRet = TRUE;
|
|
}
|
|
else {
|
|
fRet = FALSE;
|
|
}
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL WINAPI ImmSetCompositionFontA(
|
|
HIMC hImc,
|
|
LPLOGFONTA lpLogFontA)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
LOGFONTW LogFontW;
|
|
HWND hWnd;
|
|
BOOL fUnicode;
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmSetCompositionFontA: Invalid hImc %lx.", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
fUnicode = TestICF(pClientImc, IMCF_UNICODE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmSetCompositionFontA: Lock hImc %lx failed.", hImc);
|
|
return (FALSE);
|
|
}
|
|
|
|
if (fUnicode) {
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
LFontAtoLFontW(lpLogFontA, &LogFontW);
|
|
|
|
return ImmSetCompositionFontW(hImc, &LogFontW);
|
|
}
|
|
|
|
pInputContext->lfFont.A = *lpLogFontA;
|
|
pInputContext->fdwInit |= INIT_LOGFONT;
|
|
|
|
hWnd = pInputContext->hWnd;
|
|
ImmUnlockIMC(hImc);
|
|
|
|
/*
|
|
* inform IME and UI about the change of composition font.
|
|
*/
|
|
MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L,
|
|
IMC_SETCOMPOSITIONFONT, IMN_SETCOMPOSITIONFONT, 0L);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL WINAPI ImmSetCompositionFontW(
|
|
HIMC hImc,
|
|
LPLOGFONTW lpLogFontW)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
LOGFONTA LogFontA;
|
|
HWND hWnd;
|
|
BOOL fUnicode;
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL) {
|
|
RIPMSG1(RIP_WARNING, "ImmSetCompositionFontW: Invalid hImc %lx.", hImc);
|
|
return (FALSE);
|
|
}
|
|
|
|
fUnicode = TestICF(pClientImc, IMCF_UNICODE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmSetCompositionFontW: Lock hImc %lx failed.", hImc);
|
|
return (FALSE);
|
|
}
|
|
|
|
if (!fUnicode) {
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
LFontWtoLFontA(lpLogFontW, &LogFontA);
|
|
|
|
return ImmSetCompositionFontA(hImc, &LogFontA);
|
|
}
|
|
|
|
pInputContext->lfFont.W = *lpLogFontW;
|
|
pInputContext->fdwInit |= INIT_LOGFONT;
|
|
|
|
hWnd = pInputContext->hWnd;
|
|
ImmUnlockIMC(hImc);
|
|
|
|
/*
|
|
* inform IME and UI about the change of composition font.
|
|
*/
|
|
MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L,
|
|
IMC_SETCOMPOSITIONFONT, IMN_SETCOMPOSITIONFONT, 0L);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetConversionListA
|
|
*
|
|
* Obtains the list of FE character or word from one character or word.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD WINAPI ImmGetConversionListA(
|
|
HKL hKL,
|
|
HIMC hImc,
|
|
LPCSTR lpszSrc,
|
|
LPCANDIDATELIST lpCandListA,
|
|
DWORD dwBufLen,
|
|
UINT uFlag)
|
|
{
|
|
PIMEDPI pImeDpi;
|
|
DWORD dwRet;
|
|
LPWSTR lpwszSrc;
|
|
DWORD dwBufTemp;
|
|
LPCANDIDATELIST lpCandListW;
|
|
INT i;
|
|
|
|
pImeDpi = FindOrLoadImeDpi(hKL);
|
|
|
|
if (pImeDpi == NULL) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmGetConversionListA: cannot find DPI entry for hkl=%lx", hKL);
|
|
return (0);
|
|
}
|
|
|
|
if ((!pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)) {
|
|
/*
|
|
* This is an ANSI call to an ANSI IME.
|
|
*/
|
|
dwRet = (*pImeDpi->pfn.ImeConversionList.a)(hImc, lpszSrc,
|
|
lpCandListA, dwBufLen, uFlag);
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
return dwRet;
|
|
}
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
/*
|
|
* This is an ANSI call to an Unicode IME.
|
|
*/
|
|
if (lpszSrc != NULL) {
|
|
|
|
dwBufTemp = (strlen(lpszSrc) + 1) * sizeof(WCHAR);
|
|
|
|
lpwszSrc = ImmLocalAlloc(0, dwBufTemp);
|
|
if (lpwszSrc == NULL)
|
|
return (0);
|
|
|
|
i = MultiByteToWideChar(CP_ACP,
|
|
(DWORD)MB_PRECOMPOSED,
|
|
(LPSTR)lpszSrc, // src
|
|
(INT)strlen(lpszSrc),
|
|
(LPWSTR)lpwszSrc, // dest
|
|
(INT)dwBufTemp/sizeof(WCHAR));
|
|
|
|
lpwszSrc[i] = '\0';
|
|
}
|
|
else {
|
|
lpwszSrc = NULL;
|
|
}
|
|
|
|
/*
|
|
* Query the CandidateListW size required.
|
|
*/
|
|
dwBufTemp = ImmGetConversionListW(hKL, hImc, lpwszSrc, NULL, 0, uFlag);
|
|
|
|
if (dwBufTemp == 0 || (lpCandListW = ImmLocalAlloc(0, dwBufTemp)) == NULL) {
|
|
if (lpwszSrc)
|
|
ImmLocalFree(lpwszSrc);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Now get the actual CandidateListW.
|
|
*/
|
|
dwBufTemp = ImmGetConversionListW(hKL, hImc, lpwszSrc,
|
|
lpCandListW, dwBufTemp, uFlag);
|
|
|
|
/*
|
|
* Query the CandidateListA size required.
|
|
*/
|
|
if (dwBufTemp != 0) {
|
|
dwBufTemp = InternalGetCandidateListWtoA(lpCandListW, NULL, 0);
|
|
}
|
|
|
|
if (dwBufLen == 0 || dwBufTemp == 0) {
|
|
/*
|
|
* Query required buffer size or error has happened.
|
|
*/
|
|
dwRet = dwBufTemp;
|
|
}
|
|
else if (dwBufLen < dwBufTemp) {
|
|
/*
|
|
* Not enough buffer area.
|
|
*/
|
|
dwRet = 0;
|
|
}
|
|
else {
|
|
/*
|
|
* Get the actual CandidateListA
|
|
*/
|
|
dwRet = InternalGetCandidateListWtoA(lpCandListW, lpCandListA, dwBufLen);
|
|
}
|
|
|
|
if (lpwszSrc)
|
|
ImmLocalFree(lpwszSrc);
|
|
ImmLocalFree(lpCandListW);
|
|
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetConversionListW
|
|
*
|
|
* Obtains the list of FE character or word from one character or word.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD WINAPI ImmGetConversionListW(
|
|
HKL hKL,
|
|
HIMC hImc,
|
|
LPCWSTR lpwszSrc,
|
|
LPCANDIDATELIST lpCandListW,
|
|
DWORD dwBufLen,
|
|
UINT uFlag)
|
|
{
|
|
PIMEDPI pImeDpi;
|
|
DWORD dwRet;
|
|
LPSTR lpszSrc;
|
|
DWORD dwBufTemp;
|
|
LPCANDIDATELIST lpCandListA;
|
|
BOOL bUDC;
|
|
INT i;
|
|
|
|
pImeDpi = FindOrLoadImeDpi(hKL);
|
|
|
|
if (pImeDpi == NULL) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmGetConversionListW: cannot find DPI entry for hkl=%lx", hKL);
|
|
return (0);
|
|
}
|
|
|
|
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) {
|
|
/*
|
|
* This is an Unicode call to an Unicode IME.
|
|
*/
|
|
dwRet = (*pImeDpi->pfn.ImeConversionList.w)(hImc, lpwszSrc,
|
|
lpCandListW, dwBufLen, uFlag);
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
return dwRet;
|
|
}
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
/*
|
|
* This is an Unicode call to an ANSI IME.
|
|
*/
|
|
if (lpwszSrc != NULL) {
|
|
|
|
dwBufTemp = (wcslen(lpwszSrc) + 1) * sizeof(WCHAR);
|
|
|
|
lpszSrc = ImmLocalAlloc(0, dwBufTemp);
|
|
if (lpszSrc == NULL)
|
|
return (0);
|
|
|
|
i = WideCharToMultiByte(CP_ACP,
|
|
(DWORD)0,
|
|
lpwszSrc,
|
|
(INT)wcslen(lpwszSrc),
|
|
(LPSTR)lpszSrc,
|
|
(INT)dwBufTemp,
|
|
(LPSTR)NULL,
|
|
(LPBOOL)&bUDC);
|
|
|
|
lpszSrc[i] = '\0';
|
|
}
|
|
else {
|
|
lpszSrc = NULL;
|
|
}
|
|
|
|
/*
|
|
* Query the CandidateListA size required.
|
|
*/
|
|
dwBufTemp = ImmGetConversionListA(hKL, hImc, lpszSrc, NULL, 0, uFlag);
|
|
|
|
if (dwBufTemp == 0 || (lpCandListA = ImmLocalAlloc(0, dwBufTemp)) == NULL) {
|
|
if (lpszSrc)
|
|
ImmLocalFree(lpszSrc);
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Now get the actual CandidateListA.
|
|
*/
|
|
dwBufTemp = ImmGetConversionListA(hKL, hImc, lpszSrc,
|
|
lpCandListA, dwBufTemp, uFlag);
|
|
|
|
/*
|
|
* Query the CandidateListW size required.
|
|
*/
|
|
if (dwBufTemp != 0) {
|
|
dwBufTemp = InternalGetCandidateListAtoW(lpCandListA, NULL, 0);
|
|
}
|
|
|
|
if (dwBufLen == 0 || dwBufTemp == 0) {
|
|
/*
|
|
* Query required buffer size or error has happened.
|
|
*/
|
|
dwRet = dwBufTemp;
|
|
}
|
|
else if (dwBufLen < dwBufTemp) {
|
|
/*
|
|
* Not enough buffer area.
|
|
*/
|
|
dwRet = 0;
|
|
}
|
|
else {
|
|
/*
|
|
* Get the actual CandidateListW
|
|
*/
|
|
dwRet = InternalGetCandidateListAtoW(lpCandListA, lpCandListW, dwBufLen);
|
|
}
|
|
|
|
if (lpszSrc)
|
|
ImmLocalFree(lpszSrc);
|
|
ImmLocalFree(lpCandListA);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetStatusWindowPos
|
|
*
|
|
* Gets the position, in screen coordinates, of the status window.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmGetStatusWindowPos(
|
|
HIMC hImc,
|
|
LPPOINT lpptPos)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
BOOL fStatusWndPosInited;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetStatusWindowPos: Lock hImc %lx failed", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
fStatusWndPosInited = ((pInputContext->fdwInit & INIT_STATUSWNDPOS) == INIT_STATUSWNDPOS);
|
|
ImmUnlockIMC(hImc);
|
|
|
|
if (fStatusWndPosInited) {
|
|
*lpptPos = pInputContext->ptStatusWndPos;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL WINAPI ImmSetStatusWindowPos(
|
|
HIMC hImc,
|
|
LPPOINT lpptPos)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
HWND hWnd;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmSetStatusWindowPos: Lock hImc %lx failed", hImc);
|
|
return (FALSE);
|
|
}
|
|
|
|
pInputContext->ptStatusWndPos = *lpptPos;
|
|
pInputContext->fdwInit |= INIT_STATUSWNDPOS;
|
|
|
|
hWnd = pInputContext->hWnd;
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
/*
|
|
* inform IME and UI about the change of composition font.
|
|
*/
|
|
MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L,
|
|
IMC_SETSTATUSWINDOWPOS, IMN_SETSTATUSWINDOWPOS, 0L);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCompositionWindow
|
|
*
|
|
* Gets the information of the composition window.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmGetCompositionWindow(
|
|
HIMC hImc,
|
|
LPCOMPOSITIONFORM lpCompForm)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
BOOL fCompFormInited;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCompositionWindow: Lock hImc %lx failed", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
fCompFormInited = ((pInputContext->fdwInit & INIT_COMPFORM) == INIT_COMPFORM);
|
|
ImmUnlockIMC(hImc);
|
|
|
|
if (fCompFormInited) {
|
|
*lpCompForm = pInputContext->cfCompForm;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL WINAPI ImmSetCompositionWindow(
|
|
HIMC hImc,
|
|
LPCOMPOSITIONFORM lpCompForm)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
HWND hWnd;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmSetCompositionWindow: Lock hImc %lx failed", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
pInputContext->cfCompForm = *lpCompForm;
|
|
pInputContext->fdwInit |= INIT_COMPFORM;
|
|
|
|
/*
|
|
* Only WINNLS.DLL set F31COMPAT_MCWHIDDEN.
|
|
* When the apps or edit control calls this API, we need to remove
|
|
* F31COMPAT_MCWHIDDEN.
|
|
*/
|
|
if (pInputContext->fdw31Compat & F31COMPAT_CALLFROMWINNLS)
|
|
pInputContext->fdw31Compat &= ~F31COMPAT_CALLFROMWINNLS;
|
|
else
|
|
pInputContext->fdw31Compat &= ~F31COMPAT_MCWHIDDEN;
|
|
|
|
hWnd = pInputContext->hWnd;
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
/*
|
|
* inform IME and UI about the change of composition window.
|
|
*/
|
|
MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L,
|
|
IMC_SETCOMPOSITIONWINDOW, IMN_SETCOMPOSITIONWINDOW, 0L);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmGetCandidateWindow
|
|
*
|
|
* Gets the information of the candidate window specified by dwIndex.
|
|
*
|
|
* History:
|
|
* 27-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmGetCandidateWindow(
|
|
HIMC hImc,
|
|
DWORD dwIndex,
|
|
LPCANDIDATEFORM lpCandForm)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetCandidateWindow: Lock hImc %lx failed", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
if (pInputContext->cfCandForm[dwIndex].dwIndex == -1) {
|
|
ImmUnlockIMC(hImc);
|
|
return (FALSE);
|
|
}
|
|
|
|
*lpCandForm = pInputContext->cfCandForm[dwIndex];
|
|
ImmUnlockIMC(hImc);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL WINAPI ImmSetCandidateWindow(
|
|
HIMC hImc,
|
|
LPCANDIDATEFORM lpCandForm)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
HWND hWnd;
|
|
|
|
if (lpCandForm->dwIndex >= 4) // over flow candidate index
|
|
return (FALSE);
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmSetCandidateWindow: Lock hImc %lx failed", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
pInputContext->cfCandForm[lpCandForm->dwIndex] = *lpCandForm;
|
|
|
|
hWnd = pInputContext->hWnd;
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
/*
|
|
* inform IME and UI about the change of composition window.
|
|
*/
|
|
MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L, IMC_SETCANDIDATEPOS,
|
|
IMN_SETCANDIDATEPOS, (LPARAM)(0x01 << lpCandForm->dwIndex));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#define GetCompInfoA(Component) \
|
|
if (!dwBufLen) { /* query required buffer size */ \
|
|
/* not include \0 */ \
|
|
dwBufLen = pCompStr->dw ## Component ## Len * sizeof(CHAR); \
|
|
} else { \
|
|
if (dwBufLen > pCompStr->dw ## Component ## Len * sizeof(CHAR)) { \
|
|
dwBufLen = pCompStr->dw ## Component ## Len * sizeof(CHAR); \
|
|
} \
|
|
/* don't copy \0, maybe there is actually none */ \
|
|
RtlCopyMemory((LPBYTE)lpBuf, (LPBYTE)pCompStr + \
|
|
pCompStr->dw ## Component ## Offset, dwBufLen); \
|
|
}
|
|
|
|
#define GetCompInfoW(Component) \
|
|
if (!dwBufLen) { /* query required buffer size */ \
|
|
/* not include \0 */ \
|
|
dwBufLen = pCompStr->dw ## Component ## Len * sizeof(WCHAR); \
|
|
} else { \
|
|
if (dwBufLen > pCompStr->dw ## Component ## Len * sizeof(WCHAR)) { \
|
|
dwBufLen = pCompStr->dw ## Component ## Len * sizeof(WCHAR); \
|
|
} \
|
|
/* don't copy \0, maybe there is actually none */ \
|
|
RtlCopyMemory((LPBYTE)lpBuf, (LPBYTE)pCompStr + \
|
|
pCompStr->dw ## Component ## Offset, dwBufLen); \
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* InternalGetCompositionStringA
|
|
*
|
|
* Internal version of ImmGetCompositionStringA.
|
|
*
|
|
* History:
|
|
* 28-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
LONG InternalGetCompositionStringA(
|
|
PCOMPOSITIONSTRING pCompStr,
|
|
DWORD dwIndex,
|
|
LPVOID lpBuf,
|
|
DWORD dwBufLen,
|
|
BOOL fAnsiImc)
|
|
{
|
|
if (fAnsiImc) {
|
|
/*
|
|
* Composition string in input context is of ANSI style.
|
|
*/
|
|
switch (dwIndex) {
|
|
case GCS_COMPSTR:
|
|
GetCompInfoA(CompStr);
|
|
break;
|
|
case GCS_COMPATTR:
|
|
GetCompInfoA(CompAttr);
|
|
break;
|
|
case GCS_COMPREADSTR:
|
|
GetCompInfoA(CompReadStr);
|
|
break;
|
|
case GCS_COMPREADATTR:
|
|
GetCompInfoA(CompReadAttr);
|
|
break;
|
|
case GCS_COMPREADCLAUSE:
|
|
GetCompInfoA(CompReadClause);
|
|
break;
|
|
case GCS_CURSORPOS:
|
|
dwBufLen = (LONG)pCompStr->dwCursorPos;
|
|
break;
|
|
case GCS_DELTASTART:
|
|
dwBufLen = (LONG)pCompStr->dwDeltaStart;
|
|
break;
|
|
case GCS_RESULTSTR:
|
|
GetCompInfoA(ResultStr);
|
|
break;
|
|
case GCS_RESULTCLAUSE:
|
|
GetCompInfoA(ResultClause);
|
|
break;
|
|
case GCS_RESULTREADSTR:
|
|
GetCompInfoA(ResultReadStr);
|
|
break;
|
|
case GCS_RESULTREADCLAUSE:
|
|
GetCompInfoA(ResultReadClause);
|
|
break;
|
|
case GCS_COMPCLAUSE:
|
|
GetCompInfoA(CompClause);
|
|
break;
|
|
default:
|
|
dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
|
|
break;
|
|
}
|
|
|
|
return (LONG)dwBufLen;
|
|
}
|
|
|
|
/*
|
|
* ANSI caller, Unicode input context/composition string.
|
|
*/
|
|
switch (dwIndex) {
|
|
case GCS_COMPSTR:
|
|
case GCS_COMPREADSTR:
|
|
case GCS_RESULTSTR:
|
|
case GCS_RESULTREADSTR:
|
|
{
|
|
DWORD dwStrSize;
|
|
LPWSTR lpStrW;
|
|
BOOL bUDC;
|
|
|
|
/*
|
|
* Get ANSI string from Unicode composition string.
|
|
*/
|
|
dwStrSize = InternalGetCompositionStringW(pCompStr, dwIndex,
|
|
NULL, 0, fAnsiImc);
|
|
|
|
lpStrW = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(WCHAR));
|
|
if (lpStrW == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: memory failure.");
|
|
return (LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
dwStrSize = InternalGetCompositionStringW(pCompStr, dwIndex,
|
|
lpStrW, dwStrSize, fAnsiImc);
|
|
|
|
dwBufLen = WideCharToMultiByte(CP_ACP,
|
|
(DWORD)0,
|
|
lpStrW, // src
|
|
wcslen(lpStrW),
|
|
(LPSTR)lpBuf, // dest
|
|
dwBufLen,
|
|
(LPSTR)NULL,
|
|
(LPBOOL)&bUDC);
|
|
|
|
ImmLocalFree(lpStrW);
|
|
break;
|
|
}
|
|
|
|
case GCS_COMPATTR:
|
|
case GCS_COMPREADATTR:
|
|
{
|
|
DWORD dwAttrLenW, dwIndexStr, dwStrSize;
|
|
PBYTE lpAttrA, lpAttrW;
|
|
LPSTR lpStrA, lpStrT;
|
|
CHAR c;
|
|
|
|
/*
|
|
* Get ANSI attribute from Unicode composition attribute.
|
|
*/
|
|
switch (dwIndex) {
|
|
case GCS_COMPATTR:
|
|
lpAttrW = (PBYTE)pCompStr + pCompStr->dwCompAttrOffset;
|
|
dwAttrLenW = pCompStr->dwCompAttrLen;
|
|
dwIndexStr = GCS_COMPSTR;
|
|
break;
|
|
case GCS_COMPREADATTR:
|
|
lpAttrW = (PBYTE)pCompStr + pCompStr->dwCompReadAttrOffset;
|
|
dwAttrLenW = pCompStr->dwCompReadAttrLen;
|
|
dwIndexStr = GCS_COMPREADSTR;
|
|
break;
|
|
}
|
|
|
|
if (dwAttrLenW == 0) {
|
|
/*
|
|
* No CompAttr or CompReadAttr exists, do nothing.
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
dwStrSize = InternalGetCompositionStringA(pCompStr,
|
|
dwIndexStr, NULL, 0, fAnsiImc);
|
|
|
|
if (dwStrSize == (DWORD)(LONG)IMM_ERROR_GENERAL) {
|
|
RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL.");
|
|
return (LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
/*
|
|
* Query required size or early exit on error.
|
|
*/
|
|
if (dwBufLen == 0 || dwStrSize == 0)
|
|
return dwStrSize;
|
|
|
|
lpStrA = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(CHAR));
|
|
if (lpStrA == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: memory failure.");
|
|
return (LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
dwStrSize = InternalGetCompositionStringA(pCompStr,
|
|
dwIndexStr, lpStrA, dwStrSize, fAnsiImc);
|
|
|
|
if (dwStrSize == (LONG)IMM_ERROR_GENERAL) {
|
|
RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL.");
|
|
ImmLocalFree(lpStrA);
|
|
return (LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
lpStrT = lpStrA;
|
|
lpAttrA = (PBYTE)lpBuf;
|
|
|
|
while ((c=*lpStrT++) != '\0' && dwBufLen != 0 && dwAttrLenW-- != 0) {
|
|
if (IsDBCSLeadByte(c)) {
|
|
if (dwBufLen >= 2) {
|
|
*lpAttrA++ = *lpAttrW;
|
|
*lpAttrA++ = *lpAttrW;
|
|
dwBufLen--;
|
|
}
|
|
else {
|
|
*lpAttrA++ = *lpAttrW;
|
|
}
|
|
lpStrT++;
|
|
}
|
|
else {
|
|
*lpAttrA++ = *lpAttrW;
|
|
}
|
|
lpAttrW++;
|
|
dwBufLen--;
|
|
}
|
|
|
|
dwBufLen = (DWORD)(lpAttrA - (PBYTE)lpBuf);
|
|
|
|
ImmLocalFree(lpStrA);
|
|
break;
|
|
}
|
|
|
|
case GCS_COMPCLAUSE:
|
|
case GCS_COMPREADCLAUSE:
|
|
case GCS_RESULTCLAUSE:
|
|
case GCS_RESULTREADCLAUSE:
|
|
{
|
|
LPWSTR lpStrW;
|
|
DWORD dwClauseLen, dwBufLenA;
|
|
LPDWORD lpdwSrc, lpdwDst;
|
|
UINT i;
|
|
|
|
/*
|
|
* Get ANSI clause from Unicode composition clause.
|
|
*/
|
|
switch (dwIndex) {
|
|
case GCS_COMPCLAUSE:
|
|
lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset);
|
|
lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompClauseOffset);
|
|
dwClauseLen = pCompStr->dwCompClauseLen;
|
|
break;
|
|
case GCS_COMPREADCLAUSE:
|
|
lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwCompReadStrOffset);
|
|
lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompReadClauseOffset);
|
|
dwClauseLen = pCompStr->dwCompReadClauseLen;
|
|
break;
|
|
case GCS_RESULTCLAUSE:
|
|
lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwResultStrOffset);
|
|
lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultClauseOffset);
|
|
dwClauseLen = pCompStr->dwResultClauseLen;
|
|
break;
|
|
case GCS_RESULTREADCLAUSE:
|
|
lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwResultReadStrOffset);
|
|
lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultReadClauseOffset);
|
|
dwClauseLen = pCompStr->dwResultReadClauseLen;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Query clause length or early exit on error.
|
|
*/
|
|
if (dwBufLen == 0 || (LONG)dwClauseLen < 0) {
|
|
dwBufLen = dwClauseLen;
|
|
break;
|
|
}
|
|
|
|
lpdwDst = (LPDWORD)lpBuf;
|
|
dwBufLenA = dwBufLen / sizeof(DWORD);
|
|
|
|
for (i = 0; i < dwClauseLen / sizeof(DWORD) && dwBufLenA != 0; i++) {
|
|
*lpdwDst++ = CalcCharacterPositionWtoA(*lpdwSrc++, lpStrW);
|
|
dwBufLenA--;
|
|
}
|
|
|
|
dwBufLen = i * sizeof(DWORD);
|
|
break;
|
|
}
|
|
|
|
case GCS_CURSORPOS:
|
|
case GCS_DELTASTART:
|
|
/*
|
|
* Get ANSI cursor/delta start position from Unicode composition string.
|
|
*/
|
|
switch (dwIndex) {
|
|
case GCS_CURSORPOS:
|
|
dwBufLen = pCompStr->dwCursorPos;
|
|
break;
|
|
case GCS_DELTASTART:
|
|
dwBufLen = pCompStr->dwDeltaStart;
|
|
break;
|
|
}
|
|
|
|
if ((LONG)dwBufLen > 0) {
|
|
dwBufLen = CalcCharacterPositionWtoA(dwBufLen,
|
|
(LPWSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
return (LONG)dwBufLen;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* InternalGetCompositionStringW
|
|
*
|
|
* Internal version of ImmGetCompositionStringW.
|
|
*
|
|
* History:
|
|
* 28-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
LONG InternalGetCompositionStringW(
|
|
PCOMPOSITIONSTRING pCompStr,
|
|
DWORD dwIndex,
|
|
LPVOID lpBuf,
|
|
DWORD dwBufLen,
|
|
BOOL fAnsiImc)
|
|
{
|
|
if (!fAnsiImc) {
|
|
/*
|
|
* Composition string in input context is of Unicode style.
|
|
*/
|
|
switch (dwIndex) {
|
|
case GCS_COMPSTR:
|
|
GetCompInfoW(CompStr);
|
|
break;
|
|
case GCS_COMPATTR: // A-only: Check this later!
|
|
GetCompInfoW(CompAttr);
|
|
break;
|
|
case GCS_COMPREADSTR:
|
|
GetCompInfoW(CompReadStr);
|
|
break;
|
|
case GCS_COMPREADATTR:
|
|
GetCompInfoW(CompReadAttr);
|
|
break;
|
|
case GCS_COMPREADCLAUSE:
|
|
GetCompInfoW(CompReadClause);
|
|
break;
|
|
case GCS_CURSORPOS:
|
|
dwBufLen = (LONG)pCompStr->dwCursorPos;
|
|
break;
|
|
case GCS_DELTASTART:
|
|
dwBufLen = (LONG)pCompStr->dwDeltaStart;
|
|
break;
|
|
case GCS_RESULTSTR:
|
|
GetCompInfoW(ResultStr);
|
|
break;
|
|
case GCS_RESULTCLAUSE:
|
|
GetCompInfoW(ResultClause);
|
|
break;
|
|
case GCS_RESULTREADSTR:
|
|
GetCompInfoW(ResultReadStr);
|
|
break;
|
|
case GCS_RESULTREADCLAUSE:
|
|
GetCompInfoW(ResultReadClause);
|
|
break;
|
|
case GCS_COMPCLAUSE:
|
|
GetCompInfoW(CompClause);
|
|
break;
|
|
default:
|
|
dwBufLen = (DWORD)IMM_ERROR_GENERAL;
|
|
break;
|
|
}
|
|
|
|
return (LONG)dwBufLen;
|
|
}
|
|
|
|
/*
|
|
* Unicode caller, ANSI input context/composition string.
|
|
*/
|
|
switch (dwIndex) {
|
|
case GCS_COMPSTR:
|
|
case GCS_COMPREADSTR:
|
|
case GCS_RESULTSTR:
|
|
case GCS_RESULTREADSTR:
|
|
{
|
|
DWORD dwStrSize;
|
|
LPSTR lpStrA;
|
|
|
|
/*
|
|
* Get Unicode string from ANSI composition string.
|
|
*/
|
|
dwStrSize = InternalGetCompositionStringA(pCompStr, dwIndex,
|
|
NULL, 0, fAnsiImc);
|
|
|
|
lpStrA = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(CHAR));
|
|
if (lpStrA == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalGetCompositionStringW: memory failure.");
|
|
return (LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
dwStrSize = InternalGetCompositionStringA(pCompStr, dwIndex,
|
|
lpStrA, dwStrSize, fAnsiImc);
|
|
|
|
dwBufLen = MultiByteToWideChar(CP_ACP,
|
|
(DWORD)MB_PRECOMPOSED,
|
|
lpStrA, // src
|
|
strlen(lpStrA),
|
|
(LPWSTR)lpBuf, // dest
|
|
(INT)dwBufLen);
|
|
|
|
dwBufLen *= sizeof(WCHAR); // return number of bytes required.
|
|
|
|
ImmLocalFree(lpStrA);
|
|
break;
|
|
}
|
|
|
|
case GCS_COMPATTR:
|
|
case GCS_COMPREADATTR:
|
|
{
|
|
DWORD dwAttrLenA, dwIndexStr, dwStrSize;
|
|
PBYTE lpAttrA, lpAttrW;
|
|
LPWSTR lpStrW, lpStrT;
|
|
ULONG MultiByteSize;
|
|
WCHAR wc;
|
|
|
|
/*
|
|
* Get Unicode attribute from ANSI composition attribute.
|
|
*/
|
|
switch (dwIndex) {
|
|
case GCS_COMPATTR:
|
|
lpAttrA = (PBYTE)pCompStr + pCompStr->dwCompAttrOffset;
|
|
dwAttrLenA = pCompStr->dwCompAttrLen;
|
|
dwIndexStr = GCS_COMPSTR;
|
|
break;
|
|
case GCS_COMPREADATTR:
|
|
lpAttrA = (PBYTE)pCompStr + pCompStr->dwCompReadAttrOffset;
|
|
dwAttrLenA = pCompStr->dwCompReadAttrLen;
|
|
dwIndexStr = GCS_COMPREADSTR;
|
|
break;
|
|
}
|
|
|
|
if (dwAttrLenA == 0) {
|
|
/*
|
|
* No CompAttr or CompReadAttr exists, do nothing.
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
dwStrSize = InternalGetCompositionStringW(pCompStr,
|
|
dwIndexStr, NULL, 0, fAnsiImc);
|
|
|
|
if (dwStrSize == (DWORD)(LONG)IMM_ERROR_GENERAL) {
|
|
RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL.");
|
|
return (LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
/*
|
|
* Query required size or early exit on error.
|
|
*/
|
|
if (dwBufLen == 0 || dwStrSize == 0)
|
|
return dwStrSize / sizeof(WCHAR);
|
|
|
|
lpStrW = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(WCHAR));
|
|
if (lpStrW == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalGetCompositionStringW: memory failure.");
|
|
return (LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
dwStrSize = InternalGetCompositionStringW(pCompStr,
|
|
dwIndexStr, lpStrW, dwStrSize, fAnsiImc);
|
|
|
|
if (dwStrSize == (LONG)IMM_ERROR_GENERAL) {
|
|
RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL.");
|
|
ImmLocalFree(lpStrW);
|
|
return (LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
lpStrT = lpStrW;
|
|
lpAttrW = (PBYTE)lpBuf;
|
|
|
|
while ((wc=*lpStrT++) != L'\0' && dwBufLen != 0 && dwAttrLenA-- != 0) {
|
|
RtlUnicodeToMultiByteSize(&MultiByteSize, &wc, sizeof(WCHAR));
|
|
if (MultiByteSize == 2 && dwAttrLenA != 0) {
|
|
*lpAttrW++ = *lpAttrA++;
|
|
dwAttrLenA--;
|
|
}
|
|
else {
|
|
*lpAttrW++ = *lpAttrA;
|
|
}
|
|
lpAttrA++;
|
|
dwBufLen--;
|
|
}
|
|
|
|
dwBufLen = (DWORD)(lpAttrW - (PBYTE)lpBuf);
|
|
|
|
ImmLocalFree(lpStrW);
|
|
break;
|
|
}
|
|
|
|
case GCS_COMPCLAUSE:
|
|
case GCS_COMPREADCLAUSE:
|
|
case GCS_RESULTCLAUSE:
|
|
case GCS_RESULTREADCLAUSE:
|
|
{
|
|
LPSTR lpStrA;
|
|
DWORD dwClauseLen, dwBufLenW;
|
|
LPDWORD lpdwSrc, lpdwDst;
|
|
UINT i;
|
|
|
|
/*
|
|
* Get Unicode clause from ANSI composition clause.
|
|
*/
|
|
switch (dwIndex) {
|
|
case GCS_COMPCLAUSE:
|
|
lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset);
|
|
lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompClauseOffset);
|
|
dwClauseLen = pCompStr->dwCompClauseLen;
|
|
break;
|
|
case GCS_COMPREADCLAUSE:
|
|
lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwCompReadStrOffset);
|
|
lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompReadClauseOffset);
|
|
dwClauseLen = pCompStr->dwCompReadClauseLen;
|
|
break;
|
|
case GCS_RESULTCLAUSE:
|
|
lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwResultStrOffset);
|
|
lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultClauseOffset);
|
|
dwClauseLen = pCompStr->dwResultClauseLen;
|
|
break;
|
|
case GCS_RESULTREADCLAUSE:
|
|
lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwResultReadStrOffset);
|
|
lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultReadClauseOffset);
|
|
dwClauseLen = pCompStr->dwResultReadClauseLen;
|
|
break;
|
|
}
|
|
|
|
|
|
/*
|
|
* Query clause length or early exit on error.
|
|
*/
|
|
if (dwBufLen == 0 || (LONG)dwClauseLen < 0) {
|
|
dwBufLen = dwClauseLen;
|
|
break;
|
|
}
|
|
|
|
lpdwDst = (LPDWORD)lpBuf;
|
|
dwBufLenW = dwBufLen / sizeof(DWORD);
|
|
|
|
for (i = 0; i < dwClauseLen / sizeof(DWORD) && dwBufLenW != 0; i++) {
|
|
*lpdwDst++ = CalcCharacterPositionAtoW(*lpdwSrc++, lpStrA);
|
|
dwBufLenW--;
|
|
}
|
|
|
|
dwBufLen = i * sizeof(DWORD);
|
|
break;
|
|
}
|
|
|
|
case GCS_CURSORPOS:
|
|
case GCS_DELTASTART:
|
|
/*
|
|
* Get Unicode cursor/delta start position from ANSI composition string.
|
|
*/
|
|
switch (dwIndex) {
|
|
case GCS_CURSORPOS:
|
|
dwBufLen = pCompStr->dwCursorPos;
|
|
break;
|
|
case GCS_DELTASTART:
|
|
dwBufLen = pCompStr->dwDeltaStart;
|
|
break;
|
|
}
|
|
|
|
if ((LONG)dwBufLen > 0) {
|
|
dwBufLen = CalcCharacterPositionAtoW(dwBufLen,
|
|
(LPSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
|
|
}
|
|
|
|
return (LONG)dwBufLen;
|
|
}
|
|
|
|
|
|
DWORD InternalGetCandidateListAtoW(
|
|
LPCANDIDATELIST lpCandListA,
|
|
LPCANDIDATELIST lpCandListW,
|
|
DWORD dwBufLen)
|
|
{
|
|
LPWSTR lpCandStrW;
|
|
LPSTR lpCandStrA;
|
|
INT i, j;
|
|
DWORD dwCandListLen;
|
|
|
|
dwCandListLen = sizeof(CANDIDATELIST);
|
|
|
|
/*
|
|
* CANDIDATELIST has already contained the dwOffset[0]
|
|
*/
|
|
if (lpCandListA->dwCount > 0)
|
|
dwCandListLen += sizeof(DWORD) * (lpCandListA->dwCount - 1);
|
|
|
|
for (i = 0; i < (INT)lpCandListA->dwCount; i++) {
|
|
|
|
lpCandStrA = (LPSTR)((LPBYTE)lpCandListA + lpCandListA->dwOffset[i]);
|
|
|
|
j = MultiByteToWideChar(CP_ACP,
|
|
(DWORD)MB_PRECOMPOSED,
|
|
lpCandStrA,
|
|
-1,
|
|
(LPWSTR)NULL,
|
|
0);
|
|
|
|
dwCandListLen += (j * sizeof(WCHAR));
|
|
}
|
|
|
|
dwCandListLen = DWORD_ALIGN(dwCandListLen);
|
|
|
|
if (dwBufLen == 0)
|
|
return dwCandListLen;
|
|
|
|
if (dwBufLen < dwCandListLen) {
|
|
RIPMSG0(RIP_WARNING, "InternalGetCandidateListAtoW: dwBufLen too small.");
|
|
return 0;
|
|
}
|
|
|
|
lpCandListW->dwSize = dwBufLen;
|
|
lpCandListW->dwStyle = lpCandListA->dwStyle;
|
|
lpCandListW->dwCount = lpCandListA->dwCount;
|
|
lpCandListW->dwSelection = lpCandListA->dwSelection;
|
|
lpCandListW->dwPageStart = lpCandListA->dwPageStart;
|
|
lpCandListW->dwPageSize = lpCandListA->dwPageSize;
|
|
lpCandListW->dwOffset[0] = sizeof(CANDIDATELIST);
|
|
if (lpCandListW->dwCount > 0)
|
|
lpCandListW->dwOffset[0] += sizeof(DWORD) * (lpCandListW->dwCount - 1);
|
|
|
|
dwCandListLen = dwBufLen - lpCandListW->dwOffset[0];
|
|
|
|
for (i = 0; i < (INT)lpCandListW->dwCount; i++) {
|
|
|
|
lpCandStrA = (LPSTR) ((LPBYTE)lpCandListA + lpCandListA->dwOffset[i]);
|
|
lpCandStrW = (LPWSTR)((LPBYTE)lpCandListW + lpCandListW->dwOffset[i]);
|
|
|
|
j = MultiByteToWideChar(CP_ACP,
|
|
(DWORD)MB_PRECOMPOSED,
|
|
lpCandStrA,
|
|
-1,
|
|
lpCandStrW,
|
|
(INT)dwCandListLen/sizeof(WCHAR));
|
|
|
|
dwCandListLen -= (j * sizeof(WCHAR));
|
|
|
|
if (i < (INT)lpCandListW->dwCount - 1)
|
|
lpCandListW->dwOffset[i+1] = lpCandListW->dwOffset[i] + j * sizeof(WCHAR);
|
|
}
|
|
|
|
return dwBufLen;
|
|
}
|
|
|
|
|
|
DWORD InternalGetCandidateListWtoA(
|
|
LPCANDIDATELIST lpCandListW,
|
|
LPCANDIDATELIST lpCandListA,
|
|
DWORD dwBufLen)
|
|
{
|
|
LPWSTR lpCandStrW;
|
|
LPSTR lpCandStrA;
|
|
INT i, j;
|
|
DWORD dwCandListLen;
|
|
BOOL bUDC;
|
|
|
|
dwCandListLen = sizeof(CANDIDATELIST);
|
|
|
|
/*
|
|
* CANDIDATELIST has already contained the dwOffset[0]
|
|
*/
|
|
if (lpCandListW->dwCount > 0)
|
|
dwCandListLen += sizeof(DWORD) * (lpCandListW->dwCount - 1);
|
|
|
|
for (i = 0; i < (INT)lpCandListW->dwCount; i++) {
|
|
|
|
lpCandStrW = (LPWSTR)((LPBYTE)lpCandListW + lpCandListW->dwOffset[i]);
|
|
|
|
j = WideCharToMultiByte(CP_ACP,
|
|
(DWORD)0,
|
|
lpCandStrW,
|
|
-1,
|
|
(LPSTR)NULL,
|
|
(INT)0,
|
|
(LPSTR)NULL,
|
|
(LPBOOL)&bUDC);
|
|
|
|
dwCandListLen += (j * sizeof(CHAR));
|
|
}
|
|
|
|
dwCandListLen = DWORD_ALIGN(dwCandListLen);
|
|
|
|
if (dwBufLen == 0)
|
|
return dwCandListLen;
|
|
|
|
if (dwBufLen < dwCandListLen) {
|
|
RIPMSG0(RIP_WARNING, "InternalGetCandidateListWtoA: dwBufLen too small.");
|
|
return 0;
|
|
}
|
|
|
|
lpCandListA->dwSize = dwBufLen;
|
|
lpCandListA->dwStyle = lpCandListW->dwStyle;
|
|
lpCandListA->dwCount = lpCandListW->dwCount;
|
|
lpCandListA->dwSelection = lpCandListW->dwSelection;
|
|
lpCandListA->dwPageStart = lpCandListW->dwPageStart;
|
|
lpCandListA->dwPageSize = lpCandListW->dwPageSize;
|
|
lpCandListA->dwOffset[0] = sizeof(CANDIDATELIST);
|
|
if (lpCandListA->dwCount > 0)
|
|
lpCandListA->dwOffset[0] += sizeof(DWORD) * (lpCandListA->dwCount - 1);
|
|
|
|
dwCandListLen = dwBufLen - lpCandListA->dwOffset[0];
|
|
|
|
for (i = 0; i < (INT)lpCandListA->dwCount; i++) {
|
|
|
|
lpCandStrA = (LPSTR) ((LPBYTE)lpCandListA + lpCandListA->dwOffset[i]);
|
|
lpCandStrW = (LPWSTR)((LPBYTE)lpCandListW + lpCandListW->dwOffset[i]);
|
|
|
|
j = WideCharToMultiByte(CP_ACP,
|
|
(DWORD)0,
|
|
lpCandStrW,
|
|
-1,
|
|
(LPSTR)lpCandStrA,
|
|
(INT)dwCandListLen,
|
|
(LPSTR)NULL,
|
|
(LPBOOL)&bUDC);
|
|
|
|
dwCandListLen -= (j * sizeof(CHAR));
|
|
|
|
if (i < (INT)lpCandListA->dwCount - 1)
|
|
lpCandListA->dwOffset[i+1] = lpCandListA->dwOffset[i] + j * sizeof(CHAR);
|
|
}
|
|
|
|
return dwBufLen;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* CalcCharacterPositionAtoW
|
|
*
|
|
* Calculate Unicode character position to ANSI character position.
|
|
*
|
|
* History:
|
|
* 28-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD CalcCharacterPositionAtoW(
|
|
DWORD dwCharPosA,
|
|
LPSTR lpszCharStr)
|
|
{
|
|
DWORD dwCharPosW = 0;
|
|
|
|
while (dwCharPosA != 0) {
|
|
if (IsDBCSLeadByte(*lpszCharStr)) {
|
|
if (dwCharPosA >= 2) {
|
|
dwCharPosA -= 2;
|
|
}
|
|
else {
|
|
dwCharPosA--;
|
|
}
|
|
lpszCharStr += 2;
|
|
}
|
|
else {
|
|
dwCharPosA--;
|
|
lpszCharStr++;
|
|
}
|
|
dwCharPosW++;
|
|
}
|
|
|
|
return dwCharPosW;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* CalcCharacterPositionWtoA
|
|
*
|
|
* Calculate ANSI character position to Unicode character position.
|
|
*
|
|
* History:
|
|
* 28-Feb-1995 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
DWORD CalcCharacterPositionWtoA(
|
|
DWORD dwCharPosW,
|
|
LPWSTR lpwszCharStr)
|
|
{
|
|
DWORD dwCharPosA = 0;
|
|
ULONG MultiByteSize;
|
|
|
|
while (dwCharPosW != 0) {
|
|
RtlUnicodeToMultiByteSize(&MultiByteSize, lpwszCharStr, sizeof(WCHAR));
|
|
if (MultiByteSize == 2) {
|
|
dwCharPosA += 2;
|
|
}
|
|
else {
|
|
dwCharPosA++;
|
|
}
|
|
dwCharPosW--;
|
|
lpwszCharStr++;
|
|
}
|
|
|
|
return dwCharPosA;
|
|
}
|
|
|
|
|
|
VOID LFontAtoLFontW(
|
|
LPLOGFONTA lpLogFontA,
|
|
LPLOGFONTW lpLogFontW)
|
|
{
|
|
INT i;
|
|
|
|
RtlCopyMemory(lpLogFontW, lpLogFontA, sizeof(LOGFONTA)-LF_FACESIZE);
|
|
|
|
i = MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
lpLogFontA->lfFaceName,
|
|
strlen(lpLogFontA->lfFaceName),
|
|
lpLogFontW->lfFaceName,
|
|
LF_FACESIZE);
|
|
|
|
lpLogFontW->lfFaceName[i] = L'\0';
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID LFontWtoLFontA(
|
|
LPLOGFONTW lpLogFontW,
|
|
LPLOGFONTA lpLogFontA)
|
|
{
|
|
INT i;
|
|
BOOL bUDC;
|
|
|
|
RtlCopyMemory(lpLogFontA, lpLogFontW, sizeof(LOGFONTA)-LF_FACESIZE);
|
|
|
|
i = WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
lpLogFontW->lfFaceName,
|
|
wcslen(lpLogFontW->lfFaceName),
|
|
lpLogFontA->lfFaceName,
|
|
LF_FACESIZE,
|
|
(LPSTR)NULL,
|
|
&bUDC);
|
|
|
|
lpLogFontA->lfFaceName[i] = '\0';
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
BOOL MakeIMENotify(
|
|
HIMC hImc,
|
|
HWND hWnd,
|
|
DWORD dwAction,
|
|
DWORD dwIndex,
|
|
DWORD dwValue,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PIMEDPI pImeDpi;
|
|
DWORD dwThreadId;
|
|
|
|
#ifdef LATER
|
|
// implement MakeIMENotifyEvent() later
|
|
#endif
|
|
|
|
if (dwAction != 0 && (dwThreadId = GetInputContextThread(hImc)) != 0) {
|
|
|
|
pImeDpi = ImmLockImeDpi(GetKeyboardLayout(dwThreadId));
|
|
|
|
if (pImeDpi != NULL) {
|
|
(*pImeDpi->pfn.NotifyIME)(hImc, dwAction, dwIndex, dwValue);
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
}
|
|
}
|
|
|
|
if (hWnd != NULL && wParam != 0)
|
|
SendMessage(hWnd, WM_IME_NOTIFY, wParam, lParam);
|
|
|
|
return TRUE;
|
|
}
|