From: Caibin Chen Subject: riched20: ITextDocument stubs for ITextServices (retry) Message-Id: Date: Mon, 15 Jul 2013 17:47:55 -0700 (Retry with real name in mail. The name in the patch is already my real name) This patch implements a standalone stub of ITextDocument. The stub is currently used in txtsrv.c and will replace the stub in richole.c --- dlls/riched20/Makefile.in | 1 + dlls/riched20/tests/txtsrv.c | 16 ++- dlls/riched20/txtdoc.c | 282 +++++++++++++++++++++++++++++++++++++++++++ dlls/riched20/txtdoc.h | 46 +++++++ dlls/riched20/txtsrv.c | 6 + 5 files changed, 350 insertions(+), 1 deletion(-) create mode 100644 dlls/riched20/txtdoc.c create mode 100644 dlls/riched20/txtdoc.h From 2ec18f9b8baf11ecaedbc113c0023a8bbe225452 Mon Sep 17 00:00:00 2001 From: Caibin Chen Date: Sun, 30 Jun 2013 17:14:41 -0700 Subject: riched20: ITextDocument stubs for ITextServices --- dlls/riched20/Makefile.in | 1 + dlls/riched20/tests/txtsrv.c | 16 ++- dlls/riched20/txtdoc.c | 282 +++++++++++++++++++++++++++++++++++++++++++ dlls/riched20/txtdoc.h | 46 +++++++ dlls/riched20/txtsrv.c | 6 + 5 files changed, 350 insertions(+), 1 deletion(-) create mode 100644 dlls/riched20/txtdoc.c create mode 100644 dlls/riched20/txtdoc.h diff --git a/dlls/riched20/Makefile.in b/dlls/riched20/Makefile.in index 49ba7a1..be4fdce 100644 --- a/dlls/riched20/Makefile.in +++ b/dlls/riched20/Makefile.in @@ -18,6 +18,7 @@ C_SRCS = \ string.c \ style.c \ table.c \ + txtdoc.c \ txthost.c \ txtsrv.c \ undo.c \ diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c index e517e03..2ad1246 100644 --- a/dlls/riched20/tests/txtsrv.c +++ b/dlls/riched20/tests/txtsrv.c @@ -29,6 +29,8 @@ #include #include #include +/* should be included before initguid.h to avoid multiple difenition with richole.c */ +#include #include #include #include @@ -857,13 +859,15 @@ static void test_COM(void) struct unk_impl unk_obj = {{&unk_vtbl}, 19, NULL}; struct ITextHostTestImpl texthost = {{&itextHostVtbl}, 1}; ITextServices *textsrv; + ITextDocument *textdoc; ULONG refcount; HRESULT hr; - /* COM aggregation */ + /* COM aggregation on ITextServices */ hr = pCreateTextServices(&unk_obj.IUnknown_iface, &texthost.ITextHost_iface, &unk_obj.inner_unk); ok(hr == S_OK, "CreateTextServices failed: %08x\n", hr); + hr = IUnknown_QueryInterface(unk_obj.inner_unk, pIID_ITextServices, (void**)&textsrv); ok(hr == S_OK, "QueryInterface for IID_ITextServices failed: %08x\n", hr); refcount = ITextServices_AddRef(textsrv); @@ -871,6 +875,16 @@ static void test_COM(void) refcount = ITextServices_Release(textsrv); ok(refcount == unk_obj.ref, "CreateTextServices just pretends to support COM aggregation\n"); refcount = ITextServices_Release(textsrv); + + /* COM aggregation on ITextDocument */ + hr = IUnknown_QueryInterface(unk_obj.inner_unk, &IID_ITextDocument, (void**)&textdoc); + ok(hr == S_OK, "QueryInterface for IID_ITextDocument failed: %08x\n", hr); + refcount = ITextDocument_AddRef(textdoc); + ok(refcount == unk_obj.ref, "CreateTextServices just pretends to support COM aggregation\n"); + refcount = ITextDocument_Release(textdoc); + ok(refcount == unk_obj.ref, "CreateTextServices just pretends to support COM aggregation\n"); + refcount = ITextDocument_Release(textdoc); + ok(refcount == 19, "Refcount should be back at 19 but is %u\n", refcount); IUnknown_Release(unk_obj.inner_unk); diff --git a/dlls/riched20/txtdoc.c b/dlls/riched20/txtdoc.c new file mode 100644 index 0000000..781f510 --- /dev/null +++ b/dlls/riched20/txtdoc.c @@ -0,0 +1,282 @@ +/* + * RichEdit - ITextDocument implementation + * + * Copyright 2013 by Caibin Chen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#define COBJMACROS /* For COM objects interfaces definition */ + +#include "txtdoc.h" + +#include "editor.h" + +WINE_DEFAULT_DEBUG_CHANNEL(richedit); + +struct tagReTxtDoc { + IUnknown *outerObj; + ME_TextEditor *editor; + ITextDocument iTextDocumentIface; +}; + +static inline ReTxtDoc *impl_from_interface(ITextDocument *iface) +{ + return CONTAINING_RECORD(iface, ReTxtDoc, iTextDocumentIface); +} + +/* Implementation of IUnknown */ +static ULONG WINAPI ITextDocument_fnAddRef(ITextDocument *iface) +{ + ReTxtDoc *This = impl_from_interface(iface); + TRACE("(%p)\n", iface); + /* COM aggregation - delegate to outer IUnknown object. */ + return IUnknown_AddRef(This->outerObj); +} + +static ULONG WINAPI ITextDocument_fnRelease(ITextDocument *iface) +{ + ReTxtDoc *This = impl_from_interface(iface);; + TRACE("(%p)\n", iface); + /* COM aggregation - delegate to outer IUnknown object. */ + return IUnknown_Release(This->outerObj); +} + +static HRESULT WINAPI ITextDocument_fnQueryInterface(ITextDocument *iface, REFIID riid, void **ppv) +{ + ReTxtDoc *This = impl_from_interface(iface);; + TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); + + /* COM aggregation - delegate to outer IUnknown object. */ + return IUnknown_QueryInterface(This->outerObj, riid, ppv); +} + +/* Implementation of IDispatch */ + +static HRESULT WINAPI ITextDocument_fnGetTypeInfoCount(ITextDocument *iface, UINT *pctinfo) +{ + TRACE("(%p)->(%p)\n", iface, pctinfo); + /* Ruturn 0 since type info is not implemented */ + *pctinfo = 0; + + return S_OK; +} + +static HRESULT WINAPI ITextDocument_fnGetTypeInfo(ITextDocument *iface, UINT iTInfo, LCID lcid, + ITypeInfo **ppTInfo) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnGetIDsOfNames(ITextDocument *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnInvoke( + ITextDocument *me, + DISPID dispIdMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS *pDispParams, + VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, + UINT *puArgErr) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnGetName(ITextDocument *iface, BSTR *pName) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnGetSelection(ITextDocument *me, ITextSelection **ppSel) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnGetStoryCount(ITextDocument *iface, LONG *pCount) +{ + TRACE("(%p)->(%p)\n", iface, pCount); + *pCount = 1; /* GetStory is not implemented. */ + return S_OK; +} + +static HRESULT WINAPI ITextDocument_fnGetStoryRanges(ITextDocument *iface, + ITextStoryRanges **ppStories) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnGetSaved(ITextDocument *iface, LONG *pValue) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnSetSaved(ITextDocument *iface, LONG Value) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnGetDefaultTabStop(ITextDocument *iface, float *pValue) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnSetDefaultTabStop(ITextDocument *iface, float Value) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnNew(ITextDocument *iface) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnOpen(ITextDocument *iface, VARIANT *pVar, LONG Flags, + LONG CodePage) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnSave(ITextDocument *iface, VARIANT *pVar, LONG Flags, + LONG CodePage) +{ + FIXME("not implement\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnFreeze(ITextDocument *iface, LONG *pCount) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnUnfreeze(ITextDocument *iface, LONG *pCount) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnBeginEditCollection(ITextDocument *iface) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnEndEditCollection(ITextDocument *iface) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnUndo(ITextDocument *iface, LONG Count, LONG *prop) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnRedo(ITextDocument *iface, LONG Count, LONG *prop) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnRange(ITextDocument *iface, LONG cp1, LONG cp2, + ITextRange **ppRange) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextDocument_fnRangeFromPoint(ITextDocument *me, LONG x, LONG y, + ITextRange **ppRange) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static const ITextDocumentVtbl vtbl = { + /* IUnknown */ + ITextDocument_fnQueryInterface, + ITextDocument_fnAddRef, + ITextDocument_fnRelease, + /* IDispatch */ + ITextDocument_fnGetTypeInfoCount, + ITextDocument_fnGetTypeInfo, + ITextDocument_fnGetIDsOfNames, + ITextDocument_fnInvoke, + /* ITextDocument */ + ITextDocument_fnGetName, + ITextDocument_fnGetSelection, + ITextDocument_fnGetStoryCount, + ITextDocument_fnGetStoryRanges, + ITextDocument_fnGetSaved, + ITextDocument_fnSetSaved, + ITextDocument_fnGetDefaultTabStop, + ITextDocument_fnSetDefaultTabStop, + ITextDocument_fnNew, + ITextDocument_fnOpen, + ITextDocument_fnSave, + ITextDocument_fnFreeze, + ITextDocument_fnUnfreeze, + ITextDocument_fnBeginEditCollection, + ITextDocument_fnEndEditCollection, + ITextDocument_fnUndo, + ITextDocument_fnRedo, + ITextDocument_fnRange, + ITextDocument_fnRangeFromPoint +}; + +ReTxtDoc *ReTxtDoc_create(IUnknown *outerObj, ME_TextEditor *editor) +{ + ReTxtDoc *This = heap_alloc(sizeof *This); + TRACE("(%p,%p)\n", outerObj, editor); + if (!This) + return NULL; + + This->outerObj = outerObj; + This->editor = editor; + This->iTextDocumentIface.lpVtbl = &vtbl; + return This; +} + +ITextDocument *ReTxtDoc_get_ITextDocument(ReTxtDoc *document) +{ + TRACE("(%p)\n", document); + return &document->iTextDocumentIface; +} + +void ReTxtDoc_destroy(ReTxtDoc *document) +{ + TRACE("(%p)\n", document); + document->outerObj = NULL; + document->editor = NULL; + heap_free(document); +} diff --git a/dlls/riched20/txtdoc.h b/dlls/riched20/txtdoc.h new file mode 100644 index 0000000..02579b2 --- /dev/null +++ b/dlls/riched20/txtdoc.h @@ -0,0 +1,46 @@ +/* + * RichEdit - ITextDocument implementation + * + * Copyright 2013 by Caibin Chen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __TXTDOC_H +#define __TXTDOC_H + +#include + +#include "editstr.h" + +typedef struct tagReTxtDoc ReTxtDoc; + +/** + * Create an ReTxtDoc object, which acts as an inner object of COM aggression. + * + * The ReTxtDoc object will delegate all of its IUnknown calls to the specified + * {@code outerObj}. + * + * @param outerObj The outer objects that creates and delegates ITextDocument + * method calls to the created ReTxtDoc. + * @param editor The editor implementation. + * + * @return An ReTxtDoc object that should be destroyed with {@code ReTxtDoc_destroy} + */ +ReTxtDoc *ReTxtDoc_create(IUnknown *outerObj, ME_TextEditor *editor); +ITextDocument *ReTxtDoc_get_ITextDocument(ReTxtDoc *document); +void ReTxtDoc_destroy(ReTxtDoc *document); + +#endif /* __TXTDOC_H */ diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c index 0e78c53..5319f76 100644 --- a/dlls/riched20/txtsrv.c +++ b/dlls/riched20/txtsrv.c @@ -31,6 +31,7 @@ #include "richole.h" #include "imm.h" #include "textserv.h" +#include "txtdoc.h" #include "wine/debug.h" #include "editstr.h" @@ -61,6 +62,7 @@ typedef struct ITextServicesImpl { ITextHost *pMyHost; CRITICAL_SECTION csTxtSrv; ME_TextEditor *editor; + ReTxtDoc *txtDoc; char spare[256]; } ITextServicesImpl; @@ -79,6 +81,8 @@ static HRESULT WINAPI ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID r *ppv = &This->IUnknown_inner; else if (IsEqualIID(riid, &IID_ITextServices)) *ppv = &This->ITextServices_iface; + else if (IsEqualIID(riid, &IID_ITextDocument)) + *ppv = ReTxtDoc_get_ITextDocument(This->txtDoc); else { *ppv = NULL; FIXME("Unknown interface: %s\n", debugstr_guid(riid)); @@ -111,6 +115,7 @@ static ULONG WINAPI ITextServicesImpl_Release(IUnknown *iface) ITextHost_Release(This->pMyHost); This->csTxtSrv.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->csTxtSrv); + ReTxtDoc_destroy(This->txtDoc); CoTaskMemFree(This); } return ref; @@ -420,6 +425,7 @@ HRESULT WINAPI CreateTextServices(IUnknown *pUnkOuter, ITextHost *pITextHost, I ITextImpl->outer_unk = pUnkOuter; else ITextImpl->outer_unk = &ITextImpl->IUnknown_inner; + ITextImpl->txtDoc = ReTxtDoc_create(ITextImpl->outer_unk, ITextImpl->editor); *ppUnk = &ITextImpl->IUnknown_inner; return S_OK; -- 1.8.3.2