riched20: Implement EM_SETUNDOLIMIT and its conformance tests.
This commit is contained in:
parent
24157e0f74
commit
a379ac9ef5
|
@ -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 "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 hWnd, UINT msg, WPARAM wParam, LPARAM lP
|
|||
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 hWnd, UINT msg, WPARAM wParam, LPARAM lP
|
|||
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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -32,7 +32,8 @@ void ME_EmptyUndoStack(ME_TextEditor *editor)
|
|||
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 *editor)
|
|||
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_TextEditor *editor, ME_DIType type, ME_DisplayIte
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue