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.
737 lines
22 KiB
737 lines
22 KiB
#include "private.h"
|
|
#include "korimx.h"
|
|
#include "timsink.h"
|
|
#include "immxutil.h"
|
|
#include "fnrecon.h"
|
|
#include "helpers.h"
|
|
#include "skbdmode.h"
|
|
#include "osver.h"
|
|
|
|
// REVIEW
|
|
/*---------------------------------------------------------------------------
|
|
CKorIMX::_EditSessionCallback
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT CKorIMX::_EditSessionCallback2(TfEditCookie ec, CEditSession2 *pes)
|
|
{
|
|
ITfContext* pic = pes->GetContext();
|
|
CKorIMX* pKorTip = pes->GetTIP();
|
|
ESSTRUCT* pess = pes->GetStruct();
|
|
ITfRange* pRange;
|
|
CHangulAutomata* pAutomata;
|
|
LPWSTR pszCand = NULL;
|
|
|
|
Assert(pic != NULL);
|
|
Assert(pKorTip != NULL);
|
|
|
|
|
|
if ((pKorTip == NULL) || (pic == NULL))
|
|
return E_FAIL;
|
|
|
|
switch (pess->id)
|
|
{
|
|
case ESCB_FINALIZECONVERSION:
|
|
{
|
|
CCandidateListEx *pCandList;
|
|
CCandidateStringEx *pCandItem;
|
|
|
|
pCandList = pess->pCandList;
|
|
pCandItem = pess->pCandStr;
|
|
pRange = pess->pRange;
|
|
|
|
pszCand = pCandItem->m_psz;
|
|
|
|
if (pszCand)
|
|
{
|
|
size_t cchCand = 0;
|
|
StringCchLengthW(pszCand, CIC_KOR_CANDSTR_MAX, &cchCand);
|
|
// Set Reading text
|
|
SetTextAndReading(pKorTip->_GetLibTLS(), ec, pic, pRange,
|
|
pszCand,
|
|
cchCand,
|
|
pCandItem->m_langid, pCandItem->m_pszRead);
|
|
}
|
|
|
|
pCandList->Release();
|
|
|
|
// First complete current comp string
|
|
if (pAutomata = pKorTip->GetAutomata(pic))
|
|
pAutomata->MakeComplete();
|
|
|
|
pKorTip->MakeResultString(ec, pic, pRange);
|
|
|
|
pKorTip->CloseCandidateUIProc();
|
|
break;
|
|
}
|
|
|
|
case ESCB_COMPLETE:
|
|
{
|
|
BOOL fReleaseRange = fFalse;
|
|
|
|
// If No composition exist, nothing to complete
|
|
if (pKorTip->GetIPComposition(pic) == NULL)
|
|
break;
|
|
|
|
pRange = pess->pRange;
|
|
pAutomata = pKorTip->GetAutomata(pic);
|
|
|
|
// Close cand UI if exist.
|
|
pKorTip->CloseCandidateUIProc();
|
|
|
|
if (pRange == NULL)
|
|
{
|
|
GetSelectionSimple(ec, pic, &pRange);
|
|
fReleaseRange = fTrue;
|
|
}
|
|
|
|
if (pRange)
|
|
{
|
|
if (pAutomata)
|
|
pAutomata->MakeComplete();
|
|
pKorTip->MakeResultString(ec, pic, pRange);
|
|
}
|
|
|
|
if (fReleaseRange)
|
|
{
|
|
SafeRelease(pRange);
|
|
}
|
|
|
|
//return pKorTip->_MultiRangeConversion(ec, pes->_state.u, pic, pRange);
|
|
break;
|
|
}
|
|
|
|
case ESCB_INSERT_PAD_STRING:
|
|
{
|
|
WCHAR szText[2];
|
|
|
|
GetSelectionSimple(ec, pic, &pRange);
|
|
szText[0] = (WCHAR)pess->wParam;
|
|
szText[1] = L'\0';
|
|
|
|
if (FAILED(pKorTip->SetInputString(ec, pic, pRange, szText, CKorIMX::GetLangID())))
|
|
break;
|
|
|
|
pKorTip->MakeResultString(ec, pic, pRange);
|
|
|
|
SafeRelease(pRange);
|
|
break;
|
|
}
|
|
|
|
case ESCB_KEYSTROKE:
|
|
{
|
|
WPARAM wParam = pess->wParam;
|
|
LPARAM lParam = pess->lParam;
|
|
return pKorTip->_Keystroke(ec, pic, wParam, lParam, (const BYTE *)pess->pv1);
|
|
break;
|
|
}
|
|
|
|
// Complete and Selection range changed
|
|
case ESCB_TEXTEVENT:
|
|
if (pKorTip->IsKeyFocus() && (GetSelectionSimple(ec, pic, &pRange) == S_OK))
|
|
{
|
|
ITfComposition *pComposition;
|
|
ITfRange *pRangeOldComp;
|
|
//IEnumTfRanges *pEnumText = pess->pEnumRange;
|
|
BOOL fChanged = fFalse;
|
|
BOOL fEmpty;
|
|
|
|
// Check modebias here
|
|
if (pess->fBool)
|
|
fChanged = pKorTip->CheckModeBias(ec, pic, pRange);
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// To complete on mouse click we using Range change notification.
|
|
// In future version, we could remove this code and use custom property
|
|
// or reading string. Cutom property can hold Hangul Automata object.
|
|
//
|
|
// Office apps explicitly call complete but this for unknown Cicero apps.
|
|
//////////////////////////////////////////////////////////////////
|
|
pComposition = pKorTip->GetIPComposition(pic);
|
|
if (pComposition == NULL)
|
|
goto ExitTextEvent;
|
|
|
|
// Office apps are not going through here.
|
|
pComposition->GetRange(&pRangeOldComp);
|
|
if (pRangeOldComp == NULL)
|
|
goto ExitTextEvent;
|
|
|
|
pRange->IsEmpty(ec, &fEmpty);
|
|
if (fEmpty && (CR_EQUAL != CompareRanges(ec, pRange, pRangeOldComp)))
|
|
{
|
|
ITfProperty *pPropAttr;
|
|
TfGuidAtom attr;
|
|
|
|
// Clear attrib
|
|
if (SUCCEEDED(pic->GetProperty(GUID_PROP_ATTRIBUTE, &pPropAttr)))
|
|
{
|
|
if (SUCCEEDED(GetAttrPropertyData(ec, pPropAttr, pRangeOldComp, &attr)))
|
|
{
|
|
if (pKorTip->IsKorIMX_GUID_ATOM(attr))
|
|
{
|
|
pPropAttr->Clear(ec, pRangeOldComp);
|
|
}
|
|
}
|
|
pPropAttr->Release();
|
|
}
|
|
|
|
pAutomata = pKorTip->GetAutomata(pic);
|
|
if (pAutomata)
|
|
pAutomata->MakeComplete();
|
|
pKorTip->EndIPComposition(ec, pic);
|
|
// pKorTip->MakeResultString(ec, pic, pRangeOldComp);
|
|
|
|
fChanged = fTrue;
|
|
}
|
|
|
|
SafeRelease(pRangeOldComp);
|
|
|
|
ExitTextEvent:
|
|
pRange->Release();
|
|
|
|
// Close cand UI if exist.
|
|
if (fChanged)
|
|
pKorTip->CloseCandidateUIProc();
|
|
}
|
|
break;
|
|
|
|
// case ESCB_RANGEBROKEN:
|
|
// pKorTip->FlushIPRange(ec, pic);
|
|
// break;
|
|
|
|
case ESCB_CANDUI_CLOSECANDUI:
|
|
// u : ESCB_CANDUI_CLOSECANDUI
|
|
// pv : this
|
|
// hwnd : - (not used)
|
|
// wParam : - (not used)
|
|
// lParam : - (not used)
|
|
// pv1 : - (not used)
|
|
// pv2 : - (not used)
|
|
// pic : - (not used)
|
|
// pRange : - (not used)
|
|
// fBool : - (not used)
|
|
pKorTip->CloseCandidateUIProc();
|
|
break;
|
|
|
|
// Hanja conv button up
|
|
case ESCB_HANJA_CONV:
|
|
// u : ESCB_HANJA_CONV
|
|
// pv : this
|
|
// hwnd : - (not used)
|
|
// wParam : - (not used)
|
|
// lParam : - (not used)
|
|
// pv1 : - (not used)
|
|
// pv2 : - (not used)
|
|
// pic : - pic
|
|
// pRange : - (not used)
|
|
// fBool : - (not used)
|
|
|
|
// O10 #220177: Simulate VK_HANJA key to invoke HHC
|
|
if (GetAIMM(pic) && (IsOnNT5() || PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_JAPANESE))
|
|
{
|
|
keybd_event(VK_HANJA, 0, 0, 0);
|
|
keybd_event(VK_HANJA, 0, KEYEVENTF_KEYUP, 0);
|
|
}
|
|
else
|
|
if (GetSelectionSimple(ec, pic, &pRange) == S_OK)
|
|
{
|
|
if (pKorTip->GetIPComposition(pic))
|
|
pKorTip->DoHanjaConversion(ec, pic, pRange);
|
|
else
|
|
pKorTip->Reconvert(pRange);
|
|
|
|
SafeRelease(pRange);
|
|
}
|
|
// Update Hanja button
|
|
if (pKorTip->m_pToolBar != NULL)
|
|
pKorTip->m_pToolBar->Update(UPDTTB_HJMODE);
|
|
break;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Reconversion Callbacks
|
|
case ESCB_FINALIZERECONVERSION:
|
|
{
|
|
CCandidateListEx *pCandList = pess->pCandList;
|
|
CCandidateStringEx *pCandItem = pess->pCandStr;
|
|
|
|
pRange = pess->pRange;
|
|
pszCand = pCandItem->m_psz;
|
|
|
|
Assert(pRange != NULL);
|
|
pKorTip->CloseCandidateUI(pic);
|
|
|
|
if (GetAIMM(pic) == fFalse)
|
|
{
|
|
if (pszCand)
|
|
{
|
|
size_t cchCand = 0;
|
|
StringCchLengthW(pszCand, CIC_KOR_CANDSTR_MAX, &cchCand);
|
|
//ITfRange *pRangeTmp;
|
|
SetTextAndReading(pKorTip->_GetLibTLS(), ec, pic, pRange,
|
|
pszCand,
|
|
cchCand,
|
|
pCandItem->m_langid, pCandItem->m_pszRead);
|
|
}
|
|
|
|
// To clear current selection and composition
|
|
pKorTip->MakeResultString(ec, pic, pRange);
|
|
}
|
|
else
|
|
{
|
|
if (pszCand)
|
|
{
|
|
pRange->SetText(ec, 0, pszCand, 1/* wcslen(pszCand)*/);
|
|
SetSelectionSimple(ec, pic, pRange);
|
|
}
|
|
pKorTip->EndIPComposition(ec, pic);
|
|
}
|
|
|
|
// if hit reconversion on composition string, we need to clear automata.
|
|
pAutomata = pKorTip->GetAutomata(pic);
|
|
if (pRange && pAutomata && pAutomata->GetCompositionChar())
|
|
pAutomata->MakeComplete();
|
|
|
|
SafeRelease(pRange);
|
|
break;
|
|
}
|
|
|
|
case ESCB_ONSELECTRECONVERSION:
|
|
break;
|
|
|
|
case ESCB_ONCANCELRECONVERSION:
|
|
pRange = pess->pRange;
|
|
|
|
pKorTip->CancelCandidate(ec, pic);
|
|
|
|
if (GetAIMM(pic) == fFalse)
|
|
{
|
|
// To clear current selection and composition
|
|
pKorTip->MakeResultString(ec, pic, pRange);
|
|
}
|
|
else
|
|
pKorTip->EndIPComposition(ec, pic);
|
|
|
|
// if hit reconversion on composition string, we need to clear automata.
|
|
pAutomata = pKorTip->GetAutomata(pic);
|
|
if (pRange && pAutomata && pAutomata->GetCompositionChar())
|
|
pAutomata->MakeComplete();
|
|
|
|
SafeRelease(pRange);
|
|
break;
|
|
|
|
case ESCB_RECONV_QUERYRECONV:
|
|
{
|
|
CFnReconversion *pReconv = (CFnReconversion *)pess->pv1;
|
|
if (pKorTip->IsCandUIOpen())
|
|
return E_FAIL;
|
|
return pReconv->_QueryRange(ec, pic, pess->pRange, (ITfRange **)pess->pv2);
|
|
}
|
|
|
|
case ESCB_RECONV_GETRECONV:
|
|
{
|
|
CFnReconversion *pReconv = (CFnReconversion *)pess->pv1;
|
|
if (pKorTip->IsCandUIOpen())
|
|
return E_FAIL;
|
|
return pReconv->_GetReconversion(ec, pic, pess->pRange, (CCandidateListEx **)pess->pv2, pess->fBool);
|
|
}
|
|
|
|
case ESCB_RECONV_SHOWCAND:
|
|
{
|
|
ITfComposition* pComposition;
|
|
GUID attr;
|
|
ITfProperty* pProp = NULL;
|
|
|
|
pRange = pess->pRange;
|
|
|
|
pComposition = pKorTip->GetIPComposition(pic);
|
|
if (/*GetAIMM(pic) == fFalse && */ pComposition == NULL)
|
|
{
|
|
pKorTip->CreateIPComposition(ec, pic, pRange);
|
|
|
|
// Set input attr and composing state.
|
|
if (SUCCEEDED(pic->GetProperty(GUID_PROP_ATTRIBUTE, &pProp)))
|
|
{
|
|
attr = GUID_ATTR_KORIMX_INPUT;
|
|
SetAttrPropertyData(pKorTip->_GetLibTLS(), ec, pProp, pRange, attr);
|
|
pProp->Release();
|
|
}
|
|
}
|
|
|
|
pKorTip->OpenCandidateUI(ec, pic, pess->pRange, pess->pCandList);
|
|
|
|
break;
|
|
}
|
|
|
|
case ESCB_INIT_MODEBIAS:
|
|
// Check mode bias
|
|
//
|
|
// id : ESCB_INIT_MODEBIAS
|
|
// ptip : this
|
|
// pic : pic
|
|
pKorTip->InitializeModeBias(ec, pic);
|
|
break;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CKorIMX::_DIMCallback
|
|
---------------------------------------------------------------------------*/
|
|
/* static */
|
|
HRESULT CKorIMX::_DIMCallback(UINT uCode, ITfDocumentMgr *pdimNew, ITfDocumentMgr *pdimPrev, void *pv)
|
|
{
|
|
ITfContext *pic = NULL;
|
|
CKorIMX *pKorImx = (CKorIMX *)pv;
|
|
|
|
Assert(pKorImx != NULL);
|
|
|
|
switch (uCode)
|
|
{
|
|
case TIM_CODE_SETFOCUS:
|
|
if (pdimPrev)
|
|
{
|
|
TraceMsg(DM_TRACE, TEXT("TIM_CODE_SETFOCUS: pdimPrev"));
|
|
|
|
pdimPrev->GetTop(&pic);
|
|
pKorImx->OnFocusChange(pic, fFalse);
|
|
|
|
SafeRelease(pic);
|
|
SafeReleaseClear(pKorImx->m_pCurrentDim);
|
|
}
|
|
|
|
if (pdimNew)
|
|
{
|
|
TraceMsg(DM_TRACE, TEXT("TIM_CODE_SETFOCUS: pdimNew"));
|
|
|
|
SafeReleaseClear(pKorImx->m_pCurrentDim);
|
|
|
|
// Set New dim
|
|
pKorImx->m_pCurrentDim = pdimNew;
|
|
pKorImx->m_pCurrentDim->AddRef();
|
|
|
|
pdimNew->GetTop(&pic);
|
|
pKorImx->OnFocusChange(pic, fTrue);
|
|
|
|
if (pic)
|
|
pic->Release();
|
|
}
|
|
break;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CKorIMX::_ICCallback
|
|
|
|
Document Input Manager callback. ITfThreadMgrEventSink
|
|
---------------------------------------------------------------------------*/
|
|
/* static */
|
|
HRESULT CKorIMX::_ICCallback(UINT uCode, ITfContext *pic, void *pv)
|
|
{
|
|
CKorIMX *_this = (CKorIMX *)pv;
|
|
|
|
switch (uCode)
|
|
{
|
|
case TIM_CODE_INITIC:
|
|
if (!_this->IsPendingCleanup()) // ignore new ic's if we're being shutdown.
|
|
{
|
|
_this->_InitICPriv(pic);
|
|
}
|
|
break;
|
|
|
|
case TIM_CODE_UNINITIC:
|
|
_this->_DeleteICPriv(pic);
|
|
break;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CKorIMX::_CompEventSinkCallback
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT CKorIMX::_CompEventSinkCallback(void *pv, REFGUID rguid)
|
|
{
|
|
CICPriv* picp = (CICPriv*)pv;
|
|
ITfContext* pic;
|
|
CKorIMX *_this;
|
|
|
|
if (picp == NULL)
|
|
return S_OK; // error
|
|
|
|
pic = picp->GetIC();
|
|
|
|
if (pic == NULL)
|
|
return S_OK; // error
|
|
|
|
_this = picp->GetIMX();
|
|
|
|
if (_this == NULL || _this->m_pToolBar == NULL)
|
|
return S_OK; // do nothinig
|
|
|
|
// if Open/Close compartment
|
|
if (IsEqualGUID(rguid, GUID_COMPARTMENT_KEYBOARD_OPENCLOSE))
|
|
{
|
|
_this->m_pToolBar->Update(UPDTTB_CMODE|UPDTTB_FHMODE);
|
|
}
|
|
else
|
|
// if conversion mode compartment
|
|
if (IsEqualGUID(rguid, GUID_COMPARTMENT_KORIMX_CONVMODE))
|
|
{
|
|
DWORD dwConvMode = _this->GetConvMode(pic);
|
|
BOOL fIsOn = _this->IsOn(pic);
|
|
|
|
// We just open for Hangul mode do not close for Alphanumeric mode for Cicero full aware apps.
|
|
// This will prevent redundant Open/Close compartment call.
|
|
if (dwConvMode == TIP_ALPHANUMERIC_MODE && fIsOn)
|
|
_this->SetOnOff(pic, fFalse);
|
|
else
|
|
if (dwConvMode != TIP_ALPHANUMERIC_MODE && fIsOn == fFalse)
|
|
_this->SetOnOff(pic, fTrue);
|
|
_this->m_pToolBar->Update(UPDTTB_CMODE|UPDTTB_FHMODE);
|
|
}
|
|
else
|
|
// if SoftKeyboard compartmemnt
|
|
if (IsEqualGUID(rguid, GUID_COMPARTMENT_KOR_SOFTKBD_OPENCLOSE))
|
|
{
|
|
BOOL fSkbdOn = _this->GetSoftKBDOnOff();
|
|
|
|
_this->ShowSoftKBDWindow(fSkbdOn);
|
|
if (_this->m_pToolBar && _this->m_pToolBar->GetSkbdMode())
|
|
_this->m_pToolBar->GetSkbdMode()->UpdateToggle();
|
|
}
|
|
else
|
|
// if SoftKeyboard compartmemnt
|
|
if (IsEqualGUID(rguid, GUID_COMPARTMENT_SOFTKBD_KBDLAYOUT))
|
|
{
|
|
DWORD dwSoftLayout, dwCurLabel;
|
|
HRESULT hr;
|
|
|
|
if (_this->m_pSoftKbd == NULL)
|
|
return E_FAIL;
|
|
|
|
dwSoftLayout = _this->GetSoftKBDLayout();
|
|
dwCurLabel = _this->GetHangulSKbd()->dwCurLabel;
|
|
|
|
hr = _this->m_pSoftKbd->SelectSoftKeyboard(dwSoftLayout);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (dwSoftLayout == _this->m_KbdStandard.dwSoftKbdLayout)
|
|
hr = _this->m_pSoftKbd->SetKeyboardLabelText(GetKeyboardLayout(0));
|
|
else
|
|
hr = _this->m_pSoftKbd->SetKeyboardLabelTextCombination(dwCurLabel);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (_this->GetSoftKBDOnOff())
|
|
{
|
|
hr = _this->m_pSoftKbd->ShowSoftKeyboard(fTrue);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
CKorIMX::_PreKeyCallback
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT CKorIMX::_PreKeyCallback(ITfContext *pic, REFGUID rguid, BOOL *pfEaten, void *pv)
|
|
{
|
|
CKorIMX *_this = (CKorIMX *)pv;
|
|
|
|
if (_this == NULL)
|
|
return S_OK;
|
|
|
|
if (IsEqualGUID(rguid, GUID_KOREAN_HANGULSIMULATE))
|
|
{
|
|
DWORD dwConvMode;
|
|
|
|
// Toggle Hangul mode
|
|
dwConvMode = _this->GetConvMode(pic);
|
|
dwConvMode ^= TIP_HANGUL_MODE;
|
|
_this->SetConvMode(pic, dwConvMode);
|
|
|
|
*pfEaten = fTrue;
|
|
}
|
|
else if (IsEqualGUID(rguid, GUID_KOREAN_HANJASIMULATE))
|
|
{
|
|
// O10 #317983
|
|
if (PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) != LANG_JAPANESE)
|
|
{
|
|
keybd_event(VK_HANJA, 0, 0, 0);
|
|
keybd_event(VK_HANJA, 0, KEYEVENTF_KEYUP, 0);
|
|
*pfEaten = fTrue;
|
|
}
|
|
else
|
|
*pfEaten = fFalse;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/* O N E N D E D I T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
HRESULT CKorIMX::OnEndEdit(ITfContext *pic, TfEditCookie ecReadOnly, ITfEditRecord *pEditRecord)
|
|
{
|
|
UNREFERENCED_PARAMETER(ecReadOnly);
|
|
static const GUID *rgModeBiasProperties[] =
|
|
{
|
|
&GUID_PROP_MODEBIAS
|
|
};
|
|
|
|
static const GUID *rgAttrProperties[] =
|
|
{
|
|
&GUID_PROP_ATTRIBUTE,
|
|
};
|
|
|
|
CEditSession2 *pes;
|
|
ESSTRUCT ess;
|
|
HRESULT hr;
|
|
BOOL fInWriteSession;
|
|
CICPriv *picp;
|
|
IEnumTfRanges *pEnumText = NULL;
|
|
ITfRange *pRange = NULL;
|
|
ULONG ulFetched = 0;
|
|
BOOL fCallES = fFalse;
|
|
BOOL fSelChanged = fFalse;
|
|
|
|
Assert(pic != NULL);
|
|
if (pic == NULL)
|
|
return S_OK; // error
|
|
|
|
|
|
pic->InWriteSession(GetTID(), &fInWriteSession);
|
|
if (fInWriteSession)
|
|
return S_OK; // own change.
|
|
|
|
picp = GetInputContextPriv(pic);
|
|
if (picp == NULL)
|
|
return S_OK; // error
|
|
|
|
if (picp->GetfTransaction())
|
|
return S_OK; // skip in transaction.
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Init to call ESCB_TEXTEVENT
|
|
ESStructInit(&ess, ESCB_TEXTEVENT);
|
|
|
|
// Call ESCB_TEXTEVENT callback only if GUID_PROP_MODEBIAS changed.
|
|
hr = pEditRecord->GetTextAndPropertyUpdates(0/*TF_GTP_INCL_TEXT*/, rgModeBiasProperties, ARRAYSIZE(rgModeBiasProperties), &pEnumText);
|
|
if (FAILED(hr) || pEnumText == NULL)
|
|
return S_OK;
|
|
if (pEnumText->Next(1, &pRange, &ulFetched) == S_OK)
|
|
{
|
|
SafeRelease(pRange);
|
|
// ModeBias changed.
|
|
ess.fBool = fTrue;
|
|
}
|
|
pEnumText->Release();
|
|
|
|
// Selection changed?
|
|
pEditRecord->GetSelectionStatus(&fSelChanged);
|
|
|
|
// If Attribute changed, set selection change true.
|
|
if (fSelChanged == fFalse)
|
|
{
|
|
hr = pEditRecord->GetTextAndPropertyUpdates(0/*TF_GTP_INCL_TEXT*/, rgAttrProperties, ARRAYSIZE(rgAttrProperties), &pEnumText);
|
|
if (FAILED(hr) || pEnumText == NULL)
|
|
return S_OK;
|
|
if (pEnumText->Next(1, &pRange, &ulFetched) == S_OK)
|
|
{
|
|
SafeRelease(pRange);
|
|
fSelChanged = fTrue;
|
|
}
|
|
pEnumText->Release();
|
|
}
|
|
|
|
// Perf: Call ES only if (ModeBias change) or (Selection changed and comp object exist)
|
|
// I guess calling ES is pretty much costing since sel change occurs for ever cursor move.
|
|
if (fSelChanged)
|
|
fSelChanged = (GetIPComposition(pic) != NULL) ? fTrue : fFalse;
|
|
|
|
// If ModeBias changed or Selection changed, then call ESCB_TEXTEVENT sink
|
|
if (ess.fBool || fSelChanged)
|
|
{
|
|
if ((pes = new CEditSession2( pic, this, &ess, _EditSessionCallback2 )) != NULL)
|
|
{
|
|
pes->Invoke(ES2_READWRITE | ES2_ASYNC, &hr);
|
|
pes->Release();
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/* O N S T A R T E D I T T R A N S A C T I O N */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
HRESULT CKorIMX::OnStartEditTransaction(ITfContext *pic)
|
|
{
|
|
CICPriv *picp;
|
|
|
|
if (pic == NULL)
|
|
return S_OK; // error
|
|
|
|
picp = GetInputContextPriv(pic);
|
|
if (picp)
|
|
picp->SetfTransaction(fTrue);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/* O N E N D E D I T T R A N S A C T I O N */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
HRESULT CKorIMX::OnEndEditTransaction(ITfContext *pic)
|
|
{
|
|
BOOL ftran;
|
|
CICPriv *picp;
|
|
|
|
if (pic == NULL)
|
|
return S_OK; // error
|
|
|
|
picp = GetInputContextPriv(pic);
|
|
if (picp)
|
|
{
|
|
ftran = picp->GetfTransaction();
|
|
if (ftran)
|
|
{
|
|
CEditSession2 *pes;
|
|
ESSTRUCT ess;
|
|
HRESULT hr;
|
|
|
|
picp->SetfTransaction(fFalse);
|
|
|
|
ESStructInit(&ess, ESCB_TEXTEVENT);
|
|
ess.pEnumRange = NULL;
|
|
|
|
if ((pes = new CEditSession2( pic, this, &ess, _EditSessionCallback2 )) != NULL)
|
|
{
|
|
pes->Invoke(ES2_READWRITE | ES2_ASYNC, &hr);
|
|
pes->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|