Matt Finnicum : riched20:
Implement EM_SETUNDOLIMIT and its conformance tests.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue May 16 06:24:44 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: a379ac9ef5b987d7071593daf0a63af31c89499c
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=a379ac9ef5b987d7071593daf0a63af31c89499c
Author: Matt Finnicum <mattfinn at gmail.com>
Date: Mon May 15 14:00:15 2006 -0400
riched20: Implement EM_SETUNDOLIMIT and its conformance tests.
---
dlls/riched20/editor.c | 21 ++++++++++++--
dlls/riched20/editstr.h | 4 ++-
dlls/riched20/tests/editor.c | 65 ++++++++++++++++++++++++++++++++++++++++++
dlls/riched20/undo.c | 27 +++++++++++++++++
4 files changed, 112 insertions(+), 5 deletions(-)
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index d73690c..3e8c834 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -117,7 +117,7 @@
+ EM_SETTEXTEX 3.0 (unicode only, no rich text insertion handling, proper style?)
- EM_SETTEXTMODE 2.0
- EM_SETTYPOGRAPHYOPTIONS 3.0
- - EM_SETUNDOLIMIT 2.0
+ + EM_SETUNDOLIMIT 2.0
+ EM_SETWORDBREAKPROC (used only for word movement at the moment)
- EM_SETWORDBREAKPROCEX
- EM_SETWORDWRAPMODE 1.0asian
@@ -229,6 +229,9 @@ #include "shlwapi.h"
#include "imm.h"
#include "textserv.h"
#include "rtf.h"
+
+#define STACK_SIZE_DEFAULT 100
+#define STACK_SIZE_MAX 1000
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
@@ -1119,7 +1122,9 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd)
ed->bCaretAtEnd = FALSE;
ed->nEventMask = 0;
ed->nModifyStep = 0;
- ed->pUndoStack = ed->pRedoStack = NULL;
+ ed->pUndoStack = ed->pRedoStack = ed->pUndoStackBottom = NULL;
+ ed->nUndoStackSize = 0;
+ ed->nUndoLimit = STACK_SIZE_DEFAULT;
ed->nUndoMode = umAddToUndo;
ed->nParagraphs = 1;
ed->nLastSelStart = ed->nLastSelEnd = 0;
@@ -1426,7 +1431,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND
UNSUPPORTED_MSG(EM_SETTABSTOPS)
UNSUPPORTED_MSG(EM_SETTARGETDEVICE)
UNSUPPORTED_MSG(EM_SETTYPOGRAPHYOPTIONS)
- UNSUPPORTED_MSG(EM_SETUNDOLIMIT)
UNSUPPORTED_MSG(EM_SETWORDBREAKPROCEX)
UNSUPPORTED_MSG(EM_SHOWSCROLLBAR)
UNSUPPORTED_MSG(WM_SETFONT)
@@ -1477,6 +1481,17 @@ LRESULT WINAPI RichEditANSIWndProc(HWND
TRACE("EM_EXGETSEL = (%ld,%ld)\n", pRange->cpMin, pRange->cpMax);
return 0;
}
+ case EM_SETUNDOLIMIT:
+ {
+ if ((int)wParam < 0)
+ editor->nUndoLimit = STACK_SIZE_DEFAULT;
+ else
+ editor->nUndoLimit = min(wParam, STACK_SIZE_MAX);
+ /* Setting a max stack size keeps wine from getting killed
+ for hogging memory. Windows allocates all this memory at once, so
+ no program would realisticly set a value above our maxiumum. */
+ return editor->nUndoLimit;
+ }
case EM_CANUNDO:
return editor->pUndoStack != NULL;
case EM_CANREDO:
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index 0911e90..bb151fa 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -298,7 +298,9 @@ typedef struct tagME_TextEditor
BOOL bCaretAtEnd;
int nEventMask;
int nModifyStep;
- ME_DisplayItem *pUndoStack, *pRedoStack;
+ ME_DisplayItem *pUndoStack, *pRedoStack, *pUndoStackBottom;
+ int nUndoStackSize;
+ int nUndoLimit;
ME_UndoMode nUndoMode;
int nParagraphs;
int nLastSelStart, nLastSelEnd;
diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c
index 6b80903..837fb15 100644
--- a/dlls/riched20/tests/editor.c
+++ b/dlls/riched20/tests/editor.c
@@ -747,6 +747,70 @@ static void test_EM_SCROLL()
DestroyWindow(hwndRichEdit);
}
+static void test_EM_SETUNDOLIMIT()
+{
+ /* cases we test for:
+ * default behaviour - limiting at 100 undo's
+ * undo disabled - setting a limit of 0
+ * undo limited - undo limit set to some to some number, like 2
+ * bad input - sending a negative number should default to 100 undo's */
+
+ HWND hwndRichEdit = new_richedit(NULL);
+ CHARRANGE cr;
+ int i;
+ int result;
+
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "x");
+ cr.cpMin = 0;
+ cr.cpMax = 1;
+ SendMessage(hwndRichEdit, WM_COPY, 0, 0);
+ /*Load "x" into the clipboard. Paste is an easy, undo'able operation.
+ also, multiple pastes don't combine like WM_CHAR would */
+ SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr);
+
+ /* first case - check the default */
+ SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
+ for (i=0; i<101; i++) /* Put 101 undo's on the stack */
+ SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
+ for (i=0; i<100; i++) /* Undo 100 of them */
+ SendMessage(hwndRichEdit, WM_UNDO, 0, 0);
+ ok(!SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0),
+ "EM_SETUNDOLIMIT allowed more than a hundred undo's by default.\n");
+
+ /* second case - cannot undo */
+ SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0, 0);
+ SendMessage(hwndRichEdit, EM_SETUNDOLIMIT, 0, 0);
+ SendMessage(hwndRichEdit,
+ WM_PASTE, 0, 0); /* Try to put something in the undo stack */
+ ok(!SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0),
+ "EM_SETUNDOLIMIT allowed undo with UNDOLIMIT set to 0\n");
+
+ /* third case - set it to an arbitrary number */
+ SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0, 0);
+ SendMessage(hwndRichEdit, EM_SETUNDOLIMIT, 2, 0);
+ SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
+ SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
+ SendMessage(hwndRichEdit, WM_PASTE, 0, 0);
+ /* If SETUNDOLIMIT is working, there should only be two undo's after this */
+ ok(SendMessage(hwndRichEdit, EM_CANUNDO, 0,0),
+ "EM_SETUNDOLIMIT didn't allow the first undo with UNDOLIMIT set to 2\n");
+ SendMessage(hwndRichEdit, WM_UNDO, 0, 0);
+ ok(SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0),
+ "EM_SETUNDOLIMIT didn't allow a second undo with UNDOLIMIT set to 2\n");
+ SendMessage(hwndRichEdit, WM_UNDO, 0, 0);
+ ok(!SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0),
+ "EM_SETUNDOLIMIT allowed a third undo with UNDOLIMIT set to 2\n");
+
+ /* fourth case - setting negative numbers should default to 100 undos */
+ SendMessage(hwndRichEdit,EM_EMPTYUNDOBUFFER, 0,0);
+ result = SendMessage(hwndRichEdit, EM_SETUNDOLIMIT, -1, 0);
+ ok (result == 100,
+ "EM_SETUNDOLIMIT returned %d when set to -1, instead of 100",result);
+
+ DestroyWindow(hwndRichEdit);
+}
+
+
START_TEST( editor )
{
MSG msg;
@@ -764,6 +828,7 @@ START_TEST( editor )
test_EM_SETOPTIONS();
test_WM_GETTEXT();
test_EM_AUTOURLDETECT();
+ test_EM_SETUNDOLIMIT();
/* Set the environment variable WINETEST_RICHED20 to keep windows
* responsive and open for 30 seconds. This is useful for debugging.
diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c
index 916dcb3..f8895cb 100644
--- a/dlls/riched20/undo.c
+++ b/dlls/riched20/undo.c
@@ -32,7 +32,8 @@ void ME_EmptyUndoStack(ME_TextEditor *ed
TRACE("Emptying undo stack\n");
p = editor->pUndoStack;
- editor->pUndoStack = NULL;
+ editor->pUndoStack = editor->pUndoStackBottom = NULL;
+ editor->nUndoStackSize = 0;
while(p) {
pNext = p->next;
ME_DestroyDisplayItem(p);
@@ -50,6 +51,8 @@ void ME_EmptyUndoStack(ME_TextEditor *ed
ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, ME_DisplayItem *pdi) {
if (editor->nUndoMode == umIgnore)
return NULL;
+ else if (editor->nUndoLimit == 0)
+ return NULL;
else
{
ME_DisplayItem *pItem = (ME_DisplayItem *)ALLOC_OBJ(ME_UndoItem);
@@ -93,10 +96,31 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEdito
TRACE("Pushing id=%s to undo stack, deleting redo stack\n", ME_GetDITypeName(type));
else
TRACE("Pushing id=%s to undo stack\n", ME_GetDITypeName(type));
+
pItem->next = editor->pUndoStack;
+ if (type == diUndoEndTransaction)
+ editor->nUndoStackSize++;
if (editor->pUndoStack)
editor->pUndoStack->prev = pItem;
+ else
+ editor->pUndoStackBottom = pItem;
editor->pUndoStack = pItem;
+
+ if (editor->nUndoStackSize > editor->nUndoLimit)
+ { /* remove oldest undo from stack */
+ ME_DisplayItem *p = editor->pUndoStackBottom;
+ while (p->type !=diUndoEndTransaction)
+ p = p->prev; /*find new stack bottom */
+ editor->pUndoStackBottom = p->prev;
+ editor->pUndoStackBottom->next = NULL;
+ do
+ {
+ ME_DisplayItem *pp = p->next;
+ ME_DestroyDisplayItem(p);
+ p = pp;
+ } while (p);
+ editor->nUndoStackSize--;
+ }
/* any new operation (not redo) clears the redo stack */
if (editor->nUndoMode == umAddToUndo) {
ME_DisplayItem *p = editor->pRedoStack;
@@ -233,6 +257,7 @@ void ME_Undo(ME_TextEditor *editor) {
} while(p && p->type != diUndoEndTransaction);
ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
editor->pUndoStack = p;
+ editor->nUndoStackSize--;
if (p)
p->prev = NULL;
editor->nUndoMode = nMode;
More information about the wine-cvs
mailing list