From: Jinoh Kang jinoh.kang.kr@gmail.com
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/riched20/editor.h | 5 +++++ dlls/riched20/undo.c | 16 ++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 3028d9bdbd5..4e8445c99aa 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -394,6 +394,11 @@ BOOL ME_Undo(ME_TextEditor *editor) DECLSPEC_HIDDEN; BOOL ME_Redo(ME_TextEditor *editor) DECLSPEC_HIDDEN; void ME_EmptyUndoStack(ME_TextEditor *editor) DECLSPEC_HIDDEN;
+static inline BOOL editor_undo_ignored(ME_TextEditor *editor) +{ + return editor->nUndoMode == umIgnore; +} + /* txtsrv.c */ HRESULT create_text_services( IUnknown *outer, ITextHost *text_host, IUnknown **unk, BOOL emulate_10 ) DECLSPEC_HIDDEN; #ifdef __ASM_USE_THISCALL_WRAPPER diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c index d95ce121234..607f90130d5 100644 --- a/dlls/riched20/undo.c +++ b/dlls/riched20/undo.c @@ -53,7 +53,7 @@ static void empty_redo_stack(ME_TextEditor *editor) void ME_EmptyUndoStack(ME_TextEditor *editor) { struct undo_item *cursor, *cursor2; - if (editor->nUndoMode == umIgnore) + if (editor->nUndoMode == umIgnore) /* NOTE don't use editor_undo_ignored() here! */ return;
TRACE("Emptying undo stack\n"); @@ -74,7 +74,7 @@ static struct undo_item *add_undo( ME_TextEditor *editor, enum undo_type type ) struct undo_item *undo, *item; struct list *head;
- if (editor->nUndoMode == umIgnore) return NULL; + if (editor_undo_ignored(editor)) return NULL; if (editor->nUndoLimit == 0) return NULL;
undo = heap_alloc( sizeof(*undo) ); @@ -229,7 +229,7 @@ void ME_CommitUndo(ME_TextEditor *editor) struct undo_item *item; struct list *head;
- if (editor->nUndoMode == umIgnore) + if (editor_undo_ignored(editor)) return;
assert(editor->nUndoMode == umAddToUndo); @@ -267,7 +267,7 @@ void ME_ContinueCoalescingTransaction(ME_TextEditor *editor) struct undo_item *item; struct list *head;
- if (editor->nUndoMode == umIgnore) + if (editor_undo_ignored(editor)) return;
assert(editor->nUndoMode == umAddToUndo); @@ -303,7 +303,7 @@ void ME_CommitCoalescingUndo(ME_TextEditor *editor) struct undo_item *item; struct list *head;
- if (editor->nUndoMode == umIgnore) + if (editor_undo_ignored(editor)) return;
assert(editor->nUndoMode == umAddToUndo); @@ -323,7 +323,7 @@ void ME_CommitCoalescingUndo(ME_TextEditor *editor) static void ME_PlayUndoItem(ME_TextEditor *editor, struct undo_item *undo) {
- if (editor->nUndoMode == umIgnore) + if (editor_undo_ignored(editor)) return; TRACE("Playing undo/redo item, id=%d\n", undo->type);
@@ -413,7 +413,7 @@ BOOL ME_Undo(ME_TextEditor *editor) struct list *head; struct undo_item *undo, *cursor2;
- if (editor->nUndoMode == umIgnore) return FALSE; + if (editor_undo_ignored(editor)) return FALSE; assert(nMode == umAddToUndo || nMode == umIgnore);
head = list_head( &editor->undo_stack ); @@ -453,7 +453,7 @@ BOOL ME_Redo(ME_TextEditor *editor)
assert(nMode == umAddToUndo || nMode == umIgnore);
- if (editor->nUndoMode == umIgnore) return FALSE; + if (editor_undo_ignored(editor)) return FALSE;
head = list_head( &editor->redo_stack ); if (!head) return FALSE;
From: Jinoh Kang jinoh.kang.kr@gmail.com
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/riched20/editor.c | 1 + dlls/riched20/editor.h | 2 +- dlls/riched20/editstr.h | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 3628e51ac9b..a1e0395f24d 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -2973,6 +2973,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ed->nUndoStackSize = 0; ed->nUndoLimit = STACK_SIZE_DEFAULT; ed->nUndoMode = umAddToUndo; + ed->undo_ctl_state = undoActive; ed->nParagraphs = 1; ed->nLastSelStart = ed->nLastSelEnd = 0; ed->last_sel_start_para = ed->last_sel_end_para = ed->pCursors[0].para; diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 4e8445c99aa..d10ff225335 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -396,7 +396,7 @@ void ME_EmptyUndoStack(ME_TextEditor *editor) DECLSPEC_HIDDEN;
static inline BOOL editor_undo_ignored(ME_TextEditor *editor) { - return editor->nUndoMode == umIgnore; + return editor->undo_ctl_state != undoActive || editor->nUndoMode == umIgnore; }
/* txtsrv.c */ diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index 3b166234f23..db219d7e4df 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -285,6 +285,12 @@ typedef enum { umAddBackToUndo } ME_UndoMode;
+typedef enum { + undoActive, + undoSuspended, + undoDisabled +} ME_UndoControlState; + enum undo_type { undo_insert_run, @@ -402,6 +408,7 @@ typedef struct tagME_TextEditor int nUndoStackSize; int nUndoLimit; ME_UndoMode nUndoMode; + ME_UndoControlState undo_ctl_state; int nParagraphs; LONG nLastSelStart, nLastSelEnd; ME_Paragraph *last_sel_start_para, *last_sel_end_para;
From: Jinoh Kang jinoh.kang.kr@gmail.com
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; + } +}
This merge request was approved by Huw Davies.