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.
338 lines
7.6 KiB
338 lines
7.6 KiB
//
|
|
// ics.cpp
|
|
//
|
|
|
|
#include "private.h"
|
|
#include "tim.h"
|
|
#include "dim.h"
|
|
#include "ic.h"
|
|
#include "emptyic.h"
|
|
#include "acp2anch.h"
|
|
#include "enumic.h"
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetTop
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CDocumentInputManager::GetTop(ITfContext **ppic)
|
|
{
|
|
return _GetContext(_iStack, ppic);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetBase
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CDocumentInputManager::GetBase(ITfContext **ppic)
|
|
{
|
|
return _GetContext(0, ppic);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _GetContext
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CDocumentInputManager::_GetContext(int iStack, ITfContext **ppic)
|
|
{
|
|
if (ppic == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
*ppic = NULL;
|
|
|
|
if (_iStack == -1)
|
|
{
|
|
Assert(iStack == 0 || iStack == -1); // caller should be GetBottom or internal using _iStack...
|
|
if (!_peic)
|
|
{
|
|
_peic = new CEmptyInputContext(this);
|
|
|
|
if (_peic == NULL)
|
|
return E_OUTOFMEMORY;
|
|
|
|
if (FAILED(_peic->Init()))
|
|
{
|
|
SafeReleaseClear(_peic);
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
*ppic = _peic;
|
|
}
|
|
else
|
|
{
|
|
Assert(iStack >= 0 && iStack <= _iStack);
|
|
*ppic = _Stack[iStack];
|
|
}
|
|
Assert(*ppic);
|
|
|
|
(*ppic)->AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CreateContext
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
// this is a constant we removed before cicero ship, but office10 still uses it
|
|
// it can be ignored, but it must be accepted as legal
|
|
#define TF_PLAINTEXTTSI 0x1
|
|
|
|
STDAPI CDocumentInputManager::CreateContext(TfClientId tid, DWORD dwFlags, IUnknown *punk, ITfContext **ppic, TfEditCookie *pecTextStore)
|
|
{
|
|
CInputContext *pic;
|
|
ITextStoreAnchor *ptsi;
|
|
ITextStoreACP *ptsiACP;
|
|
CThreadInputMgr *tim;
|
|
ITfContextOwnerCompositionSink *pOwnerComposeSink;
|
|
HRESULT hr;
|
|
|
|
if (pecTextStore != NULL)
|
|
{
|
|
*pecTextStore = TF_INVALID_EDIT_COOKIE;
|
|
}
|
|
if (ppic != NULL)
|
|
{
|
|
*ppic = NULL;
|
|
}
|
|
|
|
if (ppic == NULL || pecTextStore == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (dwFlags & ~TF_PLAINTEXTTSI)
|
|
return E_INVALIDARG;
|
|
|
|
if ((tim = CThreadInputMgr::_GetThis()) == NULL)
|
|
return E_FAIL;
|
|
|
|
if (!tim->_IsValidTfClientId(tid))
|
|
return E_INVALIDARG;
|
|
|
|
ptsi = NULL;
|
|
pOwnerComposeSink = NULL;
|
|
|
|
if (punk != NULL)
|
|
{
|
|
if (g_fNoITextStoreAnchor ||
|
|
punk->QueryInterface(IID_ITextStoreAnchor, (void **)&ptsi) != S_OK ||
|
|
ptsi == NULL)
|
|
{
|
|
if (punk->QueryInterface(IID_ITextStoreACP, (void **)&ptsiACP) != S_OK || ptsiACP == NULL)
|
|
{
|
|
ptsiACP = NULL;
|
|
}
|
|
else
|
|
{
|
|
ptsi = new CACPWrap(ptsiACP);
|
|
ptsiACP->Release();
|
|
|
|
if (ptsi == NULL)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if (punk->QueryInterface(IID_ITfContextOwnerCompositionSink, (void **)&pOwnerComposeSink) != S_OK)
|
|
{
|
|
pOwnerComposeSink = NULL;
|
|
}
|
|
}
|
|
|
|
if ((pic = new CInputContext(tid)) == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
if (pic->_Init(tim, this, ptsi, pOwnerComposeSink) != S_OK)
|
|
{
|
|
pic->Release();
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
*ppic = pic;
|
|
|
|
if (ptsi != NULL)
|
|
{
|
|
// caller is doing the ITextStore, so return a back door ec
|
|
*pecTextStore = BACKDOOR_EDIT_COOKIE;
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Exit:
|
|
SafeRelease(ptsi);
|
|
SafeRelease(pOwnerComposeSink);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Push
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CDocumentInputManager::Push(ITfContext *pic)
|
|
{
|
|
CInputContext *pcic;
|
|
|
|
if (pic == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (_iStack == ICS_STACK_SIZE - 1)
|
|
return TF_E_STACKFULL;
|
|
|
|
pcic = GetCInputContext(pic);
|
|
if (!pcic)
|
|
return E_INVALIDARG;
|
|
|
|
if (_fPoppingStack)
|
|
return E_UNEXPECTED;
|
|
|
|
// we don't need AddRef here, GetCInputContext did AddRef().
|
|
_Stack[++_iStack] = pcic;
|
|
|
|
pcic->_AdviseSinks();
|
|
|
|
// if it's the first push, we call a notification.
|
|
if (_iStack == 0)
|
|
{
|
|
CThreadInputMgr *tim;
|
|
if ((tim = CThreadInputMgr::_GetThis()) == NULL)
|
|
return E_FAIL;
|
|
|
|
tim->_NotifyCallbacks(TIM_INITDIM, this, NULL);
|
|
}
|
|
|
|
pcic->_Pushed();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Pop
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CDocumentInputManager::Pop(DWORD dwFlags)
|
|
{
|
|
CThreadInputMgr *tim;
|
|
if (dwFlags & ~TF_POPF_ALL)
|
|
return E_INVALIDARG;
|
|
|
|
if (_iStack == -1)
|
|
return E_FAIL;
|
|
|
|
if (_fPoppingStack)
|
|
return E_UNEXPECTED;
|
|
|
|
if ((tim = CThreadInputMgr::_GetThis()) == NULL)
|
|
return E_FAIL;
|
|
|
|
if (!(dwFlags & TF_POPF_ALL))
|
|
{
|
|
if (!_iStack)
|
|
return E_FAIL;
|
|
|
|
_Pop(tim);
|
|
}
|
|
else
|
|
{
|
|
while(_iStack >= 0)
|
|
{
|
|
_Pop(tim);
|
|
}
|
|
|
|
// clear the focus if this guy has it
|
|
if (tim->_GetFocusDocInputMgr() == this)
|
|
{
|
|
tim->_SetFocus(NULL, TRUE);
|
|
}
|
|
|
|
tim->_NotifyCallbacks(TIM_UNINITDIM, this, NULL);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _Pop
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CDocumentInputManager::_Pop(CThreadInputMgr *tim)
|
|
{
|
|
CInputContext *pic;
|
|
|
|
Assert(_iStack >= 0);
|
|
|
|
pic = _Stack[_iStack];
|
|
|
|
// don't let anyone mess with the stack while we adjust it
|
|
_fPoppingStack = TRUE;
|
|
|
|
// call _Popped() to release properties and compartments.
|
|
// must do this before _UnadviseSinks while the ITextStore
|
|
// has not yet been released
|
|
pic->_Popped();
|
|
|
|
pic->_UnadviseSinks(tim);
|
|
pic->Release();
|
|
|
|
_fPoppingStack = FALSE;
|
|
|
|
_iStack--;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// EnumInputContexts
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CDocumentInputManager::EnumContexts(IEnumTfContexts **ppEnum)
|
|
{
|
|
CEnumInputContexts *pEnum;
|
|
|
|
pEnum = new CEnumInputContexts();
|
|
if (!pEnum)
|
|
return E_OUTOFMEMORY;
|
|
|
|
if (!pEnum->_Init(this))
|
|
{
|
|
pEnum->Release();
|
|
return E_FAIL;
|
|
}
|
|
|
|
*ppEnum = pEnum;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _GetTopIC
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CInputContext *CDocumentInputManager::_GetTopIC()
|
|
{
|
|
if (_iStack == -1)
|
|
return NULL;
|
|
|
|
return _Stack[_iStack];
|
|
}
|
|
|