Nikolay Sivov : riched20: Implement SetText for regular range.

Alexandre Julliard julliard at wine.codeweavers.com
Wed May 27 09:30:58 CDT 2015


Module: wine
Branch: master
Commit: d27234617cbcf1bc0f9ecefe7087fb928b1ecb33
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d27234617cbcf1bc0f9ecefe7087fb928b1ecb33

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed May 27 00:45:25 2015 +0300

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 a34c210..06ff9aa 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 adb96c3..7d90a98 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();
 }




More information about the wine-cvs mailing list