Previous: Implementation, Up: Undo Protocol


18.4.7.3 How The Buffer Handles Undo

— Class: drei:undo-mixin

Class precedence list: undo-mixin, standard-object, slot-object, t

Slots:

This is a mixin class that buffer classes can inherit from. It contains an undo tree, an undo accumulator and a flag specifyng whether or not it is currently performing undo. The undo tree and undo accumulators are initially empty.

— Generic Function: drei:undo-tree buffer

The undo-tree object associated with the buffer. This usually contains a record of every change that has been made to the buffer since it was created.

Undo is implemented as :before methods on, insert-buffer-object, insert-buffer-sequence and delete-buffer-range specialized on undo-mixin.

— Generic Function: drei:undo-accumulate buffer

A list of the changes that have been made to buffer since the last time undo was added to the undo tree for the buffer. The list returned by this function is initially NIL (the empty list). The :before methods on insert-buffer-object, insert-buffer-sequence, and delete-buffer-range push undo records on to this list.

— Generic Function: drei:performing-undo buffer

If true, the buffer is currently performing an undo operation. The :before methods on insert-buffer-object, insert-buffer-sequence, and delete-buffer-range push undo records onto the undo accumulator only if performing-undo is false, so that no undo information is added as a result of an undo operation.

Three subclasses insert-record, delete-record, and compound-record of undo-record are used. An insert record stores a position and some sequence of objects to be inserted, a delete record stores a position and the length of the sequence to be deleted, and a compound record stores a list of other undo records.

The :before methods on insert-buffer-object and insert-buffer-sequence push a record of type delete-record onto the undo accumulator for the buffer, and the :before method on delete-buffer-range pushes a record of type insert-record onto the undo accumulator.

— Macro: drei:with-undo (get-buffers-exp) &body body

This macro executes the forms of body, registering changes made to the list of buffers retrieved by evaluating get-buffers-exp. When body has run, for each buffer it will call add-undo with an undo record and the undo tree of the buffer. If the changes done by body to the buffer has resulted in only a single undo record, it is passed as is to add-undo. If it contains several undo records, a compound undo record is constructed out of the list and passed to add-undo. Finally, if the buffer has no undo records, add-undo is not called at all.

To avoid storing an undo record for each object that is inserted, the with-undo macro may in some cases just increment the length of the sequence in the last delete-record.

The method on flip-undo-record specialized on insert-record binds performing-undo for the buffer to T, inserts the sequence of objects in the buffer, and calls change-class to convert the insert-record to a delete-record, giving it a the length of the stored sequence.

The method on flip-undo-record specialized on delete-record binds performing-undo for the buffer to T, deletes the range from the buffer, and calls change-class to convert the delete-record to an insert-record, giving it the sequence at the stored offset in the buffer with the specified length.

The method on flip-undo-record specialized on compound-record binds performing-undo for the buffer to T, recursively calls flip-undo-record on each element of the list of undo records, and finally destructively reverses the list.

— Class: drei:drei-undo-record

Class precedence list: drei-undo-record, standard-undo-record, undo-record, standard-object, slot-object, t

Slots:

A base class for all output records in Drei.

— Class: drei:simple-undo-record

Class precedence list: simple-undo-record, drei-undo-record, standard-undo-record, undo-record, standard-object, slot-object, t

Slots:

A base class for output records that modify buffer contents at a specific offset.

— Class: drei:insert-record

Class precedence list: insert-record, simple-undo-record, drei-undo-record, standard-undo-record, undo-record, standard-object, slot-object, t

Slots:

Whenever objects are deleted, the sequence of objects is stored in an insert record containing a mark.

— Class: drei:delete-record

Class precedence list: delete-record, simple-undo-record, drei-undo-record, standard-undo-record, undo-record, standard-object, slot-object, t

Slots:

Whenever objects are inserted, a delete-record containing a mark is created and added to the undo tree.

— Class: drei:compound-record

Class precedence list: compound-record, drei-undo-record, standard-undo-record, undo-record, standard-object, slot-object, t

Slots:

This record simply contains a list of other records.