Module: wine Branch: master Commit: ded8227774570a1ea320dc34f2de0033f85b3ce7 URL: https://gitlab.winehq.org/wine/wine/-/commit/ded8227774570a1ea320dc34f2de003...
Author: Jinoh Kang jinoh.kang.kr@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@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@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@0) Undo: %#lx\n", i, hr); - todo_wine + todo_wine_if(i >= 1) ok(count == (i >= 1 ? i : 0), "(%ld@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@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@0) Redo: %#lx\n", i, hr); - todo_wine ok(count == 0, "(%ld@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; + } +}