TIP:            104
Title:          Generalization of the Tk Undo Subsystem
Version:        $Revision: 1.6 $
Author:         Ludwig Callewaert <ludwig.callewaert@belgacom.net>
Author:         Larry W. Virden. <lvirden@yahoo.com>
State:          Final
Type:           Project
Vote:           Done
Created:        19-Jun-2002
Post-History:   
Discussions-To: news:comp.lang.tcl
Tcl-Version:    8.4

~ Abstract

This TIP proposes a reimplementation of the Tk Text widget undo
feature.  The text widget interface is not affected.  No functional
changes are made at the Tcl level.  The purpose of the
reimplementation is to move the undo feature from a text only
implementation to a general implementation also usable by other
widgets.  This opens the door to undoing also tag, mark and other
operations, and allows for an exposure of the undo stack at the Tcl
level.  These new features are however not part of this TIP.

~ Rationale

As stated in the abstract, the current implementation of the text
widget undo feature only allows for text changes to be undone.  The
usefulness of the undo feature would increase tremendously if
other operations could be undone (tags, marks, embedded windows, ...).
This was already part of the [26] discussions.  This TIP deals with
the generalization of the undo stack to cope with these requirements.

~ Specification

As the undo functionality is no longer text widget specific, it has
been put in a separate file ''generic/tkUndo.c'' along with its header
file ''generic/tkUndo.h''.  The ''TkUndoRedoStack'' is a structure
containing the undo and redo stacks.  These undo and redo stacks are
linked lists of ''TkUndoAtom'' structures.  There are two types of
these atoms: the separator (similar to the previous implementation)
and the command.  When the type is command, both an ''apply'' and a
''revert'' action need to be provided.  The apply action is for the
redo.  The revert action is for the undo.  Both are pointers to a
''Tcl_Obj'', so they can (and should) contain a Tcl script.

The following functions all operating on a ''TkUndoRedoStack''
stack are provided to implement the undo/redo functionality.

   1. ''TkUndoInitStack(interp)'': returns a pointer to an initialized
      TkUndoRedoStack and stores ''interp'' in that stack for script
      evaluation.

   2. ''TkUndoClearStacks(stack)'': clears both the undo and the redo
      stacks.

   3. ''TkUndoFreeStack(stack)'': clears both undo and redo stacks and
      frees any memory allocated to ''stack''.

   4. ''TkUndoInsertUndoSeparator(stack)'': inserts a
      separator on the undo stack.  Note that there is currently no
      need for a ''TkUndoInsertRedoSeparator'' function, as the redo
      stack is managed by the internals of ''TkUndo''.

   5. ''TkUndoPushAction(stack, actionScript, revertScript)'': pushes 
      an action of the undo stack (an atom of type command).
      ''actionScript'' and ''revertScript'' are ''Tcl_DString''
      pointers that provide the script to redo and undo the action
      respectively.  The redo stack is cleared.

   6. ''TkUndoRevert(stack)'': undo a compound action.
      Compound means all revert script of action between two
      separators on the undo stack are evaluated in the stack's 
      interpreter and the actions are moved to the redo stack.
      Returns TCL_ERROR when unsuccessful (stack empty for instance),
      and TCL_OK otherwise.

   7. ''TkUndoApply(stack)'': redo a compound action.  The
      apply script of all actions between two separators on the redo
      stack is evaluated in the stack's interpreter.  The actions are
      moved to the undo stack.  Returns TCL_ERROR when unsuccessful
      (stack empty for instance), and TCL_OK otherwise.

   8. ''TkUndoSetDepth(stack, maxDepth)'': sets the maximum number
      of compound actions stored on the stack to ''maxDepth''.  By
      default, stacks are unlimited, and a value of ''maxDepth'' <= 0
      resets the stack to be unlimited.

   9. The option ''-maxundo'' is added to the text widget to access the
      stack limit feature of the text widget's undo stack from the
      script level.

These functions are sufficient to implement the current undo
functionality of the text widget, and they have been used for this
purpose.

~ Reference Implementation

See patch #554763 on SourceForge: ''
https://sourceforge.net/tracker/?func=detail&atid=312997&aid=554763&group_id=12997
''

~ Copyright

This document has been placed in the public domain.

