We have taken the most common case, the user typing an ordinary character, and created an undo that does that efficiently . We could approach other optimizations in the same way. As they say in the textbooks , well leave those for the reader, but well talk about them briefly here.
Our current version of Undo for single-key typing requires the selection length to be zero. We could deal with single-character typing when the selection length is greater than zero fairly readily. I think we would just observe that the selection is there, and we would grab the characters into the Snapshot object. During undo, after deleting the typed character, we would insert the saved characters back, if there are any. I believe I would extend the existing SingleCharacterSnapshot class to do that.
The tag insertions all insert complete lines. It would be easy to create a snapshot object that for undo just deleted those lines. We would record the current line and the number of lines to be inserted. The tag insertions know that information. The implementation should be simple, and it would go in just one spot, the InsertTags area. I believe I would build a new Snapshot class to do that one.
With these changes, I believe that almost all the full snapshots would be eliminated. One remaining area that would trigger a full snapshot would be a cut or paste operation. These would be easy to implement in the TextModel: we would add those characters to those recognized in the KeyPress, and handle them. We would have to learn how to access the clipboard in Microsoft .NET, but the capability is there, in the Clipboard class.
It seems to me that each of these optimizations would be rather straightforward and the structure we have would support them readily.