![]() |
|
#1
|
|||
|
|||
How to implement an "undo" routine in a programI have wondered about this and thought I'd ask.
I guess it would depend on what you were doing in the program that you wanted to 'undo'. A huge example would be say in a graphical window program like Firefox where you can udo all kinds of stuff from the text changes in this box to the url bar. Would each of them need a separate 'undo' routine? Is it impoemented through system API? Other examples would be a Excel or OpenOffice Calc, Paint or Gimp or Notepad or Gedit or even the non graphical vim editor in linux whichhas an undo capability. Take Vim , how do you think they implement that edit mode > hit 'u' undo? Do you store a list of changes somehow? Thanks, Howard |
|||
|
#2
|
|||
|
|||
Re: how to implement an "undo" routine in a programMy guess is that you would gather everything that would constitute the program state (such as text in text boxes, selected indices of list boxes, etc) into a single object. Then you would have a routine that would load one of these objects so that your program would reflect that state. You would have a collection of these state objects and every time you change something, update this object and add it to the collection so that you can retrieve it later.
|
|
#3
|
|||
|
|||
Re: how to implement an "undo" routine in a programQuote:
In general terms, the action may be equivalent to the following (implementation details may be different, but maybe this is a starting point for a Gedanken experiment at least). For a given application, every command that is "undoable" has some action that saves the "delta" from the state prior to the command and the state after the command. So, if you delete some text, you save the text in a "delta" object. Sometimes there are two stacks: an "undo" stack and a "redo" stack. Delta objects of undoable commands are saved on the "undo" stack. That is, if your last command was to delete some text, the text (as well as its position in the file and other characteristics necessary to restore it) is saved on the "undo" stack. Then if you If execute an "undo" command, it restores the text, that stuff is removed from the "undo" stack and stored on the "redo" stack. That way you can "redo" the previous command(s). With vim, try entering some text. Then "undo" it, so the newly entered text is deleted. Now, if you decide you want it there after all, you don't have to type it in again, just issue a "redo" command. You see, the delta objects on the stacks have all information needed to get you from there to here: in this case the text itself and, of course the command (whether it was "insert" or "delete" or whatever). Stuff like that. Here are a couple of articles that I think are interesting, and maybe there are enough details to experiment with your own application: http://us.geocities.com/evilsnack/undo.htm and http://us.geocities.com/evilsnack/undo2.htm Finally... According to vim documentation: http://vimdoc.sourceforge.net/htmldoc/usr_02.html#02.5 and http://vimdoc.sourceforge.net/htmldoc/usr_32.html rather than using an "undo" stack and a "redo" stack, the command history is stored in a tree. You can navigate around the tree in interesting ways. (Ways that I, maybe, don't need very much, but I am continually amazed at the general excellence and flexibility and downright usefulness of vim.) Mind-boggling, right? Or is it just me? The original vi editor only had one level of undo. If you did an "undo" and then another "undo", the second "undo" undid the first "undo," so the original was restored. If you did a couple of "bad" things, you couldn't go back more than one command. Bummer. If you decide to try some undo stuff with your own program, maybe start with one level of undo. Then decide whether you want a stack or tree (or whatever) to hold the command history. Sounds like fun! The multi-level undo of vim encourages us to experiment with all kinds of good stuff in trying to groom the contents of text files, since we can always execute repetitive "undo" steps to keep from destroying file contents and maybe preserve that little wisp of sanity that (I like to think) remains in my tired old head. Quote:
Actually, according to my muse (She Whose Name Must Not Be Spoken), the answer to all questions is: "It depends." She's funny that way. Regards, Dave |
|
#4
|
|||
|
|||
Re: how to implement an "undo" routine in a programAccording to the '4 Horsemen' (Gamma, Helm, Johnson, Vlissides), the pattern for this is called the Command pattern AKA Action or Transaction.
There is a complete example of this in their book (Design Patterns) but the general idea is this: coupled with the support of another pattern, Memento, you save state and provide an execute/unexecute interface. The example in the book is as follows (with some modifications to expose the UnExecute and Memento) CPP / C++ / C Code:
__________________
My personal site: Utilities for text processing, debugging, testing and plotting |
|
#5
|
|||
|
|||
Re: how to implement an "undo" routine in a programwell, I stepped in it again didn't I....
Oh well , no pain - no gain and all that , I will have to do some reading and thinking for shure. Seems like a good place to start would be editing a string or paragraph. Thanks for the ideas you guys . I'll be back after I get something going... hopefully |
|
#6
|
||||
|
||||
Re: how to implement an "undo" routine in a programQuote:
...never heard GoF referred to has 4 Horsemen before, but I'm thinking that, while interesting to the problem domain, references to DPs in the context of a C (as opposed to C++) programming forum section would be less desirable than a C-centric undo/redo example. However, you *can* implement it in C using opaque pointers without the data protection benefit. It seems that that would have been more interesting in the context of this forum. Perhaps better than a code fragment would be a link? While certainly dated, here is an example in code that (with minor modifications) illustrates the point: http://www.vincehuston.org/dp/MementoDemosCpp ...this site is a rather useful DP site. Here is the code "cleaned up" so that it compiles (some formatting may be lost): CPP / C++ / C Code:
...still of questionable use in a C-context. MxB |
|
#7
|
|||
|
|||
Re: How to implement an "undo" routine in a programQuote:
__________________
My personal site: Utilities for text processing, debugging, testing and plotting |
|
#8
|
||||
|
||||
Re: How to implement an "undo" routine in a programQuote:
Okay, so how do you implement Observer in FORTRAN? Have you tried applying DPs to assembly language? In a way, DPs are completely agnostic (unknown) in some languages. My point, which probably wasn't very well taken was that a C++ code fragment as a solution in the context of a C programming forum isn't as helpful as a C-centric solution. This is not to suggest that DPs are not useful for non-C++ programmers to learn, but in the context of Undo/Redo in C, where is your expose on using opaque pointers to implement "C-with classes" so that these patterns that you profess may be realized? Just because C and C++ are similar syntactically, doesn't mean that they are the same language or that a C programmer will understand any of the advanced capabilities provided by C++. For someone with no exposure to C++, you may as well be speaking Russian. Some of the characters look familiar, but what do they all mean when put together? In fact, an important point in my reply was that a link to design pattern content was probably more useful than a C++ code fragment that *partially* realizes the solution while does very little to actually disclose the pattern except through a bit of the internals. Why send the OP on a scavenger hunt to make heads or tails of the post? ...particularly if the OP is not a C++ programmer, which, in the context of a C forum, one would expect that C code would be preferred. There is nothing "wrong" with discussing DPs to solve the OP's problem. However, there was substantially no discussion of the patterns or even any links to any relevant sites that do discuss applicable patterns. Of course, you named a few, so the eager reader could obviously google into it, but that's not my point. A C++ "implementation" is not a discussion of any DP in the context of a C forum. My point was "references to Design Patterns" in that by invoking the ethos of the ethereal existence of some magical solution to common programming challenges and supporting such conjuring with a fragment of C++ code doesn't really qualify as "help" in the context of a C forum and is therefore "less desirable than a C-centric undo/redo example." Of course, that's just my opinion. While your reply provided some gems in the rough for further research, it didn't well address the problem at hand. It didn't even go so far as to suggest that even though the C++ fragment was not C, but that DP-based implementations for C "could be found" somewhere. And the "complete example" is given incompletely and is C++ code and not C code. We don't even have a one sentence defintion of what DPs are. Again, nothing that an eager reader couldn't google, rather, not exactly embracing the problem in a C-centric manner. While all of this must undoubtedly sound extremely critical, particularly as "labored" as it must appear considering the wordcount, that is not my objective. No, my effort here is to challenge you to come up with more useful, more helpful replies, if you're so inclined. However, I'd also ask you to please consider not power selling me on the merits of a so-so post. Just because DPs are useful and tend to be applicable across a varieity of languages, doesn't mean that your mentioning of them and a code fragment is all that useful. If you do want your posts to be more useful, and I believe that you do, then they should stand on their own. That is not to say that we all don't sometimes post something that "doesn't quite work," but when we do, let's not upsell it. I guess that this means no more positive "reputation" for me from you, huh? MxB |
Recent GIDBlog
Programming ebook direct download available by crystalattice
| Thread Tools | Search this Thread |
| Rate This Thread | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Equation solver | RazoR | C Programming Language | 3 | 18-May-2008 10:24 |
| Write a C++ program to implement a cash register program | Computeretard66 | C++ Forum | 2 | 29-Feb-2008 09:05 |
| Two-Tier data dissemination code installation problem | nidhibansal1984 | Computer Software Forum - Linux | 6 | 16-Sep-2007 11:13 |
| Text-Based Roulette Game | mfm1983 | C++ Forum | 5 | 29-Nov-2006 13:20 |
Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The