From ac8cabefac07d17d2fdf33b26444b74e5c910abf Mon Sep 17 00:00:00 2001
From: Jactry Zeng <wine@jactry.com>
Date: Wed, 13 Aug 2014 17:17:14 +0800
Subject: riched20: Implement ITextRange::SetRange.

---
 dlls/riched20/richole.c       | 41 +++++++++++++++++++++++++----------------
 dlls/riched20/tests/richole.c | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 16 deletions(-)

diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index 76f70a6..71fdf29 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -2016,6 +2016,23 @@ static HRESULT WINAPI ITextRange_fnSetIndex(ITextRange *me, LONG unit, LONG inde
     return E_NOTIMPL;
 }
 
+static void cp2range(ME_TextEditor *editor, LONG *cp1, LONG *cp2)
+{
+    int len = ME_GetTextLength(editor) + 1;
+    *cp1 = max(*cp1, 0);
+    *cp2 = max(*cp2, 0);
+    *cp1 = min(*cp1, len);
+    *cp2 = min(*cp2, len);
+    if (*cp1 > *cp2)
+    {
+        int tmp = *cp1;
+        *cp1 = *cp2;
+        *cp2 = tmp;
+    }
+    if (*cp1 == len)
+        *cp1 = *cp2 = len - 1;
+}
+
 static HRESULT WINAPI ITextRange_fnSetRange(ITextRange *me, LONG anchor, LONG active)
 {
     ITextRangeImpl *This = impl_from_ITextRange(me);
@@ -2025,7 +2042,13 @@ static HRESULT WINAPI ITextRange_fnSetRange(ITextRange *me, LONG anchor, LONG ac
     if (!This->child.reole)
         return CO_E_RELEASED;
 
-    return E_NOTIMPL;
+    cp2range(This->child.reole->editor, &anchor, &active);
+    if (anchor == This->start && active == This->end)
+        return S_FALSE;
+
+    This->start = anchor;
+    This->end = active;
+    return S_OK;
 }
 
 static HRESULT textrange_inrange(LONG start, LONG end, ITextRange *range, LONG *ret)
@@ -4317,26 +4340,12 @@ static HRESULT WINAPI ITextDocument2Old_fnRange(ITextDocument2Old *iface, LONG c
                                                 ITextRange **ppRange)
 {
     IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
-    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;
-
+    cp2range(This->editor, &cp1, &cp2);
     return CreateITextRange(This, cp1, cp2, ppRange);
 }
 
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index dfc6799..c98b536 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -4009,6 +4009,40 @@ static void test_ITextRange_GetText(void)
   TEST_TXTRGE_GETTEXT(1, 1, NULL)
 }
 
+static void test_ITextRange_SetRange(void)
+{
+  HWND w;
+  IRichEditOle *reOle = NULL;
+  ITextDocument *txtDoc = NULL;
+  ITextRange *txtRge = NULL;
+  HRESULT hres;
+  int start, end;
+  static const CHAR test_text1[] = "TestSomeText";
+
+  create_interfaces(&w, &reOle, &txtDoc, NULL);
+  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
+  ITextDocument_Range(txtDoc, 0, 0, &txtRge);
+
+#define TEST_TXTRGE_SETRANGE(first, lim, expected_start, expected_end, expected_return) \
+  hres = ITextRange_SetRange(txtRge, first, lim);                       \
+  ok(hres == expected_return, "ITextRange_SetRange\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_SETRANGE(2, 4, 2, 4, S_OK)
+  TEST_TXTRGE_SETRANGE(2, 4, 2, 4, S_FALSE)
+  TEST_TXTRGE_SETRANGE(4, 2, 2, 4, S_FALSE)
+  TEST_TXTRGE_SETRANGE(14, 14, 12, 12, S_OK)
+  TEST_TXTRGE_SETRANGE(15, 15, 12, 12, S_FALSE)
+  TEST_TXTRGE_SETRANGE(14, 1, 1, 13, S_OK)
+  TEST_TXTRGE_SETRANGE(-1, 4, 0, 4, S_OK)
+
+  ITextRange_Release(txtRge);
+  release_interfaces(&w, &reOle, &txtDoc, NULL);
+}
+
 START_TEST(richole)
 {
   /* Must explicitly LoadLibrary(). The test has no references to functions in
@@ -4036,6 +4070,7 @@ START_TEST(richole)
   test_ITextRange_GetFont();
   test_ITextRange_GetPara();
   test_ITextRange_GetText();
+  test_ITextRange_SetRange();
   test_GetClientSite();
   test_IOleWindow_GetWindow();
   test_IOleInPlaceSite_GetWindow();
-- 
2.7.4

