From: Jinoh Kang jinoh.kang.kr@gmail.com
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/riched20/editor.c | 10 ++++++++-- dlls/riched20/editstr.h | 13 +++++++++++++ dlls/riched20/tests/editor.c | 2 -- dlls/riched20/undo.c | 2 ++ 4 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 3628e51ac9b..2eb8b7d2a11 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -2938,6 +2938,8 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10)
ed->bEmulateVersion10 = bEmulateVersion10; ed->in_place_active = FALSE; + ed->last_undo_status = FALSE; + ed->last_redo_status = FALSE; ed->total_rows = 0; ITextHost_TxGetPropertyBits( ed->texthost, TXTBIT_RICHTEXT | TXTBIT_MULTILINE | TXTBIT_READONLY | TXTBIT_USEPASSWORD | TXTBIT_HIDESELECTION | TXTBIT_SAVESELECTION | @@ -3313,9 +3315,13 @@ LRESULT editor_handle_message( ME_TextEditor *editor, UINT msg, WPARAM wParam, return !list_empty( &editor->redo_stack ); case WM_UNDO: /* FIXME: actually not the same */ case EM_UNDO: - return ME_Undo(editor); + if (editor->nUndoMode == umIgnore) return FALSE; + ME_Undo(editor); + return editor->last_undo_status; case EM_REDO: - return ME_Redo(editor); + if (editor->nUndoMode == umIgnore) return FALSE; + ME_Redo(editor); + return editor->last_redo_status; case EM_SETFONTSIZE: { CHARFORMAT2W cf; diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index 3b166234f23..2b6e00a861f 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -384,6 +384,19 @@ typedef struct tagME_TextEditor unsigned int bEmulateVersion10 : 1; unsigned int in_place_active : 1; unsigned int have_texthost2 : 1; + /* Windows Rich Edit has a bug where undos are counted regardless + * of whether they are actually peformed or not. It appears that + * each editor instance has an "undo successful" state variable + * that is set by an internal undo routine. However, failure to + * perform the operation (e.g. undo stack is empty) supposedly does + * not clear this state variable, which leads to reporting undo + * count that may be greater than the number of times it has + * actually happened. We emulate this bug by ignoring ME_Undo's + * return value and using the state variable directly. + */ + unsigned int last_undo_status : 1; + /* Ditto for redo. */ + unsigned int last_redo_status : 1; ME_TextBuffer *pBuffer; ME_Cursor *pCursors; DWORD props; diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index 79ee7007873..fc9178136e6 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -7111,7 +7111,6 @@ static void test_undo_status_bug(void) lresult = SendMessageA(hwnd, EM_CANUNDO, 0, 0); ok(lresult == FALSE, "EM_CANUNDO returned %Id\n", lresult); lresult = SendMessageA(hwnd, EM_UNDO, 0, 0); - todo_wine ok(lresult == TRUE, "EM_UNDO returned %Id\n", lresult);
lresult = SendMessageA(hwnd, EM_CANREDO, 0, 0); @@ -7122,7 +7121,6 @@ static void test_undo_status_bug(void) lresult = SendMessageA(hwnd, EM_CANREDO, 0, 0); ok(lresult == FALSE, "EM_CANREDO returned %Id\n", lresult); lresult = SendMessageA(hwnd, EM_REDO, 0, 0); - todo_wine ok(lresult == TRUE, "EM_REDO returned %Id\n", lresult);
DestroyWindow(hwnd); diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c index d95ce121234..fdeb5e4d423 100644 --- a/dlls/riched20/undo.c +++ b/dlls/riched20/undo.c @@ -439,6 +439,7 @@ BOOL ME_Undo(ME_TextEditor *editor)
table_move_from_row_start( editor ); add_undo( editor, undo_end_transaction ); + editor->last_undo_status = TRUE; editor->nUndoStackSize--; editor->nUndoMode = nMode; ME_UpdateRepaint(editor, FALSE); @@ -475,6 +476,7 @@ BOOL ME_Redo(ME_TextEditor *editor) } table_move_from_row_start( editor ); add_undo( editor, undo_end_transaction ); + editor->last_redo_status = TRUE; editor->nUndoMode = nMode; ME_UpdateRepaint(editor, FALSE); return TRUE;