<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE TIP SYSTEM "http://www.tcl.tk/cgi-bin/tct/tip/tipxml.dtd">
<!-- Converted at Fri Feb 10 14:54:26 GMT 2012 -->
<!-- TIP AutoGenerator - written by Donal K. Fellows -->

<TIP number='104'>
<header><title>Generalization of the Tk Undo Subsystem</title><author address="mailto:ludwig.callewaert@belgacom.net">Ludwig Callewaert</author><author address="mailto:lvirden@yahoo.com">Larry W. Virden.</author><status type='project' state='final' tclversion="8.4" vote='after'>$Revision: 1.6 $</status><history></history><created day='19' month='jun' year='2002' /><discussions url='news:comp.lang.tcl'/></header>
<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.</abstract>
<body><section title="Rationale">
<para>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 <tipref type="text" tip="26"/> discussions. This TIP deals with the generalization of the undo stack to cope with these requirements.</para>
</section>
<section title="Specification">
<para>As the undo functionality is no longer text widget specific, it has been put in a separate file <emph style="italic">generic/tkUndo.c</emph> along with its header file <emph style="italic">generic/tkUndo.h</emph>. The <emph style="italic">TkUndoRedoStack</emph> is a structure containing the undo and redo stacks. These undo and redo stacks are linked lists of <emph style="italic">TkUndoAtom</emph> 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 <emph style="italic">apply</emph> and a <emph style="italic">revert</emph> action need to be provided. The apply action is for the redo. The revert action is for the undo. Both are pointers to a <emph style="italic">Tcl_Obj</emph>, so they can (and should) contain a Tcl script.</para>
<para>The following functions all operating on a <emph style="italic">TkUndoRedoStack</emph> stack are provided to implement the undo/redo functionality.</para>
<describe><item.d name='1. &apos;&apos;TkUndoInitStack(interp)&apos;&apos;'><para>returns a pointer to an initialized TkUndoRedoStack and stores <emph style="italic">interp</emph> in that stack for script evaluation.</para></item.d><item.d name='2. &apos;&apos;TkUndoClearStacks(stack)&apos;&apos;'><para>clears both the undo and the redo stacks.</para></item.d><item.d name='3. &apos;&apos;TkUndoFreeStack(stack)&apos;&apos;'><para>clears both undo and redo stacks and frees any memory allocated to <emph style="italic">stack</emph>.</para></item.d><item.d name='4. &apos;&apos;TkUndoInsertUndoSeparator(stack)&apos;&apos;'><para>inserts a separator on the undo stack. Note that there is currently no need for a <emph style="italic">TkUndoInsertRedoSeparator</emph> function, as the redo stack is managed by the internals of <emph style="italic">TkUndo</emph>.</para></item.d><item.d name='5. &apos;&apos;TkUndoPushAction(stack, actionScript, revertScript)&apos;&apos;'><para>pushes an action of the undo stack (an atom of type command). <emph style="italic">actionScript</emph> and <emph style="italic">revertScript</emph> are <emph style="italic">Tcl_DString</emph> pointers that provide the script to redo and undo the action respectively. The redo stack is cleared.</para></item.d><item.d name='6. &apos;&apos;TkUndoRevert(stack)&apos;&apos;'><para>undo a compound action. Compound means all revert script of action between two separators on the undo stack are evaluated in the stack&apos;s interpreter and the actions are moved to the redo stack. Returns TCL_ERROR when unsuccessful (stack empty for instance), and TCL_OK otherwise.</para></item.d><item.d name='7. &apos;&apos;TkUndoApply(stack)&apos;&apos;'><para>redo a compound action. The apply script of all actions between two separators on the redo stack is evaluated in the stack&apos;s interpreter. The actions are moved to the undo stack. Returns TCL_ERROR when unsuccessful (stack empty for instance), and TCL_OK otherwise.</para></item.d><item.d name='8. &apos;&apos;TkUndoSetDepth(stack, maxDepth)&apos;&apos;'><para>sets the maximum number of compound actions stored on the stack to <emph style="italic">maxDepth</emph>. By default, stacks are unlimited, and a value of <emph style="italic">maxDepth</emph> &lt;= 0 resets the stack to be unlimited.</para></item.d></describe><enumerate><item.e index='9'><para>The option <emph style="italic">-maxundo</emph> is added to the text widget to access the stack limit feature of the text widget&apos;s undo stack from the script level.</para></item.e></enumerate>
<para>These functions are sufficient to implement the current undo functionality of the text widget, and they have been used for this purpose.</para>
</section>
<section title="Reference Implementation">
<para>See patch #554763 on SourceForge: <emph style="italic"> <url ref="https://sourceforge.net/tracker/?func=detail&amp;atid=312997&amp;aid=554763&amp;group_id=12997"/> </emph></para>
</section>
<section title="Copyright">
<para>This document has been placed in the public domain.</para>
</section>
</body></TIP>

