1c2c66affSColin Finck /*
2c2c66affSColin Finck * RichEdit - functions dealing with editor object
3c2c66affSColin Finck *
4c2c66affSColin Finck * Copyright 2004 by Krzysztof Foltman
5c2c66affSColin Finck *
6c2c66affSColin Finck * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck * License as published by the Free Software Foundation; either
9c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck *
11c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14c2c66affSColin Finck * Lesser General Public License for more details.
15c2c66affSColin Finck *
16c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck */
20c2c66affSColin Finck
21c2c66affSColin Finck #include "editor.h"
22c2c66affSColin Finck
23c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(richedit);
24c2c66affSColin Finck
destroy_undo_item(struct undo_item * undo)25c2c66affSColin Finck static void destroy_undo_item( struct undo_item *undo )
26c2c66affSColin Finck {
27c2c66affSColin Finck switch( undo->type )
28c2c66affSColin Finck {
29c2c66affSColin Finck case undo_insert_run:
30c2c66affSColin Finck heap_free( undo->u.insert_run.str );
31c2c66affSColin Finck ME_ReleaseStyle( undo->u.insert_run.style );
32c2c66affSColin Finck break;
33c2c66affSColin Finck case undo_split_para:
34c2c66affSColin Finck ME_DestroyString( undo->u.split_para.eol_str );
35c2c66affSColin Finck break;
36c2c66affSColin Finck default:
37c2c66affSColin Finck break;
38c2c66affSColin Finck }
39c2c66affSColin Finck
40c2c66affSColin Finck heap_free( undo );
41c2c66affSColin Finck }
42c2c66affSColin Finck
empty_redo_stack(ME_TextEditor * editor)43c2c66affSColin Finck static void empty_redo_stack(ME_TextEditor *editor)
44c2c66affSColin Finck {
45c2c66affSColin Finck struct undo_item *cursor, *cursor2;
46c2c66affSColin Finck LIST_FOR_EACH_ENTRY_SAFE( cursor, cursor2, &editor->redo_stack, struct undo_item, entry )
47c2c66affSColin Finck {
48c2c66affSColin Finck list_remove( &cursor->entry );
49c2c66affSColin Finck destroy_undo_item( cursor );
50c2c66affSColin Finck }
51c2c66affSColin Finck }
52c2c66affSColin Finck
ME_EmptyUndoStack(ME_TextEditor * editor)53c2c66affSColin Finck void ME_EmptyUndoStack(ME_TextEditor *editor)
54c2c66affSColin Finck {
55c2c66affSColin Finck struct undo_item *cursor, *cursor2;
56c2c66affSColin Finck if (editor->nUndoMode == umIgnore)
57c2c66affSColin Finck return;
58c2c66affSColin Finck
59c2c66affSColin Finck TRACE("Emptying undo stack\n");
60c2c66affSColin Finck
61c2c66affSColin Finck editor->nUndoStackSize = 0;
62c2c66affSColin Finck
63c2c66affSColin Finck LIST_FOR_EACH_ENTRY_SAFE( cursor, cursor2, &editor->undo_stack, struct undo_item, entry )
64c2c66affSColin Finck {
65c2c66affSColin Finck list_remove( &cursor->entry );
66c2c66affSColin Finck destroy_undo_item( cursor );
67c2c66affSColin Finck }
68c2c66affSColin Finck
69c2c66affSColin Finck empty_redo_stack( editor );
70c2c66affSColin Finck }
71c2c66affSColin Finck
add_undo(ME_TextEditor * editor,enum undo_type type)72c2c66affSColin Finck static struct undo_item *add_undo( ME_TextEditor *editor, enum undo_type type )
73c2c66affSColin Finck {
74c2c66affSColin Finck struct undo_item *undo, *item;
75c2c66affSColin Finck struct list *head;
76c2c66affSColin Finck
77c2c66affSColin Finck if (editor->nUndoMode == umIgnore) return NULL;
78c2c66affSColin Finck if (editor->nUndoLimit == 0) return NULL;
79c2c66affSColin Finck
80c2c66affSColin Finck undo = heap_alloc( sizeof(*undo) );
81c2c66affSColin Finck if (!undo) return NULL;
82c2c66affSColin Finck undo->type = type;
83c2c66affSColin Finck
84c2c66affSColin Finck if (editor->nUndoMode == umAddToUndo || editor->nUndoMode == umAddBackToUndo)
85c2c66affSColin Finck {
86c2c66affSColin Finck
87c2c66affSColin Finck head = list_head( &editor->undo_stack );
88c2c66affSColin Finck if (head)
89c2c66affSColin Finck {
90c2c66affSColin Finck item = LIST_ENTRY( head, struct undo_item, entry );
91c2c66affSColin Finck if (item->type == undo_potential_end_transaction)
92c2c66affSColin Finck item->type = undo_end_transaction;
93c2c66affSColin Finck }
94c2c66affSColin Finck
95c2c66affSColin Finck if (editor->nUndoMode == umAddToUndo)
96c2c66affSColin Finck TRACE("Pushing id=%d to undo stack, deleting redo stack\n", type);
97c2c66affSColin Finck else
98c2c66affSColin Finck TRACE("Pushing id=%d to undo stack\n", type);
99c2c66affSColin Finck
100c2c66affSColin Finck list_add_head( &editor->undo_stack, &undo->entry );
101c2c66affSColin Finck
102c2c66affSColin Finck if (type == undo_end_transaction || type == undo_potential_end_transaction)
103c2c66affSColin Finck editor->nUndoStackSize++;
104c2c66affSColin Finck
105c2c66affSColin Finck if (editor->nUndoStackSize > editor->nUndoLimit)
106c2c66affSColin Finck {
107c2c66affSColin Finck struct undo_item *cursor2;
108c2c66affSColin Finck /* remove oldest undo from stack */
109c2c66affSColin Finck LIST_FOR_EACH_ENTRY_SAFE_REV( item, cursor2, &editor->undo_stack, struct undo_item, entry )
110c2c66affSColin Finck {
111c2c66affSColin Finck BOOL done = (item->type == undo_end_transaction);
112c2c66affSColin Finck list_remove( &item->entry );
113c2c66affSColin Finck destroy_undo_item( item );
114c2c66affSColin Finck if (done) break;
115c2c66affSColin Finck }
116c2c66affSColin Finck editor->nUndoStackSize--;
117c2c66affSColin Finck }
118c2c66affSColin Finck
119c2c66affSColin Finck /* any new operation (not redo) clears the redo stack */
120c2c66affSColin Finck if (editor->nUndoMode == umAddToUndo) empty_redo_stack( editor );
121c2c66affSColin Finck }
122c2c66affSColin Finck else if (editor->nUndoMode == umAddToRedo)
123c2c66affSColin Finck {
124c2c66affSColin Finck TRACE("Pushing id=%d to redo stack\n", type);
125c2c66affSColin Finck list_add_head( &editor->redo_stack, &undo->entry );
126c2c66affSColin Finck }
127c2c66affSColin Finck
128c2c66affSColin Finck return undo;
129c2c66affSColin Finck }
130c2c66affSColin Finck
add_undo_insert_run(ME_TextEditor * editor,int pos,const WCHAR * str,int len,int flags,ME_Style * style)131c2c66affSColin Finck BOOL add_undo_insert_run( ME_TextEditor *editor, int pos, const WCHAR *str, int len, int flags, ME_Style *style )
132c2c66affSColin Finck {
133c2c66affSColin Finck struct undo_item *undo = add_undo( editor, undo_insert_run );
134c2c66affSColin Finck if (!undo) return FALSE;
135c2c66affSColin Finck
136c2c66affSColin Finck undo->u.insert_run.str = heap_alloc( (len + 1) * sizeof(WCHAR) );
137c2c66affSColin Finck if (!undo->u.insert_run.str)
138c2c66affSColin Finck {
139c2c66affSColin Finck ME_EmptyUndoStack( editor );
140c2c66affSColin Finck return FALSE;
141c2c66affSColin Finck }
142c2c66affSColin Finck memcpy( undo->u.insert_run.str, str, len * sizeof(WCHAR) );
143c2c66affSColin Finck undo->u.insert_run.str[len] = 0;
144c2c66affSColin Finck undo->u.insert_run.pos = pos;
145c2c66affSColin Finck undo->u.insert_run.len = len;
146c2c66affSColin Finck undo->u.insert_run.flags = flags;
147c2c66affSColin Finck undo->u.insert_run.style = style;
148c2c66affSColin Finck ME_AddRefStyle( style );
149c2c66affSColin Finck return TRUE;
150c2c66affSColin Finck }
151c2c66affSColin Finck
add_undo_set_para_fmt(ME_TextEditor * editor,const ME_Paragraph * para)152c2c66affSColin Finck BOOL add_undo_set_para_fmt( ME_TextEditor *editor, const ME_Paragraph *para )
153c2c66affSColin Finck {
154c2c66affSColin Finck struct undo_item *undo = add_undo( editor, undo_set_para_fmt );
155c2c66affSColin Finck if (!undo) return FALSE;
156c2c66affSColin Finck
157c2c66affSColin Finck undo->u.set_para_fmt.pos = para->nCharOfs;
158c2c66affSColin Finck undo->u.set_para_fmt.fmt = para->fmt;
159c2c66affSColin Finck undo->u.set_para_fmt.border = para->border;
160c2c66affSColin Finck
161c2c66affSColin Finck return TRUE;
162c2c66affSColin Finck }
163c2c66affSColin Finck
add_undo_set_char_fmt(ME_TextEditor * editor,int pos,int len,const CHARFORMAT2W * fmt)164c2c66affSColin Finck BOOL add_undo_set_char_fmt( ME_TextEditor *editor, int pos, int len, const CHARFORMAT2W *fmt )
165c2c66affSColin Finck {
166c2c66affSColin Finck struct undo_item *undo = add_undo( editor, undo_set_char_fmt );
167c2c66affSColin Finck if (!undo) return FALSE;
168c2c66affSColin Finck
169c2c66affSColin Finck undo->u.set_char_fmt.pos = pos;
170c2c66affSColin Finck undo->u.set_char_fmt.len = len;
171c2c66affSColin Finck undo->u.set_char_fmt.fmt = *fmt;
172c2c66affSColin Finck
173c2c66affSColin Finck return TRUE;
174c2c66affSColin Finck }
175c2c66affSColin Finck
add_undo_join_paras(ME_TextEditor * editor,int pos)176c2c66affSColin Finck BOOL add_undo_join_paras( ME_TextEditor *editor, int pos )
177c2c66affSColin Finck {
178c2c66affSColin Finck struct undo_item *undo = add_undo( editor, undo_join_paras );
179c2c66affSColin Finck if (!undo) return FALSE;
180c2c66affSColin Finck
181c2c66affSColin Finck undo->u.join_paras.pos = pos;
182c2c66affSColin Finck return TRUE;
183c2c66affSColin Finck }
184c2c66affSColin Finck
add_undo_split_para(ME_TextEditor * editor,const ME_Paragraph * para,ME_String * eol_str,const ME_Cell * cell)185c2c66affSColin Finck BOOL add_undo_split_para( ME_TextEditor *editor, const ME_Paragraph *para, ME_String *eol_str, const ME_Cell *cell )
186c2c66affSColin Finck {
187c2c66affSColin Finck struct undo_item *undo = add_undo( editor, undo_split_para );
188c2c66affSColin Finck if (!undo) return FALSE;
189c2c66affSColin Finck
190c2c66affSColin Finck undo->u.split_para.pos = para->nCharOfs - eol_str->nLen;
191c2c66affSColin Finck undo->u.split_para.eol_str = eol_str;
192c2c66affSColin Finck undo->u.split_para.fmt = para->fmt;
193c2c66affSColin Finck undo->u.split_para.border = para->border;
194c2c66affSColin Finck undo->u.split_para.flags = para->prev_para->member.para.nFlags & ~MEPF_CELL;
195c2c66affSColin Finck
196c2c66affSColin Finck if (cell)
197c2c66affSColin Finck {
198c2c66affSColin Finck undo->u.split_para.cell_border = cell->border;
199c2c66affSColin Finck undo->u.split_para.cell_right_boundary = cell->nRightBoundary;
200c2c66affSColin Finck }
201c2c66affSColin Finck return TRUE;
202c2c66affSColin Finck }
203c2c66affSColin Finck
add_undo_delete_run(ME_TextEditor * editor,int pos,int len)204c2c66affSColin Finck BOOL add_undo_delete_run( ME_TextEditor *editor, int pos, int len )
205c2c66affSColin Finck {
206c2c66affSColin Finck struct undo_item *undo = add_undo( editor, undo_delete_run );
207c2c66affSColin Finck if (!undo) return FALSE;
208c2c66affSColin Finck
209c2c66affSColin Finck undo->u.delete_run.pos = pos;
210c2c66affSColin Finck undo->u.delete_run.len = len;
211c2c66affSColin Finck
212c2c66affSColin Finck return TRUE;
213c2c66affSColin Finck }
214c2c66affSColin Finck
215c2c66affSColin Finck /**
216c2c66affSColin Finck * Commits preceding changes into a transaction that can be undone together.
217c2c66affSColin Finck *
218c2c66affSColin Finck * This should be called after all the changes occur associated with an event
219c2c66affSColin Finck * so that the group of changes can be undone atomically as a transaction.
220c2c66affSColin Finck *
221c2c66affSColin Finck * This will have no effect the undo mode is set to ignore changes, or if no
222c2c66affSColin Finck * changes preceded calling this function before the last time it was called.
223c2c66affSColin Finck *
224c2c66affSColin Finck * This can also be used to conclude a coalescing transaction (used for grouping
225c2c66affSColin Finck * typed characters).
226c2c66affSColin Finck */
ME_CommitUndo(ME_TextEditor * editor)227c2c66affSColin Finck void ME_CommitUndo(ME_TextEditor *editor)
228c2c66affSColin Finck {
229c2c66affSColin Finck struct undo_item *item;
230c2c66affSColin Finck struct list *head;
231c2c66affSColin Finck
232c2c66affSColin Finck if (editor->nUndoMode == umIgnore)
233c2c66affSColin Finck return;
234c2c66affSColin Finck
235c2c66affSColin Finck assert(editor->nUndoMode == umAddToUndo);
236c2c66affSColin Finck
237c2c66affSColin Finck /* no transactions, no need to commit */
238c2c66affSColin Finck head = list_head( &editor->undo_stack );
239c2c66affSColin Finck if (!head) return;
240c2c66affSColin Finck
241c2c66affSColin Finck /* no need to commit empty transactions */
242c2c66affSColin Finck item = LIST_ENTRY( head, struct undo_item, entry );
243c2c66affSColin Finck if (item->type == undo_end_transaction) return;
244c2c66affSColin Finck
245c2c66affSColin Finck if (item->type == undo_potential_end_transaction)
246c2c66affSColin Finck {
247c2c66affSColin Finck item->type = undo_end_transaction;
248c2c66affSColin Finck return;
249c2c66affSColin Finck }
250c2c66affSColin Finck
251c2c66affSColin Finck add_undo( editor, undo_end_transaction );
252c2c66affSColin Finck }
253c2c66affSColin Finck
254c2c66affSColin Finck /**
255c2c66affSColin Finck * Groups subsequent changes with previous ones for an undo if coalescing.
256c2c66affSColin Finck *
257c2c66affSColin Finck * Has no effect if the previous changes were followed by a ME_CommitUndo. This
258c2c66affSColin Finck * function will only have an affect if the previous changes were followed by
259c2c66affSColin Finck * a call to ME_CommitCoalescingUndo, which allows the transaction to be
260c2c66affSColin Finck * continued.
261c2c66affSColin Finck *
262c2c66affSColin Finck * This allows multiple consecutively typed characters to be grouped together
263c2c66affSColin Finck * to be undone by a single undo operation.
264c2c66affSColin Finck */
ME_ContinueCoalescingTransaction(ME_TextEditor * editor)265c2c66affSColin Finck void ME_ContinueCoalescingTransaction(ME_TextEditor *editor)
266c2c66affSColin Finck {
267c2c66affSColin Finck struct undo_item *item;
268c2c66affSColin Finck struct list *head;
269c2c66affSColin Finck
270c2c66affSColin Finck if (editor->nUndoMode == umIgnore)
271c2c66affSColin Finck return;
272c2c66affSColin Finck
273c2c66affSColin Finck assert(editor->nUndoMode == umAddToUndo);
274c2c66affSColin Finck
275c2c66affSColin Finck head = list_head( &editor->undo_stack );
276c2c66affSColin Finck if (!head) return;
277c2c66affSColin Finck
278c2c66affSColin Finck item = LIST_ENTRY( head, struct undo_item, entry );
279c2c66affSColin Finck if (item->type == undo_potential_end_transaction)
280c2c66affSColin Finck {
281c2c66affSColin Finck list_remove( &item->entry );
282c2c66affSColin Finck editor->nUndoStackSize--;
283c2c66affSColin Finck destroy_undo_item( item );
284c2c66affSColin Finck }
285c2c66affSColin Finck }
286c2c66affSColin Finck
287c2c66affSColin Finck /**
288c2c66affSColin Finck * Commits preceding changes into a undo transaction that can be expanded.
289c2c66affSColin Finck *
290c2c66affSColin Finck * This function allows the transaction to be reopened with
291c2c66affSColin Finck * ME_ContinueCoalescingTransaction in order to continue the transaction. If an
292c2c66affSColin Finck * undo item is added to the undo stack as a result of a change without the
293c2c66affSColin Finck * transaction being reopened, then the transaction will be ended, and the
294c2c66affSColin Finck * changes will become a part of the next transaction.
295c2c66affSColin Finck *
296c2c66affSColin Finck * This is used to allow typed characters to be grouped together since each
297c2c66affSColin Finck * typed character results in a single event, and each event adding undo items
298c2c66affSColin Finck * must be committed. Using this function as opposed to ME_CommitUndo allows
299c2c66affSColin Finck * multiple events to be grouped, and undone together.
300c2c66affSColin Finck */
ME_CommitCoalescingUndo(ME_TextEditor * editor)301c2c66affSColin Finck void ME_CommitCoalescingUndo(ME_TextEditor *editor)
302c2c66affSColin Finck {
303c2c66affSColin Finck struct undo_item *item;
304c2c66affSColin Finck struct list *head;
305c2c66affSColin Finck
306c2c66affSColin Finck if (editor->nUndoMode == umIgnore)
307c2c66affSColin Finck return;
308c2c66affSColin Finck
309c2c66affSColin Finck assert(editor->nUndoMode == umAddToUndo);
310c2c66affSColin Finck
311c2c66affSColin Finck head = list_head( &editor->undo_stack );
312c2c66affSColin Finck if (!head) return;
313c2c66affSColin Finck
314c2c66affSColin Finck /* no need to commit empty transactions */
315c2c66affSColin Finck item = LIST_ENTRY( head, struct undo_item, entry );
316c2c66affSColin Finck if (item->type == undo_end_transaction ||
317c2c66affSColin Finck item->type == undo_potential_end_transaction)
318c2c66affSColin Finck return;
319c2c66affSColin Finck
320c2c66affSColin Finck add_undo( editor, undo_potential_end_transaction );
321c2c66affSColin Finck }
322c2c66affSColin Finck
ME_PlayUndoItem(ME_TextEditor * editor,struct undo_item * undo)323c2c66affSColin Finck static void ME_PlayUndoItem(ME_TextEditor *editor, struct undo_item *undo)
324c2c66affSColin Finck {
325c2c66affSColin Finck
326c2c66affSColin Finck if (editor->nUndoMode == umIgnore)
327c2c66affSColin Finck return;
328c2c66affSColin Finck TRACE("Playing undo/redo item, id=%d\n", undo->type);
329c2c66affSColin Finck
330c2c66affSColin Finck switch(undo->type)
331c2c66affSColin Finck {
332c2c66affSColin Finck case undo_potential_end_transaction:
333c2c66affSColin Finck case undo_end_transaction:
334c2c66affSColin Finck assert(0);
335c2c66affSColin Finck case undo_set_para_fmt:
336c2c66affSColin Finck {
337c2c66affSColin Finck ME_Cursor tmp;
338c2c66affSColin Finck ME_DisplayItem *para;
339c2c66affSColin Finck ME_CursorFromCharOfs(editor, undo->u.set_para_fmt.pos, &tmp);
340c2c66affSColin Finck para = ME_FindItemBack(tmp.pRun, diParagraph);
341c2c66affSColin Finck add_undo_set_para_fmt( editor, ¶->member.para );
342c2c66affSColin Finck para->member.para.fmt = undo->u.set_para_fmt.fmt;
343c2c66affSColin Finck para->member.para.border = undo->u.set_para_fmt.border;
344*dbfaf10dSAmine Khaldi mark_para_rewrap(editor, para);
345c2c66affSColin Finck break;
346c2c66affSColin Finck }
347c2c66affSColin Finck case undo_set_char_fmt:
348c2c66affSColin Finck {
349c2c66affSColin Finck ME_Cursor start, end;
350c2c66affSColin Finck ME_CursorFromCharOfs(editor, undo->u.set_char_fmt.pos, &start);
351c2c66affSColin Finck end = start;
352c2c66affSColin Finck ME_MoveCursorChars(editor, &end, undo->u.set_char_fmt.len, FALSE);
353c2c66affSColin Finck ME_SetCharFormat(editor, &start, &end, &undo->u.set_char_fmt.fmt);
354c2c66affSColin Finck break;
355c2c66affSColin Finck }
356c2c66affSColin Finck case undo_insert_run:
357c2c66affSColin Finck {
358c2c66affSColin Finck ME_Cursor tmp;
359c2c66affSColin Finck ME_CursorFromCharOfs(editor, undo->u.insert_run.pos, &tmp);
360c2c66affSColin Finck ME_InsertRunAtCursor(editor, &tmp, undo->u.insert_run.style,
361c2c66affSColin Finck undo->u.insert_run.str,
362c2c66affSColin Finck undo->u.insert_run.len,
363c2c66affSColin Finck undo->u.insert_run.flags);
364c2c66affSColin Finck break;
365c2c66affSColin Finck }
366c2c66affSColin Finck case undo_delete_run:
367c2c66affSColin Finck {
368c2c66affSColin Finck ME_Cursor tmp;
369c2c66affSColin Finck ME_CursorFromCharOfs(editor, undo->u.delete_run.pos, &tmp);
370c2c66affSColin Finck ME_InternalDeleteText(editor, &tmp, undo->u.delete_run.len, TRUE);
371c2c66affSColin Finck break;
372c2c66affSColin Finck }
373c2c66affSColin Finck case undo_join_paras:
374c2c66affSColin Finck {
375c2c66affSColin Finck ME_Cursor tmp;
376c2c66affSColin Finck ME_CursorFromCharOfs(editor, undo->u.join_paras.pos, &tmp);
377c2c66affSColin Finck ME_JoinParagraphs(editor, tmp.pPara, TRUE);
378c2c66affSColin Finck break;
379c2c66affSColin Finck }
380c2c66affSColin Finck case undo_split_para:
381c2c66affSColin Finck {
382c2c66affSColin Finck ME_Cursor tmp;
383c2c66affSColin Finck ME_DisplayItem *this_para, *new_para;
384c2c66affSColin Finck BOOL bFixRowStart;
385c2c66affSColin Finck int paraFlags = undo->u.split_para.flags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND);
386c2c66affSColin Finck ME_CursorFromCharOfs(editor, undo->u.split_para.pos, &tmp);
387c2c66affSColin Finck if (tmp.nOffset)
388c2c66affSColin Finck ME_SplitRunSimple(editor, &tmp);
389c2c66affSColin Finck this_para = tmp.pPara;
390c2c66affSColin Finck bFixRowStart = this_para->member.para.nFlags & MEPF_ROWSTART;
391c2c66affSColin Finck if (bFixRowStart)
392c2c66affSColin Finck {
393c2c66affSColin Finck /* Re-insert the paragraph before the table, making sure the nFlag value
394c2c66affSColin Finck * is correct. */
395c2c66affSColin Finck this_para->member.para.nFlags &= ~MEPF_ROWSTART;
396c2c66affSColin Finck }
397c2c66affSColin Finck new_para = ME_SplitParagraph(editor, tmp.pRun, tmp.pRun->member.run.style,
398c2c66affSColin Finck undo->u.split_para.eol_str->szData, undo->u.split_para.eol_str->nLen, paraFlags);
399c2c66affSColin Finck if (bFixRowStart)
400c2c66affSColin Finck new_para->member.para.nFlags |= MEPF_ROWSTART;
401c2c66affSColin Finck new_para->member.para.fmt = undo->u.split_para.fmt;
402c2c66affSColin Finck new_para->member.para.border = undo->u.split_para.border;
403c2c66affSColin Finck if (paraFlags)
404c2c66affSColin Finck {
405c2c66affSColin Finck ME_DisplayItem *pCell = new_para->member.para.pCell;
406c2c66affSColin Finck pCell->member.cell.nRightBoundary = undo->u.split_para.cell_right_boundary;
407c2c66affSColin Finck pCell->member.cell.border = undo->u.split_para.cell_border;
408c2c66affSColin Finck }
409c2c66affSColin Finck break;
410c2c66affSColin Finck }
411c2c66affSColin Finck }
412c2c66affSColin Finck }
413c2c66affSColin Finck
ME_Undo(ME_TextEditor * editor)414c2c66affSColin Finck BOOL ME_Undo(ME_TextEditor *editor)
415c2c66affSColin Finck {
416c2c66affSColin Finck ME_UndoMode nMode = editor->nUndoMode;
417c2c66affSColin Finck struct list *head;
418c2c66affSColin Finck struct undo_item *undo, *cursor2;
419c2c66affSColin Finck
420c2c66affSColin Finck if (editor->nUndoMode == umIgnore) return FALSE;
421c2c66affSColin Finck assert(nMode == umAddToUndo || nMode == umIgnore);
422c2c66affSColin Finck
423c2c66affSColin Finck head = list_head( &editor->undo_stack );
424c2c66affSColin Finck if (!head) return FALSE;
425c2c66affSColin Finck
426c2c66affSColin Finck /* watch out for uncommitted transactions ! */
427c2c66affSColin Finck undo = LIST_ENTRY( head, struct undo_item, entry );
428c2c66affSColin Finck assert(undo->type == undo_end_transaction
429c2c66affSColin Finck || undo->type == undo_potential_end_transaction);
430c2c66affSColin Finck
431c2c66affSColin Finck editor->nUndoMode = umAddToRedo;
432c2c66affSColin Finck
433c2c66affSColin Finck list_remove( &undo->entry );
434c2c66affSColin Finck destroy_undo_item( undo );
435c2c66affSColin Finck
436c2c66affSColin Finck LIST_FOR_EACH_ENTRY_SAFE( undo, cursor2, &editor->undo_stack, struct undo_item, entry )
437c2c66affSColin Finck {
438c2c66affSColin Finck if (undo->type == undo_end_transaction) break;
439c2c66affSColin Finck ME_PlayUndoItem( editor, undo );
440c2c66affSColin Finck list_remove( &undo->entry );
441c2c66affSColin Finck destroy_undo_item( undo );
442c2c66affSColin Finck }
443c2c66affSColin Finck
444c2c66affSColin Finck ME_MoveCursorFromTableRowStartParagraph(editor);
445c2c66affSColin Finck add_undo( editor, undo_end_transaction );
446c2c66affSColin Finck ME_CheckTablesForCorruption(editor);
447c2c66affSColin Finck editor->nUndoStackSize--;
448c2c66affSColin Finck editor->nUndoMode = nMode;
449c2c66affSColin Finck ME_UpdateRepaint(editor, FALSE);
450c2c66affSColin Finck return TRUE;
451c2c66affSColin Finck }
452c2c66affSColin Finck
ME_Redo(ME_TextEditor * editor)453c2c66affSColin Finck BOOL ME_Redo(ME_TextEditor *editor)
454c2c66affSColin Finck {
455c2c66affSColin Finck ME_UndoMode nMode = editor->nUndoMode;
456c2c66affSColin Finck struct list *head;
457c2c66affSColin Finck struct undo_item *undo, *cursor2;
458c2c66affSColin Finck
459c2c66affSColin Finck assert(nMode == umAddToUndo || nMode == umIgnore);
460c2c66affSColin Finck
461c2c66affSColin Finck if (editor->nUndoMode == umIgnore) return FALSE;
462c2c66affSColin Finck
463c2c66affSColin Finck head = list_head( &editor->redo_stack );
464c2c66affSColin Finck if (!head) return FALSE;
465c2c66affSColin Finck
466c2c66affSColin Finck /* watch out for uncommitted transactions ! */
467c2c66affSColin Finck undo = LIST_ENTRY( head, struct undo_item, entry );
468c2c66affSColin Finck assert( undo->type == undo_end_transaction );
469c2c66affSColin Finck
470c2c66affSColin Finck editor->nUndoMode = umAddBackToUndo;
471c2c66affSColin Finck list_remove( &undo->entry );
472c2c66affSColin Finck destroy_undo_item( undo );
473c2c66affSColin Finck
474c2c66affSColin Finck LIST_FOR_EACH_ENTRY_SAFE( undo, cursor2, &editor->redo_stack, struct undo_item, entry )
475c2c66affSColin Finck {
476c2c66affSColin Finck if (undo->type == undo_end_transaction) break;
477c2c66affSColin Finck ME_PlayUndoItem( editor, undo );
478c2c66affSColin Finck list_remove( &undo->entry );
479c2c66affSColin Finck destroy_undo_item( undo );
480c2c66affSColin Finck }
481c2c66affSColin Finck ME_MoveCursorFromTableRowStartParagraph(editor);
482c2c66affSColin Finck add_undo( editor, undo_end_transaction );
483c2c66affSColin Finck ME_CheckTablesForCorruption(editor);
484c2c66affSColin Finck editor->nUndoMode = nMode;
485c2c66affSColin Finck ME_UpdateRepaint(editor, FALSE);
486c2c66affSColin Finck return TRUE;
487c2c66affSColin Finck }
488