[PATCH v2 3/3] riched20: implement ITextRange::StartOf() and ITextRange::EndOf() for tomCharacter

Damjan Jovanovic damjan.jov at gmail.com
Tue Aug 18 22:19:52 CDT 2020


Signed-off-by: Damjan Jovanovic <damjan.jov at gmail.com>
---
 dlls/riched20/richole.c       | 100 +++++++++++++++++++++++++++++++---
 dlls/riched20/tests/richole.c |  64 ++++++++++++++++++++++
 2 files changed, 156 insertions(+), 8 deletions(-)
-------------- next part --------------
diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index c7a84b6e78..47d8442d5c 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -2153,17 +2153,91 @@ static HRESULT WINAPI ITextRange_fnSelect(ITextRange *me)
     return S_OK;
 }
 
+static HRESULT textrange_startof(ITextRange *range, LONG unit, LONG extend, LONG *delta)
+{
+    HRESULT hr;
+    LONG start, end;
+    LONG moved;
+
+    ITextRange_GetStart(range, &start);
+    ITextRange_GetEnd(range, &end);
+
+    switch (unit)
+    {
+    case tomCharacter:
+    {
+        moved = 0;
+        if (extend == tomMove) {
+            if (start != end) {
+                ITextRange_SetEnd(range, start);
+                moved = -1;
+            }
+        }
+        if (delta)
+            *delta = moved;
+        hr = moved ? S_OK : S_FALSE;
+        break;
+    }
+    default:
+        FIXME("unit %d is not supported\n", unit);
+        return E_NOTIMPL;
+    }
+    return hr;
+}
+
 static HRESULT WINAPI ITextRange_fnStartOf(ITextRange *me, LONG unit, LONG extend,
                                            LONG *delta)
 {
     ITextRangeImpl *This = impl_from_ITextRange(me);
 
-    FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
+    TRACE("(%p)->(%d %d %p)\n", This, unit, extend, delta);
 
     if (!This->child.reole)
         return CO_E_RELEASED;
 
-    return E_NOTIMPL;
+    return textrange_startof(me, unit, extend, delta);
+}
+
+static HRESULT textrange_endof(ITextRange *range, ME_TextEditor *editor, LONG unit, LONG extend, LONG *delta)
+{
+    HRESULT hr;
+    LONG old_start, old_end, new_end;
+    LONG moved;
+
+    ITextRange_GetStart(range, &old_start);
+    ITextRange_GetEnd(range, &old_end);
+
+    switch (unit)
+    {
+    case tomCharacter:
+    {
+        moved = 0;
+        new_end = old_end;
+        if (old_end == 0) {
+            ME_Cursor cursor;
+            ME_CursorFromCharOfs(editor, old_end, &cursor);
+            moved = ME_MoveCursorChars(editor, &cursor, 1, TRUE);
+            new_end = old_end + moved;
+        } else {
+            if (extend == tomMove) {
+                if (old_start != old_end) {
+                    moved = 1;
+                }
+            }
+        }
+        ITextRange_SetEnd(range, new_end);
+        if (extend == tomMove)
+            ITextRange_SetStart(range, new_end);
+        if (delta)
+            *delta = moved;
+        hr = moved ? S_OK : S_FALSE;
+        break;
+    }
+    default:
+        FIXME("unit %d is not supported\n", unit);
+        return E_NOTIMPL;
+    }
+    return hr;
 }
 
 static HRESULT WINAPI ITextRange_fnEndOf(ITextRange *me, LONG unit, LONG extend,
@@ -2171,12 +2245,12 @@ static HRESULT WINAPI ITextRange_fnEndOf(ITextRange *me, LONG unit, LONG extend,
 {
     ITextRangeImpl *This = impl_from_ITextRange(me);
 
-    FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
+    TRACE("(%p)->(%d %d %p)\n", This, unit, extend, delta);
 
     if (!This->child.reole)
         return CO_E_RELEASED;
 
-    return E_NOTIMPL;
+    return textrange_endof(me, This->child.reole->editor, unit, extend, delta);
 }
 
 static HRESULT textrange_move(ITextRange *range, ME_TextEditor *editor, LONG unit, LONG count, LONG *delta)
@@ -5064,26 +5138,36 @@ static HRESULT WINAPI ITextSelection_fnStartOf(ITextSelection *me, LONG unit, LO
     LONG *delta)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
+    ITextRange *range = NULL;
+    HRESULT hr;
 
-    FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
+    TRACE("(%p)->(%d %d %p)\n", This, unit, extend, delta);
 
     if (!This->reOle)
         return CO_E_RELEASED;
 
-    return E_NOTIMPL;
+    ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range);
+    hr = textrange_startof(range, unit, extend, delta);
+    ITextRange_Release(range);
+    return hr;
 }
 
 static HRESULT WINAPI ITextSelection_fnEndOf(ITextSelection *me, LONG unit, LONG extend,
     LONG *delta)
 {
     ITextSelectionImpl *This = impl_from_ITextSelection(me);
+    ITextRange *range = NULL;
+    HRESULT hr;
 
-    FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
+    TRACE("(%p)->(%d %d %p)\n", This, unit, extend, delta);
 
     if (!This->reOle)
         return CO_E_RELEASED;
 
-    return E_NOTIMPL;
+    ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range);
+    hr = textrange_endof(range, This->reOle->editor, unit, extend, delta);
+    ITextRange_Release(range);
+    return hr;
 }
 
 static HRESULT WINAPI ITextSelection_fnMove(ITextSelection *me, LONG unit, LONG count, LONG *delta)
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index 7fde2ca232..16ff1fafa6 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -3912,6 +3912,68 @@ static void test_character_move(ITextRange *range, int textlen, int i, int j, LO
     }
 }
 
+static void test_character_startof(ITextRange *range, int textlen, int i, int j)
+{
+    HRESULT hr;
+    LONG delta;
+
+    hr = ITextRange_SetRange(range, i, j);
+    ok(SUCCEEDED(hr), "got 0x%08x\n", hr);
+    hr = ITextRange_StartOf(range, tomCharacter, tomMove, &delta);
+    if (i == j) {
+        ok(hr == S_FALSE, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr);
+        ok(delta == 0, "(%d,%d) tomMove got delta %d\n", i, j, delta);
+    } else {
+        ok(hr == S_OK, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr);
+        ok(delta == -1, "(%d,%d) tomMove got delta %d\n", i, j, delta);
+    }
+    CHECK_RANGE(range, i, i);
+
+    hr = ITextRange_SetRange(range, i, j);
+    ok(SUCCEEDED(hr), "got 0x%08x\n", hr);
+    hr = ITextRange_StartOf(range, tomCharacter, tomExtend, &delta);
+    ok(hr == S_FALSE, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr);
+    ok(delta == 0, "(%d,%d) tomExtend got delta %d\n", i, j, delta);
+    CHECK_RANGE(range, i, j);
+}
+
+static void test_character_endof(ITextRange *range, int textlen, int i, int j)
+{
+    HRESULT hr;
+    LONG end;
+    LONG delta;
+
+    hr = ITextRange_SetRange(range, i, j);
+    ok(SUCCEEDED(hr), "got 0x%08x\n", hr);
+    hr = ITextRange_EndOf(range, tomCharacter, tomMove, &delta);
+
+    /* A character "end", apparently cannot be before the very first character */
+    end = j;
+    if (j == 0)
+        ++end;
+
+    if (i == end) {
+        ok(hr == S_FALSE, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr);
+        ok(delta == 0, "(%d,%d) tomMove got delta %d\n", i, j, delta);
+    } else {
+        ok(hr == S_OK, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr);
+        ok(delta == 1, "(%d,%d) tomMove got delta %d\n", i, j, delta);
+    }
+    CHECK_RANGE(range, end, end);
+
+    hr = ITextRange_SetRange(range, i, j);
+    ok(SUCCEEDED(hr), "got 0x%08x\n", hr);
+    hr = ITextRange_EndOf(range, tomCharacter, tomExtend, &delta);
+    if (0 < j) {
+        ok(hr == S_FALSE, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr);
+        ok(delta == 0, "(%d,%d) tomExtend got delta %d\n", i, j, delta);
+    } else {
+        ok(hr == S_OK, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr);
+        ok(delta == 1, "(%d,%d) tomExtend got delta %d\n", i, j, delta);
+    }
+    CHECK_RANGE(range, i, end);
+}
+
 static void test_character_movement(void)
 {
   static const char test_text1[] = "ab\n c";
@@ -3940,6 +4002,8 @@ static void test_character_movement(void)
               test_character_movestart(range, textlen, i, j, target);
               test_character_move(range, textlen, i, j, target);
           }
+          test_character_startof(range, textlen, i, j);
+          test_character_endof(range, textlen, i, j);
       }
   }
 


More information about the wine-devel mailing list