Jinoh Kang : riched20: Implement ITextDocument::Undo and ITextDocument::Redo.

Alexandre Julliard julliard at winehq.org
Thu Jul 14 16:59:25 CDT 2022


Module: wine
Branch: master
Commit: ded8227774570a1ea320dc34f2de0033f85b3ce7
URL:    https://gitlab.winehq.org/wine/wine/-/commit/ded8227774570a1ea320dc34f2de0033f85b3ce7

Author: Jinoh Kang <jinoh.kang.kr at gmail.com>
Date:   Tue Jun 28 00:30:06 2022 +0900

riched20: Implement ITextDocument::Undo and ITextDocument::Redo.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53289
Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>

---

 dlls/riched20/editor.c        |  1 +
 dlls/riched20/editor.h        |  2 ++
 dlls/riched20/richole.c       | 48 +++++++++++++++++++++++++++++++++++++++----
 dlls/riched20/tests/richole.c | 30 +++++----------------------
 dlls/riched20/undo.c          | 14 +++++++++++++
 5 files changed, 66 insertions(+), 29 deletions(-)

diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index a1e0395f24d..108c37a7f30 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -3299,6 +3299,7 @@ LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam,
   }
   case EM_SETUNDOLIMIT:
   {
+    editor_enable_undo(editor);
     if ((int)wParam < 0)
       editor->nUndoLimit = STACK_SIZE_DEFAULT;
     else
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index d10ff225335..072d0f62782 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -393,6 +393,8 @@ void ME_CommitCoalescingUndo(ME_TextEditor *editor) DECLSPEC_HIDDEN;
 BOOL ME_Undo(ME_TextEditor *editor) DECLSPEC_HIDDEN;
 BOOL ME_Redo(ME_TextEditor *editor) DECLSPEC_HIDDEN;
 void ME_EmptyUndoStack(ME_TextEditor *editor) DECLSPEC_HIDDEN;
+void editor_disable_undo(ME_TextEditor *editor);
+void editor_enable_undo(ME_TextEditor *editor);
 
 static inline BOOL editor_undo_ignored(ME_TextEditor *editor)
 {
diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index afecd34dc2a..8190a4e2753 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -4245,15 +4245,55 @@ static HRESULT WINAPI ITextDocument2Old_fnEndEditCollection(ITextDocument2Old *i
 static HRESULT WINAPI ITextDocument2Old_fnUndo(ITextDocument2Old *iface, LONG Count, LONG *prop)
 {
     struct text_services *services = impl_from_ITextDocument2Old(iface);
-    FIXME("stub %p\n", services);
-    return E_NOTIMPL;
+    LONG actual_undo_count;
+
+    if (prop) *prop = 0;
+
+    switch (Count)
+    {
+    case tomFalse:
+        editor_disable_undo(services->editor);
+        return S_OK;
+    default:
+        if (Count > 0) break;
+        /* fallthrough */
+    case tomTrue:
+        editor_enable_undo(services->editor);
+        return S_FALSE;
+    case tomSuspend:
+        if (services->editor->undo_ctl_state == undoActive)
+        {
+            services->editor->undo_ctl_state = undoSuspended;
+        }
+        return S_FALSE;
+    case tomResume:
+        services->editor->undo_ctl_state = undoActive;
+        return S_FALSE;
+    }
+
+    for (actual_undo_count = 0; actual_undo_count < Count; actual_undo_count++)
+    {
+        if (!ME_Undo(services->editor)) break;
+    }
+
+    if (prop) *prop = actual_undo_count;
+    return actual_undo_count == Count ? S_OK : S_FALSE;
 }
 
 static HRESULT WINAPI ITextDocument2Old_fnRedo(ITextDocument2Old *iface, LONG Count, LONG *prop)
 {
     struct text_services *services = impl_from_ITextDocument2Old(iface);
-    FIXME("stub %p\n", services);
-    return E_NOTIMPL;
+    LONG actual_redo_count;
+
+    if (prop) *prop = 0;
+
+    for (actual_redo_count = 0; actual_redo_count < Count; actual_redo_count++)
+    {
+        if (!ME_Redo(services->editor)) break;
+    }
+
+    if (prop) *prop = actual_redo_count;
+    return actual_redo_count == Count ? S_OK : S_FALSE;
 }
 
 static HRESULT CreateITextRange(struct text_services *services, LONG start, LONG end, ITextRange** ppRange)
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index a01f4e21db8..1ebc12a27ab 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -4940,8 +4940,8 @@ static void test_clipboard(void)
   ok(hr == S_OK, "Cut failed: 0x%08lx\n", hr);
   CLIPBOARD_RANGE_CONTAINS(range, 0, 4, "b\r\n c");
   hr = ITextDocument_Undo(doc, 1, NULL);
-  todo_wine ok(hr == S_OK, "Undo failed: 0x%08lx\n", hr);
-  TODO_CLIPBOARD_RANGE_CONTAINS(range, 0, 5, "ab\r\n c");
+  ok(hr == S_OK, "Undo failed: 0x%08lx\n", hr);
+  CLIPBOARD_RANGE_CONTAINS(range, 0, 5, "ab\r\n c");
 
   /* Cannot cut when read-only */
   SendMessageA(hwnd, EM_SETREADONLY, TRUE, 0);
@@ -4986,26 +4986,23 @@ static void subtest_undo(const char *dummy_text)
     if (i != tomFalse && i != tomTrue)
     {
       hr = ITextDocument_Undo(doc, i, NULL);
-      todo_wine
+      todo_wine_if(i >= 1)
       ok(hr == (i >= 1 ? S_OK : S_FALSE), "(%ld at 0) Undo: %#lx\n", i, hr);
 
       count = 0xcccccccc;
       hr = ITextDocument_Undo(doc, i, &count);
-      todo_wine
+      todo_wine_if(i >= 1)
       ok(hr == (i >= 1 ? S_OK : S_FALSE), "(%ld at 0) Undo: %#lx\n", i, hr);
-      todo_wine
+      todo_wine_if(i >= 1)
       ok(count == (i >= 1 ? i : 0), "(%ld at 0) Expected %ld, got %ld\n", i, i >= 0 ? i : 0, count);
     }
 
     hr = ITextDocument_Redo(doc, i, NULL);
-    todo_wine
     ok(hr == (i == 0 ? S_OK : S_FALSE), "(%ld at 0) Redo: %#lx\n", i, hr);
 
     count = 0xcccccccc;
     hr = ITextDocument_Redo(doc, i, &count);
-    todo_wine
     ok(hr == (i == 0 ? S_OK : S_FALSE), "(%ld at 0) Redo: %#lx\n", i, hr);
-    todo_wine
     ok(count == 0, "(%ld at 0) got %ld\n", i, count);
   }
 
@@ -5015,7 +5012,6 @@ static void subtest_undo(const char *dummy_text)
     if (dummy_text)
     {
       hr = ITextDocument_Undo(doc, tomSuspend, NULL);
-      todo_wine
       ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr);
       if (SUCCEEDED(hr))
       {
@@ -5024,7 +5020,6 @@ static void subtest_undo(const char *dummy_text)
         SendMessageA(hwnd, EM_SETSEL, 0, strlen(dummy_text));
         SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)"");
         hr = ITextDocument_Undo(doc, tomResume, NULL);
-        todo_wine
         ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr);
       }
     }
@@ -5038,7 +5033,6 @@ static void subtest_undo(const char *dummy_text)
 
     memset(buffer, 0, sizeof(buffer));
     SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
-    todo_wine_if(stack_pos != ARRAY_SIZE(text_seq) - 1)
     ok(strcmp(buffer, text_seq[stack_pos]) == 0, "Expected %s, got %s\n",
        wine_dbgstr_a(text_seq[stack_pos]), wine_dbgstr_a(buffer));
 
@@ -5049,18 +5043,14 @@ static void subtest_undo(const char *dummy_text)
     if (seq[i] < 0)
     {
       hr = ITextDocument_Undo(doc, -seq[i], &count);
-      todo_wine
       ok(hr == S_OK, "(%ld@%ld) Undo: %#lx\n", i, stack_pos, hr);
-      todo_wine
       ok(count == expect_count, "(%ld@%ld) Expected %ld, got %ld\n", i, stack_pos, expect_count, count);
       stack_pos -= count;
     }
     else
     {
       hr = ITextDocument_Redo(doc, seq[i], &count);
-      todo_wine
       ok(hr == (expect_count ? S_OK : S_FALSE), "(%ld@%ld) Redo: %#lx\n", i, stack_pos, hr);
-      todo_wine
       ok(count == expect_count, "(%ld@%ld) Expected %ld, got %ld\n", i, stack_pos, expect_count, count);
       stack_pos += count;
     }
@@ -5145,7 +5135,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi
       else
       {
         hr = ITextDocument_Undo(inst->doc, tomTrue, count);
-        todo_wine
         ok(hr == S_FALSE, "Undo: %#lx\n", hr);
       }
       if (SUCCEEDED(hr))
@@ -5159,7 +5148,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi
       break;
     case undoActionDisable:
       hr = ITextDocument_Undo(inst->doc, tomFalse, count);
-      todo_wine
       ok(hr == S_OK, "Undo: %#lx\n", hr);
       if (SUCCEEDED(hr))
       {
@@ -5170,7 +5158,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi
       break;
     case undoActionSuspend:
       hr = ITextDocument_Undo(inst->doc, tomSuspend, count);
-      todo_wine
       ok(hr == S_FALSE, "Undo: %#lx\n", hr);
       if (SUCCEEDED(hr) && inst->undo_ctl_state == undoStateActive)
       {
@@ -5179,7 +5166,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi
       break;
     case undoActionResume:
       hr = ITextDocument_Undo(inst->doc, tomResume, count);
-      todo_wine
       ok(hr == S_FALSE, "Undo: %#lx\n", hr);
       if (SUCCEEDED(hr))
       {
@@ -5193,7 +5179,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi
 
   if (count)
   {
-    todo_wine
     ok(*count == 0, "Got %ld\n", *count);
   }
   return hr;
@@ -5221,7 +5206,6 @@ static HRESULT set_editor_undo_state(struct undo_test *inst, enum editorUndoStat
       break;
   }
   ok(inst->undo_ctl_state == state, "expected state %d, got %d\n", state, inst->undo_ctl_state);
-  todo_wine
   ok(SUCCEEDED(hr), "cannot set state to %d: %#lx\n", undoStateActive, hr);
   return hr;
 }
@@ -5243,9 +5227,7 @@ static BOOL perform_undo_(struct undo_test *inst, BOOL can_undo, int line)
   {
     count = 0xcccccccc;
     hr = ITextDocument_Undo(inst->doc, 1, &count);
-    todo_wine
     ok_(__FILE__, line)(SUCCEEDED(hr), "got hr %#lx\n", hr);
-    todo_wine
     ok_(__FILE__, line)(count == (hr == S_OK), "expected count %d, got %ld\n", hr == S_OK, count);
     result = hr == S_OK && count > 0;
   }
@@ -5279,9 +5261,7 @@ static BOOL perform_redo_(struct undo_test *inst, BOOL can_redo, int line)
   {
     count = 0xcccccccc;
     hr = ITextDocument_Redo(inst->doc, 1, &count);
-    todo_wine
     ok_(__FILE__, line)(SUCCEEDED(hr), "got hr %#lx\n", hr);
-    todo_wine
     ok_(__FILE__, line)(count == (hr == S_OK), "expected count %d, got %ld\n", hr == S_OK, count);
     result = hr == S_OK && count > 0;
   }
diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c
index 607f90130d5..6e0c7c896ef 100644
--- a/dlls/riched20/undo.c
+++ b/dlls/riched20/undo.c
@@ -479,3 +479,17 @@ BOOL ME_Redo(ME_TextEditor *editor)
   ME_UpdateRepaint(editor, FALSE);
   return TRUE;
 }
+
+void editor_disable_undo(ME_TextEditor *editor)
+{
+    ME_EmptyUndoStack(editor);
+    editor->undo_ctl_state = undoDisabled;
+}
+
+void editor_enable_undo(ME_TextEditor *editor)
+{
+    if (editor->undo_ctl_state == undoDisabled)
+    {
+        editor->undo_ctl_state = undoActive;
+    }
+}




More information about the wine-cvs mailing list