Undo, a few pointers at how to code the Undo function for a text editor

ARA (May 2 2009)

Question

OK I have a good one. I am working on the Undo function for a program that saves automatically and I am going from a disaster to another. Here is why. Undo does the reverse of the last function which is what it is supposed to do. So far so good. But what happens when the last function is the automatic save? Then it unsaves and it screws up the page, deleting all the contents. Wonderful. Great saving of space. Seriously, what do I do to avoid this situation?

I might decide to take out the Undo button altogether since it is a constant source of headaches. Perhaps the best would be to create a file that would hold all the deleted text and would disappear when I exit. Any suggestions on how to do this?

Finally I'd like to do a back-up of the current page in a directory called back-up that would be attached to the current directory and would make back-ups every 6 minutes on top of the regular automatic saving. I don't want to keep all back-ups simply the latest one. Any suggestions?

I am sure even Microsoft must have bumped into the problem at one point despite the fact that all their text editors save on demand. If you hit Undo after a save in Word, Notepad or in Wordpad, I am sure it won't screw up the page. The key here is to have the program discriminate between a save function and a regular text add-on, edit or delete. If it is a save function, the undo won't work, if if it is a text function (add, edit or delete text) it will work. The problem is: how to make the program discriminate between a text edit and a function such as save? This is the key to the problem. Easier said than done.

The pseudo-code for this will be: if the last moves have been other moves then edit, delete or type in new text, don't do anything; if the last moves have been to edit text, delete text or type in new text, do Undo.

I am learning little by little so please consider that I am not an all-around expert on programming. Thanks a great deal for your help.


Answer

MG I'm not quite sure how you're running into this problem. The text widget has a built-in undo/redo feature which is only triggered by the editing of text. The widget itself has no "save" function, and coding your own normally just involves doing

  $textWidget get 1.0 end-1char

and dumping the result into a file, so I'm not sure how saving is triggering your undo code. Can you give some more info on what you're doing, or put the code up somewhere?

ARA Thanks a lot for your help, MG. Here is the code:

  proc do.undo {} {
  if [$::current_ht edit modified ] {
  if [catch {$::current_ht edit undo}] {
  return

} } }

Please note that I am not using a text widget.

Also in the create menu function I have this:

-undo 1 \

-maxundo 10

NEM Which widget are you using? The text widget is the only core widget with an undo feature, IIRC.

MG The command/option names shown in your code there do fit perfectly with Tk 8.5's text widget; to the best of my knowledge there aren't any other widgets that support all of those options/subcommands built-in. You'll likely need to post a larger snippet, at least showing how the widget is created and how the do.undo proc is being called, for us to help any further. If all the code for managing the undo stack is custom, and not coming from the text widget's built-in undo support, we'd need to see that, too.

ARA I took over someone else's code. How can I tell if a widget is called? All I have is a Tcl script. If there was a widget, would it be an attached file? How would it present itself? Sorry for my ignorance.

ARA, a few days later. I don't think a widget of any kind is called. The undo seems to be custom. I reproduced the bug in great detail and this is what I gathered:

The program works with a split screen and a full screen; when I am on the full screen the undo is coded to act once so I don't get the bug (the max undo function is inserted in the create gui function).

However, I do get the bug when I am on the left screen.

Similarly, what I need to do is put the max undo function in the function that creates the left screen. I'll try that.