From d27234617cbcf1bc0f9ecefe7087fb928b1ecb33 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Wed, 27 May 2015 00:45:25 +0300 Subject: [PATCH] riched20: Implement SetText for regular range. --- dlls/riched20/richole.c | 73 +++++++++++++++++++++++++++-- dlls/riched20/tests/richole.c | 87 +++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 3 deletions(-) diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c index a34c21022a0..06ff9aadf56 100644 --- a/dlls/riched20/richole.c +++ b/dlls/riched20/richole.c @@ -201,6 +201,10 @@ typedef union { BSTR str; } textfont_prop_val; +enum range_update_op { + RANGE_UPDATE_DELETE +}; + typedef struct IRichEditOleImpl { IUnknown IUnknown_inner; IRichEditOle IRichEditOle_iface; @@ -304,6 +308,35 @@ static inline ITextParaImpl *impl_from_ITextPara(ITextPara *iface) static HRESULT create_textfont(ITextRange*, const ITextFontImpl*, ITextFont**); static HRESULT create_textpara(ITextRange*, ITextPara**); +static void textranges_update_ranges(IRichEditOleImpl *reole, LONG start, LONG end, enum range_update_op op) +{ + ITextRangeImpl *range; + + LIST_FOR_EACH_ENTRY(range, &reole->rangelist, ITextRangeImpl, entry) { + switch (op) + { + case RANGE_UPDATE_DELETE: + /* range fully covered by deleted range - collapse to insertion point */ + if (range->start >= start && range->end <= end) + range->start = range->end = start; + /* deleted range cuts from the right */ + else if (range->start < start && range->end <= end) + range->end = start; + /* deleted range cuts from the left */ + else if (range->start >= start && range->end > end) { + range->start = start; + range->end -= end - start; + } + /* deleted range cuts within */ + else + range->end -= end - start; + break; + default: + FIXME("unknown update op, %d\n", op); + } + } +} + static inline BOOL is_equal_textfont_prop_value(enum textfont_prop_id propid, textfont_prop_val *left, textfont_prop_val *right) { @@ -1376,14 +1409,48 @@ static HRESULT WINAPI ITextRange_fnGetText(ITextRange *me, BSTR *pbstr) return E_NOTIMPL; } -static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR bstr) +static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR str) { ITextRangeImpl *This = impl_from_ITextRange(me); + ME_TextEditor *editor; + ME_Cursor cursor; + ME_Style *style; + int len; + + TRACE("(%p)->(%s)\n", This, debugstr_w(str)); + if (!This->reOle) return CO_E_RELEASED; - FIXME("not implemented %p\n", This); - return E_NOTIMPL; + editor = This->reOle->editor; + + /* delete only where's something to delete */ + if (This->start != This->end) { + ME_CursorFromCharOfs(editor, This->start, &cursor); + ME_InternalDeleteText(editor, &cursor, This->end - This->start, FALSE); + } + + if (!str || !*str) { + /* will update this range as well */ + textranges_update_ranges(This->reOle, This->start, This->end, RANGE_UPDATE_DELETE); + return S_OK; + } + + /* it's safer not to rely on stored BSTR length */ + len = strlenW(str); + cursor = editor->pCursors[0]; + ME_CursorFromCharOfs(editor, This->start, &editor->pCursors[0]); + style = ME_GetInsertStyle(editor, 0); + ME_InsertTextFromCursor(editor, 0, str, len, style); + ME_ReleaseStyle(style); + editor->pCursors[0] = cursor; + + if (len < This->end - This->start) + textranges_update_ranges(This->reOle, This->start + len, This->end, RANGE_UPDATE_DELETE); + else + This->end = len - This->start; + + return S_OK; } static HRESULT range_GetChar(ME_TextEditor *editor, ME_Cursor *cursor, LONG *pch) diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c index adb96c33166..7d90a983c4a 100644 --- a/dlls/riched20/tests/richole.c +++ b/dlls/riched20/tests/richole.c @@ -2401,6 +2401,92 @@ todo_wine release_interfaces(&hwnd, &reOle, &doc, NULL); } +static void test_SetText(void) +{ + static const CHAR test_text1[] = "TestSomeText"; + static const WCHAR textW[] = {'a','b','c','d','e','f','g','h','i',0}; + IRichEditOle *reOle = NULL; + ITextDocument *doc = NULL; + ITextRange *range, *range2; + LONG value; + HRESULT hr; + HWND hwnd; + BSTR str; + + create_interfaces(&hwnd, &reOle, &doc, NULL); + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1); + + hr = ITextDocument_Range(doc, 0, 4, &range); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = ITextDocument_Range(doc, 0, 4, &range2); + ok(hr == S_OK, "got 0x%08x\n", hr); + + value = 1; + hr = ITextRange_GetStart(range2, &value); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(value == 0, "got %d\n", value); + + value = 0; + hr = ITextRange_GetEnd(range2, &value); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(value == 4, "got %d\n", value); + + hr = ITextRange_SetText(range, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + value = 1; + hr = ITextRange_GetEnd(range2, &value); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(value == 0, "got %d\n", value); + + str = SysAllocString(textW); + hr = ITextRange_SetText(range, str); + ok(hr == S_OK, "got 0x%08x\n", hr); + + value = 1; + hr = ITextRange_GetStart(range, &value); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(value == 0, "got %d\n", value); + + value = 0; + hr = ITextRange_GetEnd(range, &value); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(value == 9, "got %d\n", value); + + value = 1; + hr = ITextRange_GetStart(range2, &value); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(value == 0, "got %d\n", value); + + value = 0; + hr = ITextRange_GetEnd(range2, &value); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(value == 0, "got %d\n", value); + + str = SysAllocStringLen(NULL, 0); + hr = ITextRange_SetText(range, str); + ok(hr == S_OK, "got 0x%08x\n", hr); + value = 1; + hr = ITextRange_GetEnd(range, &value); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(value == 0, "got %d\n", value); + SysFreeString(str); + + ITextRange_Release(range2); + release_interfaces(&hwnd, &reOle, &doc, NULL); + + hr = ITextRange_SetText(range, NULL); + ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr); + + str = SysAllocStringLen(NULL, 0); + hr = ITextRange_SetText(range, str); + ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr); + SysFreeString(str); + + ITextRange_Release(range); +} + START_TEST(richole) { /* Must explicitly LoadLibrary(). The test has no references to functions in @@ -2427,4 +2513,5 @@ START_TEST(richole) test_dispatch(); test_ITextFont(); test_Delete(); + test_SetText(); }