Leaked source code of windows server 2003
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

//
// 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