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.
655 lines
23 KiB
655 lines
23 KiB
//
|
|
// ic.h
|
|
//
|
|
|
|
#ifndef IC_H
|
|
#define IC_H
|
|
|
|
#include "private.h"
|
|
#include "globals.h"
|
|
#include "rprop.h"
|
|
#include "editrec.h"
|
|
#include "strary.h"
|
|
#include "compart.h"
|
|
|
|
#define TF_ES_INEDITSESSION 0x80000000
|
|
#define TF_ES_INNOTIFY 0x40000000
|
|
#define TF_ES_WRITE (TF_ES_READWRITE & ~TF_ES_READ)
|
|
#define TF_ES_PROPERTY_WRITE (TF_ES_READ_PROPERTY_WRITE & ~TF_ES_READ)
|
|
#define TF_ES_ALL_ACCESS_BITS (TF_ES_READWRITE | TF_ES_READ_PROPERTY_WRITE)
|
|
|
|
#define IC_NUM_CONNECTIONPTS 5
|
|
// these are indices into _rgSinks, must match CInputContext::_c_rgConnectionIIDs
|
|
#define IC_SINK_ITfTextEditSink 0
|
|
#define IC_SINK_ITfTextLayoutSink 1
|
|
#define IC_SINK_ITfStatusSink 2
|
|
#define IC_SINK_ITfStartReconversionNotifySink 3
|
|
#define IC_SINK_ITfEditTransactionSink 4
|
|
|
|
class CRange;
|
|
class CProperty;
|
|
class CThreadInputMgr;
|
|
class CFunctionProvider;
|
|
class CFunction;
|
|
class CContextView;
|
|
class CComposition;
|
|
class CDocumentInputManager;
|
|
class CInputContext;
|
|
|
|
extern const IID IID_PRIV_CINPUTCONTEXT;
|
|
|
|
#define LEFT_FILTERTIP 0
|
|
#define RIGHT_FILTERTIP 1
|
|
|
|
typedef struct _CLEANUPSINK
|
|
{
|
|
TfClientId tid;
|
|
ITfCleanupContextSink *pSink;
|
|
} CLEANUPSINK;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// QUEUE_ITEM structures
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef enum { QI_ADDREF, QI_DISPATCH, QI_FREE } QiCallbackCode;
|
|
|
|
struct _TS_QUEUE_ITEM;
|
|
|
|
typedef HRESULT (*QI_CALLBACK)(CInputContext *pic, struct _TS_QUEUE_ITEM *pItem, QiCallbackCode qiCode);
|
|
|
|
typedef struct _EDITSESSION
|
|
{
|
|
TfClientId tid;
|
|
ITfEditSession *pes;
|
|
} EDITSESSION;
|
|
|
|
typedef struct _PSEUDO_EDITSESSION
|
|
{
|
|
ULONG uCode;
|
|
void *pvState;
|
|
} PSEUDO_EDITSESSION;
|
|
|
|
class CAsyncQueueItem;
|
|
typedef struct _ASYNCQUEUE_EDITSESSION
|
|
{
|
|
CAsyncQueueItem *paqi;
|
|
} ASYNCQUEUE_EDITSESSION;
|
|
|
|
typedef struct _TS_QUEUE_ITEM
|
|
{
|
|
QI_CALLBACK pfnCallback;
|
|
DWORD dwFlags; // TF_ES_READWRITE | TF_ES_READ | TF_ES_WRITE | TF_ES_SYNC
|
|
|
|
union
|
|
{
|
|
// state for edit sessions
|
|
EDITSESSION es;
|
|
|
|
PSEUDO_EDITSESSION pes;
|
|
|
|
ASYNCQUEUE_EDITSESSION aqe;
|
|
|
|
// other state...
|
|
} state;
|
|
} TS_QUEUE_ITEM;
|
|
|
|
//
|
|
// PSEUDO_EDITSESSION callback codes
|
|
//
|
|
#define PSEUDO_ESCB_TERMCOMPOSITION 0
|
|
#define PSEUDO_ESCB_UPDATEKEYEVENTFILTER 1
|
|
#define PSEUDO_ESCB_GROWRANGE 2
|
|
#define PSEUDO_ESCB_BUILDOWNERRANGELIST 3
|
|
#define PSEUDO_ESCB_SHIFTENDTORANGE 4
|
|
#define PSEUDO_ESCB_GETSELECTION 5
|
|
#define PSEUDO_ESCB_SERIALIZE_ACP 6
|
|
#define PSEUDO_ESCB_SERIALIZE_ANCHOR 7
|
|
#define PSEUDO_ESCB_UNSERIALIZE_ACP 8
|
|
#define PSEUDO_ESCB_UNSERIALIZE_ANCHOR 9
|
|
#define PSEUDO_ESCB_GETWHOLEDOCRANGE 10
|
|
|
|
typedef struct _SERIALIZE_ANCHOR_PARAMS
|
|
{
|
|
CProperty *pProp;
|
|
CRange *pRange;
|
|
TF_PERSISTENT_PROPERTY_HEADER_ANCHOR *pHdr;
|
|
IStream *pStream;
|
|
} SERIALIZE_ANCHOR_PARAMS;
|
|
|
|
typedef struct _UNSERIALIZE_ANCHOR_PARAMS
|
|
{
|
|
CProperty *pProp;
|
|
const TF_PERSISTENT_PROPERTY_HEADER_ANCHOR *pHdr;
|
|
IStream *pStream;
|
|
ITfPersistentPropertyLoaderAnchor *pLoader;
|
|
} UNSERIALIZE_ANCHOR_PARAMS;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CAsyncQueueItem
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
class CAsyncQueueItem
|
|
{
|
|
public:
|
|
CAsyncQueueItem(BOOL fSync = FALSE)
|
|
{
|
|
_item.pfnCallback = _EditSessionQiCallback;
|
|
_item.dwFlags = TF_ES_READWRITE | (fSync ? TF_ES_SYNC : 0);
|
|
_item.state.aqe.paqi = this;
|
|
|
|
_cRef = 1;
|
|
}
|
|
|
|
virtual ~CAsyncQueueItem() {};
|
|
|
|
static HRESULT _EditSessionQiCallback(CInputContext *pic, struct _TS_QUEUE_ITEM *pItem, QiCallbackCode qiCode);
|
|
|
|
virtual HRESULT DoDispatch(CInputContext *pic) = 0;
|
|
|
|
void _CheckReadOnly(CInputContext *pic);
|
|
|
|
TS_QUEUE_ITEM *GetItem()
|
|
{
|
|
return &_item;
|
|
}
|
|
|
|
LONG _AddRef()
|
|
{
|
|
_cRef++;
|
|
return _cRef;
|
|
}
|
|
|
|
LONG _Release()
|
|
{
|
|
LONG ret = --_cRef;
|
|
if (!_cRef)
|
|
delete this;
|
|
|
|
return ret;
|
|
}
|
|
|
|
private:
|
|
LONG _cRef;
|
|
TS_QUEUE_ITEM _item;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CInputContext
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
class CInputContext : public ITfContext_P,
|
|
public ITfQueryEmbedded,
|
|
public ITfInsertAtSelection,
|
|
public ITfContextOwnerServices,
|
|
public ITfContextOwnerCompositionServices,
|
|
public ITfSource,
|
|
public ITfSourceSingle,
|
|
public ITextStoreAnchorSink,
|
|
public ITextStoreAnchorServices,
|
|
public ITfMouseTracker,
|
|
public IServiceProvider,
|
|
public ITfContextRenderingMarkup,
|
|
public CCompartmentMgr,
|
|
public CComObjectRootImmx
|
|
{
|
|
public:
|
|
CInputContext(TfClientId tid);
|
|
~CInputContext();
|
|
|
|
BEGIN_COM_MAP_IMMX(CInputContext)
|
|
COM_INTERFACE_ENTRY_IID(IID_PRIV_CINPUTCONTEXT, CInputContext)
|
|
COM_INTERFACE_ENTRY(ITfContext)
|
|
COM_INTERFACE_ENTRY(ITfContext_P)
|
|
COM_INTERFACE_ENTRY(ITfQueryEmbedded)
|
|
COM_INTERFACE_ENTRY(ITfInsertAtSelection)
|
|
COM_INTERFACE_ENTRY(ITfContextComposition)
|
|
COM_INTERFACE_ENTRY(ITfContextOwnerCompositionServices)
|
|
COM_INTERFACE_ENTRY(ITfSource)
|
|
COM_INTERFACE_ENTRY(ITfSourceSingle)
|
|
COM_INTERFACE_ENTRY(ITextStoreAnchorSink)
|
|
COM_INTERFACE_ENTRY(ITextStoreAnchorServices)
|
|
COM_INTERFACE_ENTRY(ITfCompartmentMgr)
|
|
COM_INTERFACE_ENTRY(ITfContextOwnerServices) // Issue: it would be nice if this was only avail w/ cicero def text store
|
|
// COM_INTERFACE_ENTRY_FUNC
|
|
COM_INTERFACE_ENTRY(ITfMouseTracker)
|
|
COM_INTERFACE_ENTRY(IServiceProvider)
|
|
COM_INTERFACE_ENTRY(ITfContextRenderingMarkup)
|
|
END_COM_MAP_IMMX()
|
|
|
|
IMMX_OBJECT_IUNKNOWN_FOR_ATL()
|
|
|
|
//
|
|
// ITfContext
|
|
//
|
|
STDMETHODIMP RequestEditSession(TfClientId tid, ITfEditSession *pes, DWORD dwFlags, HRESULT *phrSession);
|
|
STDMETHODIMP InWriteSession(TfClientId tid, BOOL *pfWriteSession);
|
|
STDMETHODIMP GetSelection(TfEditCookie ec, ULONG ulIndex, ULONG ulCount, TF_SELECTION *pSelection, ULONG *pcFetched);
|
|
STDMETHODIMP SetSelection(TfEditCookie ec, ULONG ulCount, const TF_SELECTION *pSelection);
|
|
STDMETHODIMP GetStart(TfEditCookie ec, ITfRange **ppStart);
|
|
STDMETHODIMP GetEnd(TfEditCookie ec, ITfRange **ppEnd);
|
|
STDMETHODIMP GetStatus(TS_STATUS *pdcs);
|
|
STDMETHODIMP GetActiveView(ITfContextView **ppView);
|
|
STDMETHODIMP EnumViews(IEnumTfContextViews **ppEnum);
|
|
STDMETHODIMP GetProperty(REFGUID guidProp, ITfProperty **ppv);
|
|
|
|
STDMETHODIMP GetAppProperty(REFGUID guidProp, ITfReadOnlyProperty **ppProp);
|
|
STDMETHODIMP TrackProperties(const GUID **pguidProp, ULONG cProp, const GUID **pguidAppProp, ULONG cAppProp, ITfReadOnlyProperty **ppPropX);
|
|
|
|
STDMETHODIMP EnumProperties(IEnumTfProperties **ppEnum);
|
|
STDMETHODIMP GetDocumentMgr(ITfDocumentMgr **ppDoc);
|
|
STDMETHODIMP CreateRangeBackup(TfEditCookie ec, ITfRange *pRange, ITfRangeBackup **ppBackup);
|
|
|
|
// ITfQueryEmbedded
|
|
STDMETHODIMP QueryInsertEmbedded(const GUID *pguidService, const FORMATETC *pFormatEtc, BOOL *pfInsertable);
|
|
|
|
// ITfInsertAtSelection
|
|
STDMETHODIMP InsertTextAtSelection(TfEditCookie ec, DWORD dwFlags, const WCHAR *pchText, LONG cch, ITfRange **ppRange);
|
|
STDMETHODIMP InsertEmbeddedAtSelection(TfEditCookie ec, DWORD dwFlags, IDataObject *pDataObject, ITfRange **ppRange);
|
|
|
|
// ITfContextOwnerServices
|
|
STDMETHODIMP OnLayoutChange();
|
|
//STDMETHODIMP OnStatusChange(); // use ITextStoreAnchorSink::OnStatusChange
|
|
STDMETHODIMP OnAttributeChange(REFGUID rguidAttribute);
|
|
STDMETHODIMP Serialize(ITfProperty *pProp, ITfRange *pRange, TF_PERSISTENT_PROPERTY_HEADER_ACP *pHdr, IStream *pStream);
|
|
STDMETHODIMP Unserialize(ITfProperty *pProp, const TF_PERSISTENT_PROPERTY_HEADER_ACP *pHdr, IStream *pStream, ITfPersistentPropertyLoaderACP *pLoader);
|
|
STDMETHODIMP ForceLoadProperty(ITfProperty *pProp);
|
|
STDMETHODIMP CreateRange(LONG acpStart, LONG acpEnd, ITfRangeACP **ppRange);
|
|
|
|
// ITfContextComposition
|
|
STDMETHODIMP StartComposition(TfEditCookie ecWrite, ITfRange *pCompositionRange, ITfCompositionSink *pSink, ITfComposition **ppComposition);
|
|
STDMETHODIMP EnumCompositions(IEnumITfCompositionView **ppEnum);
|
|
STDMETHODIMP FindComposition(TfEditCookie ecRead, ITfRange *pTestRange, IEnumITfCompositionView **ppEnum);
|
|
STDMETHODIMP TakeOwnership(TfEditCookie ecWrite, ITfCompositionView *pComposition, ITfCompositionSink *pSink, ITfComposition **ppComposition);
|
|
|
|
// ITfContextOwnerCompositionServices
|
|
STDMETHODIMP TerminateComposition(ITfCompositionView *pComposition);
|
|
|
|
// ITfSource
|
|
STDMETHODIMP AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCookie);
|
|
STDMETHODIMP UnadviseSink(DWORD dwCookie);
|
|
|
|
// ITfSourceSingle
|
|
STDMETHODIMP AdviseSingleSink(TfClientId tid, REFIID riid, IUnknown *punk);
|
|
STDMETHODIMP UnadviseSingleSink(TfClientId tid, REFIID riid);
|
|
|
|
// ITextStoreAnchorSink
|
|
STDMETHODIMP OnTextChange(DWORD dwFlags, IAnchor *paStart, IAnchor *paEnd);
|
|
STDMETHODIMP OnSelectionChange();
|
|
STDMETHODIMP OnLayoutChange(TsLayoutCode lcode, TsViewCookie vcView);
|
|
STDMETHODIMP OnStatusChange(DWORD dwFlags);
|
|
STDMETHODIMP OnAttrsChange(IAnchor *paStart, IAnchor *paEnd, ULONG cAttrs, const TS_ATTRID *paAttrs);
|
|
STDMETHODIMP OnLockGranted(DWORD dwLockFlags);
|
|
STDMETHODIMP OnStartEditTransaction();
|
|
STDMETHODIMP OnEndEditTransaction();
|
|
|
|
// ITextStoreAnchorServices
|
|
STDMETHODIMP Serialize(ITfProperty *pProp, ITfRange *pRange, TF_PERSISTENT_PROPERTY_HEADER_ANCHOR *pHdr, IStream *pStream);
|
|
STDMETHODIMP Unserialize(ITfProperty *pProp, const TF_PERSISTENT_PROPERTY_HEADER_ANCHOR *pHdr, IStream *pStream, ITfPersistentPropertyLoaderAnchor *pLoader);
|
|
STDMETHODIMP CreateRange(IAnchor *paStart, IAnchor *paEnd, ITfRangeAnchor **ppRange);
|
|
|
|
// ITfMouseTracker
|
|
STDMETHODIMP AdviseMouseSink(ITfRange *range, ITfMouseSink *pSink, DWORD *pdwCookie);
|
|
STDMETHODIMP UnadviseMouseSink(DWORD dwCookie);
|
|
|
|
// IServiceProvider
|
|
STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppv);
|
|
|
|
// ITfContextRenderingMarkup
|
|
STDMETHODIMP GetRenderingMarkup(TfEditCookie ec, DWORD dwFlags, ITfRange *pRangeCover, IEnumTfRenderingMarkup **ppEnum);
|
|
STDMETHODIMP FindNextRenderingMarkup(TfEditCookie ec, DWORD dwFlags, ITfRange *pRangeQuery, TfAnchor tfAnchorQuery,
|
|
ITfRange **ppRangeFound, TF_RENDERINGMARKUP *ptfRenderingMarkup);
|
|
|
|
// ITfContext_P
|
|
STDMETHODIMP MapAppProperty(REFGUID guidAppProp, REFGUID guidProp);
|
|
STDMETHODIMP EnableLockRequestPosting(BOOL fEnable);
|
|
|
|
|
|
HRESULT _Init(CThreadInputMgr *tim, CDocumentInputManager *dm, ITextStoreAnchor *ptsi, ITfContextOwnerCompositionSink *pOwnerComposeSink);
|
|
|
|
void _Pushed();
|
|
void _Popped();
|
|
|
|
void _AdviseSinks();
|
|
void _UnadviseSinks(CThreadInputMgr *tim);
|
|
|
|
void _UpdateKeyEventFilter();
|
|
HRESULT _UpdateKeyEventFilterCallback(TfEditCookie ec);
|
|
|
|
HRESULT _GetProperty(REFGUID rguidProp, CProperty **ppv);
|
|
|
|
BOOL _NotifyEndEdit(void);
|
|
|
|
CProperty *_FindProperty(REFGUID rguidProp)
|
|
{
|
|
TfGuidAtom ga;
|
|
|
|
if (MyRegisterGUID(rguidProp, &ga) != S_OK)
|
|
return NULL;
|
|
|
|
return _FindProperty(ga);
|
|
}
|
|
CProperty *_FindProperty(TfGuidAtom gaProp);
|
|
|
|
void _PropertyTextUpdate(DWORD dwFlags, IAnchor *paStart, IAnchor *paEnd);
|
|
CProperty *_GetFirstProperty() { return _pPropList; }
|
|
|
|
CProperty *_pPropList;
|
|
|
|
BOOL _IsCiceroTSI() { return _fCiceroTSI; }
|
|
|
|
ITextStoreAnchor *_GetTSI() { return _ptsi; }
|
|
ITextStoreAnchor *_GetAATSI() { return _pMSAAState ? _pMSAAState->pAADoc : NULL; }
|
|
|
|
BOOL _IsInEditSession() { return (_dwEditSessionFlags & TF_ES_INEDITSESSION); }
|
|
BOOL _IsConnected() { return _dm ? TRUE : FALSE; }
|
|
|
|
BOOL _IsValidEditCookie(TfEditCookie ec, DWORD dwFlags)
|
|
{
|
|
Assert(dwFlags & TF_ES_READ); // minimum access...
|
|
|
|
if (ec == BACKDOOR_EDIT_COOKIE)
|
|
{
|
|
Assert(!(dwFlags & (TF_ES_WRITE | TF_ES_PROPERTY_WRITE))); // app is trying to use def ec with write operation
|
|
return !(dwFlags & (TF_ES_WRITE | TF_ES_PROPERTY_WRITE)); // app can read anything it wants
|
|
}
|
|
|
|
Assert(_ec != TF_INVALID_EDIT_COOKIE); // must always return FALSE for TF_INVALID_EDIT_COOKIE...
|
|
Assert(!(_dwEditSessionFlags & TF_ES_WRITE) || (_dwEditSessionFlags & TF_ES_PROPERTY_WRITE)); // write implies property write
|
|
|
|
return (ec == _ec &&
|
|
(_dwEditSessionFlags & TF_ES_INEDITSESSION) &&
|
|
(!(dwFlags & TF_ES_WRITE) || (_dwEditSessionFlags & TF_ES_WRITE))) &&
|
|
(!(dwFlags & TF_ES_PROPERTY_WRITE) || (_dwEditSessionFlags & TF_ES_PROPERTY_WRITE));
|
|
}
|
|
|
|
void _IncLastLockReleaseID() { _dwLastLockReleaseID++; /* Issue: handle wrap-around */ }
|
|
DWORD _GetLastLockReleaseID() { return _dwLastLockReleaseID; }
|
|
|
|
CDocumentInputManager *_GetDm() { return _dm; }
|
|
|
|
CEditRecord *_GetEditRecord() { return _pEditRecord; }
|
|
HRESULT _OnTextChangeInternal(DWORD dwFlags, IAnchor *paStart, IAnchor *paEnd, AnchorOwnership ao);
|
|
|
|
CProperty *GetTextOwnerProperty();
|
|
|
|
TfClientId _GetClientInEditSession(TfEditCookie ec) { return ec == BACKDOOR_EDIT_COOKIE ? g_gaApp : _tidInEditSession; }
|
|
TfClientId _SetRawClientInEditSession(TfClientId tid)
|
|
{
|
|
TfClientId tidTmp = _tidInEditSession;
|
|
_tidInEditSession = tid;
|
|
return tidTmp;
|
|
}
|
|
|
|
CStructArray<GENERICSINK> *_GetTextEditSinks() { return &_rgSinks[IC_SINK_ITfTextEditSink]; }
|
|
CStructArray<GENERICSINK> *_GetTextLayoutSinks() { return &_rgSinks[IC_SINK_ITfTextLayoutSink]; }
|
|
CStructArray<GENERICSINK> *_GetStatusSinks() { return &_rgSinks[IC_SINK_ITfStatusSink]; }
|
|
CStructArray<GENERICSINK> *_GetStartReconversionNotifySinks() { return &_rgSinks[IC_SINK_ITfStartReconversionNotifySink]; }
|
|
CStructArray<GENERICSINK> *_GetEditTransactionSink() { return &_rgSinks[IC_SINK_ITfEditTransactionSink]; }
|
|
CStructArray<CLEANUPSINK> *_GetCleanupSinks() { return &_rgCleanupSinks; }
|
|
|
|
BOOL _AppSupportsCompositions() { return _pCompositionList != NULL; }
|
|
CComposition *_GetCompositionList() { return _pCompositionList; }
|
|
CComposition **_GetCompositionListPtr() { return &_pCompositionList; }
|
|
ITfContextOwnerCompositionSink *_GetOwnerCompositionSink() { return _pOwnerComposeSink; }
|
|
BOOL _DoesAppSupportCompositions() { return _pOwnerComposeSink != NULL; }
|
|
BOOL _EnterCompositionOp()
|
|
{
|
|
return (_fInCompositionOp ? FALSE : (_fInCompositionOp = TRUE));
|
|
}
|
|
void _LeaveCompositionOp()
|
|
{
|
|
Assert(_fInCompositionOp);
|
|
_fInCompositionOp = FALSE;
|
|
}
|
|
|
|
HRESULT _StartComposition(TfEditCookie ecWrite, IAnchor *paStart, IAnchor *paEnd, ITfCompositionSink *pSink, CComposition **ppComposition);
|
|
HRESULT _TerminateCompositionWithLock(ITfCompositionView *pComposition, TfEditCookie ec);
|
|
void _AbortCompositions();
|
|
|
|
static void _PostponeLockRequestCallback(SYSTHREAD *psfn, CInputContext *pic);
|
|
|
|
HRESULT _DoPseudoSyncEditSession(DWORD dwFlags, ULONG uCode, void *pvState, HRESULT *phrSession)
|
|
{
|
|
TS_QUEUE_ITEM item;
|
|
|
|
item.pfnCallback = _PseudoSyncEditSessionQiCallback;
|
|
item.dwFlags = dwFlags | TF_ES_SYNC;
|
|
item.state.pes.uCode = uCode;
|
|
item.state.pes.pvState = pvState;
|
|
|
|
return _QueueItem(&item, FALSE, phrSession);
|
|
}
|
|
HRESULT _QueueItem(TS_QUEUE_ITEM *pItem, BOOL fForceAsync, HRESULT *phrSession);
|
|
|
|
BOOL _ContextNeedsCleanup(const GUID *pCatId, LANGID langid, CStructArray<TfClientId> **pprgClientIds);
|
|
void _CleanupContext(CStructArray<TfClientId> *prgClientIds);
|
|
|
|
HRESULT GetMappedAppProperty(REFGUID guidProp, CProperty **ppProp);
|
|
|
|
private:
|
|
|
|
friend CThreadInputMgr;
|
|
friend CRange;
|
|
friend CProperty;
|
|
friend CFunction;
|
|
|
|
typedef struct _IAS_OBJ
|
|
{
|
|
enum { IAS_TEXT, IAS_DATAOBJ } type;
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
const WCHAR *pchText;
|
|
LONG cch;
|
|
} text;
|
|
struct
|
|
{
|
|
IDataObject *pDataObject;
|
|
} obj;
|
|
} state;
|
|
} IAS_OBJ;
|
|
|
|
HRESULT _InsertXAtSelection(TfEditCookie ec, DWORD dwFlags, IAS_OBJ *pObj, ITfRange **ppRange);
|
|
void _DoPostTextEditNotifications(CComposition *pComposition, TfEditCookie ec, DWORD dwFlags, ULONG cchInserted, IAnchor *paStart, IAnchor *paEnd, CRange *range);
|
|
BOOL _InsertXAtSelectionAggressive(TfEditCookie ec, DWORD dwFlags, IAS_OBJ *pObj, IAnchor **ppaStart, IAnchor **ppaEnd);
|
|
|
|
int _GetCleanupListIndex(TfClientId tid);
|
|
|
|
HRESULT _UnadviseOwnerSink();
|
|
|
|
HRESULT _GetStartOrEnd(TfEditCookie ec, BOOL fStart, ITfRange **ppStart);
|
|
|
|
BOOL _SynchAppChanges(DWORD dwLockFlags);
|
|
HRESULT _EmptyLockQueue(DWORD dwLockFlags, BOOL fAppChangesSent);
|
|
void _AbortQueueItems();
|
|
void _PostponeLockRequest(DWORD dwFlags);
|
|
|
|
HRESULT _DispatchQueueItem(TS_QUEUE_ITEM *pItem)
|
|
{
|
|
return pItem->pfnCallback(this, pItem, QI_DISPATCH);
|
|
}
|
|
void _ReleaseQueueItem(TS_QUEUE_ITEM *pItem)
|
|
{
|
|
pItem->pfnCallback(this, pItem, QI_FREE);
|
|
}
|
|
void _AddRefQueueItem(TS_QUEUE_ITEM *pItem)
|
|
{
|
|
pItem->pfnCallback(this, pItem, QI_ADDREF);
|
|
}
|
|
|
|
HRESULT _DoEditSession(TfClientId tid, ITfEditSession *pes, DWORD dwFlags);
|
|
static HRESULT _EditSessionQiCallback(CInputContext *pic, TS_QUEUE_ITEM *pItem, QiCallbackCode qiCode);
|
|
static HRESULT _PseudoSyncEditSessionQiCallback(CInputContext *pic, TS_QUEUE_ITEM *pItem, QiCallbackCode qiCode);
|
|
|
|
HRESULT _OnSelectionChangeInternal(BOOL fAppChange);
|
|
HRESULT _OnLayoutChangeInternal(TsLayoutCode lcode, TsViewCookie vcView);
|
|
HRESULT _OnStatusChangeInternal();
|
|
|
|
void _MarkDirtyRanges(IAnchor *paStart, IAnchor *paEnd);
|
|
TFPROPERTYSTYLE _GetPropStyle(REFGUID rguidProp);
|
|
|
|
void _IncEditCookie()
|
|
{
|
|
_ec++;
|
|
|
|
// avoid reserved values!
|
|
if (_ec == 0)
|
|
{
|
|
_ec = EC_MIN;
|
|
}
|
|
}
|
|
|
|
void _Dbg_AssertNoSyncQueueItems()
|
|
{
|
|
#ifdef DEBUG
|
|
for (int i=0; i<_rgLockQueue.Count(); i++)
|
|
{
|
|
Assert((_rgLockQueue.GetPtr(i)->dwFlags & TF_ES_SYNC) == 0);
|
|
}
|
|
#endif // DEBUG
|
|
}
|
|
|
|
CDocumentInputManager *_dm;
|
|
|
|
ITextStoreAnchor *_ptsi;
|
|
BOOL _fCiceroTSI;
|
|
|
|
DWORD _dwLastLockReleaseID;
|
|
|
|
TfEditCookie _ec;
|
|
int _cEditRef;
|
|
DWORD _dwEditSessionFlags;
|
|
BOOL _fLockHeld; // perf: redundant with _dwlt?
|
|
DWORD _dwlt; // perf: only need 2 bits
|
|
TfClientId _tidInEditSession;
|
|
DWORD _dwPendingLockRequest; // perf: only need 2 bits
|
|
|
|
CEditRecord *_pEditRecord;
|
|
BOOL EnsureEditRecord()
|
|
{
|
|
if (!_pEditRecord)
|
|
_pEditRecord = new CEditRecord(this);
|
|
|
|
return _pEditRecord ? TRUE : FALSE;
|
|
}
|
|
BOOL _fLayoutChanged;
|
|
BOOL _fStatusChanged; // perf: redundant w/ _dwStatusChangedFlags?
|
|
DWORD _dwStatusChangedFlags;
|
|
|
|
// array of TIP guidatom for both left and right side of the caret.
|
|
TfGuidAtom _gaKeyEventFilterTIP[2];
|
|
BOOL _fInvalidKeyEventFilterTIP;
|
|
|
|
ITfContextKeyEventSink *_pICKbdSink;
|
|
|
|
DWORD _dwSysFuncPrvCookie; // system function provider cookie
|
|
|
|
//
|
|
// TextOwner Property cache
|
|
//
|
|
CProperty *_pPropTextOwner;
|
|
|
|
static const GUID *_c_rgPropStyle[];
|
|
|
|
CStructArray<TS_QUEUE_ITEM> _rgLockQueue;
|
|
|
|
static const IID *_c_rgConnectionIIDs[IC_NUM_CONNECTIONPTS];
|
|
CStructArray<GENERICSINK> _rgSinks[IC_NUM_CONNECTIONPTS];
|
|
CStructArray<CLEANUPSINK> _rgCleanupSinks;
|
|
|
|
CStructArray<SPAN> _rgAppTextChanges;
|
|
|
|
CComposition *_pCompositionList;
|
|
|
|
CRange *_pOnChangeRanges; // ranges with ITfRangeChange sinks
|
|
|
|
CContextView *_pActiveView;
|
|
|
|
ITfContextOwnerCompositionSink *_pOwnerComposeSink; // may be NULL, be careful
|
|
|
|
LONG _cRefEditTransaction;
|
|
|
|
BOOL _fInCompositionOp : 1; // TRUE if we're inside a write modification to a composition (ceate, terminate, etc.)
|
|
BOOL _fInUnserialize : 1; // TRUE if we're inside a property _Unserialize
|
|
|
|
//
|
|
// App Property Map
|
|
//
|
|
typedef struct _APPPROPMAP
|
|
{
|
|
GUID guidAppProp;
|
|
GUID guidProp;
|
|
} APPPROPMAP;
|
|
CStructArray<APPPROPMAP> _rgAppPropMap;
|
|
APPPROPMAP *FindMapAppProperty(REFGUID guidAppProp);
|
|
|
|
//
|
|
// disable PostThreadMessage for LoackRequest.
|
|
//
|
|
ULONG _nLockReqPostDisableRef;
|
|
|
|
// aa stuff
|
|
//
|
|
void _InitMSAAHook(IAccServerDocMgr *pAAAdaptor);
|
|
void _UninitMSAAHook(IAccServerDocMgr *pAAAdaptor);
|
|
|
|
typedef struct
|
|
{
|
|
ITextStoreAnchor *ptsiOrg; // the original, unwrapped ptsi
|
|
ITextStoreAnchor *pAADoc; // the wrapped ITextStoreAnchor passed to _pAAAdaptor
|
|
} MSAA_STATE;
|
|
|
|
MSAA_STATE *_pMSAAState; // use a struct since we rarely use msaa
|
|
//
|
|
// end aa stuff
|
|
|
|
#ifdef DEBUG
|
|
BOOL _dbg_fInOnLockGranted;
|
|
#endif
|
|
|
|
DBG_ID_DECLARE;
|
|
};
|
|
|
|
inline CInputContext *GetCInputContext(IUnknown *punk)
|
|
{
|
|
CInputContext *pic;
|
|
|
|
punk->QueryInterface(IID_PRIV_CINPUTCONTEXT, (void **)&pic);
|
|
|
|
return pic;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SafeRequestLock
|
|
//
|
|
// ITextStoreAnchor::RequestLock wrapper.
|
|
//
|
|
// Normally each CInputContext holds a ref to a text store in its _ptsi member.
|
|
// But, it's possible that some crazy tip will Pop the context inside a
|
|
// RequestLock call, which releases and clears _ptsi. This will likely crash
|
|
// the ptsi code, since after OnLockGranted, the object will be freed.
|
|
// So we protect the app by AddRef'ing the ptsi before the RequestLock call.
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline HRESULT SafeRequestLock(ITextStoreAnchor *ptsi, DWORD dwLockFlags, HRESULT *phrSession)
|
|
{
|
|
HRESULT hr;
|
|
|
|
ptsi->AddRef(); // protect pointer in case someone Pops this context inside the RequestLock
|
|
|
|
hr = ptsi->RequestLock(dwLockFlags, phrSession);
|
|
|
|
ptsi->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
#endif // IC_H
|