From: Jactry Zeng Subject: [PATCH 1/8] riched20: Stub for ITextRange interface and implement ITextDocument::Range. (try 4) Message-Id: <53E8620F.1050407@jactry.com> Date: Mon, 11 Aug 2014 14:26:23 +0800 Superseded patches 105917 - 105924. -- This series is for fixing Bug 18303: http://bugs.winehq.org/show_bug.cgi?id=18303 And also good for Bug 12458: http://bugs.winehq.org/show_bug.cgi?id=12458 -- ChangeLog: [PATCH 1/8] - Simplify with macros in include/wine/list.h - Using LONG instead of int in This->start and This->end - Limit cp1 to (0, TextLength) [PATCH 3/8] - Add tests for ITextDocument_Range/GetSelection(txtDoc, 13, 13, txtRge/Sel) [PATCH 7-8/8] - Simplify with macros in include/wine/list.h --- dlls/riched20/richole.c | 730 +++++++++++++++++++++++++++++++++++++++++- dlls/riched20/tests/richole.c | 35 +- 2 files changed, 762 insertions(+), 3 deletions(-) diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c index 487fcda..5e2ffd0 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; + struct list rangelist; } IRichEditOleImpl; +struct ITextRangeImpl { + ITextRange ITextRange_iface; + LONG ref; + LONG start, end; + struct list entry; + + IRichEditOleImpl *reOle; +}; + struct ITextSelectionImpl { ITextSelection ITextSelection_iface; LONG ref; @@ -128,10 +139,13 @@ IRichEditOle_fnRelease(IRichEditOle *me) if (!ref) { + ITextRangeImpl *txtRge; TRACE ("Destroying %p\n", This); This->txtSel->reOle = NULL; ITextSelection_Release(&This->txtSel->ITextSelection_iface); IOleClientSite_Release(&This->clientSite->IOleClientSite_iface); + LIST_FOR_EACH_ENTRY(txtRge, &This->rangelist, ITextRangeImpl, entry) + txtRge->reOle = NULL; heap_free(This); } return ref; @@ -443,6 +457,682 @@ 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; + list_remove(&This->entry); + 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); + if (!This->reOle) + return CO_E_RELEASED; + + 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) @@ -646,13 +1336,48 @@ ITextDocument_fnRedo(ITextDocument* me, LONG Count, LONG* prop) return E_NOTIMPL; } +static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, + ITextRangeImpl *txtRge, ITextRange** ppRange) +{ + txtRge->ITextRange_iface.lpVtbl = &trvt; + txtRge->ref = 1; + txtRge->reOle = reOle; + txtRge->start = start; + txtRge->end = end; + list_add_head(&reOle->rangelist, &txtRge->entry); + *ppRange = &txtRge->ITextRange_iface; + return S_OK; +} + static HRESULT WINAPI 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) + { + LONG tmp; + tmp = cp1; + cp1 = cp2; + cp2 = tmp; + } + if (cp1 == len) + cp1 = cp2 = len - 1; + txtRge = heap_alloc(sizeof(ITextRangeImpl)); + if (!txtRge) + return E_OUTOFMEMORY; + return CreateITextRange(This, cp1, cp2, txtRge, ppRange); } static HRESULT WINAPI @@ -1548,6 +2273,7 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) } TRACE("Created %p\n",reo); *ppObj = reo; + list_init(&reo->rangelist); return 1; } diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c index 571e5cd..f56a14a 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,37 @@ 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 +528,5 @@ START_TEST(richole) test_Interfaces(); test_ITextDocument_Open(); test_ITextSelection_GetText(); + test_ITextDocument_Range(); }