diff --git a/README.md b/README.md index d24d4a7f..46d0caae 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Wine-Compholio contains fixes for the following Wine bugs: * Fix for ConnectNamedPort return value in overlapped mode ([Wine Bug #16550](http://bugs.winehq.org/show_bug.cgi?id=16550 "ConnectNamedPort should never return OK in overlapped mode (affects chromium ui_tests.exe)")) * Fix for programs leaking wndproc slots ([Wine Bug #32451](http://bugs.winehq.org/show_bug.cgi?id=32451 "Multiple GOG.com installer bundles show a broken/unresponsive dialog window during installation (installer process running out of wndproc slots)")) * GetSecurityInfo returns NULL DACL for process object ([Wine Bug #15980](http://bugs.winehq.org/show_bug.cgi?id=15980 "Rhapsody 2 crashes on startup (GetSecurityInfo returns NULL DACL for process object)")) +* Implement ITextDocument_fnRange function ([Wine Bug #12458](http://bugs.winehq.org/show_bug.cgi?id=12458 "Multiple apps fail due to RichEdit ITextDocument_fnRange stub (MySQL Workbench, BlitzMaxDemo137)")) * Implement LoadIconMetric function ([Wine Bug #35375](http://bugs.winehq.org/show_bug.cgi?id=35375 "Multiple applications need Vista+ API COMCTL32.dll.380 a.k.a. 'LoadIconMetric' (Solidworks 2013 systray monitor, Microsoft One/SkyDrive)")) * Implement a Microsoft Yahei replacement font ([Wine Bug #13829](http://bugs.winehq.org/show_bug.cgi?id=13829 "Wine does not have CJK fonts")) * Implement an Arial replacement font ([Wine Bug #32323](http://bugs.winehq.org/show_bug.cgi?id=32323 "Netflix (Silverlight 4.x) and several .NET Framework 3.x/4.0 WPF apps require either Arial or Verdana to be installed")) @@ -35,6 +36,7 @@ Wine-Compholio contains fixes for the following Wine bugs: * Set ldr.EntryPoint for main executable ([Wine Bug #33034](http://bugs.winehq.org/show_bug.cgi?id=33034 "Many GFWL (Games For Windows Live) 1.x/2.x/3.x games crash or exit silently on startup (DiRT 2/3, GTA IV Steam)")) * Support for AllocateAndGetTcpExTableFromStack ([Wine Bug #34372](http://bugs.winehq.org/show_bug.cgi?id=34372 "Add missing function AllocateAndGetTcpExTableFromStack() to iphlpapi.dll")) * Support for GetSystemTimes ([Wine Bug #19813](http://bugs.winehq.org/show_bug.cgi?id=19813 "Voddler needs GetSystemTimes to run")) +* Support for ITextRange, ITextFont and ITextPara ([Wine Bug #18303](http://bugs.winehq.org/show_bug.cgi?id=18303 "Adobe Acrobat Pro 7: Crashes when selecting the \"edit\" menu while having a file open.")) * Support for Junction Points ([Wine Bug #12401](http://bugs.winehq.org/show_bug.cgi?id=12401 "Support junction points, i.e. DeviceIoCtl(FSCTL_SET_REPARSE_POINT/FSCTL_GET_REPARSE_POINT)")) * Support for NtSetInformationFile class FileDispositionInformation ([Wine Bug #30397](http://bugs.winehq.org/show_bug.cgi?id=30397 "Multiple applications need support for NtSetInformationFile class FileDispositionInformation (Cygwin installer, Stylizer 5.x Visual CSS editor, Spoon Studio 2011 (ex Xenocode) application sandboxing scheme)")) * Support for PulseAudio backend for audio ([Wine Bug #10495](http://bugs.winehq.org/show_bug.cgi?id=10495 "Wine should support PulseAudio")) diff --git a/debian/changelog b/debian/changelog index a3e8eef8..09665432 100644 --- a/debian/changelog +++ b/debian/changelog @@ -21,6 +21,7 @@ wine-compholio (1.7.24) UNRELEASED; urgency=low * Added patch to use a linear resampler when there a large number of dsound mixing buffers. * Added patch to fix comparison of punctuation characters in lstrcmp. * Added patch to workaround programs leaking wndproc splots. + * Added patch to implement ITextRange, ITextFont and ITextPara. * Removed patch to create Vista directories (accepted upstream). * Removed strmbase/quartz locking fix patches (accepted upstream). * Removed windowscodecs/PropertyBag patch (accepted upstream). diff --git a/patches/Makefile b/patches/Makefile index 77de374f..19ba6d7a 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -29,6 +29,7 @@ PATCHLIST := \ ntdll-Pipe_SpecialCharacters.ok \ ntdll-loader_EntryPoint.ok \ quartz-MediaSeeking_Positions.ok \ + riched20-IText_Interface.ok \ server-ACL_Compat.ok \ server-Address_Change_Notification.ok \ server-CreateProcess_ACLs.ok \ @@ -478,6 +479,38 @@ quartz-MediaSeeking_Positions.ok: echo '+ { "quartz-MediaSeeking_Positions", "Erich E. Hoover", "Return correct IMediaSeeking stream positions in quartz." },'; \ ) > quartz-MediaSeeking_Positions.ok +# Patchset riched20-IText_Interface +# | +# | Included patches: +# | * Implement Stubs for ITextRange interface. [by Jactry Zeng] +# | * Implement IText{Range,Selection}::{GetChar,GetStart,GetEnd,GetDuplicate,Collapse,SetStart,SetEnd}. [by Jactry Zeng] +# | * Implement Stubs for ITextFont interface. [by Jactry Zeng] +# | * Implement Stubs for ITextPara interface. [by Jactry Zeng] +# | +# | This patchset fixes the following Wine bugs: +# | * [#12458] Multiple apps fail due to RichEdit ITextDocument_fnRange stub (MySQL Workbench, BlitzMaxDemo137) +# | * [#18303] Adobe Acrobat Pro 7: Crashes when selecting the "edit" menu while having a file open. +# | +# | Modified files: +# | * dlls/riched20/richole.c, dlls/riched20/tests/richole.c +# | +.INTERMEDIATE: riched20-IText_Interface.ok +riched20-IText_Interface.ok: + $(call APPLY_FILE,riched20-IText_Interface/0001-riched20-Stub-for-ITextRange-interface-and-implement.patch) + $(call APPLY_FILE,riched20-IText_Interface/0002-riched20-Implement-ITextSelection-GetChar-and-ITextR.patch) + $(call APPLY_FILE,riched20-IText_Interface/0003-riched20-Implement-IText-Selection-Range-Get-Start-E.patch) + $(call APPLY_FILE,riched20-IText_Interface/0004-riched20-Implement-ITextRange-GetDuplicate.patch) + $(call APPLY_FILE,riched20-IText_Interface/0005-riched20-Implement-ITextRange-Collapse-and-ITextSele.patch) + $(call APPLY_FILE,riched20-IText_Interface/0006-riched20-Implement-IText-Selection-Range-Set-Start-E.patch) + $(call APPLY_FILE,riched20-IText_Interface/0007-riched20-Stub-for-ITextFont-interface-and-implement-.patch) + $(call APPLY_FILE,riched20-IText_Interface/0008-riched20-Stub-for-ITextPara-interface-and-implement-.patch) + @( \ + echo '+ { "riched20-IText_Interface", "Jactry Zeng", "Implement Stubs for ITextRange interface." },'; \ + echo '+ { "riched20-IText_Interface", "Jactry Zeng", "Implement IText{Range,Selection}::{GetChar,GetStart,GetEnd,GetDuplicate,Collapse,SetStart,SetEnd}." },'; \ + echo '+ { "riched20-IText_Interface", "Jactry Zeng", "Implement Stubs for ITextFont interface." },'; \ + echo '+ { "riched20-IText_Interface", "Jactry Zeng", "Implement Stubs for ITextPara interface." },'; \ + ) > riched20-IText_Interface.ok + # Patchset server-ACL_Compat # | # | Included patches: diff --git a/patches/riched20-IText_Interface/0001-riched20-Stub-for-ITextRange-interface-and-implement.patch b/patches/riched20-IText_Interface/0001-riched20-Stub-for-ITextRange-interface-and-implement.patch new file mode 100644 index 00000000..be0a992a --- /dev/null +++ b/patches/riched20-IText_Interface/0001-riched20-Stub-for-ITextRange-interface-and-implement.patch @@ -0,0 +1,908 @@ +From 1fb42d0cc90d02df67dc117764f6352da0e40195 Mon Sep 17 00:00:00 2001 +From: Jactry Zeng +Date: Fri, 8 Aug 2014 20:12:54 +0800 +Subject: riched20: Stub for ITextRange interface and implement + ITextDocument::Range. + +--- + dlls/riched20/richole.c | 773 ++++++++++++++++++++++++++++++++++++++++- + dlls/riched20/tests/richole.c | 36 +- + 2 files changed, 806 insertions(+), 3 deletions(-) + +diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c +index 487fcda..314bc1e 100644 +--- a/dlls/riched20/richole.c ++++ b/dlls/riched20/richole.c +@@ -49,6 +49,7 @@ DEFINE_GUID(IID_ITextSelection, 0x8cc497c1, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0x + + typedef struct ITextSelectionImpl ITextSelectionImpl; + typedef struct IOleClientSiteImpl IOleClientSiteImpl; ++typedef struct ITextRangeImpl ITextRangeImpl; + + typedef struct IRichEditOleImpl { + IRichEditOle IRichEditOle_iface; +@@ -58,8 +59,18 @@ typedef struct IRichEditOleImpl { + ME_TextEditor *editor; + ITextSelectionImpl *txtSel; + IOleClientSiteImpl *clientSite; ++ ITextRangeImpl *txtRgehead, *txtRgetail; + } IRichEditOleImpl; + ++struct ITextRangeImpl { ++ ITextRange ITextRange_iface; ++ LONG ref; ++ int start, end; ++ ITextRangeImpl *prev, *next; ++ ++ IRichEditOleImpl *reOle; ++}; ++ + struct ITextSelectionImpl { + ITextSelection ITextSelection_iface; + LONG ref; +@@ -128,10 +139,18 @@ IRichEditOle_fnRelease(IRichEditOle *me) + + if (!ref) + { ++ ITextRangeImpl *txtRgeImpl = This->txtRgehead->next; + TRACE ("Destroying %p\n", This); + This->txtSel->reOle = NULL; + ITextSelection_Release(&This->txtSel->ITextSelection_iface); + IOleClientSite_Release(&This->clientSite->IOleClientSite_iface); ++ while (txtRgeImpl) ++ { ++ txtRgeImpl->reOle = NULL; ++ txtRgeImpl = txtRgeImpl->next; ++ } ++ heap_free(This->txtRgehead); ++ heap_free(This->txtRgetail); + heap_free(This); + } + return ref; +@@ -443,6 +462,681 @@ static const IRichEditOleVtbl revt = { + IRichEditOle_fnImportDataObject + }; + ++/* ITextRange interface */ ++static inline ITextRangeImpl *impl_from_ITextRange(ITextRange *iface) ++{ ++ return CONTAINING_RECORD(iface, ITextRangeImpl, ITextRange_iface); ++} ++ ++static HRESULT WINAPI ITextRange_fnQueryInterface(ITextRange *me, REFIID riid, void **ppvObj) ++{ ++ *ppvObj = NULL; ++ if (IsEqualGUID(riid, &IID_IUnknown) ++ || IsEqualGUID(riid, &IID_IDispatch) ++ || IsEqualGUID(riid, &IID_ITextRange)) ++ { ++ *ppvObj = me; ++ ITextRange_AddRef(me); ++ return S_OK; ++ } ++ ++ return E_NOINTERFACE; ++} ++ ++static ULONG WINAPI ITextRange_fnAddRef(ITextRange *me) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ return InterlockedIncrement(&This->ref); ++} ++ ++static ULONG WINAPI ITextRange_fnRelease(ITextRange *me) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ ULONG ref = InterlockedDecrement(&This->ref); ++ ++ TRACE ("%p ref=%u\n", This, ref); ++ if (ref == 0) ++ { ++ This->reOle = NULL; ++ This->prev->next = This->next; ++ This->next->prev = This->prev; ++ heap_free(This); ++ } ++ return ref; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetTypeInfoCount(ITextRange *me, UINT *pctinfo) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetTypeInfo(ITextRange *me, UINT iTInfo, LCID lcid, ++ ITypeInfo **ppTInfo) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetIDsOfNames(ITextRange *me, REFIID riid, LPOLESTR *rgszNames, ++ UINT cNames, LCID lcid, DISPID *rgDispId) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnInvoke(ITextRange *me, DISPID dispIdMember, REFIID riid, ++ LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, ++ VARIANT *pVarResult, EXCEPINFO *pExcepInfo, ++ UINT *puArgErr) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetText(ITextRange *me, BSTR *pbstr) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR bstr) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetChar(ITextRange *me, LONG *pch) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnSetChar(ITextRange *me, LONG ch) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetDuplicate(ITextRange *me, ITextRange **ppRange) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetFormattedText(ITextRange *me, ITextRange **ppRange) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnSetFormattedText(ITextRange *me, ITextRange *pRange) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetStart(ITextRange *me, LONG *pcpFirst) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnSetStart(ITextRange *me, LONG cpFirst) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetEnd(ITextRange *me, LONG *pcpLim) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnSetEnd(ITextRange *me, LONG cpLim) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetFont(ITextRange *me, ITextFont **pFont) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnSetFont(ITextRange *me, ITextFont *pFont) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetPara(ITextRange *me, ITextPara **ppPara) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnSetPara(ITextRange *me, ITextPara *pPara) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetStoryLength(ITextRange *me, LONG *pcch) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetStoryType(ITextRange *me, LONG *pValue) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnCollapse(ITextRange *me, LONG bStart) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnExpand(ITextRange *me, LONG Unit, LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetIndex(ITextRange *me, LONG Unit, LONG *pIndex) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnSetIndex(ITextRange *me, LONG Unit, LONG Index, ++ LONG Extend) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnSetRange(ITextRange *me, LONG cpActive, LONG cpOther) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnInRange(ITextRange *me, ITextRange *pRange, LONG *pb) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnInStory(ITextRange *me, ITextRange *pRange, LONG *pb) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnIsEqual(ITextRange *me, ITextRange *pRange, LONG *pb) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnSelect(ITextRange *me) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnStartOf(ITextRange *me, LONG Unit, LONG Extend, ++ LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnEndOf(ITextRange *me, LONG Unit, LONG Extend, ++ LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnMove(ITextRange *me, LONG Unit, LONG Count, LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnMoveStart(ITextRange *me, LONG Unit, LONG Count, ++ LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnMoveEnd(ITextRange *me, LONG Unit, LONG Count, ++ LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnMoveWhile(ITextRange *me, VARIANT *Cset, LONG Count, ++ LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnMoveStartWhile(ITextRange *me, VARIANT *Cset, LONG Count, ++ LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnMoveEndWhile(ITextRange *me, VARIANT *Cset, LONG Count, ++ LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnMoveUntil(ITextRange *me, VARIANT *Cset, LONG Count, ++ LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnMoveStartUntil(ITextRange *me, VARIANT *Cset, LONG Count, ++ LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnMoveEndUntil(ITextRange *me, VARIANT *Cset, LONG Count, ++ LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnFindText(ITextRange *me, BSTR bstr, LONG cch, LONG Flags, ++ LONG *pLength) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnFindTextStart(ITextRange *me, BSTR bstr, LONG cch, ++ LONG Flags, LONG *pLength) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnFindTextEnd(ITextRange *me, BSTR bstr, LONG cch, ++ LONG Flags, LONG *pLength) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnDelete(ITextRange *me, LONG Unit, LONG Count, ++ LONG *pDelta) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnCut(ITextRange *me, VARIANT *pVar) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnCopy(ITextRange *me, VARIANT *pVar) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnPaste(ITextRange *me, VARIANT *pVar, LONG Format) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnCanPaste(ITextRange *me, VARIANT *pVar, LONG Format, ++ LONG *pb) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnCanEdit(ITextRange *me, LONG *pb) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnChangeCase(ITextRange *me, LONG Type) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetPoint(ITextRange *me, LONG Type, LONG *cx, LONG *cy) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnSetPoint(ITextRange *me, LONG x, LONG y, LONG Type, ++ LONG Extend) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnScrollIntoView(ITextRange *me, LONG Value) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextRange_fnGetEmbeddedObject(ITextRange *me, IUnknown **ppv) ++{ ++ ITextRangeImpl *This = impl_from_ITextRange(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static const ITextRangeVtbl trvt = { ++ ITextRange_fnQueryInterface, ++ ITextRange_fnAddRef, ++ ITextRange_fnRelease, ++ ITextRange_fnGetTypeInfoCount, ++ ITextRange_fnGetTypeInfo, ++ ITextRange_fnGetIDsOfNames, ++ ITextRange_fnInvoke, ++ ITextRange_fnGetText, ++ ITextRange_fnSetText, ++ ITextRange_fnGetChar, ++ ITextRange_fnSetChar, ++ ITextRange_fnGetDuplicate, ++ ITextRange_fnGetFormattedText, ++ ITextRange_fnSetFormattedText, ++ ITextRange_fnGetStart, ++ ITextRange_fnSetStart, ++ ITextRange_fnGetEnd, ++ ITextRange_fnSetEnd, ++ ITextRange_fnGetFont, ++ ITextRange_fnSetFont, ++ ITextRange_fnGetPara, ++ ITextRange_fnSetPara, ++ ITextRange_fnGetStoryLength, ++ ITextRange_fnGetStoryType, ++ ITextRange_fnCollapse, ++ ITextRange_fnExpand, ++ ITextRange_fnGetIndex, ++ ITextRange_fnSetIndex, ++ ITextRange_fnSetRange, ++ ITextRange_fnInRange, ++ ITextRange_fnInStory, ++ ITextRange_fnIsEqual, ++ ITextRange_fnSelect, ++ ITextRange_fnStartOf, ++ ITextRange_fnEndOf, ++ ITextRange_fnMove, ++ ITextRange_fnMoveStart, ++ ITextRange_fnMoveEnd, ++ ITextRange_fnMoveWhile, ++ ITextRange_fnMoveStartWhile, ++ ITextRange_fnMoveEndWhile, ++ ITextRange_fnMoveUntil, ++ ITextRange_fnMoveStartUntil, ++ ITextRange_fnMoveEndUntil, ++ ITextRange_fnFindText, ++ ITextRange_fnFindTextStart, ++ ITextRange_fnFindTextEnd, ++ ITextRange_fnDelete, ++ ITextRange_fnCut, ++ ITextRange_fnCopy, ++ ITextRange_fnPaste, ++ ITextRange_fnCanPaste, ++ ITextRange_fnCanEdit, ++ ITextRange_fnChangeCase, ++ ITextRange_fnGetPoint, ++ ITextRange_fnSetPoint, ++ ITextRange_fnScrollIntoView, ++ ITextRange_fnGetEmbeddedObject ++}; ++/* ITextRange interface */ ++ + static HRESULT WINAPI + ITextDocument_fnQueryInterface(ITextDocument* me, REFIID riid, + void** ppvObject) +@@ -651,8 +1345,40 @@ ITextDocument_fnRange(ITextDocument* me, LONG cp1, LONG cp2, + ITextRange** ppRange) + { + IRichEditOleImpl *This = impl_from_ITextDocument(me); +- FIXME("stub %p\n",This); +- return E_NOTIMPL; ++ ITextRangeImpl *txtRge = NULL; ++ const int len = ME_GetTextLength(This->editor) + 1; ++ ++ TRACE("%p %p %d %d\n", This, ppRange, cp1, cp2); ++ if (!ppRange) ++ return E_INVALIDARG; ++ ++ cp1 = max(cp1, 0); ++ cp2 = max(cp2, 0); ++ cp1 = min(cp1, len); ++ cp2 = min(cp2, len); ++ if (cp1 >= cp2) ++ { ++ int tmp; ++ tmp = cp1; ++ cp1 = cp2; ++ cp2 = tmp; ++ } ++ ++ txtRge = heap_alloc(sizeof *txtRge); ++ if (!txtRge) ++ return E_OUTOFMEMORY; ++ txtRge->ITextRange_iface.lpVtbl = &trvt; ++ txtRge->ref = 1; ++ txtRge->reOle = This; ++ txtRge->start = cp1; ++ txtRge->end = cp2; ++ txtRge->next = This->txtRgehead->next; ++ This->txtRgehead->next->prev = txtRge; ++ This->txtRgehead->next = txtRge; ++ txtRge->prev = This->txtRgehead; ++ *ppRange = &txtRge->ITextRange_iface; ++ ++ return S_OK; + } + + static HRESULT WINAPI +@@ -1521,6 +2247,30 @@ CreateTextSelection(IRichEditOleImpl *reOle) + return txtSel; + } + ++static void CreateEmptyITextRangeImpl(IRichEditOleImpl *reOle, int type) ++{ ++ ITextRangeImpl *txtRgeImpl; ++ if (type) ++ { ++ txtRgeImpl = reOle->txtRgehead; ++ txtRgeImpl->prev = NULL; ++ txtRgeImpl->next = reOle->txtRgetail; ++ } ++ else ++ { ++ txtRgeImpl = reOle->txtRgetail; ++ txtRgeImpl->prev = reOle->txtRgehead; ++ txtRgeImpl->next = NULL; ++ } ++ ++ txtRgeImpl->ITextRange_iface.lpVtbl = &trvt; ++ txtRgeImpl->ref = 1; ++ txtRgeImpl->reOle = NULL; ++ txtRgeImpl->start = 0; ++ txtRgeImpl->end = 0; ++ ++} ++ + LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) + { + IRichEditOleImpl *reo; +@@ -1549,6 +2299,25 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) + TRACE("Created %p\n",reo); + *ppObj = reo; + ++ reo->txtRgehead = heap_alloc(sizeof(ITextRangeImpl)); ++ if (!reo->txtRgehead) ++ { ++ ITextSelection_Release(&reo->txtSel->ITextSelection_iface); ++ IOleClientSite_Release(&reo->clientSite->IOleClientSite_iface); ++ heap_free(reo); ++ return 0; ++ } ++ reo->txtRgetail = heap_alloc(sizeof(ITextRangeImpl)); ++ if (!reo->txtRgetail) ++ { ++ ITextSelection_Release(&reo->txtSel->ITextSelection_iface); ++ IOleClientSite_Release(&reo->clientSite->IOleClientSite_iface); ++ heap_free(reo->txtRgehead); ++ heap_free(reo); ++ return 0; ++ } ++ CreateEmptyITextRangeImpl(reo, 1); ++ CreateEmptyITextRangeImpl(reo, 0); + return 1; + } + +diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c +index 571e5cd..417b68f 100644 +--- a/dlls/riched20/tests/richole.c ++++ b/dlls/riched20/tests/richole.c +@@ -86,10 +86,11 @@ static void create_interfaces(HWND *w, IRichEditOle **reOle, ITextDocument **txt + static void release_interfaces(HWND *w, IRichEditOle **reOle, ITextDocument **txtDoc, + ITextSelection **txtSel) + { ++ if(txtSel) ++ ITextSelection_Release(*txtSel); + ITextDocument_Release(*txtDoc); + IRichEditOle_Release(*reOle); + DestroyWindow(*w); +- ITextSelection_Release(*txtSel); + } + + static ULONG get_refcount(IUnknown *iface) +@@ -486,6 +487,38 @@ static void test_ITextSelection_GetText(void) + release_interfaces(&w, &reOle, &txtDoc, &txtSel); + } + ++static void test_ITextDocument_Range(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextRange *txtRge = NULL; ++ ITextRange *pointer = NULL; ++ HRESULT hres; ++ ULONG refcount; ++ ++ create_interfaces(&w, &reOle, &txtDoc, NULL); ++ hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge); ++ ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres); ++ refcount = get_refcount((IUnknown *)txtRge); ++ ok(refcount == 1, "get wrong refcount: returned %d expected 1\n", refcount); ++ ++ pointer = txtRge; ++ hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge); ++ ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres); ++ ok(pointer != txtRge, "A new pointer should be returned\n"); ++ ITextRange_Release(pointer); ++ ++ hres = ITextDocument_Range(txtDoc, 0, 0, NULL); ++ ok(hres == E_INVALIDARG, "ITextDocument_Range should fail 0x%x.\n", hres); ++ ++ release_interfaces(&w, &reOle, &txtDoc, NULL); ++ hres = ITextRange_CanEdit(txtRge, NULL); ++ ok(hres == CO_E_RELEASED, "ITextRange after ITextDocument destroyed\n"); ++ ITextRange_Release(txtRge); ++} ++ ++ + START_TEST(richole) + { + /* Must explicitly LoadLibrary(). The test has no references to functions in +@@ -496,4 +529,5 @@ START_TEST(richole) + test_Interfaces(); + test_ITextDocument_Open(); + test_ITextSelection_GetText(); ++ test_ITextDocument_Range(); + } +-- +1.7.9.5 + diff --git a/patches/riched20-IText_Interface/0002-riched20-Implement-ITextSelection-GetChar-and-ITextR.patch b/patches/riched20-IText_Interface/0002-riched20-Implement-ITextSelection-GetChar-and-ITextR.patch new file mode 100644 index 00000000..e725c754 --- /dev/null +++ b/patches/riched20-IText_Interface/0002-riched20-Implement-ITextSelection-GetChar-and-ITextR.patch @@ -0,0 +1,154 @@ +From e62c0def4ec23fcbc74f217fe1f12458b2eb5225 Mon Sep 17 00:00:00 2001 +From: Jactry Zeng +Date: Thu, 7 Aug 2014 13:50:08 +0800 +Subject: riched20: Implement ITextSelection::GetChar and ITextRange::GetChar. + +--- + dlls/riched20/richole.c | 28 ++++++++++++++--- + dlls/riched20/tests/richole.c | 69 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 93 insertions(+), 4 deletions(-) + +diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c +index 314bc1e..e93070a 100644 +--- a/dlls/riched20/richole.c ++++ b/dlls/riched20/richole.c +@@ -568,14 +568,29 @@ static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR bstr) + return E_NOTIMPL; + } + ++static HRESULT range_GetChar(ME_TextEditor *editor, ME_Cursor *cursor, LONG *pch) ++{ ++ WCHAR wch[2]; ++ ++ ME_GetTextW(editor, wch, 1, cursor, 1, FALSE, cursor->pRun->next->type == diTextEnd); ++ *pch = wch[0]; ++ ++ return S_OK; ++} ++ + static HRESULT WINAPI ITextRange_fnGetChar(ITextRange *me, LONG *pch) + { + ITextRangeImpl *This = impl_from_ITextRange(me); ++ ME_Cursor cursor; ++ + if (!This->reOle) + return CO_E_RELEASED; ++ TRACE("%p\n", pch); ++ if (!pch) ++ return E_INVALIDARG; + +- FIXME("not implemented %p\n", This); +- return E_NOTIMPL; ++ ME_CursorFromCharOfs(This->reOle->editor, This->start, &cursor); ++ return range_GetChar(This->reOle->editor, &cursor, pch); + } + + static HRESULT WINAPI ITextRange_fnSetChar(ITextRange *me, LONG ch) +@@ -1552,11 +1567,16 @@ static HRESULT WINAPI ITextSelection_fnSetText(ITextSelection *me, BSTR bstr) + static HRESULT WINAPI ITextSelection_fnGetChar(ITextSelection *me, LONG *pch) + { + ITextSelectionImpl *This = impl_from_ITextSelection(me); ++ ME_Cursor *start = NULL, *end = NULL; ++ + if (!This->reOle) + return CO_E_RELEASED; ++ TRACE("%p\n", pch); ++ if (!pch) ++ return E_INVALIDARG; + +- FIXME("not implemented\n"); +- return E_NOTIMPL; ++ ME_GetSelection(This->reOle->editor, &start, &end); ++ return range_GetChar(This->reOle->editor, start, pch); + } + + static HRESULT WINAPI ITextSelection_fnSetChar(ITextSelection *me, LONG ch) +diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c +index 417b68f..152d144 100644 +--- a/dlls/riched20/tests/richole.c ++++ b/dlls/riched20/tests/richole.c +@@ -518,6 +518,73 @@ static void test_ITextDocument_Range(void) + ITextRange_Release(txtRge); + } + ++static void test_ITextSelection_GetChar(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextSelection *txtSel = NULL; ++ HRESULT hres; ++ LONG pch = 0xdeadbeef; ++ static const CHAR test_text1[] = "TestSomeText"; ++ ++ create_interfaces(&w, &reOle, &txtDoc, &txtSel); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ ++#define TEST_TXTSEL_GETCHAR(first, lim, expected_char) \ ++ SendMessageA(w, EM_SETSEL, first, lim); \ ++ pch = 0xdeadbeef; \ ++ hres = ITextSelection_GetChar(txtSel, &pch); \ ++ ok(hres == S_OK, "ITextSelection_GetChar\n"); \ ++ ok(pch == expected_char, "got wrong char: %c\n", pch); ++ ++ TEST_TXTSEL_GETCHAR(0, 4, 'T') ++ TEST_TXTSEL_GETCHAR(0, 0, 'T') ++ TEST_TXTSEL_GETCHAR(12, 12, '\r') ++ TEST_TXTSEL_GETCHAR(13, 13, '\r') ++ ++ hres = ITextSelection_GetChar(txtSel, NULL); ++ ok(hres == E_INVALIDARG, "ITextSelection_GetChar\n"); ++ ++ release_interfaces(&w, &reOle, &txtDoc, &txtSel); ++} ++ ++static void test_ITextRange_GetChar(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextRange *txtRge = NULL; ++ HRESULT hres; ++ LONG pch = 0xdeadbeef; ++ int first, lim; ++ static const CHAR test_text1[] = "TestSomeText"; ++ ++#define TEST_TXTRGE_GETCHAR(first, lim, expected_char) \ ++ create_interfaces(&w, &reOle, &txtDoc, NULL); \ ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); \ ++ ITextDocument_Range(txtDoc, first, lim, &txtRge); \ ++ pch = 0xdeadbeef; \ ++ hres = ITextRange_GetChar(txtRge, &pch); \ ++ ok(hres == S_OK, "ITextRange_GetChar\n"); \ ++ ok(pch == expected_char, "got wrong char: %c\n", pch); \ ++ ITextRange_Release(txtRge); \ ++ release_interfaces(&w, &reOle, &txtDoc, NULL); ++ ++ TEST_TXTRGE_GETCHAR(0, 4, 'T') ++ TEST_TXTRGE_GETCHAR(0, 0, 'T') ++ TEST_TXTRGE_GETCHAR(12, 12, '\r') ++ TEST_TXTRGE_GETCHAR(13, 13, '\r') ++ ++ create_interfaces(&w, &reOle, &txtDoc, NULL); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ first = 12, lim = 12; ++ ITextDocument_Range(txtDoc, first, lim, &txtRge); ++ hres = ITextRange_GetChar(txtRge, NULL); ++ ok(hres == E_INVALIDARG, "ITextRange_GetChar\n"); ++ ITextRange_Release(txtRge); ++ release_interfaces(&w, &reOle, &txtDoc, NULL); ++} + + START_TEST(richole) + { +@@ -529,5 +596,7 @@ START_TEST(richole) + test_Interfaces(); + test_ITextDocument_Open(); + test_ITextSelection_GetText(); ++ test_ITextSelection_GetChar(); + test_ITextDocument_Range(); ++ test_ITextRange_GetChar(); + } +-- +1.7.9.5 + diff --git a/patches/riched20-IText_Interface/0003-riched20-Implement-IText-Selection-Range-Get-Start-E.patch b/patches/riched20-IText_Interface/0003-riched20-Implement-IText-Selection-Range-Get-Start-E.patch new file mode 100644 index 00000000..ed97be85 --- /dev/null +++ b/patches/riched20-IText_Interface/0003-riched20-Implement-IText-Selection-Range-Get-Start-E.patch @@ -0,0 +1,147 @@ +From 2ac5a6bc7f97a2179fcf566183d7a5f989ebe401 Mon Sep 17 00:00:00 2001 +From: Jactry Zeng +Date: Thu, 7 Aug 2014 14:59:13 +0800 +Subject: riched20: Implement IText{Selection, Range}::Get{Start, End}. + +--- + dlls/riched20/richole.c | 30 ++++++++++++++++++------- + dlls/riched20/tests/richole.c | 50 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 72 insertions(+), 8 deletions(-) + +diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c +index e93070a..bd3dee8 100644 +--- a/dlls/riched20/richole.c ++++ b/dlls/riched20/richole.c +@@ -639,8 +639,11 @@ static HRESULT WINAPI ITextRange_fnGetStart(ITextRange *me, LONG *pcpFirst) + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented %p\n", This); +- return E_NOTIMPL; ++ if (!pcpFirst) ++ return E_INVALIDARG; ++ *pcpFirst = This->start; ++ TRACE("%d\n", *pcpFirst); ++ return S_OK; + } + + static HRESULT WINAPI ITextRange_fnSetStart(ITextRange *me, LONG cpFirst) +@@ -659,8 +662,11 @@ static HRESULT WINAPI ITextRange_fnGetEnd(ITextRange *me, LONG *pcpLim) + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented %p\n", This); +- return E_NOTIMPL; ++ if (!pcpLim) ++ return E_INVALIDARG; ++ *pcpLim = This->end; ++ TRACE("%d\n", *pcpLim); ++ return S_OK; + } + + static HRESULT WINAPI ITextRange_fnSetEnd(ITextRange *me, LONG cpLim) +@@ -1622,11 +1628,15 @@ static HRESULT WINAPI ITextSelection_fnSetFormattedText(ITextSelection *me, ITex + static HRESULT WINAPI ITextSelection_fnGetStart(ITextSelection *me, LONG *pcpFirst) + { + ITextSelectionImpl *This = impl_from_ITextSelection(me); ++ int lim; + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented\n"); +- return E_NOTIMPL; ++ if (!pcpFirst) ++ return E_INVALIDARG; ++ ME_GetSelectionOfs(This->reOle->editor, pcpFirst, &lim); ++ TRACE("%d\n", *pcpFirst); ++ return S_OK; + } + + static HRESULT WINAPI ITextSelection_fnSetStart(ITextSelection *me, LONG cpFirst) +@@ -1642,11 +1652,15 @@ static HRESULT WINAPI ITextSelection_fnSetStart(ITextSelection *me, LONG cpFirst + static HRESULT WINAPI ITextSelection_fnGetEnd(ITextSelection *me, LONG *pcpLim) + { + ITextSelectionImpl *This = impl_from_ITextSelection(me); ++ int first; + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented\n"); +- return E_NOTIMPL; ++ if (!pcpLim) ++ return E_INVALIDARG; ++ ME_GetSelectionOfs(This->reOle->editor, &first, pcpLim); ++ TRACE("%d\n", *pcpLim); ++ return S_OK; + } + + static HRESULT WINAPI ITextSelection_fnSetEnd(ITextSelection *me, LONG cpLim) +diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c +index 152d144..22ee4b5 100644 +--- a/dlls/riched20/tests/richole.c ++++ b/dlls/riched20/tests/richole.c +@@ -586,6 +586,55 @@ static void test_ITextRange_GetChar(void) + release_interfaces(&w, &reOle, &txtDoc, NULL); + } + ++static void test_GetStart_GetEnd(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextRange *txtRge = NULL; ++ ITextSelection *txtSel = NULL; ++ HRESULT hres; ++ int start, end; ++ static const CHAR test_text1[] = "TestSomeText"; ++ ++ create_interfaces(&w, &reOle, &txtDoc, &txtSel); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ ++ /* tests for ITextRange::Get{Start, End} */ ++#define TEST_TXTRGE_GETSTARTEND(first, lim, expected_start, expected_end) \ ++ ITextDocument_Range(txtDoc, first, lim, &txtRge); \ ++ start = 0xdeadbeef; \ ++ hres = ITextRange_GetStart(txtRge, &start); \ ++ ok(hres == S_OK, "ITextRange_GetStart\n"); \ ++ ok(start == expected_start, "got wrong start value: %d\n", start); \ ++ end = 0xdeadbeef; \ ++ hres = ITextRange_GetEnd(txtRge, &end); \ ++ ok(hres == S_OK, "ITextRange_GetEnd\n"); \ ++ ok(end == expected_end, "got wrong end value: %d\n", end); \ ++ ITextRange_Release(txtRge); ++ ++ TEST_TXTRGE_GETSTARTEND(1, 6, 1, 6); ++ TEST_TXTRGE_GETSTARTEND(6, 1, 1, 6); ++ TEST_TXTRGE_GETSTARTEND(-1, 13, 0, 13); ++ ++ /* tests for ITextSelection::Get{Start, End} */ ++#define TEST_TXTSEL_GETSTARTEND(first, lim, expected_start, expected_end) \ ++ SendMessageA(w, EM_SETSEL, first, lim); \ ++ start = 0xdeadbeef; \ ++ hres = ITextSelection_GetStart(txtSel, &start); \ ++ ok(hres == S_OK, "ITextSelection_GetStart\n"); \ ++ ok(start == expected_start, "got wrong start value: %d\n", start); \ ++ end = 0xdeadbeef; \ ++ hres = ITextSelection_GetEnd(txtSel, &end); \ ++ ok(end == expected_end, "got wrong end value: %d\n", end); ++ ++ TEST_TXTSEL_GETSTARTEND(2, 5, 2, 5) ++ TEST_TXTSEL_GETSTARTEND(5, 2, 2, 5) ++ TEST_TXTSEL_GETSTARTEND(0, -1, 0, strlen(test_text1)+1) ++ ++ release_interfaces(&w, &reOle, &txtDoc, &txtSel); ++} ++ + START_TEST(richole) + { + /* Must explicitly LoadLibrary(). The test has no references to functions in +@@ -599,4 +648,5 @@ START_TEST(richole) + test_ITextSelection_GetChar(); + test_ITextDocument_Range(); + test_ITextRange_GetChar(); ++ test_GetStart_GetEnd(); + } +-- +1.7.9.5 + diff --git a/patches/riched20-IText_Interface/0004-riched20-Implement-ITextRange-GetDuplicate.patch b/patches/riched20-IText_Interface/0004-riched20-Implement-ITextRange-GetDuplicate.patch new file mode 100644 index 00000000..df6f2ee7 --- /dev/null +++ b/patches/riched20-IText_Interface/0004-riched20-Implement-ITextRange-GetDuplicate.patch @@ -0,0 +1,102 @@ +From 3cc40358e08460d01b43647844f260eafc670e28 Mon Sep 17 00:00:00 2001 +From: Jactry Zeng +Date: Thu, 7 Aug 2014 15:11:07 +0800 +Subject: riched20: Implement ITextRange::GetDuplicate. + +--- + dlls/riched20/richole.c | 23 +++++++++++++++++++++-- + dlls/riched20/tests/richole.c | 35 +++++++++++++++++++++++++++++++++++ + 2 files changed, 56 insertions(+), 2 deletions(-) + +diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c +index bd3dee8..229fb5d 100644 +--- a/dlls/riched20/richole.c ++++ b/dlls/riched20/richole.c +@@ -606,11 +606,30 @@ static HRESULT WINAPI ITextRange_fnSetChar(ITextRange *me, LONG ch) + static HRESULT WINAPI ITextRange_fnGetDuplicate(ITextRange *me, ITextRange **ppRange) + { + ITextRangeImpl *This = impl_from_ITextRange(me); ++ ITextRangeImpl *txtRge = NULL; + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented %p\n", This); +- return E_NOTIMPL; ++ TRACE("%p %p\n", This, ppRange); ++ if (!ppRange) ++ return E_INVALIDARG; ++ ++ txtRge = heap_alloc(sizeof *txtRge); ++ if (!txtRge) ++ return E_FAIL; ++ ++ txtRge->ITextRange_iface.lpVtbl = This->ITextRange_iface.lpVtbl; ++ txtRge->ref = 1; ++ txtRge->reOle = This->reOle; ++ txtRge->start = This->start; ++ txtRge->end = This->end; ++ txtRge->next = This->reOle->txtRgehead->next; ++ This->reOle->txtRgehead->next->prev = txtRge; ++ This->reOle->txtRgehead->next = txtRge; ++ txtRge->prev = This->reOle->txtRgehead; ++ *ppRange = &txtRge->ITextRange_iface; ++ ++ return S_OK; + } + + static HRESULT WINAPI ITextRange_fnGetFormattedText(ITextRange *me, ITextRange **ppRange) +diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c +index 22ee4b5..bc04c84 100644 +--- a/dlls/riched20/tests/richole.c ++++ b/dlls/riched20/tests/richole.c +@@ -635,6 +635,40 @@ static void test_GetStart_GetEnd(void) + release_interfaces(&w, &reOle, &txtDoc, &txtSel); + } + ++static void test_ITextRange_GetDuplicate(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextRange *txtRge = NULL; ++ ITextRange *txtRgeDup = NULL; ++ HRESULT hres; ++ LONG first, lim, start, end; ++ static const CHAR test_text1[] = "TestSomeText"; ++ ++ create_interfaces(&w, &reOle, &txtDoc, NULL); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ first = 0, lim = 4; ++ hres = ITextDocument_Range(txtDoc, first, lim, &txtRge); ++ ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres); ++ ++ hres = ITextRange_GetDuplicate(txtRge, &txtRgeDup); ++ ok(hres == S_OK, "ITextRange_GetDuplicate\n"); ++ ok(txtRgeDup != txtRge, "A new pointer should be returned\n"); ++ ITextRange_GetStart(txtRgeDup, &start); ++ ok(start == first, "got wrong value: %d\n", start); ++ ITextRange_GetEnd(txtRgeDup, &end); ++ ok(end == lim, "got wrong value: %d\n", end); ++ ++ ITextRange_Release(txtRgeDup); ++ ++ hres = ITextRange_GetDuplicate(txtRge, NULL); ++ ok(hres == E_INVALIDARG, "ITextRange_GetDuplicate\n"); ++ ++ ITextRange_Release(txtRge); ++ release_interfaces(&w, &reOle, &txtDoc, NULL); ++} ++ + START_TEST(richole) + { + /* Must explicitly LoadLibrary(). The test has no references to functions in +@@ -648,5 +682,6 @@ START_TEST(richole) + test_ITextSelection_GetChar(); + test_ITextDocument_Range(); + test_ITextRange_GetChar(); ++ test_ITextRange_GetDuplicate(); + test_GetStart_GetEnd(); + } +-- +1.7.9.5 + diff --git a/patches/riched20-IText_Interface/0005-riched20-Implement-ITextRange-Collapse-and-ITextSele.patch b/patches/riched20-IText_Interface/0005-riched20-Implement-ITextRange-Collapse-and-ITextSele.patch new file mode 100644 index 00000000..0ced79b5 --- /dev/null +++ b/patches/riched20-IText_Interface/0005-riched20-Implement-ITextRange-Collapse-and-ITextSele.patch @@ -0,0 +1,167 @@ +From a1d0978ce36f81b0bc547e3a357bd985c3b16abe Mon Sep 17 00:00:00 2001 +From: Jactry Zeng +Date: Sat, 9 Aug 2014 00:40:17 +0800 +Subject: riched20: Implement ITextRange::Collapse and + ITextSelection::Collapse. + +--- + dlls/riched20/richole.c | 26 +++++++++++--- + dlls/riched20/tests/richole.c | 80 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 101 insertions(+), 5 deletions(-) + +diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c +index 229fb5d..9a7e690 100644 +--- a/dlls/riched20/richole.c ++++ b/dlls/riched20/richole.c +@@ -757,15 +757,26 @@ static HRESULT WINAPI ITextRange_fnGetStoryType(ITextRange *me, LONG *pValue) + FIXME("not implemented %p\n", This); + return E_NOTIMPL; + } ++static HRESULT range_Collapse(LONG bStart, LONG *start, LONG *end) ++{ ++ BOOL isdege = !(*end - *start); ++ ++ if (isdege) ++ return S_FALSE; ++ ++ if (bStart == tomEnd || bStart == tomFalse) ++ *start = *end; ++ else ++ *end = *start; ++ return S_OK; ++} + + static HRESULT WINAPI ITextRange_fnCollapse(ITextRange *me, LONG bStart) + { + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; +- +- FIXME("not implemented %p\n", This); +- return E_NOTIMPL; ++ return range_Collapse(bStart, &This->start, &This->end); + } + + static HRESULT WINAPI ITextRange_fnExpand(ITextRange *me, LONG Unit, LONG *pDelta) +@@ -1755,11 +1766,16 @@ static HRESULT WINAPI ITextSelection_fnGetStoryType(ITextSelection *me, LONG *pV + static HRESULT WINAPI ITextSelection_fnCollapse(ITextSelection *me, LONG bStart) + { + ITextSelectionImpl *This = impl_from_ITextSelection(me); ++ int start, end; ++ HRESULT hres; + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented\n"); +- return E_NOTIMPL; ++ ME_GetSelectionOfs(This->reOle->editor, &start, &end); ++ hres = range_Collapse(bStart, &start, &end); ++ if (!hres) ++ ME_SetSelection(This->reOle->editor, start, end); ++ return hres; + } + + static HRESULT WINAPI ITextSelection_fnExpand(ITextSelection *me, LONG Unit, LONG *pDelta) +diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c +index bc04c84..7effc3d 100644 +--- a/dlls/riched20/tests/richole.c ++++ b/dlls/riched20/tests/richole.c +@@ -669,6 +669,84 @@ static void test_ITextRange_GetDuplicate(void) + release_interfaces(&w, &reOle, &txtDoc, NULL); + } + ++static void test_ITextRange_Collapse(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextRange *txtRge = NULL; ++ HRESULT hres; ++ LONG first, lim, start, end; ++ static const CHAR test_text1[] = "TestSomeText"; ++ ++ create_interfaces(&w, &reOle, &txtDoc, NULL); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ ++#define TEST_TXTRGE_COLLAPSE(bStart, expected_start, expected_end, expected_return) \ ++ ITextDocument_Range(txtDoc, first, lim, &txtRge); \ ++ hres = ITextRange_Collapse(txtRge, bStart); \ ++ ok(hres == expected_return, "ITextRange_Collapse\n"); \ ++ ITextRange_GetStart(txtRge, &start); \ ++ ok(start == expected_start, "got wrong start value: %d\n", start); \ ++ ITextRange_GetEnd(txtRge, &end); \ ++ ok(end == expected_end, "got wrong end value: %d\n", end); \ ++ ITextRange_Release(txtRge); ++ ++ first = 4, lim = 8; ++ TEST_TXTRGE_COLLAPSE(tomTrue, 4, 4, S_OK) ++ TEST_TXTRGE_COLLAPSE(tomStart, 4, 4, S_OK) ++ TEST_TXTRGE_COLLAPSE(tomFalse, 8, 8, S_OK) ++ TEST_TXTRGE_COLLAPSE(tomEnd, 8, 8, S_OK) ++ /* tomStart is the default */ ++ TEST_TXTRGE_COLLAPSE(256, 4, 4, S_OK) ++ ++ first = 6, lim = 6; ++ TEST_TXTRGE_COLLAPSE(tomEnd, 6, 6, S_FALSE) ++ ++ first = 8, lim = 8; ++ TEST_TXTRGE_COLLAPSE(tomStart, 8, 8, S_FALSE) ++ ++ release_interfaces(&w, &reOle, &txtDoc, NULL); ++} ++ ++static void test_ITextSelection_Collapse(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextSelection *txtSel = NULL; ++ HRESULT hres; ++ LONG first, lim, start, end; ++ static const CHAR test_text1[] = "TestSomeText"; ++ ++ create_interfaces(&w, &reOle, &txtDoc, &txtSel); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ ++#define TEST_TXTSEL_COLLAPSE(bStart, expected_start, expected_end, expected_return) \ ++ SendMessageA(w, EM_SETSEL, first, lim); \ ++ hres = ITextSelection_Collapse(txtSel, bStart); \ ++ ok(hres == expected_return, "ITextSelection_Collapse\n"); \ ++ SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); \ ++ ok(start == expected_start, "got wrong start value: %d\n", start); \ ++ ok(end == expected_end, "got wrong end value: %d\n", end); ++ ++ first = 4, lim = 8; ++ TEST_TXTSEL_COLLAPSE(tomTrue, 4, 4, S_OK) ++ TEST_TXTSEL_COLLAPSE(tomStart, 4, 4, S_OK) ++ TEST_TXTSEL_COLLAPSE(tomFalse, 8, 8, S_OK) ++ TEST_TXTSEL_COLLAPSE(tomEnd, 8, 8, S_OK) ++ /* tomStart is the default */ ++ TEST_TXTSEL_COLLAPSE(256, 4, 4, S_OK) ++ ++ first = 6, lim = 6; ++ TEST_TXTSEL_COLLAPSE(tomEnd, 6, 6, S_FALSE) ++ ++ first = 8, lim = 8; ++ TEST_TXTSEL_COLLAPSE(tomStart, 8, 8, S_FALSE) ++ ++ release_interfaces(&w, &reOle, &txtDoc, &txtSel); ++} ++ + START_TEST(richole) + { + /* Must explicitly LoadLibrary(). The test has no references to functions in +@@ -680,8 +758,10 @@ START_TEST(richole) + test_ITextDocument_Open(); + test_ITextSelection_GetText(); + test_ITextSelection_GetChar(); ++ test_ITextSelection_Collapse(); + test_ITextDocument_Range(); + test_ITextRange_GetChar(); + test_ITextRange_GetDuplicate(); + test_GetStart_GetEnd(); ++ test_ITextRange_Collapse(); + } +-- +1.7.9.5 + diff --git a/patches/riched20-IText_Interface/0006-riched20-Implement-IText-Selection-Range-Set-Start-E.patch b/patches/riched20-IText_Interface/0006-riched20-Implement-IText-Selection-Range-Set-Start-E.patch new file mode 100644 index 00000000..51770f8b --- /dev/null +++ b/patches/riched20-IText_Interface/0006-riched20-Implement-IText-Selection-Range-Set-Start-E.patch @@ -0,0 +1,272 @@ +From e6d0113506679fc705bfd65f9ae759fce0152159 Mon Sep 17 00:00:00 2001 +From: Jactry Zeng +Date: Fri, 8 Aug 2014 21:32:57 +0800 +Subject: riched20: Implement IText{Selection, Range}::Set{Start, End}. + +--- + dlls/riched20/richole.c | 52 +++++++++++++--- + dlls/riched20/tests/richole.c | 135 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 179 insertions(+), 8 deletions(-) + +diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c +index 9a7e690..5a16d6d 100644 +--- a/dlls/riched20/richole.c ++++ b/dlls/riched20/richole.c +@@ -665,14 +665,27 @@ static HRESULT WINAPI ITextRange_fnGetStart(ITextRange *me, LONG *pcpFirst) + return S_OK; + } + ++static HRESULT range_SetStart(ME_TextEditor *editor, LONG cpFirst, LONG *start, LONG *end) ++{ ++ int len = ME_GetTextLength(editor); ++ ++ TRACE("%d\n", cpFirst); ++ if (cpFirst == *start) ++ return S_FALSE; ++ cpFirst = min(cpFirst, len); ++ cpFirst = max(cpFirst, 0); ++ *end = max(*end, cpFirst); ++ *start = cpFirst; ++ return S_OK; ++} ++ + static HRESULT WINAPI ITextRange_fnSetStart(ITextRange *me, LONG cpFirst) + { + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented %p\n", This); +- return E_NOTIMPL; ++ return range_SetStart(This->reOle->editor, cpFirst, &This->start, &This->end); + } + + static HRESULT WINAPI ITextRange_fnGetEnd(ITextRange *me, LONG *pcpLim) +@@ -688,14 +701,27 @@ static HRESULT WINAPI ITextRange_fnGetEnd(ITextRange *me, LONG *pcpLim) + return S_OK; + } + ++static HRESULT range_SetEnd(ME_TextEditor *editor, LONG cpLim, LONG *start, LONG *end) ++{ ++ int len = ME_GetTextLength(editor) + 1; ++ ++ TRACE("%d\n", cpLim); ++ if (cpLim == *end) ++ return S_FALSE; ++ cpLim = min(cpLim, len); ++ cpLim = max(cpLim, 0); ++ *start = min(*start, cpLim); ++ *end = cpLim; ++ return S_OK; ++} ++ + static HRESULT WINAPI ITextRange_fnSetEnd(ITextRange *me, LONG cpLim) + { + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented %p\n", This); +- return E_NOTIMPL; ++ return range_SetEnd(This->reOle->editor, cpLim, &This->start, &This->end); + } + + static HRESULT WINAPI ITextRange_fnGetFont(ITextRange *me, ITextFont **pFont) +@@ -1672,11 +1698,16 @@ static HRESULT WINAPI ITextSelection_fnGetStart(ITextSelection *me, LONG *pcpFir + static HRESULT WINAPI ITextSelection_fnSetStart(ITextSelection *me, LONG cpFirst) + { + ITextSelectionImpl *This = impl_from_ITextSelection(me); ++ int start, end; ++ HRESULT hres; + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented\n"); +- return E_NOTIMPL; ++ ME_GetSelectionOfs(This->reOle->editor, &start, &end); ++ hres = range_SetStart(This->reOle->editor, cpFirst, &start, &end); ++ if (!hres) ++ ME_SetSelection(This->reOle->editor, start, end); ++ return hres; + } + + static HRESULT WINAPI ITextSelection_fnGetEnd(ITextSelection *me, LONG *pcpLim) +@@ -1696,11 +1727,16 @@ static HRESULT WINAPI ITextSelection_fnGetEnd(ITextSelection *me, LONG *pcpLim) + static HRESULT WINAPI ITextSelection_fnSetEnd(ITextSelection *me, LONG cpLim) + { + ITextSelectionImpl *This = impl_from_ITextSelection(me); ++ int start, end; ++ HRESULT hres; + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented\n"); +- return E_NOTIMPL; ++ ME_GetSelectionOfs(This->reOle->editor, &start, &end); ++ hres = range_SetEnd(This->reOle->editor, cpLim, &start, &end); ++ if (!hres) ++ ME_SetSelection(This->reOle->editor, start, end); ++ return hres; + } + + static HRESULT WINAPI ITextSelection_fnGetFont(ITextSelection *me, ITextFont **pFont) +diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c +index 7effc3d..2916bc5 100644 +--- a/dlls/riched20/tests/richole.c ++++ b/dlls/riched20/tests/richole.c +@@ -747,6 +747,137 @@ static void test_ITextSelection_Collapse(void) + release_interfaces(&w, &reOle, &txtDoc, &txtSel); + } + ++static void test_ITextRange_SetStart(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextRange *txtRge = NULL; ++ HRESULT hres; ++ LONG first, lim, start, end; ++ static const CHAR test_text1[] = "TestSomeText"; ++ ++ create_interfaces(&w, &reOle, &txtDoc, NULL); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ ++ first = 4, lim = 8; ++ ITextDocument_Range(txtDoc, first, lim, &txtRge); ++ hres = ITextRange_SetStart(txtRge, first); ++ ok(hres == S_FALSE, "ITextRange_SetStart\n"); ++ ++#define TEST_TXTRGE_SETSTART(cp, expected_start, expected_end) \ ++ hres = ITextRange_SetStart(txtRge, cp); \ ++ ok(hres == S_OK, "ITextRange_SetStart\n"); \ ++ ITextRange_GetStart(txtRge, &start); \ ++ ITextRange_GetEnd(txtRge, &end); \ ++ ok(start == expected_start, "got wrong start value: %d\n", start); \ ++ ok(end == expected_end, "got wrong end value: %d\n", end); ++ ++ TEST_TXTRGE_SETSTART(2, 2, 8) ++ TEST_TXTRGE_SETSTART(-1, 0, 8) ++ TEST_TXTRGE_SETSTART(13, 12, 12) ++ ++ release_interfaces(&w, &reOle, &txtDoc, NULL); ++} ++ ++static void test_ITextRange_SetEnd(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextRange *txtRge = NULL; ++ HRESULT hres; ++ LONG first, lim, start, end; ++ static const CHAR test_text1[] = "TestSomeText"; ++ ++ create_interfaces(&w, &reOle, &txtDoc, NULL); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ ++ first = 4, lim = 8; ++ ITextDocument_Range(txtDoc, first, lim, &txtRge); ++ hres = ITextRange_SetEnd(txtRge, lim); ++ ok(hres == S_FALSE, "ITextRange_SetEnd\n"); ++ ++#define TEST_TXTRGE_SETEND(cp, expected_start, expected_end) \ ++ hres = ITextRange_SetEnd(txtRge, cp); \ ++ ok(hres == S_OK, "ITextRange_SetEnd\n"); \ ++ ITextRange_GetStart(txtRge, &start); \ ++ ITextRange_GetEnd(txtRge, &end); \ ++ ok(start == expected_start, "got wrong start value: %d\n", start); \ ++ ok(end == expected_end, "got wrong end value: %d\n", end); ++ ++ TEST_TXTRGE_SETEND(6, 4, 6) ++ TEST_TXTRGE_SETEND(14, 4, 13) ++ TEST_TXTRGE_SETEND(-1, 0, 0) ++ ++ ITextRange_Release(txtRge); ++ release_interfaces(&w, &reOle, &txtDoc, NULL); ++} ++ ++static void test_ITextSelection_SetStart(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextSelection *txtSel = NULL; ++ HRESULT hres; ++ LONG first, lim, start, end; ++ static const CHAR test_text1[] = "TestSomeText"; ++ ++ create_interfaces(&w, &reOle, &txtDoc, &txtSel); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ ++ first = 4, lim = 8; ++ SendMessageA(w, EM_SETSEL, first, lim); ++ hres = ITextSelection_SetStart(txtSel, first); ++ ok(hres == S_FALSE, "ITextSelection_SetStart\n"); ++ ++#define TEST_TXTSEL_SETSTART(cp, expected_start, expected_end) \ ++ hres = ITextSelection_SetStart(txtSel, cp); \ ++ ok(hres == S_OK, "ITextSelection_SetStart\n"); \ ++ SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); \ ++ ok(start == expected_start, "got wrong start value: %d\n", start); \ ++ ok(end == expected_end, "got wrong end value: %d\n", end); ++ ++ TEST_TXTSEL_SETSTART(2, 2, 8) ++ TEST_TXTSEL_SETSTART(-1, 0, 8) ++ TEST_TXTSEL_SETSTART(13, 12, 12) ++ ++ release_interfaces(&w, &reOle, &txtDoc, &txtSel); ++} ++ ++static void test_ITextSelection_SetEnd(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextSelection *txtSel = NULL; ++ HRESULT hres; ++ LONG first, lim, start, end; ++ static const CHAR test_text1[] = "TestSomeText"; ++ ++ create_interfaces(&w, &reOle, &txtDoc, &txtSel); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ ++ first = 4, lim = 8; ++ SendMessageA(w, EM_SETSEL, first, lim); ++ hres = ITextSelection_SetEnd(txtSel, lim); ++ ok(hres == S_FALSE, "ITextSelection_SetEnd\n"); ++ ++#define TEST_TXTSEL_SETEND(cp, expected_start, expected_end) \ ++ hres = ITextSelection_SetEnd(txtSel, cp); \ ++ ok(hres == S_OK, "ITextSelection_SetEnd\n"); \ ++ SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); \ ++ ok(start == expected_start, "got wrong start value: %d\n", start); \ ++ ok(end == expected_end, "got wrong end value: %d\n", end); ++ ++ TEST_TXTSEL_SETEND(6, 4, 6) ++ TEST_TXTSEL_SETEND(14, 4, 13) ++ TEST_TXTSEL_SETEND(-1, 0, 0) ++ ++ release_interfaces(&w, &reOle, &txtDoc, &txtSel); ++} ++ + START_TEST(richole) + { + /* Must explicitly LoadLibrary(). The test has no references to functions in +@@ -758,10 +889,14 @@ START_TEST(richole) + test_ITextDocument_Open(); + test_ITextSelection_GetText(); + test_ITextSelection_GetChar(); ++ test_ITextSelection_SetStart(); ++ test_ITextSelection_SetEnd(); + test_ITextSelection_Collapse(); + test_ITextDocument_Range(); + test_ITextRange_GetChar(); + test_ITextRange_GetDuplicate(); + test_GetStart_GetEnd(); + test_ITextRange_Collapse(); ++ test_ITextRange_SetStart(); ++ test_ITextRange_SetEnd(); + } +-- +1.7.9.5 + diff --git a/patches/riched20-IText_Interface/0007-riched20-Stub-for-ITextFont-interface-and-implement-.patch b/patches/riched20-IText_Interface/0007-riched20-Stub-for-ITextFont-interface-and-implement-.patch new file mode 100644 index 00000000..097c0be8 --- /dev/null +++ b/patches/riched20-IText_Interface/0007-riched20-Stub-for-ITextFont-interface-and-implement-.patch @@ -0,0 +1,1045 @@ +From 16cb4e2704dc7f7226a3f82771139e0087f5f313 Mon Sep 17 00:00:00 2001 +From: Jactry Zeng +Date: Sat, 9 Aug 2014 00:41:58 +0800 +Subject: riched20: Stub for ITextFont interface and implement + ITextRange::GetFont and ITextSelection::GetFont. + +--- + dlls/riched20/richole.c | 835 ++++++++++++++++++++++++++++++++++++++++- + dlls/riched20/tests/richole.c | 93 +++++ + 2 files changed, 924 insertions(+), 4 deletions(-) + +diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c +index 5a16d6d..c1569b0 100644 +--- a/dlls/riched20/richole.c ++++ b/dlls/riched20/richole.c +@@ -46,10 +46,12 @@ DEFINE_GUID(IID_ITextHost2, 0x13e670f5,0x1a5a,0x11cf,0xab,0xeb,0x00,0xaa,0x00,0x + DEFINE_GUID(IID_ITextDocument, 0x8cc497c0, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); + DEFINE_GUID(IID_ITextRange, 0x8cc497c2, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); + DEFINE_GUID(IID_ITextSelection, 0x8cc497c1, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); ++DEFINE_GUID(IID_ITextFont, 0x8cc497c3, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); + + typedef struct ITextSelectionImpl ITextSelectionImpl; + typedef struct IOleClientSiteImpl IOleClientSiteImpl; + typedef struct ITextRangeImpl ITextRangeImpl; ++typedef struct ITextFontImpl ITextFontImpl; + + typedef struct IRichEditOleImpl { + IRichEditOle IRichEditOle_iface; +@@ -60,6 +62,7 @@ typedef struct IRichEditOleImpl { + ITextSelectionImpl *txtSel; + IOleClientSiteImpl *clientSite; + ITextRangeImpl *txtRgehead, *txtRgetail; ++ ITextFontImpl *txtFonthead, *txtFonttail; + } IRichEditOleImpl; + + struct ITextRangeImpl { +@@ -71,6 +74,16 @@ struct ITextRangeImpl { + IRichEditOleImpl *reOle; + }; + ++struct ITextFontImpl { ++ ITextFont ITextFont_iface; ++ LONG ref; ++ ITextFontImpl *prev, *next; ++ ++ IRichEditOleImpl *reOle; ++ ITextRangeImpl *txtRge; ++ ITextSelectionImpl *txtSel; ++}; ++ + struct ITextSelectionImpl { + ITextSelection ITextSelection_iface; + LONG ref; +@@ -140,6 +153,7 @@ IRichEditOle_fnRelease(IRichEditOle *me) + if (!ref) + { + ITextRangeImpl *txtRgeImpl = This->txtRgehead->next; ++ ITextFontImpl *txtFontImpl = This->txtFonthead->next; + TRACE ("Destroying %p\n", This); + This->txtSel->reOle = NULL; + ITextSelection_Release(&This->txtSel->ITextSelection_iface); +@@ -151,6 +165,13 @@ IRichEditOle_fnRelease(IRichEditOle *me) + } + heap_free(This->txtRgehead); + heap_free(This->txtRgetail); ++ while (txtFontImpl) ++ { ++ txtFontImpl->reOle = NULL; ++ txtFontImpl = txtFontImpl->next; ++ } ++ heap_free(This->txtFonthead); ++ heap_free(This->txtFonttail); + heap_free(This); + } + return ref; +@@ -462,6 +483,741 @@ static const IRichEditOleVtbl revt = { + IRichEditOle_fnImportDataObject + }; + ++/* ITextFont interface */ ++static inline ITextFontImpl *impl_from_ITextFont(ITextFont *iface) ++{ ++ return CONTAINING_RECORD(iface, ITextFontImpl, ITextFont_iface); ++} ++ ++static HRESULT WINAPI ITextFont_fnQueryInterface(ITextFont *me, REFIID riid, void **ppvObj) ++{ ++ *ppvObj = NULL; ++ if (IsEqualGUID(riid, &IID_IUnknown) ++ || IsEqualGUID(riid, &IID_ITextFont) ++ || IsEqualGUID(riid, &IID_IDispatch)) ++ { ++ *ppvObj = me; ++ ITextFont_AddRef(me); ++ return S_OK; ++ } ++ ++ return E_NOINTERFACE; ++} ++ ++static ULONG WINAPI ITextFont_fnAddRef(ITextFont *me) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ return InterlockedIncrement(&This->ref); ++} ++ ++static ULONG WINAPI ITextFont_fnRelease(ITextFont *me) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ ULONG ref = InterlockedDecrement(&This->ref); ++ ++ TRACE ("%p ref=%u\n", This, ref); ++ if (ref == 0) ++ { ++ if (!This->txtSel) ++ ITextRange_Release(&This->txtRge->ITextRange_iface); ++ else ++ ITextSelection_Release(&This->txtSel->ITextSelection_iface); ++ This->reOle = NULL; ++ This->txtRge = NULL; ++ This->txtSel = NULL; ++ This->prev->next = This->next; ++ This->next->prev = This->prev; ++ heap_free(This); ++ } ++ return ref; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetTypeInfoCount(ITextFont *me, UINT *pctinfo) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetTypeInfo(ITextFont *me, UINT iTInfo, LCID lcid, ++ ITypeInfo **ppTInfo) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetIDsOfNames(ITextFont *me, REFIID riid, ++ LPOLESTR *rgszNames, UINT cNames, ++ LCID lcid, DISPID *rgDispId) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnInvoke(ITextFont *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 ITextFont_fnGetDuplicate(ITextFont *me, ITextFont **ppFont) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetDuplicate(ITextFont *me, ITextFont *pFont) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnCanChange(ITextFont *me, LONG *pB) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnIsEqual(ITextFont *me, ITextFont *pFont, LONG *pB) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnReset(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetStyle(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetStyle(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetAllCaps(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetAllCaps(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetAnimation(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetAnimation(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetBackColor(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetBackColor(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetBold(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!pValue) ++ return E_INVALIDARG; ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("Stub\n"); ++ *pValue = tomFalse; ++ return S_OK; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetBold(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetEmboss(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetEmboss(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetForeColor(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!pValue) ++ return E_INVALIDARG; ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("Stub\n"); ++ *pValue = tomAutoColor; ++ return S_OK; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetForeColor(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetHidden(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetHidden(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetEngrave(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetEngrave(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetItalic(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!pValue) ++ return E_INVALIDARG; ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("Stub\n"); ++ *pValue = tomFalse; ++ return S_OK; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetItalic(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetKerning(ITextFont *me, float *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetKerning(ITextFont *me, float Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetLanguageID(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetLanguageID(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetName(ITextFont *me, BSTR *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ WCHAR font[] = {'S', 'y', 's', 't', 'e', 'm', 0}; ++ if (!pValue) ++ return E_INVALIDARG; ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("Stub\n"); ++ *pValue = SysAllocString(font); ++ return S_OK; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetName(ITextFont *me, BSTR Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetOutline(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetOutline(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetPosition(ITextFont *me, float *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetPosition(ITextFont *me, float Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetProtected(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetProtected(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetShadow(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetShadow(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetSize(ITextFont *me, float *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!pValue) ++ return E_INVALIDARG; ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("Stub\n"); ++ *pValue = 12.0; ++ return S_OK; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetSize(ITextFont *me, float Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetSmallCaps(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetSmallCaps(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetSpacing(ITextFont *me, float *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetSpacing(ITextFont *me, float Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetStrikeThrough(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!pValue) ++ return E_INVALIDARG; ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("Stub\n"); ++ *pValue = tomFalse; ++ return S_OK; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetStrikeThrough(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetSubscript(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!pValue) ++ return E_INVALIDARG; ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("Stub\n"); ++ *pValue = tomFalse; ++ return S_OK; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetSubscript(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetSuperscript(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (pValue) ++ return E_INVALIDARG; ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("Stub\n"); ++ *pValue = tomFalse; ++ return S_OK; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetSuperscript(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetUnderline(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!pValue) ++ return E_INVALIDARG; ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("Stub\n"); ++ *pValue = tomNone; ++ return S_OK; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetUnderline(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnGetWeight(ITextFont *me, LONG *pValue) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextFont_fnSetWeight(ITextFont *me, LONG Value) ++{ ++ ITextFontImpl *This = impl_from_ITextFont(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static const ITextFontVtbl tfvt = { ++ ITextFont_fnQueryInterface, ++ ITextFont_fnAddRef, ++ ITextFont_fnRelease, ++ ITextFont_fnGetTypeInfoCount, ++ ITextFont_fnGetTypeInfo, ++ ITextFont_fnGetIDsOfNames, ++ ITextFont_fnInvoke, ++ ITextFont_fnGetDuplicate, ++ ITextFont_fnSetDuplicate, ++ ITextFont_fnCanChange, ++ ITextFont_fnIsEqual, ++ ITextFont_fnReset, ++ ITextFont_fnGetStyle, ++ ITextFont_fnSetStyle, ++ ITextFont_fnGetAllCaps, ++ ITextFont_fnSetAllCaps, ++ ITextFont_fnGetAnimation, ++ ITextFont_fnSetAnimation, ++ ITextFont_fnGetBackColor, ++ ITextFont_fnSetBackColor, ++ ITextFont_fnGetBold, ++ ITextFont_fnSetBold, ++ ITextFont_fnGetEmboss, ++ ITextFont_fnSetEmboss, ++ ITextFont_fnGetForeColor, ++ ITextFont_fnSetForeColor, ++ ITextFont_fnGetHidden, ++ ITextFont_fnSetHidden, ++ ITextFont_fnGetEngrave, ++ ITextFont_fnSetEngrave, ++ ITextFont_fnGetItalic, ++ ITextFont_fnSetItalic, ++ ITextFont_fnGetKerning, ++ ITextFont_fnSetKerning, ++ ITextFont_fnGetLanguageID, ++ ITextFont_fnSetLanguageID, ++ ITextFont_fnGetName, ++ ITextFont_fnSetName, ++ ITextFont_fnGetOutline, ++ ITextFont_fnSetOutline, ++ ITextFont_fnGetPosition, ++ ITextFont_fnSetPosition, ++ ITextFont_fnGetProtected, ++ ITextFont_fnSetProtected, ++ ITextFont_fnGetShadow, ++ ITextFont_fnSetShadow, ++ ITextFont_fnGetSize, ++ ITextFont_fnSetSize, ++ ITextFont_fnGetSmallCaps, ++ ITextFont_fnSetSmallCaps, ++ ITextFont_fnGetSpacing, ++ ITextFont_fnSetSpacing, ++ ITextFont_fnGetStrikeThrough, ++ ITextFont_fnSetStrikeThrough, ++ ITextFont_fnGetSubscript, ++ ITextFont_fnSetSubscript, ++ ITextFont_fnGetSuperscript, ++ ITextFont_fnSetSuperscript, ++ ITextFont_fnGetUnderline, ++ ITextFont_fnSetUnderline, ++ ITextFont_fnGetWeight, ++ ITextFont_fnSetWeight ++}; ++/* ITextFont interface */ ++ + /* ITextRange interface */ + static inline ITextRangeImpl *impl_from_ITextRange(ITextRange *iface) + { +@@ -724,14 +1480,45 @@ static HRESULT WINAPI ITextRange_fnSetEnd(ITextRange *me, LONG cpLim) + return range_SetEnd(This->reOle->editor, cpLim, &This->start, &This->end); + } + ++static HRESULT range_GetFont(IRichEditOleImpl *reOle, ITextFontImpl **ptxtFont) ++{ ++ ITextFontImpl *txtFont = NULL; ++ txtFont = heap_alloc(sizeof(ITextFontImpl)); ++ if (!txtFont) ++ return E_OUTOFMEMORY; ++ ++ txtFont->ITextFont_iface.lpVtbl = &tfvt; ++ txtFont->ref = 1; ++ txtFont->reOle = reOle; ++ txtFont->next = reOle->txtFonthead->next; ++ reOle->txtFonthead->next->prev = txtFont; ++ reOle->txtFonthead->next = txtFont; ++ txtFont->prev = reOle->txtFonthead; ++ *ptxtFont = txtFont; ++ return S_OK; ++} ++ + static HRESULT WINAPI ITextRange_fnGetFont(ITextRange *me, ITextFont **pFont) + { + ITextRangeImpl *This = impl_from_ITextRange(me); ++ ITextFontImpl *txtFont = NULL; ++ HRESULT hres; ++ + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented %p\n", This); +- return E_NOTIMPL; ++ TRACE("%p\n", This); ++ if (!pFont) ++ return E_INVALIDARG; ++ hres = range_GetFont(This->reOle, &txtFont); ++ if (!hres) ++ { ++ txtFont->txtSel = NULL; ++ txtFont->txtRge = This; ++ ITextRange_AddRef(me); ++ *pFont = &txtFont->ITextFont_iface; ++ } ++ return hres; + } + + static HRESULT WINAPI ITextRange_fnSetFont(ITextRange *me, ITextFont *pFont) +@@ -1742,11 +2529,24 @@ static HRESULT WINAPI ITextSelection_fnSetEnd(ITextSelection *me, LONG cpLim) + static HRESULT WINAPI ITextSelection_fnGetFont(ITextSelection *me, ITextFont **pFont) + { + ITextSelectionImpl *This = impl_from_ITextSelection(me); ++ ITextFontImpl *txtFont = NULL; ++ HRESULT hres; ++ + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented\n"); +- return E_NOTIMPL; ++ TRACE("%p\n", This); ++ if (!pFont) ++ return E_INVALIDARG; ++ hres = range_GetFont(This->reOle, &txtFont); ++ if (!hres) ++ { ++ txtFont->txtSel = This; ++ txtFont->txtRge = NULL; ++ ITextSelection_AddRef(me); ++ *pFont = &txtFont->ITextFont_iface; ++ } ++ return hres; + } + + static HRESULT WINAPI ITextSelection_fnSetFont(ITextSelection *me, ITextFont *pFont) +@@ -2423,6 +3223,33 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) + } + CreateEmptyITextRangeImpl(reo, 1); + CreateEmptyITextRangeImpl(reo, 0); ++ ++ reo->txtFonthead = heap_alloc(sizeof(ITextFontImpl)); ++ if (!reo->txtFonthead) ++ { ++ ITextSelection_Release(&reo->txtSel->ITextSelection_iface); ++ IOleClientSite_Release(&reo->clientSite->IOleClientSite_iface); ++ heap_free(reo->txtRgehead); ++ heap_free(reo->txtRgetail); ++ heap_free(reo); ++ return 0; ++ } ++ reo->txtFonttail = heap_alloc(sizeof(ITextFontImpl)); ++ if (!reo->txtFonttail) ++ { ++ ITextSelection_Release(&reo->txtSel->ITextSelection_iface); ++ IOleClientSite_Release(&reo->clientSite->IOleClientSite_iface); ++ heap_free(reo->txtRgehead); ++ heap_free(reo->txtRgetail); ++ heap_free(reo->txtFonthead); ++ heap_free(reo); ++ return 0; ++ } ++ reo->txtFonthead->next = reo->txtFonttail; ++ reo->txtFonthead->prev = NULL; ++ reo->txtFonttail->next = NULL; ++ reo->txtFonttail->prev = reo->txtFonthead; ++ + return 1; + } + +diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c +index 2916bc5..69d4453 100644 +--- a/dlls/riched20/tests/richole.c ++++ b/dlls/riched20/tests/richole.c +@@ -878,6 +878,97 @@ static void test_ITextSelection_SetEnd(void) + release_interfaces(&w, &reOle, &txtDoc, &txtSel); + } + ++static void test_ITextRange_GetFont(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextRange *txtRge = NULL; ++ ITextFont *txtFont = NULL, *txtFont1 = NULL; ++ HRESULT hres; ++ int first, lim; ++ int refcount; ++ static const CHAR test_text1[] = "TestSomeText"; ++ LONG value; ++ ++ create_interfaces(&w, &reOle, &txtDoc, NULL); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ ++ first = 4, lim = 4; ++ ITextDocument_Range(txtDoc, first, lim, &txtRge); ++ refcount = get_refcount((IUnknown *)txtRge); ++ ok(refcount == 1, "got wrong ref count: %d\n", refcount); ++ ++ hres = ITextRange_GetFont(txtRge, &txtFont); ++ ok(hres == S_OK, "ITextRange_GetFont\n"); ++ refcount = get_refcount((IUnknown *)txtFont); ++ ok(refcount == 1, "got wrong ref count: %d\n", refcount); ++ refcount = get_refcount((IUnknown *)txtRge); ++ ok(refcount == 2, "got wrong ref count: %d\n", refcount); ++ ++ hres = ITextRange_GetFont(txtRge, &txtFont1); ++ ok(hres == S_OK, "ITextRange_GetFont\n"); ++ ok(txtFont1 != txtFont, "A new pointer should be return\n"); ++ refcount = get_refcount((IUnknown *)txtFont1); ++ ok(refcount == 1, "got wrong ref count: %d\n", refcount); ++ ITextFont_Release(txtFont1); ++ refcount = get_refcount((IUnknown *)txtRge); ++ ok(refcount == 2, "got wrong ref count: %d\n", refcount); ++ ++ ITextRange_Release(txtRge); ++ release_interfaces(&w, &reOle, &txtDoc, NULL); ++ ++ hres = ITextFont_GetOutline(txtFont, &value); ++ ok(hres == CO_E_RELEASED, "ITextFont after ITextDocument destroyed\n"); ++ ++ ITextFont_Release(txtFont); ++} ++ ++static void test_ITextSelection_GetFont(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextSelection *txtSel = NULL; ++ ITextFont *txtFont = NULL, *txtFont1 = NULL; ++ HRESULT hres; ++ int first, lim; ++ int refcount; ++ static const CHAR test_text1[] = "TestSomeText"; ++ LONG value; ++ ++ create_interfaces(&w, &reOle, &txtDoc, &txtSel); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ ++ first = 4, lim = 4; ++ SendMessageA(w, EM_SETSEL, first, lim); ++ refcount = get_refcount((IUnknown *)txtSel); ++ ok(refcount == 2, "got wrong ref count: %d\n", refcount); ++ ++ hres = ITextSelection_GetFont(txtSel, &txtFont); ++ ok(hres == S_OK, "ITextSelection_GetFont\n"); ++ refcount = get_refcount((IUnknown *)txtFont); ++ ok(refcount == 1, "got wrong ref count: %d\n", refcount); ++ refcount = get_refcount((IUnknown *)txtSel); ++ ok(refcount == 3, "got wrong ref count: %d\n", refcount); ++ ++ hres = ITextSelection_GetFont(txtSel, &txtFont1); ++ ok(hres == S_OK, "ITextSelection_GetFont\n"); ++ ok(txtFont1 != txtFont, "A new pointer should be return\n"); ++ refcount = get_refcount((IUnknown *)txtFont1); ++ ok(refcount == 1, "got wrong ref count: %d\n", refcount); ++ ITextFont_Release(txtFont1); ++ refcount = get_refcount((IUnknown *)txtSel); ++ ok(refcount == 3, "got wrong ref count: %d\n", refcount); ++ ++ release_interfaces(&w, &reOle, &txtDoc, &txtSel); ++ ++ hres = ITextFont_GetOutline(txtFont, &value); ++ ok(hres == CO_E_RELEASED, "ITextFont after ITextDocument destroyed\n"); ++ ++ ITextFont_Release(txtFont); ++} ++ + START_TEST(richole) + { + /* Must explicitly LoadLibrary(). The test has no references to functions in +@@ -892,6 +983,7 @@ START_TEST(richole) + test_ITextSelection_SetStart(); + test_ITextSelection_SetEnd(); + test_ITextSelection_Collapse(); ++ test_ITextSelection_GetFont(); + test_ITextDocument_Range(); + test_ITextRange_GetChar(); + test_ITextRange_GetDuplicate(); +@@ -899,4 +991,5 @@ START_TEST(richole) + test_ITextRange_Collapse(); + test_ITextRange_SetStart(); + test_ITextRange_SetEnd(); ++ test_ITextRange_GetFont(); + } +-- +1.7.9.5 + diff --git a/patches/riched20-IText_Interface/0008-riched20-Stub-for-ITextPara-interface-and-implement-.patch b/patches/riched20-IText_Interface/0008-riched20-Stub-for-ITextPara-interface-and-implement-.patch new file mode 100644 index 00000000..b3a2ebd4 --- /dev/null +++ b/patches/riched20-IText_Interface/0008-riched20-Stub-for-ITextPara-interface-and-implement-.patch @@ -0,0 +1,869 @@ +From dd0e81dcc531aff95bde3c121c6f108a32f8374c Mon Sep 17 00:00:00 2001 +From: Jactry Zeng +Date: Fri, 8 Aug 2014 23:41:22 +0800 +Subject: riched20: Stub for ITextPara interface and implement + ITextRange::GetPara. + +--- + dlls/riched20/richole.c | 721 ++++++++++++++++++++++++++++++++++++++++- + dlls/riched20/tests/richole.c | 47 +++ + 2 files changed, 766 insertions(+), 2 deletions(-) + +diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c +index c1569b0..0a80b8f 100644 +--- a/dlls/riched20/richole.c ++++ b/dlls/riched20/richole.c +@@ -47,11 +47,13 @@ DEFINE_GUID(IID_ITextDocument, 0x8cc497c0, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xa + DEFINE_GUID(IID_ITextRange, 0x8cc497c2, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); + DEFINE_GUID(IID_ITextSelection, 0x8cc497c1, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); + DEFINE_GUID(IID_ITextFont, 0x8cc497c3, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); ++DEFINE_GUID(IID_ITextPara, 0x8cc497c4, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); + + typedef struct ITextSelectionImpl ITextSelectionImpl; + typedef struct IOleClientSiteImpl IOleClientSiteImpl; + typedef struct ITextRangeImpl ITextRangeImpl; + typedef struct ITextFontImpl ITextFontImpl; ++typedef struct ITextParaImpl ITextParaImpl; + + typedef struct IRichEditOleImpl { + IRichEditOle IRichEditOle_iface; +@@ -63,6 +65,7 @@ typedef struct IRichEditOleImpl { + IOleClientSiteImpl *clientSite; + ITextRangeImpl *txtRgehead, *txtRgetail; + ITextFontImpl *txtFonthead, *txtFonttail; ++ ITextParaImpl *txtParahead, *txtParatail; + } IRichEditOleImpl; + + struct ITextRangeImpl { +@@ -74,6 +77,16 @@ struct ITextRangeImpl { + IRichEditOleImpl *reOle; + }; + ++struct ITextParaImpl { ++ ITextPara ITextPara_iface; ++ LONG ref; ++ ITextParaImpl *prev, *next; ++ ++ IRichEditOleImpl *reOle; ++ ITextRangeImpl *txtRge; ++ ITextSelectionImpl *txtSel; ++}; ++ + struct ITextFontImpl { + ITextFont ITextFont_iface; + LONG ref; +@@ -154,6 +167,7 @@ IRichEditOle_fnRelease(IRichEditOle *me) + { + ITextRangeImpl *txtRgeImpl = This->txtRgehead->next; + ITextFontImpl *txtFontImpl = This->txtFonthead->next; ++ ITextParaImpl *txtParaImpl = This->txtParahead->next; + TRACE ("Destroying %p\n", This); + This->txtSel->reOle = NULL; + ITextSelection_Release(&This->txtSel->ITextSelection_iface); +@@ -172,6 +186,13 @@ IRichEditOle_fnRelease(IRichEditOle *me) + } + heap_free(This->txtFonthead); + heap_free(This->txtFonttail); ++ while (txtParaImpl) ++ { ++ txtParaImpl->reOle = NULL; ++ txtParaImpl = txtParaImpl->next; ++ } ++ heap_free(This->txtParahead); ++ heap_free(This->txtParatail); + heap_free(This); + } + return ref; +@@ -483,6 +504,642 @@ static const IRichEditOleVtbl revt = { + IRichEditOle_fnImportDataObject + }; + ++/* ITextPara interface */ ++static inline ITextParaImpl *impl_from_ITextPara(ITextPara *iface) ++{ ++ return CONTAINING_RECORD(iface, ITextParaImpl, ITextPara_iface); ++} ++ ++static HRESULT WINAPI ITextPara_fnQueryInterface(ITextPara *me, REFIID riid, void **ppvObj) ++{ ++ *ppvObj = NULL; ++ if (IsEqualGUID(riid, &IID_IUnknown) ++ || IsEqualGUID(riid, &IID_ITextPara) ++ || IsEqualGUID(riid, &IID_IDispatch)) ++ { ++ *ppvObj = me; ++ ITextPara_AddRef(me); ++ return S_OK; ++ } ++ ++ return E_NOINTERFACE; ++} ++ ++static ULONG WINAPI ITextPara_fnAddRef(ITextPara *me) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ return InterlockedIncrement(&This->ref); ++} ++ ++static ULONG WINAPI ITextPara_fnRelease(ITextPara *me) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ ULONG ref = InterlockedDecrement(&This->ref); ++ ++ TRACE ("%p ref=%u\n", This, ref); ++ if (ref == 0) ++ { ++ if (!This->txtSel) ++ ITextRange_Release(&This->txtRge->ITextRange_iface); ++ else ++ ITextSelection_Release(&This->txtSel->ITextSelection_iface); ++ This->reOle = NULL; ++ This->txtRge = NULL; ++ This->txtSel = NULL; ++ This->prev->next = This->next; ++ This->next->prev = This->prev; ++ heap_free(This); ++ } ++ return ref; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetTypeInfoCount(ITextPara *me, UINT *pctinfo) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetTypeInfo(ITextPara *me, UINT iTInfo, LCID lcid, ++ ITypeInfo **ppTInfo) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetIDsOfNames(ITextPara *me, REFIID riid, ++ LPOLESTR *rgszNames, UINT cNames, ++ LCID lcid, DISPID *rgDispId) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnInvoke(ITextPara *me, DISPID dispIdMember, REFIID riid, ++ LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, ++ VARIANT *pVarResult, EXCEPINFO *pExcepInfo, ++ UINT *puArgErr) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented\n"); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetDuplicate(ITextPara *me, ITextPara **ppPara) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetDuplicate(ITextPara *me, ITextPara *pPara) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnCanChange(ITextPara *me, LONG *pB) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnIsEqual(ITextPara *me, ITextPara *pPara, LONG *pB) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnReset(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetStyle(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetStyle(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetAlignment(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetAlignment(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetHyphenation(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetHyphenation(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetFirstLineIndent(ITextPara *me, float *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetKeepTogether(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetKeepTogether(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetKeepWithNext(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetKeepWithNext(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetLeftIndent(ITextPara *me, float *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetLineSpacing(ITextPara *me, float *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetLineSpacingRule(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetListAlignment(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetListAlignment(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetListLevelIndex(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetListLevelIndex(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetListStart(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetListStart(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetListTab(ITextPara *me, float *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetListTab(ITextPara *me, float Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetListType(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetListType(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetNoLineNumber(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetNoLineNumber(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetPageBreakBefore(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetPageBreakBefore(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetRightIndent(ITextPara *me, float *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetRightIndent(ITextPara *me, float Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetIndents(ITextPara *me, float StartIndent, float LeftIndent, ++ float RightIndent) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetLineSpacing(ITextPara *me, LONG LineSpacingRule, float LineSpacing) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetSpaceAfter(ITextPara *me, float *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetSpaceAfter(ITextPara *me, float Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetSpaceBefore(ITextPara *me, float *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetSpaceBefore(ITextPara *me, float Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetWindowControl(ITextPara *me, LONG *pValue) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnSetWindowControl(ITextPara *me, LONG Value) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetTabCount(ITextPara *me, LONG *pCount) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnAddTab(ITextPara *me, float tbPos, LONG tbAlign, LONG tbLeader) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnClearAllTabs(ITextPara *me) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnDeleteTab(ITextPara *me, float tbPos) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static HRESULT WINAPI ITextPara_fnGetTab(ITextPara *me, LONG iTab, float *ptbPos, ++ LONG *ptbAlign, LONG *ptbLeader) ++{ ++ ITextParaImpl *This = impl_from_ITextPara(me); ++ if (!This->reOle) ++ return CO_E_RELEASED; ++ ++ FIXME("not implemented: %p\n", This); ++ return E_NOTIMPL; ++} ++ ++static const ITextParaVtbl tpvt = { ++ ITextPara_fnQueryInterface, ++ ITextPara_fnAddRef, ++ ITextPara_fnRelease, ++ ITextPara_fnGetTypeInfoCount, ++ ITextPara_fnGetTypeInfo, ++ ITextPara_fnGetIDsOfNames, ++ ITextPara_fnInvoke, ++ ITextPara_fnGetDuplicate, ++ ITextPara_fnSetDuplicate, ++ ITextPara_fnCanChange, ++ ITextPara_fnIsEqual, ++ ITextPara_fnReset, ++ ITextPara_fnGetStyle, ++ ITextPara_fnSetStyle, ++ ITextPara_fnGetAlignment, ++ ITextPara_fnSetAlignment, ++ ITextPara_fnGetHyphenation, ++ ITextPara_fnSetHyphenation, ++ ITextPara_fnGetFirstLineIndent, ++ ITextPara_fnGetKeepTogether, ++ ITextPara_fnSetKeepTogether, ++ ITextPara_fnGetKeepWithNext, ++ ITextPara_fnSetKeepWithNext, ++ ITextPara_fnGetLeftIndent, ++ ITextPara_fnGetLineSpacing, ++ ITextPara_fnGetLineSpacingRule, ++ ITextPara_fnGetListAlignment, ++ ITextPara_fnSetListAlignment, ++ ITextPara_fnGetListLevelIndex, ++ ITextPara_fnSetListLevelIndex, ++ ITextPara_fnGetListStart, ++ ITextPara_fnSetListStart, ++ ITextPara_fnGetListTab, ++ ITextPara_fnSetListTab, ++ ITextPara_fnGetListType, ++ ITextPara_fnSetListType, ++ ITextPara_fnGetNoLineNumber, ++ ITextPara_fnSetNoLineNumber, ++ ITextPara_fnGetPageBreakBefore, ++ ITextPara_fnSetPageBreakBefore, ++ ITextPara_fnGetRightIndent, ++ ITextPara_fnSetRightIndent, ++ ITextPara_fnSetIndents, ++ ITextPara_fnSetLineSpacing, ++ ITextPara_fnGetSpaceAfter, ++ ITextPara_fnSetSpaceAfter, ++ ITextPara_fnGetSpaceBefore, ++ ITextPara_fnSetSpaceBefore, ++ ITextPara_fnGetWindowControl, ++ ITextPara_fnSetWindowControl, ++ ITextPara_fnGetTabCount, ++ ITextPara_fnAddTab, ++ ITextPara_fnClearAllTabs, ++ ITextPara_fnDeleteTab, ++ ITextPara_fnGetTab ++}; ++/* ITextPara interface */ ++ + /* ITextFont interface */ + static inline ITextFontImpl *impl_from_ITextFont(ITextFont *iface) + { +@@ -1531,14 +2188,45 @@ static HRESULT WINAPI ITextRange_fnSetFont(ITextRange *me, ITextFont *pFont) + return E_NOTIMPL; + } + ++static HRESULT range_GetPara(IRichEditOleImpl *reOle, ITextParaImpl **ptxtPara) ++{ ++ ITextParaImpl *txtPara = NULL; ++ txtPara = heap_alloc(sizeof(ITextParaImpl)); ++ if (!txtPara) ++ return E_OUTOFMEMORY; ++ ++ txtPara->ITextPara_iface.lpVtbl = &tpvt; ++ txtPara->ref = 1; ++ txtPara->reOle = reOle; ++ txtPara->next = reOle->txtParahead->next; ++ reOle->txtParahead->next->prev = txtPara; ++ reOle->txtParahead->next = txtPara; ++ txtPara->prev = reOle->txtParahead; ++ *ptxtPara = txtPara; ++ return S_OK; ++} ++ + static HRESULT WINAPI ITextRange_fnGetPara(ITextRange *me, ITextPara **ppPara) + { + ITextRangeImpl *This = impl_from_ITextRange(me); ++ ITextParaImpl *txtPara = NULL; ++ HRESULT hres; ++ + if (!This->reOle) + return CO_E_RELEASED; + +- FIXME("not implemented %p\n", This); +- return E_NOTIMPL; ++ TRACE("%p\n", This); ++ if (!ppPara) ++ return E_INVALIDARG; ++ hres = range_GetPara(This->reOle, &txtPara); ++ if (!hres) ++ { ++ txtPara->txtSel = NULL; ++ txtPara->txtRge = This; ++ ITextRange_AddRef(me); ++ *ppPara = &txtPara->ITextPara_iface; ++ } ++ return hres; + } + + static HRESULT WINAPI ITextRange_fnSetPara(ITextRange *me, ITextPara *pPara) +@@ -3249,6 +3937,35 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) + reo->txtFonthead->prev = NULL; + reo->txtFonttail->next = NULL; + reo->txtFonttail->prev = reo->txtFonthead; ++ reo->txtParahead = heap_alloc(sizeof(ITextParaImpl)); ++ if (!reo->txtParahead) ++ { ++ ITextSelection_Release(&reo->txtSel->ITextSelection_iface); ++ IOleClientSite_Release(&reo->clientSite->IOleClientSite_iface); ++ heap_free(reo->txtRgehead); ++ heap_free(reo->txtRgetail); ++ heap_free(reo->txtFonthead); ++ heap_free(reo->txtFonttail); ++ heap_free(reo); ++ return 0; ++ } ++ reo->txtParatail = heap_alloc(sizeof(ITextParaImpl)); ++ if (!reo->txtParatail) ++ { ++ ITextSelection_Release(&reo->txtSel->ITextSelection_iface); ++ IOleClientSite_Release(&reo->clientSite->IOleClientSite_iface); ++ heap_free(reo->txtRgehead); ++ heap_free(reo->txtRgetail); ++ heap_free(reo->txtFonthead); ++ heap_free(reo->txtFonttail); ++ heap_free(reo->txtParahead); ++ heap_free(reo); ++ return 0; ++ } ++ reo->txtParahead->next = reo->txtParatail; ++ reo->txtParahead->prev = NULL; ++ reo->txtParatail->next = NULL; ++ reo->txtParatail->prev = reo->txtParahead; + + return 1; + } +diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c +index 69d4453..6c65798 100644 +--- a/dlls/riched20/tests/richole.c ++++ b/dlls/riched20/tests/richole.c +@@ -969,6 +969,52 @@ static void test_ITextSelection_GetFont(void) + ITextFont_Release(txtFont); + } + ++static void test_ITextRange_GetPara(void) ++{ ++ HWND w; ++ IRichEditOle *reOle = NULL; ++ ITextDocument *txtDoc = NULL; ++ ITextRange *txtRge = NULL; ++ ITextPara *txtPara = NULL, *txtPara1 = NULL; ++ HRESULT hres; ++ int first, lim; ++ int refcount; ++ static const CHAR test_text1[] = "TestSomeText"; ++ LONG value; ++ ++ create_interfaces(&w, &reOle, &txtDoc, NULL); ++ SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); ++ ++ first = 4, lim = 4; ++ ITextDocument_Range(txtDoc, first, lim, &txtRge); ++ refcount = get_refcount((IUnknown *)txtRge); ++ ok(refcount == 1, "got wrong ref count: %d\n", refcount); ++ ++ hres = ITextRange_GetPara(txtRge, &txtPara); ++ ok(hres == S_OK, "ITextRange_GetPara\n"); ++ refcount = get_refcount((IUnknown *)txtPara); ++ ok(refcount == 1, "got wrong ref count: %d\n", refcount); ++ refcount = get_refcount((IUnknown *)txtRge); ++ ok(refcount == 2, "got wrong ref count: %d\n", refcount); ++ ++ hres = ITextRange_GetPara(txtRge, &txtPara1); ++ ok(hres == S_OK, "ITextRange_GetPara\n"); ++ ok(txtPara1 != txtPara, "A new pointer should be return\n"); ++ refcount = get_refcount((IUnknown *)txtPara1); ++ ok(refcount == 1, "got wrong ref count: %d\n", refcount); ++ ITextPara_Release(txtPara1); ++ refcount = get_refcount((IUnknown *)txtRge); ++ ok(refcount == 2, "got wrong ref count: %d\n", refcount); ++ ++ ITextRange_Release(txtRge); ++ release_interfaces(&w, &reOle, &txtDoc, NULL); ++ ++ hres = ITextPara_GetStyle(txtPara, &value); ++ ok(hres == CO_E_RELEASED, "ITextPara after ITextDocument destroyed\n"); ++ ++ ITextPara_Release(txtPara); ++} ++ + START_TEST(richole) + { + /* Must explicitly LoadLibrary(). The test has no references to functions in +@@ -992,4 +1038,5 @@ START_TEST(richole) + test_ITextRange_SetStart(); + test_ITextRange_SetEnd(); + test_ITextRange_GetFont(); ++ test_ITextRange_GetPara(); + } +-- +1.7.9.5 + diff --git a/patches/riched20-IText_Interface/definition b/patches/riched20-IText_Interface/definition new file mode 100644 index 00000000..fdcd074b --- /dev/null +++ b/patches/riched20-IText_Interface/definition @@ -0,0 +1,18 @@ +Author: Jactry Zeng +Subject: Implement Stubs for ITextRange interface. +Revision: 1 + +Author: Jactry Zeng +Subject: Implement IText{Range,Selection}::{GetChar,GetStart,GetEnd,GetDuplicate,Collapse,SetStart,SetEnd}. +Revision: 1 + +Author: Jactry Zeng +Subject: Implement Stubs for ITextFont interface. +Revision: 1 + +Author: Jactry Zeng +Subject: Implement Stubs for ITextPara interface. +Revision: 1 + +Fixes: [12458] Implement ITextDocument_fnRange function +Fixes: [18303] Support for ITextRange, ITextFont and ITextPara