You can do it in two ways:
- keep a list of editor states and a pointer in the list; undo moves the pointer back and restores the state there, redo moves forward instead, doing something throws away everything beyond the pointer and inserts the state as the new top element;
- do not keep states, but actions, which requires that for every action you have a counteraction to undo the effects of that action
In my (diagram) editor, there are four levels of state changes:
- action fragments: these are part of a larger action and not separately undoable or redoable
(e.g. moving the mouse)
- actions: one or more action fragments that form a meaningful change which can be undone or redone,
but which are not reflected in the edited document as changed on disk
(e.g. selecting elements)
- document changes: one or more actions that change the edited document as it would be saved to disk
(e.g. changing, adding or deleting elements)
- document saves: the present state of the document is explicitly saved to disk - at this point my editor throws away the undo history, so you can't undo past a save