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.
506 lines
15 KiB
506 lines
15 KiB
/*++
|
|
|
|
Copyright (c) 2001, Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
icocb.cpp
|
|
|
|
Abstract:
|
|
|
|
This file implements the CInputContextOwnerCallBack Class.
|
|
|
|
Author:
|
|
|
|
Revision History:
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
|
|
#include "private.h"
|
|
#include "icocb.h"
|
|
#include "imc.h"
|
|
#include "mouse.h"
|
|
#include "tls.h"
|
|
#include "profile.h"
|
|
#include "uicomp.h"
|
|
|
|
|
|
//
|
|
// MSIME private smode. Office 2k uses this bit to set KOUGO mode.
|
|
//
|
|
#define IME_SMODE_PRIVATE_KOUGO 0x10000
|
|
|
|
|
|
CInputContextOwnerCallBack::CInputContextOwnerCallBack(
|
|
TfClientId tid,
|
|
Interface_Attach<ITfContext> pic,
|
|
LIBTHREAD *pLibTLS) : m_tid(tid), m_ic(pic), m_pLibTLS(pLibTLS),
|
|
CInputContextOwner(ICOwnerSinkCallback, NULL)
|
|
{
|
|
m_pMouseSink = NULL;
|
|
}
|
|
|
|
CInputContextOwnerCallBack::~CInputContextOwnerCallBack(
|
|
)
|
|
{
|
|
if (m_pMouseSink) {
|
|
m_pMouseSink->InternalRelease();
|
|
m_pMouseSink = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CInputContextOwnerCallBack::Init()
|
|
{
|
|
//
|
|
// Create Mouse Sink
|
|
//
|
|
Assert(!m_pMouseSink);
|
|
|
|
m_pMouseSink = new CMouseSink(m_tid, m_ic, m_pLibTLS);
|
|
if (m_pMouseSink == NULL)
|
|
return FALSE;
|
|
|
|
if (!m_pMouseSink->Init())
|
|
{
|
|
delete m_pMouseSink;
|
|
m_pMouseSink = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// static
|
|
HRESULT
|
|
CInputContextOwnerCallBack::ICOwnerSinkCallback(
|
|
UINT uCode,
|
|
ICOARGS *pargs,
|
|
void *pv
|
|
)
|
|
{
|
|
DebugMsg(TF_FUNC, TEXT("ICOwnerSinkCallback"));
|
|
|
|
POINT pt;
|
|
|
|
CInputContextOwnerCallBack* _this = (CInputContextOwnerCallBack*)pv;
|
|
|
|
TLS* ptls = TLS::ReferenceTLS(); // Should not allocate TLS. ie. TLS::GetTLS
|
|
// DllMain -> ImeDestroy -> DeactivateIMMX -> Deactivate
|
|
if (ptls == NULL)
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback. ptls==NULL."));
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
switch (uCode)
|
|
{
|
|
case ICO_POINT_TO_ACP:
|
|
Assert(0);
|
|
return E_NOTIMPL;
|
|
|
|
case ICO_KEYDOWN:
|
|
case ICO_KEYUP:
|
|
*pargs->key.pfEaten = FALSE;
|
|
break;
|
|
|
|
case ICO_SCREENEXT:
|
|
{
|
|
HRESULT hr;
|
|
IMCLock imc(GetActiveContext());
|
|
if (FAILED(hr=imc.GetResult()))
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback. imc==NULL."));
|
|
return hr;
|
|
}
|
|
|
|
GetClientRect(imc->hWnd, pargs->scr_ext.prc);
|
|
pt.x = pt.y = 0;
|
|
ClientToScreen(imc->hWnd, &pt);
|
|
|
|
pargs->scr_ext.prc->left += pt.x;
|
|
pargs->scr_ext.prc->right += pt.x;
|
|
pargs->scr_ext.prc->top += pt.y;
|
|
pargs->scr_ext.prc->bottom += pt.y;
|
|
}
|
|
|
|
break;
|
|
|
|
case ICO_TEXTEXT:
|
|
//
|
|
// consider.
|
|
//
|
|
// hack TextExtent from CANDIDATEFORM of HIMC.
|
|
//
|
|
// more hacks
|
|
// - may want to send WM_OPENCANDIDATEPOS to let apps
|
|
// call ImmSetCandidateWindow().
|
|
// - may need to calculate the actual point from rcArea.
|
|
//
|
|
{
|
|
HRESULT hr;
|
|
IMCLock imc(GetActiveContext());
|
|
if (FAILED(hr=imc.GetResult()))
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback. imc==NULL."));
|
|
return hr;
|
|
}
|
|
|
|
IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
|
|
if (imc_ctfime.Invalid())
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback(ICO_TEXTEXT). imc_ctfime==NULL."));
|
|
break;
|
|
}
|
|
|
|
CicInputContext* _pCicContext = imc_ctfime->m_pCicContext;
|
|
if (_pCicContext == NULL)
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback(ICO_TEXTEXT). _pCicContext==NULL."));
|
|
break;
|
|
}
|
|
|
|
LANGID langid;
|
|
CicProfile* _pProfile = ptls->GetCicProfile();
|
|
if (_pProfile == NULL)
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback(ICO_TEXTEXT). _pProfile==NULL."));
|
|
break;
|
|
}
|
|
|
|
_pProfile->GetLangId(&langid);
|
|
|
|
_this->IcoTextExt(imc, *_pCicContext, langid, pargs);
|
|
}
|
|
break;
|
|
|
|
case ICO_STATUS:
|
|
pargs->status.pdcs->dwDynamicFlags = 0;
|
|
pargs->status.pdcs->dwStaticFlags = TF_SS_TRANSITORY;
|
|
break;
|
|
|
|
case ICO_WND:
|
|
{
|
|
HRESULT hr;
|
|
IMCLock imc(GetActiveContext());
|
|
if (FAILED(hr=imc.GetResult()))
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback. imc==NULL."));
|
|
return hr;
|
|
}
|
|
|
|
*(pargs->hwnd.phwnd) = imc->hWnd;
|
|
}
|
|
break;
|
|
|
|
case ICO_ATTR:
|
|
{
|
|
HRESULT hr;
|
|
IMCLock imc(GetActiveContext());
|
|
if (FAILED(hr=imc.GetResult()))
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback. imc==NULL."));
|
|
return hr;
|
|
}
|
|
|
|
IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
|
|
if (imc_ctfime.Invalid())
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback(ICO_ATTR). imc_ctfime==NULL."));
|
|
break;
|
|
}
|
|
|
|
CicInputContext* _pCicContext = imc_ctfime->m_pCicContext;
|
|
if (_pCicContext == NULL)
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback(ICO_ATTR). _pCicContext==NULL."));
|
|
break;
|
|
}
|
|
|
|
LANGID langid;
|
|
CicProfile* _pProfile = ptls->GetCicProfile();
|
|
if (_pProfile == NULL)
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback(ICO_ATTR). _pProfile==NULL."));
|
|
break;
|
|
}
|
|
|
|
_pProfile->GetLangId(&langid);
|
|
|
|
return _this->GetAttribute(imc, *_pCicContext, langid, pargs->sys_attr.pguid, pargs->sys_attr.pvar);
|
|
}
|
|
|
|
case ICO_ADVISEMOUSE:
|
|
{
|
|
HRESULT hr;
|
|
IMCLock imc(GetActiveContext());
|
|
if (FAILED(hr=imc.GetResult()))
|
|
{
|
|
DebugMsg(TF_ERROR, TEXT("CInputContextOwnerCallBack::ICOwnerSinkCallback. imc==NULL."));
|
|
return hr;
|
|
}
|
|
|
|
_this->m_pMouseSink->InternalAddRef();
|
|
return _this->m_pMouseSink->AdviseMouseSink(imc,
|
|
pargs->advise_mouse.rangeACP,
|
|
pargs->advise_mouse.pSink,
|
|
pargs->advise_mouse.pdwCookie);
|
|
}
|
|
break;
|
|
|
|
case ICO_UNADVISEMOUSE:
|
|
{
|
|
HRESULT hr = _this->m_pMouseSink->UnadviseMouseSink(pargs->unadvise_mouse.dwCookie);
|
|
_this->m_pMouseSink->InternalRelease();
|
|
return hr;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Assert(0); // shouldn't ever get here
|
|
break;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*++
|
|
|
|
Method:
|
|
|
|
CInputContextOwnerCallBack::GetAttribute
|
|
|
|
Routine Description:
|
|
|
|
Implementation of ITfContextOwner::GetAttribute. Returns the value of a cicero
|
|
app property attribute.
|
|
|
|
Arguments:
|
|
|
|
|
|
pguid - [in] GUID of the attrib in question.
|
|
pvarValue - [out] VARIANT, receives the value. VT_EMPTY if we don't support it.
|
|
|
|
Return Value:
|
|
|
|
Returns S_OK if successful, or an error code otherwise.
|
|
|
|
--*/
|
|
|
|
HRESULT
|
|
CInputContextOwnerCallBack::GetAttribute(
|
|
IMCLock& imc,
|
|
CicInputContext& CicContext,
|
|
LANGID langid,
|
|
const GUID *pguid,
|
|
VARIANT *pvarValue
|
|
)
|
|
{
|
|
TfGuidAtom ga;
|
|
const GUID *pguidValue;
|
|
|
|
QuickVariantInit(pvarValue);
|
|
|
|
if (IsEqualGUID(*pguid, GUID_PROP_MODEBIAS))
|
|
{
|
|
BOOL fModeChanged = CicContext.m_fConversionSentenceModeChanged.IsSetFlag();
|
|
CicContext.m_fConversionSentenceModeChanged.ResetFlag();
|
|
|
|
// xlate conversion mode, sentence mode to cicero mode bias
|
|
GUID guidModeBias = CicContext.m_ModeBias.GetModeBias();
|
|
|
|
if (CicContext.m_fOnceModeChanged.IsResetFlag())
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
if (CicContext.m_nInConversionModeResetRef)
|
|
{
|
|
pguidValue = &GUID_NULL;
|
|
fModeChanged = TRUE;
|
|
goto SetGA;
|
|
}
|
|
|
|
if (! IsEqualGUID(guidModeBias, GUID_MODEBIAS_NONE))
|
|
{
|
|
if (IsEqualGUID(guidModeBias, GUID_MODEBIAS_DEFAULT))
|
|
{
|
|
// reset mode bias to GUID_MODEBIAS_NONE
|
|
CicContext.m_ModeBias.SetModeBias(GUID_MODEBIAS_NONE);
|
|
|
|
// GUID_MODEBIAS_NONE == GUID_NULL;
|
|
pguidValue = &GUID_NULL;
|
|
fModeChanged = TRUE;
|
|
|
|
// Reset flag
|
|
CicContext.m_fOnceModeChanged.ResetFlag();
|
|
}
|
|
else
|
|
{
|
|
pguidValue = &guidModeBias;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// existing logic:
|
|
//
|
|
// if imcp->lModeBias == MODEBIASMODE_DEFAULT
|
|
// IME_SMODE_CONVERSATION -> GUID_MODEBIAS_CONVERSATION
|
|
// otherwise -> GUID_MODEBIAS_NONE
|
|
// otherwise
|
|
// -> MODEBIASMODE_FILENAME -> GUID_MODEBIAS_FILENAME
|
|
//
|
|
|
|
if (IsEqualGUID(guidModeBias, GUID_MODEBIAS_NONE))
|
|
{
|
|
pguidValue = &GUID_MODEBIAS_NONE;
|
|
|
|
if (imc->fdwConversion & IME_CMODE_KATAKANA)
|
|
{
|
|
if (imc->fdwConversion & IME_CMODE_FULLSHAPE)
|
|
pguidValue = &GUID_MODEBIAS_KATAKANA;
|
|
else
|
|
pguidValue = &GUID_MODEBIAS_HALFWIDTHKATAKANA;
|
|
}
|
|
else if (imc->fdwConversion & IME_CMODE_NATIVE)
|
|
{
|
|
pguidValue = &GUID_MODEBIAS_HALFWIDTHALPHANUMERIC;
|
|
if (langid == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT))
|
|
{
|
|
if (imc->fdwConversion & IME_CMODE_FULLSHAPE)
|
|
pguidValue = &GUID_MODEBIAS_HIRAGANA;
|
|
else
|
|
pguidValue = &GUID_MODEBIAS_HALFWIDTHALPHANUMERIC;
|
|
}
|
|
else if (langid == MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT))
|
|
{
|
|
if (imc->fdwConversion & IME_CMODE_FULLSHAPE)
|
|
pguidValue = &GUID_MODEBIAS_FULLWIDTHHANGUL;
|
|
else
|
|
pguidValue = &GUID_MODEBIAS_HANGUL;
|
|
}
|
|
else if (PRIMARYLANGID(langid) == LANG_CHINESE)
|
|
{
|
|
pguidValue = &GUID_MODEBIAS_CHINESE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (imc->fdwConversion & IME_CMODE_FULLSHAPE)
|
|
pguidValue = &GUID_MODEBIAS_FULLWIDTHALPHANUMERIC;
|
|
else
|
|
pguidValue = &GUID_MODEBIAS_HALFWIDTHALPHANUMERIC;
|
|
}
|
|
}
|
|
|
|
if (!CicContext.m_nInConversionModeChangingRef)
|
|
{
|
|
//
|
|
// We overwrite modebias here....
|
|
//
|
|
if ((imc->fdwSentence & IME_SMODE_CONVERSATION) ||
|
|
((imc->fdwSentence & (IME_SMODE_PHRASEPREDICT | IME_SMODE_PRIVATE_KOUGO)) == (IME_SMODE_PHRASEPREDICT | IME_SMODE_PRIVATE_KOUGO)))
|
|
{
|
|
pguidValue = &GUID_MODEBIAS_CONVERSATION;
|
|
}
|
|
else if (imc->fdwSentence & IME_SMODE_PLAURALCLAUSE)
|
|
{
|
|
pguidValue = &GUID_MODEBIAS_NAME;
|
|
}
|
|
}
|
|
}
|
|
|
|
SetGA:
|
|
if (!GetGUIDATOMFromGUID(m_pLibTLS, *pguidValue, &ga))
|
|
return E_FAIL;
|
|
|
|
//
|
|
// Cicero 5073:
|
|
//
|
|
// returning valid variant value, Satori set back to its default
|
|
// input mode.
|
|
//
|
|
if (!IsEqualGUID(*pguidValue, GUID_NULL) || fModeChanged)
|
|
{
|
|
pvarValue->vt = VT_I4; // for TfGuidAtom
|
|
pvarValue->lVal = ga;
|
|
}
|
|
}
|
|
if (IsEqualGUID(*pguid, TSATTRID_Text_Orientation))
|
|
{
|
|
// xlate conversion mode, sentence mode to cicero mode bias
|
|
IME_UIWND_STATE uists = UIComposition::InquireImeUIWndState(imc);
|
|
|
|
pvarValue->vt = VT_I4;
|
|
if (uists == IME_UIWND_LEVEL1)
|
|
pvarValue->lVal = 0;
|
|
else
|
|
pvarValue->lVal = imc->lfFont.W.lfEscapement;
|
|
}
|
|
if (IsEqualGUID(*pguid, TSATTRID_Text_VerticalWriting))
|
|
{
|
|
// xlate conversion mode, sentence mode to cicero mode bias
|
|
LOGFONT font;
|
|
|
|
if (ImmGetCompositionFont((HIMC)imc, &font)) {
|
|
pvarValue->vt = VT_BOOL;
|
|
pvarValue->lVal = (font.lfFaceName[0] == L'@' ? TRUE : FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CInputContextOwnerCallBack::MsImeMouseHandler
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
LRESULT
|
|
CInputContextOwnerCallBack::MsImeMouseHandler(
|
|
ULONG uEdge,
|
|
ULONG uQuadrant,
|
|
ULONG dwBtnStatus,
|
|
IMCLock& imc
|
|
)
|
|
{
|
|
return m_pMouseSink->MsImeMouseHandler(uEdge, uQuadrant, dwBtnStatus, imc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CInputContextOwnerCallBack::IcoTextExt
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CInputContextOwnerCallBack::IcoTextExt(
|
|
IMCLock& imc,
|
|
CicInputContext& CicContext,
|
|
LANGID langid,
|
|
ICOARGS *pargs)
|
|
{
|
|
IME_UIWND_STATE uists;
|
|
uists = UIComposition::InquireImeUIWndState(imc);
|
|
if (uists == IME_UIWND_LEVEL1 ||
|
|
uists == IME_UIWND_LEVEL2 ||
|
|
uists == IME_UIWND_LEVEL1_OR_LEVEL2)
|
|
{
|
|
|
|
UIComposition::TEXTEXT uicomp_text_ext;
|
|
uicomp_text_ext.SetICOARGS(pargs);
|
|
return UIComposition::GetImeUIWndTextExtent(&uicomp_text_ext) ? S_OK : E_FAIL;
|
|
}
|
|
|
|
CCandidatePosition cand_pos(m_tid, m_ic, m_pLibTLS);
|
|
return cand_pos.GetCandidatePosition(imc, CicContext, uists, langid, pargs->text_ext.prc);
|
|
}
|
|
|