Commit ded82277 authored by Jinoh Kang's avatar Jinoh Kang Committed by Alexandre Julliard

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

parent 40c54854
...@@ -3299,6 +3299,7 @@ LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam, ...@@ -3299,6 +3299,7 @@ LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam,
} }
case EM_SETUNDOLIMIT: case EM_SETUNDOLIMIT:
{ {
editor_enable_undo(editor);
if ((int)wParam < 0) if ((int)wParam < 0)
editor->nUndoLimit = STACK_SIZE_DEFAULT; editor->nUndoLimit = STACK_SIZE_DEFAULT;
else else
......
...@@ -393,6 +393,8 @@ void ME_CommitCoalescingUndo(ME_TextEditor *editor) DECLSPEC_HIDDEN; ...@@ -393,6 +393,8 @@ void ME_CommitCoalescingUndo(ME_TextEditor *editor) DECLSPEC_HIDDEN;
BOOL ME_Undo(ME_TextEditor *editor) DECLSPEC_HIDDEN; BOOL ME_Undo(ME_TextEditor *editor) DECLSPEC_HIDDEN;
BOOL ME_Redo(ME_TextEditor *editor) DECLSPEC_HIDDEN; BOOL ME_Redo(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_EmptyUndoStack(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) static inline BOOL editor_undo_ignored(ME_TextEditor *editor)
{ {
......
...@@ -4245,15 +4245,55 @@ static HRESULT WINAPI ITextDocument2Old_fnEndEditCollection(ITextDocument2Old *i ...@@ -4245,15 +4245,55 @@ static HRESULT WINAPI ITextDocument2Old_fnEndEditCollection(ITextDocument2Old *i
static HRESULT WINAPI ITextDocument2Old_fnUndo(ITextDocument2Old *iface, LONG Count, LONG *prop) static HRESULT WINAPI ITextDocument2Old_fnUndo(ITextDocument2Old *iface, LONG Count, LONG *prop)
{ {
struct text_services *services = impl_from_ITextDocument2Old(iface); struct text_services *services = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n", services); LONG actual_undo_count;
return E_NOTIMPL;
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) static HRESULT WINAPI ITextDocument2Old_fnRedo(ITextDocument2Old *iface, LONG Count, LONG *prop)
{ {
struct text_services *services = impl_from_ITextDocument2Old(iface); struct text_services *services = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n", services); LONG actual_redo_count;
return E_NOTIMPL;
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) static HRESULT CreateITextRange(struct text_services *services, LONG start, LONG end, ITextRange** ppRange)
......
...@@ -4940,8 +4940,8 @@ static void test_clipboard(void) ...@@ -4940,8 +4940,8 @@ static void test_clipboard(void)
ok(hr == S_OK, "Cut failed: 0x%08lx\n", hr); ok(hr == S_OK, "Cut failed: 0x%08lx\n", hr);
CLIPBOARD_RANGE_CONTAINS(range, 0, 4, "b\r\n c"); CLIPBOARD_RANGE_CONTAINS(range, 0, 4, "b\r\n c");
hr = ITextDocument_Undo(doc, 1, NULL); hr = ITextDocument_Undo(doc, 1, NULL);
todo_wine ok(hr == S_OK, "Undo failed: 0x%08lx\n", hr); ok(hr == S_OK, "Undo failed: 0x%08lx\n", hr);
TODO_CLIPBOARD_RANGE_CONTAINS(range, 0, 5, "ab\r\n c"); CLIPBOARD_RANGE_CONTAINS(range, 0, 5, "ab\r\n c");
/* Cannot cut when read-only */ /* Cannot cut when read-only */
SendMessageA(hwnd, EM_SETREADONLY, TRUE, 0); SendMessageA(hwnd, EM_SETREADONLY, TRUE, 0);
...@@ -4986,26 +4986,23 @@ static void subtest_undo(const char *dummy_text) ...@@ -4986,26 +4986,23 @@ static void subtest_undo(const char *dummy_text)
if (i != tomFalse && i != tomTrue) if (i != tomFalse && i != tomTrue)
{ {
hr = ITextDocument_Undo(doc, i, NULL); 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); ok(hr == (i >= 1 ? S_OK : S_FALSE), "(%ld@0) Undo: %#lx\n", i, hr);
count = 0xcccccccc; count = 0xcccccccc;
hr = ITextDocument_Undo(doc, i, &count); 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); 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); 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); hr = ITextDocument_Redo(doc, i, NULL);
todo_wine
ok(hr == (i == 0 ? S_OK : S_FALSE), "(%ld@0) Redo: %#lx\n", i, hr); ok(hr == (i == 0 ? S_OK : S_FALSE), "(%ld@0) Redo: %#lx\n", i, hr);
count = 0xcccccccc; count = 0xcccccccc;
hr = ITextDocument_Redo(doc, i, &count); hr = ITextDocument_Redo(doc, i, &count);
todo_wine
ok(hr == (i == 0 ? S_OK : S_FALSE), "(%ld@0) Redo: %#lx\n", i, hr); 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); ok(count == 0, "(%ld@0) got %ld\n", i, count);
} }
...@@ -5015,7 +5012,6 @@ static void subtest_undo(const char *dummy_text) ...@@ -5015,7 +5012,6 @@ static void subtest_undo(const char *dummy_text)
if (dummy_text) if (dummy_text)
{ {
hr = ITextDocument_Undo(doc, tomSuspend, NULL); hr = ITextDocument_Undo(doc, tomSuspend, NULL);
todo_wine
ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr); ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
...@@ -5024,7 +5020,6 @@ static void subtest_undo(const char *dummy_text) ...@@ -5024,7 +5020,6 @@ static void subtest_undo(const char *dummy_text)
SendMessageA(hwnd, EM_SETSEL, 0, strlen(dummy_text)); SendMessageA(hwnd, EM_SETSEL, 0, strlen(dummy_text));
SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)""); SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)"");
hr = ITextDocument_Undo(doc, tomResume, NULL); hr = ITextDocument_Undo(doc, tomResume, NULL);
todo_wine
ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr); ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr);
} }
} }
...@@ -5038,7 +5033,6 @@ static void subtest_undo(const char *dummy_text) ...@@ -5038,7 +5033,6 @@ static void subtest_undo(const char *dummy_text)
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)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", ok(strcmp(buffer, text_seq[stack_pos]) == 0, "Expected %s, got %s\n",
wine_dbgstr_a(text_seq[stack_pos]), wine_dbgstr_a(buffer)); wine_dbgstr_a(text_seq[stack_pos]), wine_dbgstr_a(buffer));
...@@ -5049,18 +5043,14 @@ static void subtest_undo(const char *dummy_text) ...@@ -5049,18 +5043,14 @@ static void subtest_undo(const char *dummy_text)
if (seq[i] < 0) if (seq[i] < 0)
{ {
hr = ITextDocument_Undo(doc, -seq[i], &count); hr = ITextDocument_Undo(doc, -seq[i], &count);
todo_wine
ok(hr == S_OK, "(%ld@%ld) Undo: %#lx\n", i, stack_pos, hr); 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); ok(count == expect_count, "(%ld@%ld) Expected %ld, got %ld\n", i, stack_pos, expect_count, count);
stack_pos -= count; stack_pos -= count;
} }
else else
{ {
hr = ITextDocument_Redo(doc, seq[i], &count); 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); 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); ok(count == expect_count, "(%ld@%ld) Expected %ld, got %ld\n", i, stack_pos, expect_count, count);
stack_pos += count; stack_pos += count;
} }
...@@ -5145,7 +5135,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi ...@@ -5145,7 +5135,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi
else else
{ {
hr = ITextDocument_Undo(inst->doc, tomTrue, count); hr = ITextDocument_Undo(inst->doc, tomTrue, count);
todo_wine
ok(hr == S_FALSE, "Undo: %#lx\n", hr); ok(hr == S_FALSE, "Undo: %#lx\n", hr);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
...@@ -5159,7 +5148,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi ...@@ -5159,7 +5148,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi
break; break;
case undoActionDisable: case undoActionDisable:
hr = ITextDocument_Undo(inst->doc, tomFalse, count); hr = ITextDocument_Undo(inst->doc, tomFalse, count);
todo_wine
ok(hr == S_OK, "Undo: %#lx\n", hr); ok(hr == S_OK, "Undo: %#lx\n", hr);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
...@@ -5170,7 +5158,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi ...@@ -5170,7 +5158,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi
break; break;
case undoActionSuspend: case undoActionSuspend:
hr = ITextDocument_Undo(inst->doc, tomSuspend, count); hr = ITextDocument_Undo(inst->doc, tomSuspend, count);
todo_wine
ok(hr == S_FALSE, "Undo: %#lx\n", hr); ok(hr == S_FALSE, "Undo: %#lx\n", hr);
if (SUCCEEDED(hr) && inst->undo_ctl_state == undoStateActive) 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 ...@@ -5179,7 +5166,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi
break; break;
case undoActionResume: case undoActionResume:
hr = ITextDocument_Undo(inst->doc, tomResume, count); hr = ITextDocument_Undo(inst->doc, tomResume, count);
todo_wine
ok(hr == S_FALSE, "Undo: %#lx\n", hr); ok(hr == S_FALSE, "Undo: %#lx\n", hr);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
...@@ -5193,7 +5179,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi ...@@ -5193,7 +5179,6 @@ static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum edi
if (count) if (count)
{ {
todo_wine
ok(*count == 0, "Got %ld\n", *count); ok(*count == 0, "Got %ld\n", *count);
} }
return hr; return hr;
...@@ -5221,7 +5206,6 @@ static HRESULT set_editor_undo_state(struct undo_test *inst, enum editorUndoStat ...@@ -5221,7 +5206,6 @@ static HRESULT set_editor_undo_state(struct undo_test *inst, enum editorUndoStat
break; break;
} }
ok(inst->undo_ctl_state == state, "expected state %d, got %d\n", state, inst->undo_ctl_state); 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); ok(SUCCEEDED(hr), "cannot set state to %d: %#lx\n", undoStateActive, hr);
return hr; return hr;
} }
...@@ -5243,9 +5227,7 @@ static BOOL perform_undo_(struct undo_test *inst, BOOL can_undo, int line) ...@@ -5243,9 +5227,7 @@ static BOOL perform_undo_(struct undo_test *inst, BOOL can_undo, int line)
{ {
count = 0xcccccccc; count = 0xcccccccc;
hr = ITextDocument_Undo(inst->doc, 1, &count); hr = ITextDocument_Undo(inst->doc, 1, &count);
todo_wine
ok_(__FILE__, line)(SUCCEEDED(hr), "got hr %#lx\n", hr); 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); ok_(__FILE__, line)(count == (hr == S_OK), "expected count %d, got %ld\n", hr == S_OK, count);
result = hr == S_OK && count > 0; result = hr == S_OK && count > 0;
} }
...@@ -5279,9 +5261,7 @@ static BOOL perform_redo_(struct undo_test *inst, BOOL can_redo, int line) ...@@ -5279,9 +5261,7 @@ static BOOL perform_redo_(struct undo_test *inst, BOOL can_redo, int line)
{ {
count = 0xcccccccc; count = 0xcccccccc;
hr = ITextDocument_Redo(inst->doc, 1, &count); hr = ITextDocument_Redo(inst->doc, 1, &count);
todo_wine
ok_(__FILE__, line)(SUCCEEDED(hr), "got hr %#lx\n", hr); 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); ok_(__FILE__, line)(count == (hr == S_OK), "expected count %d, got %ld\n", hr == S_OK, count);
result = hr == S_OK && count > 0; result = hr == S_OK && count > 0;
} }
......
...@@ -479,3 +479,17 @@ BOOL ME_Redo(ME_TextEditor *editor) ...@@ -479,3 +479,17 @@ BOOL ME_Redo(ME_TextEditor *editor)
ME_UpdateRepaint(editor, FALSE); ME_UpdateRepaint(editor, FALSE);
return TRUE; 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;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment