~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/riched20/undo.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * RichEdit - functions dealing with editor object
  3  *
  4  * Copyright 2004 by Krzysztof Foltman
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #include "editor.h"
 22 
 23 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
 24 
 25 void ME_EmptyUndoStack(ME_TextEditor *editor)
 26 {
 27   ME_DisplayItem *p, *pNext;
 28   
 29   if (editor->nUndoMode == umIgnore)
 30     return;
 31   
 32   TRACE("Emptying undo stack\n");
 33 
 34   p = editor->pUndoStack;
 35   editor->pUndoStack = editor->pUndoStackBottom = NULL;
 36   editor->nUndoStackSize = 0;
 37   while(p) {
 38     pNext = p->next;
 39     ME_DestroyDisplayItem(p);    
 40     p = pNext;
 41   } 
 42   p = editor->pRedoStack;
 43   editor->pRedoStack = NULL;
 44   while(p) {
 45     pNext = p->next;
 46     ME_DestroyDisplayItem(p);    
 47     p = pNext;
 48   } 
 49 }
 50 
 51 ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_DisplayItem *pdi) {
 52   if (editor->nUndoMode == umIgnore)
 53     return NULL;
 54   else if (editor->nUndoLimit == 0)
 55     return NULL;
 56   else
 57   {
 58     ME_DisplayItem *pItem = (ME_DisplayItem *)ALLOC_OBJ(ME_UndoItem);
 59     ((ME_UndoItem *)pItem)->nCR = ((ME_UndoItem *)pItem)->nLF = -1;
 60     switch(type)
 61     {
 62     case diUndoEndTransaction:
 63       break;
 64     case diUndoSetParagraphFormat:
 65       assert(pdi);
 66       pItem->member.para = pdi->member.para;
 67       pItem->member.para.pFmt = ALLOC_OBJ(PARAFORMAT2);
 68       *pItem->member.para.pFmt = *pdi->member.para.pFmt;
 69       break;
 70     case diUndoInsertRun:
 71       assert(pdi);
 72       pItem->member.run = pdi->member.run;
 73       pItem->member.run.strText = ME_StrDup(pItem->member.run.strText);
 74       ME_AddRefStyle(pItem->member.run.style);
 75       if (pdi->member.run.ole_obj)
 76       {
 77         pItem->member.run.ole_obj = ALLOC_OBJ(*pItem->member.run.ole_obj);
 78         ME_CopyReObject(pItem->member.run.ole_obj, pdi->member.run.ole_obj);
 79       }
 80       else pItem->member.run.ole_obj = NULL;
 81       break;
 82     case diUndoSetCharFormat:
 83     case diUndoSetDefaultCharFormat:
 84       break;
 85     case diUndoDeleteRun:
 86     case diUndoJoinParagraphs:
 87       break;
 88     case diUndoSplitParagraph:
 89       pItem->member.para.pFmt = ALLOC_OBJ(PARAFORMAT2);
 90       pItem->member.para.pFmt->cbSize = sizeof(PARAFORMAT2);
 91       pItem->member.para.pFmt->dwMask = 0;
 92  
 93       break;
 94     default:
 95       assert(0 == "AddUndoItem, unsupported item type");
 96       return NULL;
 97     }
 98     pItem->type = type;
 99     pItem->prev = NULL;
100     if (editor->nUndoMode == umAddToUndo || editor->nUndoMode == umAddBackToUndo)
101     {
102       if (editor->nUndoMode == umAddToUndo)
103         TRACE("Pushing id=%s to undo stack, deleting redo stack\n", ME_GetDITypeName(type));
104       else
105         TRACE("Pushing id=%s to undo stack\n", ME_GetDITypeName(type));
106 
107       pItem->next = editor->pUndoStack;
108       if (type == diUndoEndTransaction)
109         editor->nUndoStackSize++;
110       if (editor->pUndoStack)
111         editor->pUndoStack->prev = pItem;
112       else
113         editor->pUndoStackBottom = pItem;
114       editor->pUndoStack = pItem;
115       
116       if (editor->nUndoStackSize > editor->nUndoLimit)
117       { /* remove oldest undo from stack */
118         ME_DisplayItem *p = editor->pUndoStackBottom;
119         while (p->type !=diUndoEndTransaction)
120           p = p->prev; /*find new stack bottom */
121         editor->pUndoStackBottom = p->prev;
122           editor->pUndoStackBottom->next = NULL;
123         do
124         {
125           ME_DisplayItem *pp = p->next;
126           ME_DestroyDisplayItem(p);
127           p = pp;
128         } while (p);
129         editor->nUndoStackSize--;
130       }
131       /* any new operation (not redo) clears the redo stack */
132       if (editor->nUndoMode == umAddToUndo) {
133         ME_DisplayItem *p = editor->pRedoStack;
134         while(p)
135         {
136           ME_DisplayItem *pp = p->next;
137           ME_DestroyDisplayItem(p);
138           p = pp;
139         }
140         editor->pRedoStack = NULL;
141       }
142     }
143     else if (editor->nUndoMode == umAddToRedo)
144     {
145       TRACE("Pushing id=%s to redo stack\n", ME_GetDITypeName(type));
146       pItem->next = editor->pRedoStack;
147       if (editor->pRedoStack)
148         editor->pRedoStack->prev = pItem;
149       editor->pRedoStack = pItem;
150     }
151     else
152       assert(0);
153     return (ME_UndoItem *)pItem;
154   }
155 }
156 
157 void ME_CommitUndo(ME_TextEditor *editor) {
158   if (editor->nUndoMode == umIgnore)
159     return;
160   
161   assert(editor->nUndoMode == umAddToUndo);
162   
163   /* no transactions, no need to commit */
164   if (!editor->pUndoStack)
165     return;
166 
167   /* no need to commit empty transactions */
168   if (editor->pUndoStack->type == diUndoEndTransaction)
169     return;
170     
171   ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
172   ME_SendSelChange(editor);
173 }
174 
175 static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
176 {
177   ME_UndoItem *pUItem = (ME_UndoItem *)pItem;
178 
179   if (editor->nUndoMode == umIgnore)
180     return;
181   TRACE("Playing undo/redo item, id=%s\n", ME_GetDITypeName(pItem->type));
182 
183   switch(pItem->type)
184   {
185   case diUndoEndTransaction:
186     assert(0);
187   case diUndoSetParagraphFormat:
188   {
189     ME_Cursor tmp;
190     ME_CursorFromCharOfs(editor, pItem->member.para.nCharOfs, &tmp);
191     ME_SetParaFormat(editor, ME_FindItemBack(tmp.pRun, diParagraph), pItem->member.para.pFmt);
192     break;
193   }
194   case diUndoSetCharFormat:
195   {
196     ME_SetCharFormat(editor, pUItem->nStart, pUItem->nLen, &pItem->member.ustyle->fmt);
197     break;
198   }
199   case diUndoSetDefaultCharFormat:
200   {
201     ME_SetDefaultCharFormat(editor, &pItem->member.ustyle->fmt);
202     break;
203   }
204   case diUndoInsertRun:
205   {
206     ME_InsertRun(editor, pItem->member.run.nCharOfs, pItem);
207     break;
208   }
209   case diUndoDeleteRun:
210   {
211     ME_InternalDeleteText(editor, pUItem->nStart, pUItem->nLen);
212     break;
213   }
214   case diUndoJoinParagraphs:
215   {
216     ME_Cursor tmp;
217     ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
218     /* the only thing that's needed is paragraph offset, so no need to split runs */
219     ME_JoinParagraphs(editor, ME_GetParagraph(tmp.pRun));
220     break;
221   }
222   case diUndoSplitParagraph:
223   {
224     ME_Cursor tmp;
225     ME_DisplayItem *new_para;
226     ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
227     if (tmp.nOffset)
228       tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset);
229     assert(pUItem->nCR >= 0);
230     assert(pUItem->nLF >= 0);
231     new_para = ME_SplitParagraph(editor, tmp.pRun, tmp.pRun->member.run.style,
232       pUItem->nCR, pUItem->nLF);
233     assert(pItem->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
234     *new_para->member.para.pFmt = *pItem->member.para.pFmt;
235     break;
236   }
237   default:
238     assert(0 == "PlayUndoItem, unexpected type");
239   }
240 }
241 
242 void ME_Undo(ME_TextEditor *editor) {
243   ME_DisplayItem *p;
244   ME_UndoMode nMode = editor->nUndoMode;
245   
246   if (editor->nUndoMode == umIgnore)
247     return;
248   assert(nMode == umAddToUndo || nMode == umIgnore);
249   
250   /* no undo items ? */
251   if (!editor->pUndoStack)
252     return;
253     
254   /* watch out for uncommitted transactions ! */
255   assert(editor->pUndoStack->type == diUndoEndTransaction);
256   
257   editor->nUndoMode = umAddToRedo;
258   p = editor->pUndoStack->next;
259   ME_DestroyDisplayItem(editor->pUndoStack);
260   do {
261     ME_DisplayItem *pp = p;
262     ME_PlayUndoItem(editor, p);
263     p = p->next;
264     ME_DestroyDisplayItem(pp);
265   } while(p && p->type != diUndoEndTransaction);
266   ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
267   editor->pUndoStack = p;
268   editor->nUndoStackSize--;
269   if (p)
270     p->prev = NULL;
271   editor->nUndoMode = nMode;
272   ME_UpdateRepaint(editor);
273 }
274 
275 void ME_Redo(ME_TextEditor *editor) {
276   ME_DisplayItem *p;
277   ME_UndoMode nMode = editor->nUndoMode;
278   
279   assert(nMode == umAddToUndo || nMode == umIgnore);
280   
281   if (editor->nUndoMode == umIgnore)
282     return;
283   /* no redo items ? */
284   if (!editor->pRedoStack)
285     return;
286     
287   /* watch out for uncommitted transactions ! */
288   assert(editor->pRedoStack->type == diUndoEndTransaction);
289   
290   editor->nUndoMode = umAddBackToUndo;
291   p = editor->pRedoStack->next;
292   ME_DestroyDisplayItem(editor->pRedoStack);
293   do {
294     ME_DisplayItem *pp = p;
295     ME_PlayUndoItem(editor, p);
296     p = p->next;
297     ME_DestroyDisplayItem(pp);
298   } while(p && p->type != diUndoEndTransaction);
299   ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
300   editor->pRedoStack = p;
301   if (p)
302     p->prev = NULL;
303   editor->nUndoMode = nMode;
304   ME_UpdateRepaint(editor);
305 }
306 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.