Leaked source code of windows server 2003
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.
 
 
 
 
 
 

3845 lines
120 KiB

/**************************************************************************\
* Module Name: ctxtinfo.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* Get/set routines of various Input context information for imm32.dll
*
* History:
* 26-Feb-1996 wkwok
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
// Helper function:
// Converts RECONVERTSTRING structure between ANSI and UNICODE.
extern DWORD ImmReconversionWorker(LPRECONVERTSTRING lpRecTo, LPRECONVERTSTRING lpRecFrom, BOOL bToAnsi, DWORD dwCodePage);
int UnicodeToMultiByteSize(DWORD dwCodePage, LPCWSTR pwstr)
{
char dummy[2], *lpszDummy = dummy;
return WCSToMBEx((WORD)dwCodePage, pwstr, 1, &lpszDummy, sizeof(WCHAR), FALSE);
}
/***************************************************************************\
* 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;
DWORD dwCodePage;
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);
dwCodePage = CImcCodePage(pClientImc);
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;
}
#if !defined(CUAS_ENABLE)
lRet = InternalGetCompositionStringA(pCompStr, dwIndex,
lpBuf, dwBufLen, fAnsi, dwCodePage);
#else
lRet = InternalGetCompositionStringA(hImc, pCompStr, dwIndex,
lpBuf, dwBufLen, fAnsi, dwCodePage);
#endif
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;
DWORD dwCodePage;
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);
dwCodePage = CImcCodePage(pClientImc);
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;
}
#if !defined(CUAS_ENABLE)
lRet = InternalGetCompositionStringW(pCompStr, dwIndex,
lpBuf, dwBufLen, fAnsi, dwCodePage);
#else
lRet = InternalGetCompositionStringW(hImc, pCompStr, dwIndex,
lpBuf, dwBufLen, fAnsi, dwCodePage);
#endif
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,
LPVOID lpComp,
DWORD dwCompLen,
LPVOID lpRead,
DWORD dwReadLen)
{
return ImmSetCompositionStringWorker(hImc, dwIndex, lpComp,
dwCompLen, lpRead, dwReadLen, TRUE);
}
/***************************************************************************\
* ImmSetCompositionStringW
*
* Set composition string information specified by dwIndex.
*
* History:
* 28-Feb-1995 wkwok Created
\***************************************************************************/
BOOL WINAPI ImmSetCompositionStringW(
HIMC hImc,
DWORD dwIndex,
LPVOID lpComp,
DWORD dwCompLen,
LPVOID lpRead,
DWORD dwReadLen)
{
return ImmSetCompositionStringWorker(hImc, dwIndex, lpComp,
dwCompLen, lpRead, dwReadLen, FALSE);
}
LONG CompositionString(
HIMC hImc,
PINPUTCONTEXT *ppInputContext,
PCOMPOSITIONSTRING *ppCompStr,
BOOL fCheckSize)
{
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 (fCheckSize && 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;
UNREFERENCED_PARAMETER(dwClauseLen);
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,
DWORD dwCodePage)
{
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(dwCodePage,
(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(dwCodePage,
(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,
DWORD dwCodePage)
{
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 (IsDBCSLeadByteEx(dwCodePage, 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') {
MultiByteSize = UnicodeToMultiByteSize(dwCodePage, &wc);
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,
DWORD dwCodePage)
{
LPDWORD lpdw, lpNewdw, lpBufRet;
DWORD dwBufLenA, dwBufLenW;
LPSTR lpStrBufA = NULL;
LPWSTR lpStrBufW = NULL;
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, dwCodePage)
: CalcCharacterPositionWtoA(*lpdw++, lpStrBufW, dwCodePage);
}
if (lpStrBufA) {
ImmLocalFree(lpStrBufA);
UserAssert(lpStrBufW == NULL);
} else {
UserAssert(lpStrBufW);
ImmLocalFree(lpStrBufW);
}
return (LPBYTE)lpBufRet;
}
LPBYTE InternalSCS_RECONVERTSTRING(
LPRECONVERTSTRING lpReconv,
DWORD dwReconvLen,
LPRECONVERTSTRING *lplpNewReconv,
DWORD *lpdwNewReconvLen,
BOOL fAnsi,
DWORD dwCodePage)
{
LPRECONVERTSTRING lpNewReconv;
DWORD dwBufSize;
if (lpReconv == NULL || dwReconvLen == 0)
return NULL;
if (fAnsi) {
// AtoW
dwBufSize = (lpReconv->dwSize - sizeof *lpReconv + 1) * sizeof(WCHAR) + sizeof *lpReconv;
}
else {
dwBufSize = lpReconv->dwSize + sizeof(BYTE);
}
lpNewReconv = ImmLocalAlloc(0, dwBufSize);
if (lpNewReconv == NULL) {
RIPMSG0(RIP_WARNING, "InternalSCS_RECONVERTSTRING: memory failure.");
return NULL;
}
lpNewReconv->dwVersion = 0;
lpNewReconv->dwSize= dwBufSize;
lpNewReconv->dwSize = ImmReconversionWorker(lpNewReconv, lpReconv, !fAnsi, dwCodePage);
if (lpNewReconv->dwSize == 0) {
ImmLocalFree(lpNewReconv);
return NULL;;
}
*lpdwNewReconvLen = lpNewReconv->dwSize;
*lplpNewReconv = lpNewReconv;
return (LPBYTE)lpNewReconv;
}
/***************************************************************************\
* ImmSetCompositionStringWorker
*
* Worker function of ImmSetCompositionStringA/ImmSetCompositionStringW
*
* History:
* 28-Feb-1995 wkwok Created
\***************************************************************************/
BOOL ImmSetCompositionStringWorker(
HIMC hImc,
DWORD dwIndex,
LPVOID lpComp,
DWORD dwCompLen,
LPVOID lpRead,
DWORD dwReadLen,
BOOL fAnsi)
{
PINPUTCONTEXT pInputContext;
PCOMPOSITIONSTRING pCompStr;
DWORD dwThreadId;
PIMEDPI pImeDpi;
LPBYTE lpCompBuf, lpReadBuf;
LPBYTE lpNewComp = NULL, lpNewRead = NULL;
DWORD dwNewCompLen, dwNewReadLen;
BOOL fRet = FALSE;
BOOL fCheckSize = TRUE;
BOOL fNeedAWConversion;
LPBYTE lpOrgComp, lpOrgRead;
DWORD dwOrgCompLen, dwOrgReadLen;
dwThreadId = GetInputContextThread(hImc);
if (dwThreadId != GetCurrentThreadId()) {
RIPMSG1(RIP_WARNING,
"ImmSetCompositionString: Invalid input context access %lx.", hImc);
return FALSE;
}
pImeDpi = ImmLockImeDpi(GetKeyboardLayout(dwThreadId));
if (pImeDpi == NULL)
return FALSE;
lpCompBuf = lpReadBuf = NULL;
// Backup original pointers to copyback for QUERY.
lpOrgComp = lpComp;
lpOrgRead = lpRead;
dwOrgCompLen = dwCompLen;
dwOrgReadLen = dwReadLen;
/*
* 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.
*/
fNeedAWConversion = FALSE;
goto start_scs;
}
fNeedAWConversion = TRUE;
switch (dwIndex) {
case SCS_SETSTR:
if ( lpComp &&
(lpCompBuf = InternalSCS_SETSTR(lpComp, dwCompLen,
&lpNewComp, &dwNewCompLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
goto callime_scs;
if ( lpRead &&
(lpReadBuf = InternalSCS_SETSTR(lpRead, dwReadLen,
&lpNewRead, &dwNewReadLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
goto callime_scs;
fCheckSize = FALSE;
break;
case SCS_CHANGEATTR:
if ( lpComp &&
(lpCompBuf = InternalSCS_CHANGEATTR(
hImc, lpComp, dwCompLen, GCS_COMPSTR,
&lpNewComp, &dwNewCompLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
goto callime_scs;
if ( lpRead &&
(lpReadBuf = InternalSCS_CHANGEATTR(
hImc, lpRead, dwReadLen, GCS_COMPREADSTR,
&lpNewRead, &dwNewReadLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
goto callime_scs;
break;
case SCS_CHANGECLAUSE:
if ( lpComp &&
(lpCompBuf = InternalSCS_CHANGECLAUSE(
hImc, lpComp, dwCompLen, GCS_COMPSTR,
(LPDWORD *)&lpNewComp, &dwNewCompLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
goto callime_scs;
if ( lpRead &&
(lpReadBuf = InternalSCS_CHANGECLAUSE(
hImc, lpRead, dwReadLen, GCS_COMPREADSTR,
(LPDWORD *)&lpNewRead, &dwNewReadLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
goto callime_scs;
break;
case SCS_SETRECONVERTSTRING:
case SCS_QUERYRECONVERTSTRING:
if (lpComp &&
(lpCompBuf = InternalSCS_RECONVERTSTRING((LPRECONVERTSTRING)lpComp, dwCompLen,
(LPRECONVERTSTRING *)&lpNewComp, &dwNewCompLen,
fAnsi, IMECodePage(pImeDpi))) == NULL)
goto callime_scs;
if (lpRead &&
(lpReadBuf = InternalSCS_RECONVERTSTRING((LPRECONVERTSTRING)lpRead, dwReadLen,
(LPRECONVERTSTRING *)&lpNewRead, &dwNewReadLen,
fAnsi, IMECodePage(pImeDpi))) == NULL)
goto callime_scs;
fCheckSize = FALSE;
break;
default:
goto callime_scs;
}
if (lpCompBuf != NULL) {
lpComp = lpNewComp;
dwCompLen = dwNewCompLen;
}
if (lpReadBuf != NULL) {
lpRead = lpNewRead;
dwReadLen = dwNewReadLen;
}
start_scs:
if (CompositionString(hImc, &pInputContext, &pCompStr, fCheckSize) <= 0)
goto callime_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;
case SCS_SETRECONVERTSTRING:
case SCS_QUERYRECONVERTSTRING:
if (pImeDpi->ImeInfo.fdwSCSCaps & SCS_CAP_SETRECONVERTSTRING) {
fRet = TRUE;
}
break;
default:
break;
}
ImmUnlockIMCC(pInputContext->hCompStr);
ImmUnlockIMC(hImc);
callime_scs:
if (fRet) {
fRet = (*pImeDpi->pfn.ImeSetCompositionString)(hImc, dwIndex,
lpComp, dwCompLen, lpRead, dwReadLen);
}
/*
* Check if we need ANSI/Unicode back conversion
*/
if (fNeedAWConversion) {
LPBYTE lpCompBufBack = NULL, lpReadBufBack = NULL;
/*
* A/W back conversion needed.
*/
switch (dwIndex) {
case SCS_QUERYRECONVERTSTRING:
if (lpOrgComp &&
(lpCompBufBack = InternalSCS_RECONVERTSTRING((LPRECONVERTSTRING)lpComp, dwCompLen,
(LPRECONVERTSTRING *)&lpNewComp, &dwNewCompLen,
!fAnsi, IMECodePage(pImeDpi)))) {
if (dwOrgCompLen < dwNewCompLen) {
// lpOrgComp buffer length is too small.
fRet = FALSE;
}
else {
RtlCopyMemory(lpOrgComp, lpNewComp, dwNewCompLen);
}
}
if (lpOrgRead &&
(lpReadBufBack = InternalSCS_RECONVERTSTRING(
(LPRECONVERTSTRING)lpRead, dwReadLen,
(LPRECONVERTSTRING *)&lpNewRead, &dwNewReadLen,
!fAnsi, IMECodePage(pImeDpi)))) {
if (dwOrgReadLen < dwNewReadLen) {
// lpOrgRead buffer length is too small.
fRet = FALSE;
}
else {
RtlCopyMemory(lpOrgRead, lpNewRead, dwNewReadLen);
}
}
}
if (lpCompBufBack != NULL)
LocalFree(lpCompBufBack);
if (lpReadBufBack != NULL)
LocalFree(lpReadBufBack);
}
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;
DWORD dwCodePage;
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;
}
dwCodePage = CImcCodePage(pClientImc);
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, dwCodePage);
}
}
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, dwCodePage);
}
}
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;
DWORD dwCodePage;
pClientImc = ImmLockClientImc(hImc);
if (pClientImc == NULL) {
RIPMSG1(RIP_WARNING, "ImmGetCandidateList: Invalid hImc %lx.", hImc);
goto GetCandListExit;
}
dwCodePage = CImcCodePage(pClientImc);
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, dwCodePage);
}
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
/*
* Unicode Caller with an ANSI hImc.
*/
dwBufLenTemp = InternalGetCandidateListAtoW(lpCandListTemp, NULL, 0, dwCodePage);
}
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, dwCodePage);
}
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
dwRet = InternalGetCandidateListAtoW(lpCandListTemp, lpCandList, dwBufLenTemp, dwCodePage);
}
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;
DWORD dwCodePage;
pClientImc = ImmLockClientImc(hImc);
if (pClientImc == NULL) {
RIPMSG1(RIP_WARNING, "ImmGetGuideLine: Invalid hImc %lx.", hImc);
goto GetGuideLineExit;
}
dwCodePage = CImcCodePage(pClientImc);
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(dwCodePage,
(DWORD)0,
(LPWSTR)lpBufTemp,
(INT)lpGuideLine->dwStrLen,
(LPSTR)NULL,
(INT)0,
(LPSTR)NULL,
(LPBOOL)&bUDC);
}
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
dwBufLenNeeded = MultiByteToWideChar(dwCodePage,
(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(dwCodePage,
(DWORD)0,
(LPWSTR)lpBufTemp,
(INT)lpGuideLine->dwStrLen,
(LPSTR)lpBuf,
(INT)dwBufLen,
(LPSTR)NULL,
(LPBOOL)&bUDC);
}
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
dwRet = MultiByteToWideChar(dwCodePage,
(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, dwCodePage);
}
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE) &&
lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) {
dwBufLenNeeded = InternalGetCandidateListAtoW(
(LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)NULL, 0, dwCodePage);
}
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, dwCodePage);
}
else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE) &&
lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) {
dwRet = InternalGetCandidateListAtoW(
(LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)lpBuf, dwBufLenNeeded, dwCodePage);
}
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;
}
if (lpfdwConversion != NULL)
*lpfdwConversion = pInputContext->fdwConversion;
if (lpfdwSentence != NULL)
*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;
DWORD dwOpenStatus;
DWORD dwConversion;
#if defined(CUAS_ENABLE)
BOOL fMakeNotifyAlways = FALSE;
HKL hKL = GetKeyboardLayout(0);
if (!IS_IME_KBDLAYOUT(hKL) && IS_CICERO_ENABLED_AND_NOT16BIT())
fMakeNotifyAlways = TRUE;
#endif
if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
RIPMSG1(RIP_WARNING,
"ImmSetConversionStatus: Invalid input context access %lx.", hImc);
return FALSE;
}
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;
if ( fConvModeChg ) {
dwOpenStatus = (DWORD)pInputContext->fOpen;
dwConversion = pInputContext->fdwConversion;
}
ImmUnlockIMC(hImc);
#ifdef LATER
// Do uNumLangVKey and uNumVKey checking later.
#endif
/*
* inform IME and UI about the conversion mode changes.
*/
#if !defined(CUAS_ENABLE)
if (fConvModeChg)
#else
if (fConvModeChg || fMakeNotifyAlways)
#endif
{
MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, fdwOldConversion,
IMC_SETCONVERSIONMODE, IMN_SETCONVERSIONMODE, 0L);
/*
* notify shell and keyboard the conversion mode change
*/
#if defined(CUAS_ENABLE)
if (fConvModeChg)
#endif
NtUserNotifyIMEStatus( hWnd, dwOpenStatus, dwConversion );
}
/*
* inform IME and UI about the sentence mode changes.
*/
#if !defined(CUAS_ENABLE)
if (fSentenceChg)
#else
if (fSentenceChg || fMakeNotifyAlways)
#endif
{
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;
if (hImc == NULL_HIMC)
return FALSE;
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;
DWORD dwOpenStatus;
DWORD dwConversion;
BOOL fOpenChg = FALSE;
if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
RIPMSG1(RIP_WARNING,
"ImmSetOpenStatus: Invalid input context access %lx.", hImc);
return 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;
}
if ( fOpenChg ) {
hWnd = (HWND)pInputContext->hWnd;
dwOpenStatus = (DWORD)pInputContext->fOpen;
dwConversion = (DWORD)pInputContext->fdwConversion;
}
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);
NtUserNotifyIMEStatus( hWnd, dwOpenStatus, dwConversion );
}
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;
if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
RIPMSG1(RIP_WARNING,
"ImmSetCompositionFontA: Invalid input context access %lx.", hImc);
return FALSE;
}
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);
}
/*
* Japanese 3.x applications need to receive 3.x compatible notification message.
*
*/
if ( (GetClientInfo()->dwExpWinVer < VER40) &&
(PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) == LANG_JAPANESE) &&
! (pInputContext->fdw31Compat & F31COMPAT_MCWHIDDEN) &&
(pInputContext->cfCompForm.dwStyle != CFS_DEFAULT) ) {
PostMessageA( pInputContext->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, (LPARAM)NULL);
}
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;
if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
RIPMSG1(RIP_WARNING,
"ImmSetCompositionFontW: Invalid input context access %lx.", hImc);
return FALSE;
}
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);
}
/*
* Japanese 3.x applications need to receive 3.x compatible notification message.
*
*/
if ( (GetClientInfo()->dwExpWinVer < VER40) &&
(PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) == LANG_JAPANESE) &&
! (pInputContext->fdw31Compat & F31COMPAT_MCWHIDDEN) &&
(pInputContext->cfCompForm.dwStyle != CFS_DEFAULT) ) {
PostMessageW( pInputContext->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, (LPARAM)NULL);
}
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;
DWORD dwCodePage;
pImeDpi = FindOrLoadImeDpi(hKL);
if (pImeDpi == NULL) {
RIPMSG1(RIP_WARNING,
"ImmGetConversionListA: cannot find DPI entry for hkl=%lx", hKL);
return (0);
}
dwCodePage = IMECodePage(pImeDpi);
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(dwCodePage,
(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, dwCodePage);
}
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, dwCodePage);
}
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;
DWORD dwCodePage;
pImeDpi = FindOrLoadImeDpi(hKL);
if (pImeDpi == NULL) {
RIPMSG1(RIP_WARNING,
"ImmGetConversionListW: cannot find DPI entry for hkl=%lx", hKL);
return (0);
}
dwCodePage = IMECodePage(pImeDpi);
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(dwCodePage,
(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, dwCodePage);
}
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, dwCodePage);
}
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;
if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
RIPMSG1(RIP_WARNING,
"ImmSetStatusWindowPos: Invalid input context access %lx.", hImc);
return FALSE;
}
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;
if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
RIPMSG1(RIP_WARNING,
"ImmSetCompositionWindow: Invalid input context access %lx.", hImc);
return FALSE;
}
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;
}
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);
if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
RIPMSG1(RIP_WARNING,
"ImmSetCandidateWindow: Invalid input context access %lx.", hImc);
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); \
}
#ifdef CUAS_ENABLE
#define GetPrivInfoA(pv, Component) \
if (!dwBufLen) { /* query required buffer size */ \
/* not include \0 */ \
dwBufLen = ## pv ## ->dw ## Component ## Len * sizeof(CHAR); \
} else { \
if (dwBufLen > ## pv ## ->dw ## Component ## Len * sizeof(CHAR)) { \
dwBufLen = ## pv ## ->dw ## Component ## Len * sizeof(CHAR); \
} \
/* don't copy \0, maybe there is actually none */ \
RtlCopyMemory((LPBYTE)lpBuf, (LPBYTE) ## pv ## + \
## pv ## ->dw ## Component ## Offset, dwBufLen); \
}
#define GetPrivInfoW(pv, Component) \
if (!dwBufLen) { /* query required buffer size */ \
/* not include \0 */ \
dwBufLen = ## pv ## ->dw ## Component ## Len * sizeof(WCHAR); \
} else { \
if (dwBufLen > ## pv ## ->dw ## Component ## Len * sizeof(WCHAR)) {\
dwBufLen = ## pv ## ->dw ## Component ## Len * sizeof(WCHAR); \
} \
/* don't copy \0, maybe there is actually none */ \
RtlCopyMemory((LPBYTE)lpBuf, (LPBYTE) ## pv ## + \
## pv ## ->dw ## Component ## Offset, dwBufLen); \
}
#endif // CUAS_ENABLE
/***************************************************************************\
* InternalGetCompositionStringA
*
* Internal version of ImmGetCompositionStringA.
*
* History:
* 28-Feb-1995 wkwok Created
\***************************************************************************/
LONG InternalGetCompositionStringA(
#ifdef CUAS_ENABLE
HIMC hImc,
#endif // CUAS_ENABLE
PCOMPOSITIONSTRING pCompStr,
DWORD dwIndex,
LPVOID lpBuf,
DWORD dwBufLen,
BOOL fAnsiImc,
DWORD dwCodePage)
{
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;
#ifdef CUAS_ENABLE
case GCS_COMPGUIDATTR:
if (CtfImmIsGuidMapEnable(hImc) && (pCompStr->dwPrivateSize >= sizeof(GUIDMAPATTRIBUTE)))
{
PGUIDMAPATTRIBUTE pGuidMap = (PGUIDMAPATTRIBUTE)((PBYTE)pCompStr + pCompStr->dwPrivateOffset);
if (pGuidMap != NULL)
{
GetPrivInfoA(pGuidMap, GuidMapAttr);
}
else
{
dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
}
}
else
{
dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
}
break;
#endif // CUAS_ENABLE
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.
*/
#if !defined(CUAS_ENABLE)
dwStrSize = InternalGetCompositionStringW(pCompStr, dwIndex,
NULL, 0, fAnsiImc, dwCodePage);
#else
dwStrSize = InternalGetCompositionStringW(hImc, pCompStr, dwIndex,
NULL, 0, fAnsiImc, dwCodePage);
#endif
lpStrW = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(WCHAR));
if (lpStrW == NULL) {
RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: memory failure.");
return (LONG)IMM_ERROR_GENERAL;
}
#if !defined(CUAS_ENABLE)
dwStrSize = InternalGetCompositionStringW(pCompStr, dwIndex,
lpStrW, dwStrSize, fAnsiImc, dwCodePage);
#else
dwStrSize = InternalGetCompositionStringW(hImc, pCompStr, dwIndex,
lpStrW, dwStrSize, fAnsiImc, dwCodePage);
#endif
dwBufLen = WideCharToMultiByte(dwCodePage,
(DWORD)0,
lpStrW, // src
wcslen(lpStrW),
(LPSTR)lpBuf, // dest
dwBufLen,
(LPSTR)NULL,
(LPBOOL)&bUDC);
ImmLocalFree(lpStrW);
break;
}
case GCS_COMPATTR:
case GCS_COMPREADATTR:
#ifdef CUAS_ENABLE
case GCS_COMPGUIDATTR:
#endif // CUAS_ENABLE
{
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;
#ifdef CUAS_ENABLE
case GCS_COMPGUIDATTR:
if (CtfImmIsGuidMapEnable(hImc) && (pCompStr->dwPrivateSize >= sizeof(GUIDMAPATTRIBUTE)))
{
PGUIDMAPATTRIBUTE pGuidMap = (PGUIDMAPATTRIBUTE)((PBYTE)pCompStr + pCompStr->dwPrivateOffset);
if (pGuidMap != NULL)
{
lpAttrW = (PBYTE)pGuidMap + pGuidMap->dwGuidMapAttrOffset;
dwAttrLenW = pGuidMap->dwGuidMapAttrLen;
dwIndexStr = GCS_COMPSTR;
break;
}
else
{
return (DWORD)(LONG)IMM_ERROR_GENERAL;
}
}
else
{
return (DWORD)(LONG)IMM_ERROR_GENERAL;
}
break;
#endif // CUAS_ENABLE
}
if (dwAttrLenW == 0) {
/*
* No CompAttr or CompReadAttr exists, do nothing.
*/
return 0;
}
#if !defined(CUAS_ENABLE)
dwStrSize = InternalGetCompositionStringA(pCompStr,
dwIndexStr, NULL, 0, fAnsiImc, dwCodePage);
#else
dwStrSize = InternalGetCompositionStringA(hImc, pCompStr,
dwIndexStr, NULL, 0, fAnsiImc, dwCodePage);
#endif
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;
}
#if !defined(CUAS_ENABLE)
dwStrSize = InternalGetCompositionStringA(pCompStr,
dwIndexStr, lpStrA, dwStrSize, fAnsiImc, dwCodePage);
#else
dwStrSize = InternalGetCompositionStringA(hImc, pCompStr,
dwIndexStr, lpStrA, dwStrSize, fAnsiImc, dwCodePage);
#endif
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 (IsDBCSLeadByteEx(dwCodePage, 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, dwCodePage);
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),
dwCodePage);
}
break;
default:
dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
}
return (LONG)dwBufLen;
}
/***************************************************************************\
* InternalGetCompositionStringW
*
* Internal version of ImmGetCompositionStringW.
*
* History:
* 28-Feb-1995 wkwok Created
\***************************************************************************/
LONG InternalGetCompositionStringW(
#ifdef CUAS_ENABLE
HIMC hImc,
#endif // CUAS_ENABLE
PCOMPOSITIONSTRING pCompStr,
DWORD dwIndex,
LPVOID lpBuf,
DWORD dwBufLen,
BOOL fAnsiImc,
DWORD dwCodePage)
{
if (!fAnsiImc) {
/*
* Composition string in input context is of Unicode style.
*/
switch (dwIndex) {
case GCS_COMPSTR:
GetCompInfoW(CompStr);
break;
case GCS_COMPATTR: // ANSI-only
GetCompInfoA(CompAttr);
break;
case GCS_COMPREADSTR:
GetCompInfoW(CompReadStr);
break;
case GCS_COMPREADATTR: // ANSI-only
GetCompInfoA(CompReadAttr);
break;
case GCS_COMPREADCLAUSE: // ANSI-only
GetCompInfoA(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: // ANSI-only
GetCompInfoA(ResultClause);
break;
case GCS_RESULTREADSTR:
GetCompInfoW(ResultReadStr);
break;
case GCS_RESULTREADCLAUSE: // ANSI-only
GetCompInfoA(ResultReadClause);
break;
case GCS_COMPCLAUSE: // ANSI-only
GetCompInfoA(CompClause);
break;
#ifdef CUAS_ENABLE
case GCS_COMPGUIDATTR: // ANSI-only
if (CtfImmIsGuidMapEnable(hImc) && (pCompStr->dwPrivateSize >= sizeof(GUIDMAPATTRIBUTE)))
{
PGUIDMAPATTRIBUTE pGuidMap = (PGUIDMAPATTRIBUTE)((PBYTE)pCompStr + pCompStr->dwPrivateOffset);
if (pGuidMap != NULL)
{
GetPrivInfoA(pGuidMap, GuidMapAttr);
}
else
{
dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
}
}
else
{
dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
}
break;
#endif // CUAS_ENABLE
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.
*/
#if !defined(CUAS_ENABLE)
dwStrSize = InternalGetCompositionStringA(pCompStr, dwIndex,
NULL, 0, fAnsiImc, dwCodePage);
#else
dwStrSize = InternalGetCompositionStringA(hImc, pCompStr, dwIndex,
NULL, 0, fAnsiImc, dwCodePage);
#endif
lpStrA = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(CHAR));
if (lpStrA == NULL) {
RIPMSG0(RIP_WARNING, "InternalGetCompositionStringW: memory failure.");
return (LONG)IMM_ERROR_GENERAL;
}
#if !defined(CUAS_ENABLE)
dwStrSize = InternalGetCompositionStringA(pCompStr, dwIndex,
lpStrA, dwStrSize, fAnsiImc, dwCodePage);
#else
dwStrSize = InternalGetCompositionStringA(hImc, pCompStr, dwIndex,
lpStrA, dwStrSize, fAnsiImc, dwCodePage);
#endif
dwBufLen = MultiByteToWideChar(dwCodePage,
(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:
#ifdef CUAS_ENABLE
case GCS_COMPGUIDATTR:
#endif // CUAS_ENABLE
{
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;
#ifdef CUAS_ENABLE
case GCS_COMPGUIDATTR:
if (CtfImmIsGuidMapEnable(hImc) && (pCompStr->dwPrivateSize >= sizeof(GUIDMAPATTRIBUTE)))
{
PGUIDMAPATTRIBUTE pGuidMap = (PGUIDMAPATTRIBUTE)((PBYTE)pCompStr + pCompStr->dwPrivateOffset);
if (pGuidMap != NULL)
{
lpAttrA = (PBYTE)pGuidMap + pGuidMap->dwGuidMapAttrOffset;
dwAttrLenA = pGuidMap->dwGuidMapAttrLen;
dwIndexStr = GCS_COMPSTR;
break;
}
else
{
return (DWORD)(LONG)IMM_ERROR_GENERAL;
}
}
else
{
return (DWORD)(LONG)IMM_ERROR_GENERAL;
}
break;
#endif // CUAS_ENABLE
}
if (dwAttrLenA == 0) {
/*
* No CompAttr or CompReadAttr exists, do nothing.
*/
return 0;
}
#if !defined(CUAS_ENABLE)
dwStrSize = InternalGetCompositionStringW(pCompStr,
dwIndexStr, NULL, 0, fAnsiImc, dwCodePage);
#else
dwStrSize = InternalGetCompositionStringW(hImc, pCompStr,
dwIndexStr, NULL, 0, fAnsiImc, dwCodePage);
#endif
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;
}
#if !defined(CUAS_ENABLE)
dwStrSize = InternalGetCompositionStringW(pCompStr,
dwIndexStr, lpStrW, dwStrSize, fAnsiImc, dwCodePage);
#else
dwStrSize = InternalGetCompositionStringW(hImc, pCompStr,
dwIndexStr, lpStrW, dwStrSize, fAnsiImc, dwCodePage);
#endif
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) {
MultiByteSize = UnicodeToMultiByteSize(dwCodePage, &wc);
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, dwCodePage);
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),
dwCodePage);
}
break;
default:
dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
}
return (LONG)dwBufLen;
}
DWORD InternalGetCandidateListAtoW(
LPCANDIDATELIST lpCandListA,
LPCANDIDATELIST lpCandListW,
DWORD dwBufLen,
DWORD dwCodePage)
{
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(dwCodePage,
(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(dwCodePage,
(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,
DWORD dwCodePage)
{
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(dwCodePage,
(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(dwCodePage,
(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 dwCodePage)
{
DWORD dwCharPosW = 0;
while (dwCharPosA != 0) {
if (IsDBCSLeadByteEx(dwCodePage, *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 dwCodePage)
{
DWORD dwCharPosA = 0;
ULONG MultiByteSize;
while (dwCharPosW != 0) {
MultiByteSize = UnicodeToMultiByteSize(dwCodePage, lpwszCharStr);
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, // Note: font face name should use ACP for A/W conversion.
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, // Note: font face name should use ACP for A/W conversion.
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;
}
//////////////////////////////////////////////////////////////////////
// Reconversion support
//////////////////////////////////////////////////////////////////////
typedef enum {FROM_IME, FROM_APP} REQ_CALLER;
///////////////////////////////////////////////////////////////////////////////////
// ImmGetReconvertTotalSize
//
// calculate the appropriate size of the buffer, based on caller/ansi information
//
// History:
// 28-Feb-1997 hiroyama Created
///////////////////////////////////////////////////////////////////////////////////
DWORD ImmGetReconvertTotalSize(DWORD dwSize, REQ_CALLER eCaller, BOOL bAnsiTarget)
{
if (dwSize < sizeof(RECONVERTSTRING)) {
return 0;
}
if (bAnsiTarget) {
dwSize -= sizeof(RECONVERTSTRING);
if (eCaller == FROM_IME) {
dwSize /= 2;
} else {
dwSize *= 2;
}
dwSize += sizeof(RECONVERTSTRING);
}
return dwSize;
}
DWORD ImmReconversionWorker(
LPRECONVERTSTRING lpRecTo,
LPRECONVERTSTRING lpRecFrom,
BOOL bToAnsi,
DWORD dwCodePage)
{
INT i;
DWORD dwSize = 0;
UserAssert(lpRecTo);
UserAssert(lpRecFrom);
if (lpRecFrom->dwVersion != 0 || lpRecTo->dwVersion != 0) {
RIPMSG0(RIP_WARNING, "ImmReconversionWorker: dwVersion in lpRecTo or lpRecFrom is incorrect.");
return 0;
}
// Note:
// In any IME related structures, use the following principal.
// 1) xxxStrOffset is an actual offset, i.e. byte count.
// 2) xxxStrLen is a number of characters, i.e. TCHAR count.
//
// CalcCharacterPositionXtoY() takes TCHAR count so that we
// need to adjust xxxStrOffset if it's being converted. But you
// should be careful, because the actual position of the string
// is always at something like (LPBYTE)lpStruc + lpStruc->dwStrOffset.
//
if (bToAnsi) {
// Convert W to A
lpRecTo->dwStrOffset = sizeof *lpRecTo;
i = WideCharToMultiByte(dwCodePage,
(DWORD)0,
(LPWSTR)((LPSTR)lpRecFrom + lpRecFrom->dwStrOffset), // src
(INT)lpRecFrom->dwStrLen,
(LPSTR)lpRecTo + lpRecTo->dwStrOffset, // dest
(INT)lpRecFrom->dwStrLen * DBCS_CHARSIZE,
(LPSTR)NULL,
(LPBOOL)NULL);
lpRecTo->dwCompStrOffset =
CalcCharacterPositionWtoA(lpRecFrom->dwCompStrOffset / sizeof(WCHAR),
(LPWSTR)((LPBYTE)lpRecFrom + lpRecFrom->dwStrOffset),
dwCodePage)
* sizeof(CHAR);
lpRecTo->dwCompStrLen =
(CalcCharacterPositionWtoA(lpRecFrom->dwCompStrOffset / sizeof(WCHAR) +
lpRecFrom->dwCompStrLen,
(LPWSTR)((LPBYTE)lpRecFrom + lpRecFrom->dwStrOffset),
dwCodePage)
* sizeof(CHAR))
- lpRecTo->dwCompStrOffset;
lpRecTo->dwTargetStrOffset =
CalcCharacterPositionWtoA(lpRecFrom->dwTargetStrOffset / sizeof(WCHAR),
(LPWSTR)((LPBYTE)lpRecFrom +
lpRecFrom->dwStrOffset),
dwCodePage)
* sizeof(CHAR);
lpRecTo->dwTargetStrLen =
(CalcCharacterPositionWtoA(lpRecFrom->dwTargetStrOffset / sizeof(WCHAR) +
lpRecFrom->dwTargetStrLen,
(LPWSTR)((LPBYTE)lpRecFrom + lpRecFrom->dwStrOffset),
dwCodePage)
* sizeof(CHAR))
- lpRecTo->dwTargetStrOffset;
((LPSTR)lpRecTo)[lpRecTo->dwStrOffset + i] = '\0';
lpRecTo->dwStrLen = i * sizeof(CHAR);
dwSize = sizeof(RECONVERTSTRING) + ((i + 1) * sizeof(CHAR));
} else {
// AtoW
lpRecTo->dwStrOffset = sizeof *lpRecTo;
i = MultiByteToWideChar(dwCodePage,
(DWORD)MB_PRECOMPOSED,
(LPSTR)lpRecFrom + lpRecFrom->dwStrOffset, // src
(INT)lpRecFrom->dwStrLen,
(LPWSTR)((LPSTR)lpRecTo + lpRecTo->dwStrOffset), // dest
(INT)lpRecFrom->dwStrLen);
lpRecTo->dwCompStrOffset =
CalcCharacterPositionAtoW(lpRecFrom->dwCompStrOffset,
(LPSTR)lpRecFrom + lpRecFrom->dwStrOffset,
dwCodePage) * sizeof(WCHAR);
lpRecTo->dwCompStrLen =
((CalcCharacterPositionAtoW(lpRecFrom->dwCompStrOffset +
lpRecFrom->dwCompStrLen,
(LPSTR)lpRecFrom + lpRecFrom->dwStrOffset,
dwCodePage) * sizeof(WCHAR))
- lpRecTo->dwCompStrOffset) / sizeof(WCHAR);
lpRecTo->dwTargetStrOffset =
CalcCharacterPositionAtoW(lpRecFrom->dwTargetStrOffset,
(LPSTR)lpRecFrom + lpRecFrom->dwStrOffset,
dwCodePage) * sizeof(WCHAR);
lpRecTo->dwTargetStrLen =
((CalcCharacterPositionAtoW(lpRecFrom->dwTargetStrOffset +
lpRecFrom->dwTargetStrLen,
(LPSTR)lpRecFrom + lpRecFrom->dwStrOffset,
dwCodePage) * sizeof(WCHAR))
- lpRecTo->dwTargetStrOffset) / sizeof(WCHAR);
lpRecTo->dwStrLen = i; // Length is TCHAR count.
if (lpRecTo->dwSize >= (DWORD)(lpRecTo->dwStrOffset + (i + 1)* sizeof(WCHAR))) {
LPWSTR lpW = (LPWSTR)((LPSTR)lpRecTo + lpRecTo->dwStrOffset);
lpW[i] = L'\0';
}
dwSize = sizeof(RECONVERTSTRING) + ((i + 1) * sizeof(WCHAR));
}
return dwSize;
}
///////////////////////////////////////////////////////////////////////////////////
// ImmRequestMessageWorker
//
// worker function for WM_IME_REQUEST message
//
// History:
// 30-Mar-1997 hiroyama Created
///////////////////////////////////////////////////////////////////////////////////
LRESULT ImmRequestMessageWorker(HIMC hIMC, PWND pwnd, WPARAM wParam, LPARAM lParam, BOOL bAnsiOrigin)
{
// the (least) size of the structure given in lParam: for valid pointer checking
static CONST int nReqBufSize[][7] = {
{ // sizes if IME is UNICODE
sizeof(COMPOSITIONFORM), // IMR_COMPOSITIONWINDOW
sizeof(CANDIDATEFORM), // IMR_CANDIDATEWINDOW
sizeof(LOGFONTW), // IMR_COMPOSITIONFONT
sizeof(RECONVERTSTRING), // IMR_RECONVERTSTRING
sizeof(RECONVERTSTRING), // IMR_CONFIRMRECONVERTSTRING
sizeof(IMECHARPOSITION), // IMR_QUERYCHARPOSITION
sizeof(RECONVERTSTRING), // IMR_DOCUMENTFEED
},
{ // sizes if IME is ANSI
sizeof(COMPOSITIONFORM), // IMR_COMPOSITIONWINDOW
sizeof(CANDIDATEFORM), // IMR_CANDIDATEWINDOW
sizeof(LOGFONTA), // IMR_COMPOSITIONFONT
sizeof(RECONVERTSTRING), // IMR_RECONVERTSTRING
sizeof(RECONVERTSTRING), // IMR_CONFIRMRECONVERTSTRING
sizeof(IMECHARPOSITION), // IMR_QUERYCHARPOSITION
sizeof(RECONVERTSTRING), // IMR_DOCUMENTFEED
}
};
LRESULT lRet = 0L;
CONST BOOLEAN bAnsiTarget = !!TestWF(pwnd, WFANSIPROC); // TRUE if the target Window Proc is ANSI
LPBYTE lpReq = (LPBYTE)lParam; // return buffer (maybe allocated buffer)
LPBYTE lpNew = NULL; // buffer allocated within this function
DWORD dwSaveCharPos;
PCLIENTIMC pClientImc;
DWORD dwCodePage;
#define SEND_MESSAGE(bAnsi) ((bAnsi) ? SendMessageA : SendMessageW)
//////////////////////////////////////////////
// Parameter checking
// check wParam as sub messages
if (wParam == 0 || wParam > IMR_DOCUMENTFEED) { // wParam is not a proper sub message
RIPMSG1(RIP_WARNING, "ImmRequestMessageWorker: wParam(%lx) out of range.", wParam);
return 0L;
}
// Check if the pointer which is given through lParam points the proper memory block.
UserAssert(bAnsiOrigin == 0 || bAnsiOrigin == 1); // we'll use bAnsiOrigin as an index
// The first sub message IMR_COMPOSITIONWINDOW is 1, so substract 1 from wParam
if (lpReq && IsBadWritePtr(lpReq, nReqBufSize[bAnsiOrigin][wParam - 1])) {
RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: Bad pointer passed from IME to write");
return 0L;
}
// check the lpReq(==lParam): the spec does not allow lParam as NULL
// except IMR_RECONVERTSTRING and IMR_DOCUMENTFEED
if (wParam == IMR_RECONVERTSTRING || wParam == IMR_DOCUMENTFEED) {
//
// check version number
//
if (lpReq != NULL) {
LPRECONVERTSTRING lpReconv = (LPRECONVERTSTRING)lParam;
if (lpReconv->dwVersion != 0) {
RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid version number: %d",
lpReconv->dwVersion);
return 0L;
}
if (lpReconv->dwSize < sizeof(RECONVERTSTRING)) {
RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid dwSize: %d",
lpReconv->dwSize);
return 0L;
}
}
} else if (wParam == IMR_CONFIRMRECONVERTSTRING) {
// check if lParam is not NULL, and version of the structure is correct.
if (lpReq == NULL || ((LPRECONVERTSTRING)lpReq)->dwVersion != 0) {
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid argument or invalid version number");
return 0L;
}
} else if (lpReq == NULL) {
RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING,
"ImmRequestMessageWorker: lParam should not be NULL with this wParam(%lx).",
wParam);
return 0L;
}
// end parameter checking
////////////////////////////////////////////
pClientImc = ImmLockClientImc(hIMC);
if (pClientImc != NULL) {
dwCodePage = CImcCodePage(pClientImc);
ImmUnlockClientImc(pClientImc);
}
else {
dwCodePage = CP_ACP;
}
// allocate and prepare required buffer if we need A/W conversion
switch (wParam) {
case IMR_CONFIRMRECONVERTSTRING:
case IMR_RECONVERTSTRING:
case IMR_DOCUMENTFEED:
if (bAnsiOrigin != bAnsiTarget) {
if (lpReq != NULL) {
// IME wants not only the buffer size but the real reconversion information
DWORD dwSize = ImmGetReconvertTotalSize(((LPRECONVERTSTRING)lpReq)->dwSize, FROM_IME, bAnsiTarget);
LPRECONVERTSTRING lpReconv;
lpNew = ImmLocalAlloc(0, dwSize + sizeof(WCHAR));
if (lpNew == NULL) {
RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: failed to allocate a buffer for reconversion.");
return 0L;
}
lpReconv = (LPRECONVERTSTRING)lpNew;
// setup the information in the allocated structure
lpReconv->dwVersion = 0;
lpReconv->dwSize = dwSize;
//
// if it's confirmation message, we need to translate the contents
//
if (wParam == IMR_CONFIRMRECONVERTSTRING) {
ImmReconversionWorker(lpReconv, (LPRECONVERTSTRING)lParam, bAnsiTarget, dwCodePage);
}
}
}
break;
case IMR_COMPOSITIONFONT:
UserAssert(lpReq != NULL); // has been checked so far
if (bAnsiOrigin != bAnsiTarget) {
if (bAnsiTarget) {
lpNew = ImmLocalAlloc(0, sizeof(LOGFONTA));
} else {
lpNew = ImmLocalAlloc(0, sizeof(LOGFONTW));
}
if (lpNew == NULL) {
RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: IMR_COMPOSITIONFONT: failed to allocate memory for A/W conversion.");
return 0L;
}
}
break;
case IMR_QUERYCHARPOSITION:
UserAssert(lpReq != NULL);
if (bAnsiOrigin != bAnsiTarget) {
#define lpIMEPOS ((LPIMECHARPOSITION)lParam)
LPVOID lpstr;
DWORD dwLen;
dwSaveCharPos = lpIMEPOS->dwCharPos;
dwLen = (!bAnsiOrigin ? ImmGetCompositionStringW : ImmGetCompositionStringA)(hIMC, GCS_COMPSTR, 0, 0);
if (dwLen == 0) {
RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: IMR_QUERYCHARPOSITION no compositiong string.");
return 0L;
}
lpstr = ImmLocalAlloc(0, (dwLen + 1) * (!bAnsiOrigin ? sizeof(WCHAR) : sizeof(CHAR)));
if (lpstr == NULL) {
RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: IMR_QUERYCHARPOSITION: failed to allocate memory for A/W conversion.");
return 0L;
}
(!bAnsiOrigin ? ImmGetCompositionStringW : ImmGetCompositionStringA)(hIMC, GCS_COMPSTR, lpstr, dwLen);
if (bAnsiTarget) {
lpIMEPOS->dwCharPos = CalcCharacterPositionWtoA(lpIMEPOS->dwCharPos, lpstr, dwCodePage);
} else {
lpIMEPOS->dwCharPos = CalcCharacterPositionAtoW(lpIMEPOS->dwCharPos, lpstr, dwCodePage);
}
ImmLocalFree(lpstr);
}
break;
default:
UserAssert(lpReq != NULL); // has been checked so far
break;
}
if (lpNew) {
// if we allocated the buffer, let lpReq point it; lpNew is used later to free memory
lpReq = lpNew;
}
//////////////////////////////////
lRet = SEND_MESSAGE(bAnsiTarget)(HW(pwnd), WM_IME_REQUEST, wParam, (LPARAM)lpReq);
//////////////////////////////////
// copy back the results from WinProc to IME's buffer (only if conversion is needed)
if (bAnsiOrigin != bAnsiTarget) {
switch (wParam) {
case IMR_RECONVERTSTRING:
case IMR_DOCUMENTFEED:
// Note: by definition, we don't have to do back-conversion for IMR_CONFIRMRECONVERTSTRING
if (lRet != 0) {
// IME wants the buffer size
lRet = ImmGetReconvertTotalSize((DWORD)lRet, FROM_APP, bAnsiTarget);
if (lRet < sizeof(RECONVERTSTRING)) {
RIPMSG1(RIP_WARNING, "ImmRequestMessageWorker: return value from application %d is invalid.", lRet);
lRet = 0;
} else if (lpReq) {
// We need to perform the A/W conversion of the contents
if (!ImmReconversionWorker((LPRECONVERTSTRING)lParam, (LPRECONVERTSTRING)lpReq, bAnsiOrigin, dwCodePage)) {
lRet = 0; // Error !
}
}
}
break;
case IMR_COMPOSITIONFONT:
if (bAnsiOrigin) {
LFontWtoLFontA((LPLOGFONTW)lpNew, (LPLOGFONTA)lParam);
} else {
LFontAtoLFontW((LPLOGFONTA)lpNew, (LPLOGFONTW)lParam);
}
break;
case IMR_QUERYCHARPOSITION:
UserAssert((LPVOID)lParam != NULL);
lpIMEPOS->dwCharPos = dwSaveCharPos;
#undef lpIMEPOS
break;
default:
break;
}
}
if (lpNew) {
// buffer has been allocated, free it before returning
ImmLocalFree(lpNew);
}
return lRet;
}
/**************************************************************************\
* ImmRequestMessage: Send WM_IME_REQUEST message to the given HIMC window
*
* IME function
*
* 27-Feb-1997 hiroyama Created
\**************************************************************************/
LRESULT ImmRequestMessageAorW(HIMC hIMC, WPARAM wParam, LPARAM lParam, BOOL bAnsiOrigin)
{
LPINPUTCONTEXT lpInputContext;
PWND pwnd;
LRESULT lRet = 0L;
DWORD dwThreadId = GetInputContextThread(hIMC);
if (dwThreadId != GetCurrentThreadId()) {
RIPMSG1(RIP_WARNING,
"ImmRequestMessageAorW:: Invalid input context access %lx.", hIMC);
return lRet;
}
if (hIMC == NULL || (lpInputContext = ImmLockIMC(hIMC)) == NULL) {
RIPMSG1(RIP_WARNING, "ImmRequestMessage: Invalid hImc %lx.", hIMC);
return 0L;
}
// check if the window of the input context is valid
if ((pwnd = ValidateHwnd(lpInputContext->hWnd)) == NULL) {
RIPMSG1(RIP_WARNING, "ImmRequestMessage: Invalid hWnd %lx.", lpInputContext->hWnd);
} else {
// check if the message is being sent inter thread
if (PtiCurrent() != GETPTI(pwnd)) {
RIPMSG0(RIP_WARNING, "ImmRequestMessage: IME Attempt to send IMR_ message to different thread.");
} else {
lRet = ImmRequestMessageWorker(hIMC, pwnd, wParam, lParam, bAnsiOrigin);
}
}
ImmUnlockIMC(hIMC);
return lRet;
}
LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
{
return ImmRequestMessageAorW(hIMC, wParam, lParam, TRUE /* ANSI */);
}
LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
{
return ImmRequestMessageAorW(hIMC, wParam, lParam, FALSE /* not ANSI */);
}