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.
1169 lines
28 KiB
1169 lines
28 KiB
/*++
|
|
|
|
Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
context.cpp
|
|
|
|
Abstract:
|
|
|
|
This file implements the Input Context Class.
|
|
|
|
Author:
|
|
|
|
Revision History:
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#include "private.h"
|
|
|
|
#include "cdimm.h"
|
|
#include "context.h"
|
|
#include "globals.h"
|
|
#include "defs.h"
|
|
#include "delay.h"
|
|
#include "computil.h"
|
|
|
|
|
|
BOOL
|
|
CInputContext::_CreateDefaultInputContext(
|
|
IN DWORD dwPrivateSize,
|
|
IN BOOL fUnicode,
|
|
IN BOOL fCiceroActivated
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a default input context
|
|
|
|
Arguments:
|
|
|
|
dwPrivateSize - [in] Unsigned integer long value that contains the size of private IMCC
|
|
data.
|
|
|
|
Return Value:
|
|
|
|
Returns TRUE if successful, or an error code otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
// create a default IMC for this thread
|
|
if (IsOnImm()) {
|
|
// On FE systems, we use system allocated HIMCs
|
|
// but here we want to use the thread default HIMC
|
|
// which the system has already allocated.
|
|
|
|
CActiveIMM *_pActiveIMM = GetTLS();
|
|
if (_pActiveIMM == NULL)
|
|
return FALSE;
|
|
|
|
// consider: find a better way to get the def HIMC!
|
|
HWND hWnd = CreateWindow(TEXT("STATIC"), TEXT(""), WS_DISABLED | WS_POPUP,
|
|
0, 0, 0, 0, 0, 0, g_hInst, NULL);
|
|
if (hWnd)
|
|
{
|
|
Imm32_GetContext(hWnd, &_hDefaultIMC);
|
|
if (_hDefaultIMC)
|
|
Imm32_ReleaseContext(hWnd, _hDefaultIMC);
|
|
|
|
DestroyWindow(hWnd);
|
|
}
|
|
|
|
if (_hDefaultIMC == NULL)
|
|
return FALSE;
|
|
|
|
CContextList::CLIENT_IMC_FLAG client_flag = (fUnicode ? CContextList::IMCF_UNICODE
|
|
: CContextList::IMCF_NONE );
|
|
ContextList.SetAt(_hDefaultIMC, client_flag);
|
|
|
|
// we can't create the cicero context until ITfThreadMgr::Activate has been called
|
|
// we'll do this later if we need to
|
|
if (fCiceroActivated)
|
|
{
|
|
if (FAILED(CreateAImeContext(_hDefaultIMC))) {
|
|
ContextList.RemoveKey(_hDefaultIMC);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
_pActiveIMM->_ResizePrivateIMCC(_hDefaultIMC, dwPrivateSize);
|
|
}
|
|
else {
|
|
if (FAILED(CreateContext(dwPrivateSize, fUnicode, &_hDefaultIMC, fCiceroActivated)))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CInputContext::_DestroyDefaultInputContext(
|
|
)
|
|
{
|
|
// destroy a default IMC for this thread
|
|
if (! IsOnImm()) {
|
|
if (FAILED(DestroyContext(_hDefaultIMC)))
|
|
return FALSE;
|
|
}
|
|
else {
|
|
if (FAILED(DestroyAImeContext(_hDefaultIMC)))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::UpdateInputContext(
|
|
IN HIMC hIMC,
|
|
IN DWORD dwPrivateDataSize
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
DIMM_IMCLock lpIMC(hIMC);
|
|
if (FAILED(hr = lpIMC.GetResult()))
|
|
return hr;
|
|
|
|
/*
|
|
* hPrivate
|
|
*/
|
|
if (FAILED(hr = UpdateIMCC(&lpIMC->hPrivate, dwPrivateDataSize))) {
|
|
TraceMsg(TF_ERROR, "CInputContext::UpdateInputContext: hIMCC::hRivate failure");
|
|
return hr;
|
|
}
|
|
|
|
/*
|
|
* hMsgBuf
|
|
*/
|
|
if (FAILED(hr = UpdateIMCC(&lpIMC->hMsgBuf, sizeof(UINT)))) {
|
|
TraceMsg(TF_ERROR, "CInputContext::UpdateInputContext: hIMCC::hMsgBuf failure");
|
|
return hr;
|
|
}
|
|
|
|
lpIMC->dwNumMsgBuf = 0;
|
|
|
|
/*
|
|
* hGuideLine
|
|
*/
|
|
if (FAILED(hr = UpdateIMCC(&lpIMC->hGuideLine, sizeof(GUIDELINE)))) {
|
|
TraceMsg(TF_ERROR, "CInputContext::UpdateInputContext: hIMCC::hGuideLine failure");
|
|
return hr;
|
|
}
|
|
|
|
DIMM_IMCCLock<GUIDELINE> pGuideLine(lpIMC->hGuideLine);
|
|
if (FAILED(hr = pGuideLine.GetResult())) {
|
|
TraceMsg(TF_ERROR, "CInputContext::UpdateInputContext: can not lock hGuideLine");
|
|
return hr;
|
|
}
|
|
|
|
pGuideLine->dwSize = sizeof(GUIDELINE);
|
|
|
|
/*
|
|
* hCandInfo
|
|
*/
|
|
if (FAILED(hr = UpdateIMCC(&lpIMC->hCandInfo, sizeof(CANDIDATEINFO)))) {
|
|
TraceMsg(TF_ERROR, "CInputContext::UpdateInputContext: hIMCC::hCandInfo failure");
|
|
return hr;
|
|
}
|
|
|
|
DIMM_IMCCLock<CANDIDATEINFO> pCandInfo(lpIMC->hCandInfo);
|
|
if (FAILED(hr = pCandInfo.GetResult())) {
|
|
TraceMsg(TF_ERROR, "CInputContext::UpdateInputContext: can not lock hCandInfo");
|
|
return hr;
|
|
}
|
|
|
|
pCandInfo->dwSize = sizeof(CANDIDATEINFO);
|
|
|
|
/*
|
|
* hCompStr
|
|
*/
|
|
if (FAILED(hr = UpdateIMCC(&lpIMC->hCompStr, sizeof(COMPOSITIONSTRING_AIMM12)))) {
|
|
TraceMsg(TF_ERROR, "CInputContext::UpdateInputContext: hIMCC::hCompStr failure");
|
|
return hr;
|
|
}
|
|
|
|
DIMM_IMCCLock<COMPOSITIONSTRING_AIMM12> lpCompStr(lpIMC->hCompStr);
|
|
if (FAILED(hr = lpCompStr.GetResult())) {
|
|
TraceMsg(TF_ERROR, "CInputContext::UpdateInputContext: can not lock hCompStr");
|
|
return hr;
|
|
}
|
|
|
|
lpCompStr->CompStr.dwSize = sizeof(COMPOSITIONSTRING_AIMM12);
|
|
|
|
/*
|
|
* AIME private context.
|
|
*/
|
|
if (lpIMC->m_pContext != NULL) {
|
|
hr = lpIMC->m_pContext->UpdateAImeContext(hIMC);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::ResizePrivateIMCC(
|
|
IN HIMC hIMC,
|
|
IN DWORD dwPrivateSize
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Make sure Private context data size
|
|
DIMM_IMCLock imc(hIMC);
|
|
if (FAILED(hr = imc.GetResult()))
|
|
return hr;
|
|
|
|
return UpdateIMCC(&imc->hPrivate, dwPrivateSize);
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::UpdateIMCC(
|
|
IN HIMCC* phIMCC,
|
|
IN DWORD dwRequestSize
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwSize;
|
|
DWORD dwLockCount;
|
|
const DWORD IMCC_ALLOC_TOOLARGE = 0x1000;
|
|
|
|
if (*phIMCC == NULL) {
|
|
hr = CreateIMCC(dwRequestSize, phIMCC);
|
|
}
|
|
else {
|
|
|
|
hr = GetIMCCSize(*phIMCC, &dwSize);
|
|
if (SUCCEEDED(hr)) {
|
|
if (dwSize < dwRequestSize ||
|
|
dwSize > IMCC_ALLOC_TOOLARGE) {
|
|
hr = GetIMCCLockCount(*phIMCC, &dwLockCount);
|
|
if (SUCCEEDED(hr)) {
|
|
ASSERT(dwLockCount == 0);
|
|
if (dwLockCount != 0) {
|
|
TraceMsg(TF_ERROR, "CInputContext::UpdateIMCC: Unlock resource");
|
|
|
|
do {
|
|
if (FAILED(hr = _UnlockIMCC(*phIMCC)))
|
|
return hr;
|
|
|
|
if (FAILED(hr = GetIMCCLockCount(*phIMCC, &dwLockCount)))
|
|
return hr;
|
|
} while(dwLockCount);
|
|
|
|
if (SUCCEEDED(hr = DestroyIMCC(*phIMCC)))
|
|
hr = CreateIMCC(dwRequestSize, phIMCC);
|
|
}
|
|
else {
|
|
HIMCC hResizeIMCC;
|
|
hr = ReSizeIMCC(*phIMCC, dwRequestSize, &hResizeIMCC);
|
|
if (SUCCEEDED(hr)) {
|
|
*phIMCC = hResizeIMCC;
|
|
}
|
|
else {
|
|
TraceMsg(TF_WARNING, "CInputContext::UpdateIMCC: Resize hIMCC %lX failure", dwRequestSize);
|
|
|
|
if (SUCCEEDED(hr = DestroyIMCC(*phIMCC)))
|
|
hr = CreateIMCC(dwRequestSize, phIMCC);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CInputContext::EnumInputContext(
|
|
DWORD idThread,
|
|
IMCENUMPROC lpfn,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
UINT cHimc;
|
|
|
|
/*
|
|
* Get the hIMC list. It is returned in a block of memory allocated.
|
|
*/
|
|
if ((cHimc = BuildHimcList(idThread, NULL)) == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL fSuccess = FALSE;
|
|
|
|
HIMC* pHimc = new HIMC[cHimc];
|
|
if (pHimc) {
|
|
BuildHimcList(idThread, pHimc);
|
|
|
|
/*
|
|
* Loop through the input contexts, call the function pointer back for each one.
|
|
* End loop if either FALSE is returned or the end-of-list is reached.
|
|
*/
|
|
UINT index;
|
|
for (index = 0; index < cHimc; index++) {
|
|
if (! (fSuccess = (*lpfn)(pHimc[index], lParam)) )
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Free up buffer and return status - TRUE if entire list was enumerated,
|
|
* FALSE otherwise.
|
|
*/
|
|
delete [] pHimc;
|
|
}
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
DWORD
|
|
CInputContext::BuildHimcList(
|
|
DWORD idThread,
|
|
HIMC pHimc[]
|
|
)
|
|
{
|
|
if (idThread != 0 && idThread != GetCurrentThreadId())
|
|
return 0;
|
|
|
|
if (pHimc != NULL) {
|
|
POSITION pos = ContextList.GetStartPosition();
|
|
int index;
|
|
for (index = 0; index < ContextList.GetCount(); index++) {
|
|
ContextList.GetNextHimc(pos, &pHimc[index]);
|
|
}
|
|
}
|
|
return (DWORD)(ContextList.GetCount());
|
|
}
|
|
|
|
/*
|
|
* AIMM Input Context (hIMC) API Methods.
|
|
*/
|
|
HRESULT
|
|
CInputContext::CreateContext(
|
|
IN DWORD dwPrivateSize,
|
|
IN BOOL fUnicode,
|
|
OUT HIMC *phIMC,
|
|
IN BOOL fCiceroActivated,
|
|
IN DWORD fdwInitConvMode,
|
|
IN BOOL fInitOpen
|
|
)
|
|
{
|
|
TraceMsg(TF_API, TEXT("CInputContext::CreateContext"));
|
|
|
|
*phIMC = NULL;
|
|
|
|
if (IsOnImm()) {
|
|
|
|
// defer to the system IMM
|
|
HRESULT hr;
|
|
CActiveIMM *_pActiveIMM = GetTLS();
|
|
if (_pActiveIMM == NULL)
|
|
return E_FAIL;
|
|
|
|
if (FAILED(hr = Imm32_CreateContext(phIMC)))
|
|
return hr;
|
|
|
|
CContextList::CLIENT_IMC_FLAG client_flag = (fUnicode ? CContextList::IMCF_UNICODE
|
|
: CContextList::IMCF_NONE );
|
|
ContextList.SetAt(*phIMC, client_flag);
|
|
|
|
// we can't create the cicero context until ITfThreadMgr::Activate has been called
|
|
// we'll do this later if we need to
|
|
if (fCiceroActivated)
|
|
{
|
|
if (FAILED(hr=CreateAImeContext(*phIMC))) {
|
|
Imm32_DestroyContext(*phIMC);
|
|
ContextList.RemoveKey(*phIMC);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
_pActiveIMM->_ResizePrivateIMCC(*phIMC, dwPrivateSize);
|
|
}
|
|
else {
|
|
HIMC hIMC = static_cast<HIMC>(LocalAlloc(LHND, sizeof(INPUTCONTEXT_AIMM12)));
|
|
|
|
CContextList::CLIENT_IMC_FLAG client_flag = (fUnicode ? CContextList::IMCF_UNICODE
|
|
: CContextList::IMCF_NONE );
|
|
ContextList.SetAt(hIMC, client_flag);
|
|
|
|
/*
|
|
* Ready to use hIMC
|
|
*/
|
|
DIMM_IMCLock lpIMC(hIMC);
|
|
if (lpIMC.Valid()) {
|
|
//
|
|
// Initialize context data.
|
|
//
|
|
lpIMC->dwNumMsgBuf = 0;
|
|
lpIMC->fOpen = fInitOpen;
|
|
lpIMC->fdwConversion = fdwInitConvMode;
|
|
lpIMC->fdwSentence = 0;
|
|
lpIMC->m_pContext = NULL;
|
|
|
|
for (UINT i = 0; i < 4; i++) {
|
|
lpIMC->cfCandForm[i].dwIndex = (DWORD)(-1);
|
|
}
|
|
|
|
HRESULT hr;
|
|
|
|
// we can't create the cicero context until ITfThreadMgr::Activate has been called
|
|
// we'll do this later if we need to
|
|
if (fCiceroActivated)
|
|
{
|
|
if (FAILED(hr=CreateAImeContext(hIMC))) {
|
|
DestroyContext(hIMC);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
if (FAILED(CreateIMCC(sizeof(COMPOSITIONSTRING_AIMM12), &lpIMC->hCompStr)) ||
|
|
FAILED(CreateIMCC(sizeof(CANDIDATEINFO), &lpIMC->hCandInfo)) ||
|
|
FAILED(CreateIMCC(sizeof(GUIDELINE), &lpIMC->hGuideLine)) ||
|
|
FAILED(CreateIMCC(sizeof(DWORD), &lpIMC->hMsgBuf)) ||
|
|
FAILED(CreateIMCC(dwPrivateSize, &lpIMC->hPrivate)) ) {
|
|
|
|
DestroyContext((HIMC)lpIMC);
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
else {
|
|
*phIMC = hIMC;
|
|
}
|
|
}
|
|
else {
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::DestroyContext(
|
|
IN HIMC hIMC
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::DestroyContext");
|
|
|
|
if (IsOnImm()) {
|
|
HRESULT hr;
|
|
|
|
if (FAILED(hr=DestroyAImeContext(hIMC)))
|
|
return hr;
|
|
|
|
ContextList.RemoveKey(hIMC);
|
|
|
|
return Imm32_DestroyContext(hIMC);
|
|
}
|
|
else {
|
|
{
|
|
DIMM_IMCLock pIMC(hIMC);
|
|
if (!pIMC.Valid())
|
|
return E_FAIL;
|
|
|
|
if (FAILED(DestroyIMCC(pIMC->hCompStr)) ||
|
|
FAILED(DestroyIMCC(pIMC->hCandInfo)) ||
|
|
FAILED(DestroyIMCC(pIMC->hGuideLine)) ||
|
|
FAILED(DestroyIMCC(pIMC->hMsgBuf)) ||
|
|
FAILED(DestroyIMCC(pIMC->hPrivate)) ) {
|
|
return E_FAIL;
|
|
}
|
|
HRESULT hr;
|
|
if (FAILED(hr=DestroyAImeContext(hIMC)))
|
|
return hr;
|
|
|
|
ContextList.RemoveKey(hIMC);
|
|
} // pIMC dtor called here! We must unlock hIMC before calling LocalFree
|
|
|
|
return LocalFree(hIMC) ? E_FAIL : S_OK;
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::AssociateContext(
|
|
IN HWND hWnd,
|
|
IN HIMC hIMC,
|
|
OUT HIMC *phPrev
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::AssociateContext");
|
|
|
|
if (!IsWindow(hWnd))
|
|
return E_INVALIDARG;
|
|
|
|
DWORD dwProcessId;
|
|
if (hIMC && ! ContextLookup(hIMC, &dwProcessId))
|
|
return E_ACCESSDENIED;
|
|
|
|
HRESULT hr = GetContext(hWnd, phPrev);
|
|
|
|
AssociateList.SetAt(hWnd, hIMC);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::AssociateContextEx(
|
|
IN HWND hWnd,
|
|
IN HIMC hIMC,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::AssociateContextEx");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::GetContext(
|
|
IN HWND hWnd,
|
|
OUT HIMC* phIMC
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetContext");
|
|
|
|
if (hWnd == NULL || ! IsWindow(hWnd)) {
|
|
TraceMsg(TF_WARNING, "CInputContext::GetContext: Invalid window handle %x", hWnd);
|
|
return E_FAIL;
|
|
}
|
|
|
|
HIMC hIMC = _hDefaultIMC;
|
|
BOOL ret = AssociateList.Lookup(hWnd, hIMC);
|
|
if (! ret) {
|
|
if (IsOnImm()) {
|
|
Imm32_GetContext(hWnd, &hIMC);
|
|
|
|
if (hIMC) {
|
|
/*
|
|
* Guaranty of Win98 IMM code that Win98 have a reference count
|
|
* of GetContext/ReleaseContext. If under ref cnt occurred, then
|
|
* apps had the AV in the IMM code.
|
|
* Because it ref cnt keeps the 32bit hIMC data segment for refer
|
|
* from 16bit code. When ref cnt is zero, hIMC's data segment has been freed.
|
|
* Of course, AIMM1.2's ReleaseContext nothing else to do.
|
|
*/
|
|
Imm32_ReleaseContext(hWnd, hIMC);
|
|
}
|
|
}
|
|
}
|
|
*phIMC = hIMC;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::GetIMCLockCount(
|
|
IN HIMC hIMC,
|
|
OUT DWORD* pdwLockCount
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetIMCLockCount");
|
|
|
|
if (IsOnImm()) {
|
|
return Imm32_GetIMCLockCount(hIMC, pdwLockCount);
|
|
}
|
|
else {
|
|
*pdwLockCount = LocalFlags(hIMC) & LMEM_LOCKCOUNT;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::CreateAImeContext(
|
|
HIMC hIMC
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
DIMM_IMCLock imc(hIMC);
|
|
if (FAILED(hr=imc.GetResult()))
|
|
return hr;
|
|
|
|
IAImeContext* pAImeContext;
|
|
extern HRESULT CAImeContext_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj);
|
|
|
|
hr = CAImeContext_CreateInstance(NULL, IID_IAImeContext, (void**)&pAImeContext);
|
|
|
|
if (FAILED(hr)) {
|
|
TraceMsg(TF_ERROR, "CreateAImeContext failed");
|
|
return hr;
|
|
}
|
|
|
|
return pAImeContext->CreateAImeContext(hIMC, m_pActiveIME);
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::DestroyAImeContext(
|
|
HIMC hIMC
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
DIMM_IMCLock imc(hIMC);
|
|
if (FAILED(hr=imc.GetResult()))
|
|
return hr;
|
|
|
|
// imc->m_pContext may be NULL if ITfThreadMgr::Activate has not been called
|
|
if (imc->m_pContext == NULL)
|
|
return S_OK;
|
|
|
|
//
|
|
// Backup IAImeContext pointer and NULL out in imc->m_pContext.
|
|
// DestroyAImeContext::pdim->Pop maybe calls ActivateAssembly if it is in queueing.
|
|
// ActivateAssembly maybe changes keyboard layout between Cicero and Real IME hKL.
|
|
// It happens called ImeActivateLayout from IMM32 and this function updates input context.
|
|
// However, imc->m_pContext's object already gone and occurred AV when touch NULL object.
|
|
// This NULL out is previent AV in the imc->m_pContext object.
|
|
//
|
|
IAImeContext* pContext = imc->m_pContext;
|
|
imc->m_pContext = NULL;
|
|
|
|
hr = pContext->DestroyAImeContext(hIMC);
|
|
|
|
pContext->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*
|
|
* AIMM Input Context Components (hIMCC) API Methods.
|
|
*/
|
|
HRESULT
|
|
CInputContext::CreateIMCC(
|
|
IN DWORD dwSize,
|
|
OUT HIMCC *phIMCC
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::CreateIMCC");
|
|
|
|
if (IsOnImm()) {
|
|
return Imm32_CreateIMCC(dwSize, phIMCC);
|
|
}
|
|
else {
|
|
if ((*phIMCC = static_cast<HIMCC>(LocalAlloc(LHND, dwSize+sizeof(DWORD)))) == NULL)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::DestroyIMCC(
|
|
IN HIMCC hIMCC
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::DestroyIMCC");
|
|
|
|
if (IsOnImm()) {
|
|
return Imm32_DestroyIMCC(hIMCC);
|
|
}
|
|
else {
|
|
return LocalFree(hIMCC) ? E_FAIL : S_OK;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::GetIMCCSize(
|
|
IN HIMCC hIMCC,
|
|
OUT DWORD *pdwSize
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetIMCCSize");
|
|
|
|
if (hIMCC == NULL) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (IsOnImm()) {
|
|
return Imm32_GetIMCCSize(hIMCC, pdwSize);
|
|
}
|
|
else {
|
|
*pdwSize = (DWORD)LocalSize(hIMCC);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::ReSizeIMCC(
|
|
IN HIMCC hIMCC,
|
|
IN DWORD dwSize,
|
|
OUT HIMCC *phIMCC
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::ReSizeIMCC");
|
|
|
|
if (hIMCC == NULL) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (IsOnImm()) {
|
|
return Imm32_ReSizeIMCC(hIMCC, dwSize, phIMCC);
|
|
}
|
|
else {
|
|
if ((*phIMCC = (HIMCC)LocalReAlloc(hIMCC, dwSize+sizeof(DWORD), LHND)) == NULL) {
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::GetIMCCLockCount(
|
|
IN HIMCC hIMCC,
|
|
OUT DWORD* pdwLockCount
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetIMCLockCount");
|
|
|
|
if (IsOnImm()) {
|
|
return Imm32_GetIMCCLockCount(hIMCC, pdwLockCount);
|
|
}
|
|
else {
|
|
*pdwLockCount = LocalFlags(hIMCC) & LMEM_LOCKCOUNT;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* AIMM Open Status API Methods
|
|
*/
|
|
HRESULT
|
|
CInputContext::GetOpenStatus(
|
|
IN HIMC hIMC
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetOpenStatus");
|
|
|
|
DIMM_IMCLock lpIMC(hIMC);
|
|
if (lpIMC.Invalid())
|
|
return E_FAIL;
|
|
|
|
return (lpIMC->fOpen ? S_OK : S_FALSE);
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::SetOpenStatus(
|
|
IN DIMM_IMCLock& lpIMC,
|
|
IN BOOL fOpen,
|
|
OUT BOOL* pfOpenChg
|
|
)
|
|
{
|
|
DWORD dwOpenStatus;
|
|
DWORD dwConversion;
|
|
|
|
TraceMsg(TF_API, "CInputContext::SetOpenStatus");
|
|
|
|
*pfOpenChg = FALSE;
|
|
|
|
if (lpIMC->fOpen != fOpen) {
|
|
lpIMC->fOpen = fOpen;
|
|
*pfOpenChg = TRUE;
|
|
}
|
|
|
|
if (*pfOpenChg) {
|
|
dwOpenStatus = (DWORD)lpIMC->fOpen;
|
|
dwConversion = (DWORD)lpIMC->fdwConversion;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* AIMM Conversion Status API Methods
|
|
*/
|
|
HRESULT
|
|
CInputContext::GetConversionStatus(
|
|
IN HIMC hIMC,
|
|
OUT LPDWORD lpfdwConversion,
|
|
OUT LPDWORD lpfdwSentence
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetConversionStatus");
|
|
|
|
if (IsOnImm()) {
|
|
return Imm32_GetConversionStatus(hIMC, lpfdwConversion, lpfdwSentence);
|
|
}
|
|
|
|
DIMM_IMCLock pIMC(hIMC);
|
|
if (pIMC.Invalid())
|
|
return E_FAIL;
|
|
|
|
*lpfdwSentence = pIMC->fdwSentence;
|
|
*lpfdwConversion = pIMC->fdwConversion;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::SetConversionStatus(
|
|
IN DIMM_IMCLock& lpIMC,
|
|
IN DWORD fdwConversion,
|
|
IN DWORD fdwSentence,
|
|
OUT BOOL* pfConvModeChg,
|
|
OUT BOOL* pfSentenceChg,
|
|
OUT DWORD* pfdwOldConversion,
|
|
OUT DWORD* pfdwOldSentence
|
|
)
|
|
{
|
|
DWORD dwOpenStatus;
|
|
DWORD dwConversion;
|
|
|
|
TraceMsg(TF_API, "CInputContext::SetConversionStatus");
|
|
|
|
if (fdwConversion != lpIMC->fdwConversion) {
|
|
if ((fdwConversion & IME_CMODE_LANGUAGE) == IME_CMODE_KATAKANA) {
|
|
TraceMsg(TF_WARNING, "SetConversionStatus: wrong fdwConversion");
|
|
}
|
|
*pfdwOldConversion = lpIMC->fdwConversion;
|
|
lpIMC->fdwConversion = fdwConversion;
|
|
*pfConvModeChg = TRUE;
|
|
}
|
|
|
|
if (fdwSentence != lpIMC->fdwSentence) {
|
|
*pfdwOldSentence = lpIMC->fdwSentence;
|
|
lpIMC->fdwSentence = fdwSentence;
|
|
*pfSentenceChg = TRUE;
|
|
}
|
|
|
|
if (*pfConvModeChg) {
|
|
dwOpenStatus = (DWORD)lpIMC->fOpen;
|
|
dwConversion = lpIMC->fdwConversion;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* AIMM Status Window Pos API Methods
|
|
*/
|
|
HRESULT WINAPI
|
|
CInputContext::GetStatusWindowPos(
|
|
IN HIMC hIMC,
|
|
OUT LPPOINT lpCandidate
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetStatusWindowPos");
|
|
|
|
if (IsOnImm()) {
|
|
return Imm32_GetStatusWindowPos(hIMC, lpCandidate);
|
|
}
|
|
|
|
if (hIMC == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
DIMM_IMCLock pIMC(hIMC);
|
|
if (pIMC.Invalid())
|
|
return E_FAIL;
|
|
|
|
if (pIMC->fdwInit & INIT_STATUSWNDPOS) {
|
|
*lpCandidate = pIMC->ptStatusWndPos;
|
|
return S_OK;
|
|
}
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::SetStatusWindowPos(
|
|
IN DIMM_IMCLock& lpIMC,
|
|
IN LPPOINT lpptPos
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::SetStatusWindowPos");
|
|
|
|
lpIMC->ptStatusWndPos = *lpptPos;
|
|
lpIMC->fdwInit |= INIT_STATUSWNDPOS;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* AIMM Composition String API Methods
|
|
*/
|
|
HRESULT
|
|
CInputContext::GetCompositionString(
|
|
IN DIMM_IMCCLock<COMPOSITIONSTRING_AIMM12>& lpCompStr,
|
|
IN DWORD dwIndex,
|
|
IN LONG*& lpCopied,
|
|
IN size_t size
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TraceMsg(TF_API, "CInputContext::GetCompositionStringA(LONG*)");
|
|
|
|
switch (dwIndex) {
|
|
case GCS_COMPSTR:
|
|
hr = GetCompInfo(size, lpCompStr->CompStr.dwCompStrLen, lpCopied);
|
|
break;
|
|
case GCS_COMPREADSTR:
|
|
hr = GetCompInfo(size, lpCompStr->CompStr.dwCompReadStrLen, lpCopied);
|
|
break;
|
|
case GCS_RESULTSTR:
|
|
hr = GetCompInfo(size, lpCompStr->CompStr.dwResultStrLen, lpCopied);
|
|
break;
|
|
case GCS_RESULTREADSTR:
|
|
hr = GetCompInfo(size, lpCompStr->CompStr.dwResultReadStrLen, lpCopied);
|
|
break;
|
|
|
|
case GCS_COMPATTR:
|
|
hr = GetCompInfo(size, lpCompStr->CompStr.dwCompAttrLen, lpCopied);
|
|
break;
|
|
case GCS_COMPREADATTR:
|
|
hr = GetCompInfo(size, lpCompStr->CompStr.dwCompReadAttrLen, lpCopied);
|
|
break;
|
|
case GCS_COMPREADCLAUSE:
|
|
hr = GetCompInfo(size, lpCompStr->CompStr.dwCompReadClauseLen, lpCopied);
|
|
break;
|
|
case GCS_RESULTCLAUSE:
|
|
hr = GetCompInfo(size, lpCompStr->CompStr.dwResultClauseLen, lpCopied);
|
|
break;
|
|
case GCS_RESULTREADCLAUSE:
|
|
hr = GetCompInfo(size, lpCompStr->CompStr.dwResultReadClauseLen, lpCopied);
|
|
break;
|
|
case GCS_COMPCLAUSE:
|
|
hr = GetCompInfo(size, lpCompStr->CompStr.dwCompClauseLen, lpCopied);
|
|
break;
|
|
|
|
case GCS_CURSORPOS:
|
|
*lpCopied = lpCompStr->CompStr.dwCursorPos;
|
|
hr = S_OK;
|
|
break;
|
|
case GCS_DELTASTART:
|
|
*lpCopied = lpCompStr->CompStr.dwDeltaStart;
|
|
hr = S_OK;
|
|
break;
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
*lpCopied = IMM_ERROR_GENERAL; // ala Win32
|
|
break;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*
|
|
* AIMM Composition Font API Methods
|
|
*/
|
|
HRESULT
|
|
CInputContext::GetCompositionFont(
|
|
IN DIMM_IMCLock& lpIMC,
|
|
OUT LOGFONTAW* lplf,
|
|
IN BOOL fUnicode
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetCompositionFont");
|
|
|
|
if ((lpIMC->fdwInit & INIT_LOGFONT) == INIT_LOGFONT) {
|
|
if (fUnicode)
|
|
*(&lplf->W) = lpIMC->lfFont.W;
|
|
else
|
|
*(&lplf->A) = lpIMC->lfFont.A;
|
|
return S_OK;
|
|
}
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::SetCompositionFont(
|
|
IN DIMM_IMCLock& lpIMC,
|
|
IN LOGFONTAW* lplf,
|
|
IN BOOL fUnicode
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::SetCompositionFont");
|
|
|
|
if (fUnicode)
|
|
lpIMC->lfFont.W = *(&lplf->W);
|
|
else
|
|
lpIMC->lfFont.A = *(&lplf->A);
|
|
lpIMC->fdwInit |= INIT_LOGFONT;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* AIMM Composition Window API Method
|
|
*/
|
|
HRESULT
|
|
CInputContext::GetCompositionWindow(
|
|
IN HIMC hIMC,
|
|
OUT LPCOMPOSITIONFORM lpCompForm
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetCompositionWindow");
|
|
|
|
if (IsOnImm()) {
|
|
return Imm32_GetCompositionWindow(hIMC, lpCompForm);
|
|
}
|
|
else {
|
|
HRESULT hr;
|
|
DIMM_IMCLock pIMC(hIMC);
|
|
if (FAILED(hr = pIMC.GetResult()))
|
|
return hr;
|
|
|
|
if ((pIMC->fdwInit & INIT_COMPFORM) == INIT_COMPFORM) {
|
|
*lpCompForm = pIMC->cfCompForm;
|
|
return S_OK;
|
|
}
|
|
}
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::SetCompositionWindow(
|
|
IN DIMM_IMCLock& lpIMC,
|
|
IN LPCOMPOSITIONFORM lpCompForm
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::SetCompositionWindow");
|
|
|
|
lpIMC->cfCompForm = *lpCompForm;
|
|
lpIMC->fdwInit |= INIT_COMPFORM;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* AIMM Candidate List API Methods
|
|
*/
|
|
HRESULT
|
|
CInputContext::GetCandidateList(
|
|
IN HIMC hIMC,
|
|
IN DWORD dwIndex,
|
|
IN DWORD dwBufLen,
|
|
OUT LPCANDIDATELIST lpCandList,
|
|
OUT UINT* puCopied,
|
|
BOOL fUnicode
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetCandidateList");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::GetCandidateListCount(
|
|
IN HIMC hIMC,
|
|
OUT DWORD* lpdwListSize,
|
|
OUT DWORD* pdwBufLen,
|
|
BOOL fUnicode
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetCandidateListCount");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/*
|
|
* AIMM Candidate Window API Methods
|
|
*/
|
|
HRESULT
|
|
CInputContext::GetCandidateWindow(
|
|
IN HIMC hIMC,
|
|
IN DWORD dwIndex,
|
|
OUT LPCANDIDATEFORM lpCandidate
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetCandidateWindow");
|
|
|
|
if (IsOnImm()) {
|
|
return Imm32_GetCandidateWindow(hIMC, dwIndex, lpCandidate);
|
|
}
|
|
else {
|
|
HRESULT hr;
|
|
DIMM_IMCLock pIMC(hIMC);
|
|
if (FAILED(hr = pIMC.GetResult()))
|
|
return hr;
|
|
|
|
if (pIMC->cfCandForm[dwIndex].dwIndex == -1) {
|
|
return E_FAIL;
|
|
}
|
|
|
|
*lpCandidate = pIMC->cfCandForm[dwIndex];
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CInputContext::SetCandidateWindow(
|
|
IN DIMM_IMCLock& lpIMC,
|
|
IN LPCANDIDATEFORM lpCandForm
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::SetCandidateWindow");
|
|
lpIMC->cfCandForm[lpCandForm->dwIndex] = *lpCandForm;
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* AIMM Guide Line API Methods
|
|
*/
|
|
HRESULT
|
|
CInputContext::GetGuideLine(
|
|
IN HIMC hIMC,
|
|
IN DWORD dwIndex,
|
|
IN DWORD dwBufLen,
|
|
OUT CHARAW* lpBuf,
|
|
OUT DWORD* pdwResult,
|
|
BOOL fUnicode
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetGuideLine");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
/*
|
|
* AIMM Notify IME API Method
|
|
*/
|
|
HRESULT
|
|
CInputContext::NotifyIME(
|
|
IN HIMC hIMC,
|
|
IN DWORD dwAction,
|
|
IN DWORD dwIndex,
|
|
IN DWORD dwValue
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::NotifyIME");
|
|
|
|
if (IsOnImm()) {
|
|
return Imm32_NotifyIME(hIMC, dwAction, dwIndex, dwValue);
|
|
}
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/*
|
|
* AIMM Menu Items API Methods
|
|
*/
|
|
HRESULT
|
|
CInputContext::GetImeMenuItems(
|
|
IN HIMC hIMC,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwType,
|
|
IN IMEMENUITEMINFOAW *pImeParentMenu,
|
|
OUT IMEMENUITEMINFOAW *pImeMenu,
|
|
IN DWORD dwSize,
|
|
OUT DWORD* pdwResult,
|
|
BOOL fUnicode
|
|
)
|
|
{
|
|
TraceMsg(TF_API, "CInputContext::GetImeMenuItems");
|
|
return E_NOTIMPL;
|
|
}
|