changeset 4739:f51a9f01b508

Starting to implement ITextStoreACP. It's very incomplete and will probably change quite a bit but it's a start. ITextStoreACP is the minimum interface to be considered TSF-aware.
author dewyatt
date Mon, 21 Jun 2010 17:16:37 -0400
parents 381d402a5e90
children abf528de6d2e
files EXCLUDE/GLTSF/include/TSF.hpp EXCLUDE/GLTSF/src/TSF.cpp
diffstat 2 files changed, 369 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/EXCLUDE/GLTSF/include/TSF.hpp	Sat Jun 12 03:21:54 2010 -0400
+++ b/EXCLUDE/GLTSF/include/TSF.hpp	Mon Jun 21 17:16:37 2010 -0400
@@ -11,11 +11,73 @@
 	static void Finalize();
 
 private:
+	class TSF_Text_Store : public ITextStoreACP, public ITfContextOwnerCompositionSink
+	{
+	public:
+		//IUnknown
+		STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
+		STDMETHODIMP_(ULONG) AddRef();
+		STDMETHODIMP_(ULONG) Release();
+
+		//ITextStoreACP
+		STDMETHODIMP AdviseSink(REFIID riid, IUnknown *punk, DWORD dwMask);
+		STDMETHODIMP UnadviseSink(IUnknown *punk);
+		STDMETHODIMP RequestLock(DWORD dwLockFlags, HRESULT *phrSession);
+		STDMETHODIMP GetStatus(TS_STATUS *pdcs);
+		STDMETHODIMP QueryInsert(LONG acpTestStart, LONG acpTestEnd, ULONG cch, LONG *pacpResultStart, LONG *pacpResultEnd);
+		STDMETHODIMP GetSelection(ULONG ulIndex, ULONG ulCount, TS_SELECTION_ACP *pSelection, ULONG *pcFetched);
+		STDMETHODIMP SetSelection(ULONG ulCount, const TS_SELECTION_ACP *pSelection);
+		STDMETHODIMP GetText(LONG acpStart, LONG acpEnd, WCHAR *pchPlain, ULONG cchPlainReq, ULONG *pcchPlainRet, TS_RUNINFO *prgRunInfo, ULONG cRunInfoReq, ULONG *pcRunInfoRet, LONG *pacpNext);
+		STDMETHODIMP SetText(DWORD dwFlags, LONG acpStart, LONG acpEnd, const WCHAR *pchText, ULONG cch, TS_TEXTCHANGE *pChange);
+		STDMETHODIMP GetFormattedText(LONG acpStart, LONG acpEnd, IDataObject **ppDataObject);
+		STDMETHODIMP GetEmbedded(LONG acpPos, REFGUID rguidService, REFIID riid, IUnknown **ppunk);
+		STDMETHODIMP QueryInsertEmbedded(const GUID *pguidService, const FORMATETC *pFormatEtc, BOOL *pfInsertable);
+		STDMETHODIMP InsertEmbedded(DWORD dwFlags, LONG acpStart, LONG acpEnd, IDataObject *pDataObject, TS_TEXTCHANGE *pChange);
+		STDMETHODIMP InsertTextAtSelection(DWORD dwFlags, const WCHAR *pchText, ULONG cch, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange);
+		STDMETHODIMP InsertEmbeddedAtSelection(DWORD dwFlags, IDataObject *pDataObject, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange);
+		STDMETHODIMP RequestSupportedAttrs(DWORD dwFlags, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs);
+		STDMETHODIMP RequestAttrsAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags);
+		STDMETHODIMP RequestAttrsTransitioningAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags);
+		STDMETHODIMP FindNextAttrTransition(LONG acpStart, LONG acpHalt, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags, LONG *pacpNext, BOOL *pfFound, LONG *plFoundOffset);
+		STDMETHODIMP RetrieveRequestedAttrs(ULONG ulCount, TS_ATTRVAL *paAttrVals, ULONG *pcFetched);
+		STDMETHODIMP GetEndACP(LONG *pacp);
+		STDMETHODIMP GetActiveView(TsViewCookie *pvcView);
+		STDMETHODIMP GetACPFromPoint(TsViewCookie vcView, const POINT *ptScreen, DWORD dwFlags, LONG *pacp);
+		STDMETHODIMP GetTextExt(TsViewCookie vcView, LONG acpStart, LONG acpEnd, RECT *prc, BOOL *pfClipped);
+		STDMETHODIMP GetScreenExt(TsViewCookie vcView, RECT *prc);
+		STDMETHODIMP GetWnd(TsViewCookie vcView, HWND *phwnd);
+
+		//ITfOwnerCompositionSink
+		STDMETHODIMP OnStartComposition(ITfCompositionView *pComposition, BOOL *pfOk);
+		STDMETHODIMP OnUpdateComposition(ITfCompositionView *pComposition, ITfRange *pRangeNew);
+		STDMETHODIMP OnEndComposition(ITfCompositionView *pComposition);
+
+		void Initialize();
+		void Finalize();
+
+		TSF_Text_Store();
+		~TSF_Text_Store();
+
+	private:
+		ULONG my_Reference_Count;
+		CComPtr<ITfDocumentMgr> my_Document_Manager;
+		CComPtr<ITfContext> my_Context;
+		DWORD my_Edit_Cookie;
+		CComPtr<ITextStoreACPSink> my_Sink;
+		DWORD my_Sink_Mask;
+		DWORD my_Lock;
+		DWORD my_Lock_Queued;
+		CComPtr<ITfCompositionView> my_Composition_View;
+		TS_SELECTION_ACP my_Composition_Selection;
+	};
+
 	TSF();
 
 	static bool COM_Initialized;
 
 	static CComPtr<ITfThreadMgr> Thread_Manager;
+	static TfClientId Client_Id;
+	static TSF_Text_Store *Text_Store;
 };
 
 #endif
--- a/EXCLUDE/GLTSF/src/TSF.cpp	Sat Jun 12 03:21:54 2010 -0400
+++ b/EXCLUDE/GLTSF/src/TSF.cpp	Mon Jun 21 17:16:37 2010 -0400
@@ -3,6 +3,8 @@
 
 bool TSF::COM_Initialized = false;
 CComPtr<ITfThreadMgr> TSF::Thread_Manager;
+TfClientId TSF::Client_Id;
+TSF::TSF_Text_Store *TSF::Text_Store = NULL;
 
 void TSF::Initialize()
 {
@@ -19,9 +21,11 @@
 		if (FAILED(CoCreateInstance(CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfThreadMgr, reinterpret_cast<void **>(&Thread_Manager))))
 			throw std::runtime_error("Failed to create ITfThreadMgr instance");
 
-		TfClientId ClientId;
-		if (FAILED(Thread_Manager->Activate(&ClientId)))
+		if (FAILED(Thread_Manager->Activate(&Client_Id)))
 			throw std::runtime_error("ITfThreadMgr::Activate failed");
+
+		Text_Store = new TSF_Text_Store;
+		Text_Store->Initialize();
 	}
 }
 
@@ -38,3 +42,304 @@
 		COM_Initialized = false;
 	}
 }
+
+STDMETHODIMP TSF::TSF_Text_Store::QueryInterface(REFIID riid, void **ppvObject)
+{
+	*ppvObject = NULL;
+	if (IID_IUnknown == riid || IID_ITextStoreACP == riid)
+		*ppvObject = static_cast<ITextStoreACP *>(this);
+	else if (IID_ITfContextOwnerCompositionSink == riid)
+		*ppvObject = static_cast<ITfContextOwnerCompositionSink *>(this);
+
+	if (*ppvObject)
+	{
+		AddRef();
+		return S_OK;
+	}
+	return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) TSF::TSF_Text_Store::AddRef()
+{
+	return ++my_Reference_Count;
+}
+
+STDMETHODIMP_(ULONG) TSF::TSF_Text_Store::Release()
+{
+	--my_Reference_Count;
+	if (0 != my_Reference_Count)
+		return my_Reference_Count;
+
+	delete this;
+	return 0;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::AdviseSink(REFIID riid, IUnknown *punk, DWORD dwMask)
+{
+	if (!punk || IID_ITextStoreACPSink != riid)
+		return E_INVALIDARG;
+
+	if (!my_Sink)
+	{
+		punk->QueryInterface(&my_Sink);
+		if (!my_Sink)
+			return E_UNEXPECTED;
+	}
+	else
+	{
+		CComPtr<IUnknown> Unknown_1, Unknown_2;
+		punk->QueryInterface(&Unknown_1);
+		my_Sink->QueryInterface(&Unknown_2);
+		if (Unknown_1 != Unknown_2)
+			return CONNECT_E_ADVISELIMIT;
+	}
+	my_Sink_Mask = dwMask;
+	return S_OK;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::UnadviseSink(IUnknown *punk)
+{
+	if (!punk)
+		return E_INVALIDARG;
+
+	if (!my_Sink)
+		return CONNECT_E_NOCONNECTION;
+
+	CComPtr<IUnknown> Unknown_1, Unknown_2;
+	punk->QueryInterface(&Unknown_1);
+	my_Sink->QueryInterface(&Unknown_2);
+
+	if (Unknown_1 != Unknown_2)
+		return CONNECT_E_NOCONNECTION;
+
+	my_Sink = NULL;
+	my_Sink_Mask = 0;
+	return S_OK;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::RequestLock(DWORD dwLockFlags, HRESULT *phrSession)
+{
+	if (!my_Sink)
+		return E_FAIL;
+
+	if (!phrSession)
+		return E_INVALIDARG;
+
+	if (my_Lock)
+	{
+		if (TS_LF_READ == (my_Lock & TS_LF_READWRITE)
+			&& TS_LF_READWRITE == (dwLockFlags & TS_LF_READWRITE)
+			&& !(dwLockFlags & TS_LF_SYNC))
+		{
+			*phrSession = TS_S_ASYNC;
+			my_Lock_Queued = dwLockFlags & (~TS_LF_SYNC);
+		}
+		else
+		{
+			*phrSession = TS_E_SYNCHRONOUS;
+			return E_FAIL;
+		}
+	}
+	else
+	{
+		my_Lock = dwLockFlags & (~TS_LF_SYNC);
+		*phrSession = my_Sink->OnLockGranted(my_Lock);
+		while (my_Lock_Queued)
+		{
+			my_Lock = my_Lock_Queued;
+			my_Lock_Queued = 0;
+			my_Sink->OnLockGranted(my_Lock);
+		}
+		my_Lock = 0;
+	}
+	return S_OK;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::GetStatus(TS_STATUS *pdcs)
+{
+	if (!pdcs)
+		return E_INVALIDARG;
+
+	pdcs->dwDynamicFlags = 0;
+	pdcs->dwStaticFlags = TS_SS_NOHIDDENTEXT;
+	return S_OK;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::QueryInsert(LONG acpTestStart, LONG acpTestEnd, ULONG cch, LONG *pacpResultStart, LONG *pacpResultEnd)
+{
+	if (acpTestStart < 0 || acpTestStart > acpTestEnd || !pacpResultStart || !pacpResultEnd)
+		return E_INVALIDARG;
+
+	*pacpResultStart = acpTestStart;
+	*pacpResultEnd = acpTestStart + cch;
+	return S_OK;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::GetSelection(ULONG ulIndex, ULONG ulCount, TS_SELECTION_ACP *pSelection, ULONG *pcFetched)
+{
+	if (TS_LF_READ != (my_Lock & TS_LF_READ))
+		return TS_E_NOLOCK;
+
+	if (!ulCount || !pSelection || !pcFetched)
+		return E_INVALIDARG;
+
+	*pcFetched = 0;
+	if (TS_DEFAULT_SELECTION != ulIndex && 0 != ulIndex)
+		return TS_E_NOSELECTION;
+
+	if (my_Composition_View)
+	{
+		*pSelection = my_Composition_Selection;
+	}
+	else
+	{
+		//TODO
+	}
+	return S_OK;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::SetSelection(ULONG ulCount, const TS_SELECTION_ACP *pSelection)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::GetText(LONG acpStart, LONG acpEnd, WCHAR *pchPlain, ULONG cchPlainReq, ULONG *pcchPlainRet, TS_RUNINFO *prgRunInfo, ULONG cRunInfoReq, ULONG *pcRunInfoRet, LONG *pacpNext)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::SetText(DWORD dwFlags, LONG acpStart, LONG acpEnd, const WCHAR *pchText, ULONG cch, TS_TEXTCHANGE *pChange)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::GetFormattedText(LONG acpStart, LONG acpEnd, IDataObject **ppDataObject)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::GetEmbedded(LONG acpPos, REFGUID rguidService, REFIID riid, IUnknown **ppunk)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::QueryInsertEmbedded(const GUID *pguidService, const FORMATETC *pFormatEtc, BOOL *pfInsertable)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::InsertEmbedded(DWORD dwFlags, LONG acpStart, LONG acpEnd, IDataObject *pDataObject, TS_TEXTCHANGE *pChange)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::InsertTextAtSelection(DWORD dwFlags, const WCHAR *pchText, ULONG cch, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::InsertEmbeddedAtSelection(DWORD dwFlags, IDataObject *pDataObject, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::RequestSupportedAttrs(DWORD dwFlags, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::RequestAttrsAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::RequestAttrsTransitioningAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::FindNextAttrTransition(LONG acpStart, LONG acpHalt, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags, LONG *pacpNext, BOOL *pfFound, LONG *plFoundOffset)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::RetrieveRequestedAttrs(ULONG ulCount, TS_ATTRVAL *paAttrVals, ULONG *pcFetched)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::GetEndACP(LONG *pacp)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::GetActiveView(TsViewCookie *pvcView)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::GetACPFromPoint(TsViewCookie vcView, const POINT *ptScreen, DWORD dwFlags, LONG *pacp)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::GetTextExt(TsViewCookie vcView, LONG acpStart, LONG acpEnd, RECT *prc, BOOL *pfClipped)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::GetScreenExt(TsViewCookie vcView, RECT *prc)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::GetWnd(TsViewCookie vcView, HWND *phwnd)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::OnStartComposition(ITfCompositionView *pComposition, BOOL *pfOk)
+{
+	*pfOk = FALSE;
+	return S_OK;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::OnUpdateComposition(ITfCompositionView *pComposition, ITfRange *pRangeNew)
+{
+	return E_NOTIMPL;
+}
+
+STDMETHODIMP TSF::TSF_Text_Store::OnEndComposition(ITfCompositionView *pComposition)
+{
+	return E_NOTIMPL;
+}
+
+TSF::TSF_Text_Store::TSF_Text_Store() : my_Reference_Count(1),
+										my_Edit_Cookie(0),
+										my_Lock(0),
+										my_Lock_Queued(0)
+{
+
+}
+
+TSF::TSF_Text_Store::~TSF_Text_Store()
+{
+
+}
+
+void TSF::TSF_Text_Store::Initialize()
+{
+	if (FAILED(Thread_Manager->CreateDocumentMgr(&my_Document_Manager)))
+		throw std::runtime_error("Failed to create document manager");
+
+	if (FAILED(my_Document_Manager->CreateContext(Client_Id, 0, static_cast<ITextStoreACP *>(this), &my_Context, &my_Edit_Cookie)))
+		throw std::runtime_error("Failed to create document context");
+
+	if (FAILED(my_Document_Manager->Push(my_Context)))
+		throw std::runtime_error("Failed to push context");
+}
+
+void TSF::TSF_Text_Store::Finalize()
+{
+
+}