/**************************************************************************\ * 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 */); }