[PATCH 1/4] riched20: Basic ITextDocument implementation for ITextServices (try 3)

Caibin Chen tigersoldi at gmail.com
Wed Jul 31 01:57:47 CDT 2013


Thanks Jacek for reviewing. This time I send all the changes I have in
4 patches to make it clear that ReTxtDoc is reused between txtsrv.c
and richole.c
- Suppressed Patch 97331
- Change log from try 2:
 - follow COM naming convention
 - move ReTxtDoc definition to header, removed
ReTxtDoc_get_ITextDocument() function
 - remove COM aggregation test for ITextDocument, only test
ITextService supports querying for the interface.

---
 dlls/riched20/Makefile.in    |   1 +
 dlls/riched20/tests/txtsrv.c |  10 ++
 dlls/riched20/txtdoc.c       | 270 +++++++++++++++++++++++++++++++++++++++++++
 dlls/riched20/txtdoc.h       |  51 ++++++++
 dlls/riched20/txtsrv.c       |   6 +
-------------- next part --------------
From ccd409befdc02e3cb989c1c07713b66e90a44a36 Mon Sep 17 00:00:00 2001
From: Caibin Chen <tigersoldi at gmail.com>
Date: Sun, 30 Jun 2013 17:14:41 -0700
Subject: [PATCH 1/4] riched20: Basic ITextDocument implementation for
 ITextServices

---
 dlls/riched20/Makefile.in    |   1 +
 dlls/riched20/tests/txtsrv.c |  10 ++
 dlls/riched20/txtdoc.c       | 270 +++++++++++++++++++++++++++++++++++++++++++
 dlls/riched20/txtdoc.h       |  51 ++++++++
 dlls/riched20/txtsrv.c       |   6 +
 5 files changed, 338 insertions(+)
 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..5f7d7de 100644
--- a/dlls/riched20/tests/txtsrv.c
+++ b/dlls/riched20/tests/txtsrv.c
@@ -29,6 +29,8 @@
 #include <winbase.h>
 #include <objbase.h>
 #include <richedit.h>
+/* should be included before initguid.h to avoid multiple difenition with richole.c */
+#include <tom.h>
 #include <initguid.h>
 #include <textserv.h>
 #include <wine/test.h>
@@ -857,6 +859,7 @@ 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;
 
@@ -864,6 +867,7 @@ static void test_COM(void)
     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,12 @@ 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);
+
+    /* Test that ITextDocument is supported */
+    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_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..697e1f9
--- /dev/null
+++ b/dlls/riched20/txtdoc.c
@@ -0,0 +1,270 @@
+/*
+ * 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);
+
+static inline ReTxtDoc *impl_from_ITextDocument(ITextDocument *iface)
+{
+  return CONTAINING_RECORD(iface, ReTxtDoc, ITextDocument_iface);
+}
+
+/* Implementation of IUnknown */
+static ULONG WINAPI ITextDocument_fnAddRef(ITextDocument *iface)
+{
+  ReTxtDoc *This = impl_from_ITextDocument(iface);
+  TRACE("(%p)\n", iface);
+  /* COM aggregation - delegate to outer IUnknown object. */
+  return IUnknown_AddRef(This->outer_unk);
+}
+
+static ULONG WINAPI ITextDocument_fnRelease(ITextDocument *iface)
+{
+  ReTxtDoc *This = impl_from_ITextDocument(iface);
+  TRACE("(%p)\n", iface);
+  /* COM aggregation - delegate to outer IUnknown object. */
+  return IUnknown_Release(This->outer_unk);
+}
+
+static HRESULT WINAPI ITextDocument_fnQueryInterface(ITextDocument *iface, REFIID riid, void **ppv)
+{
+  ReTxtDoc *This = impl_from_ITextDocument(iface);
+  TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
+
+  /* COM aggregation - delegate to outer IUnknown object. */
+  return IUnknown_QueryInterface(This->outer_unk, 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 *outer_unk, ME_TextEditor *editor)
+{
+  ReTxtDoc *This = heap_alloc(sizeof *This);
+  TRACE("(%p,%p)\n", outer_unk, editor);
+  if (!This)
+    return NULL;
+
+  This->outer_unk = outer_unk;
+  This->editor = editor;
+  This->ITextDocument_iface.lpVtbl = &vtbl;
+  return This;
+}
+
+void ReTxtDoc_destroy(ReTxtDoc *document)
+{
+  TRACE("(%p)\n", document);
+  document->outer_unk = 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..a8a86bc
--- /dev/null
+++ b/dlls/riched20/txtdoc.h
@@ -0,0 +1,51 @@
+/*
+ * 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 <tom.h>
+
+#include "editstr.h"
+
+typedef struct tagReTxtDoc ReTxtDoc;
+struct tagReTxtDoc {
+  IUnknown *outer_unk;
+  ME_TextEditor *editor;
+  ITextDocument ITextDocument_iface;
+};
+
+/**
+ * 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 outer_unk}.
+ *
+ * @param outer_unk 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 *outer_unk, ME_TextEditor *editor);
+
+void ReTxtDoc_destroy(ReTxtDoc *document);
+
+#endif /* __TXTDOC_H */
diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c
index 0e78c53..f72ce3a 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 = &This->txtDoc->ITextDocument_iface;
    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.4


More information about the wine-patches mailing list