Saving selection into undo history

Neil Hodgson <[email protected]> Wed, 22 Jan 2025 03:52:24 -0800 (PST)
Newsgroups gmane.comp.lib.scintilla.devel
Message-ID <[email protected]>
A new feature was committed that allows restoration of the selection when 
performing undo and redo. It is turned on and off with an API 
SCI_SETSELECTIONUNDOHISTORY(bool selectionUndoHistory).

This only stores selections associated with text modifications, it is not a 
general navigation stack that can travel back through the areas examined by 
the user. It also does not store the scroll position at the time of 
modification (as the view is scrolled to show the restored selection) 
although the scroll position could be added.

There may still be issues with this. Existing command implementation code 
may need to change to cooperate with saving selections precisely, both 
inside Scintilla and within application code. SCI_SETSELECTIONUNDOHISTORY 
currently takes a simple bool but it may change to take a bit mask turning 
sub-features on and off. Unlike many undo features, this one doesn't depend 
on a complete history back to the start of undo - it can be turned on and 
off at any point.

To work completely, the feature needs to store separate before and after 
states so the selection is restored both for undo (state before change) and 
redo (state after change). For the undo case, the selection state is stored 
in a temporary buffer during (BeforeInsert | BeforeDelete) modifications 
then, once the change has been successfully made (InsertText | DeleteText) 
the temporary copy is saved onto the history. This has worked with tested 
commands but there may be commands that need some tweaks, if, for example, 
they change the selection.

For the redo case, its more difficult as, often the selection is changed 
after the text modification but there isn't a call to indicate that the 
command, including the selection change, is complete. There are two 
techniques used. When an undo group was used, then the final undo group 
closing is used as the completion event. In one case, that mean moving some 
selection changes earlier in the code inside the scope of an undo group. 
When there is no undo group active, then the selection is saved when 
exiting the API processing for the modification. For application commands 
which perform multiple modifications, an undo group can surround the 
modifications. There could be further APIs to allow more control by 
applications.

Remembering the selection uses memory and it is often more than the basic 
undo data at around 150 bytes for remembering a single range selection. 
There is some mitigation by avoiding saving selection states inside an undo 
group (just saving the selection at the start/end of the group) so a large 
global replace won't exhaust memory. Only the boundaries of rectangular 
selections are stored, not the array of per-line ranges used normally for 
stability. Since selections have several optional features (not every 
selection will include virtual space, for example) the basic per-action 
memory could be shrunk by something like an average 8x with some more 
complexity.

There could be an option to limit the number of actions or number of bytes 
stored to avoid memory exhaustion but that would produce a feature that is 
more complex to explain.

An 'undo.selection.history' property was added to SciTE that calls 
SCI_SETSELECTIONUNDOHISTORY.

The committed changes can be examined either in the repositories 

hg clone http://hg.code.sf.net/p/scintilla/code scintilla 
hg clone http://hg.code.sf.net/p/scintilla/scite 

or from 

https://www.scintilla.org/scite.zip Source 
https://www.scintilla.org/wscite.zip Windows executable (64-bit) 

Neil 

-- 
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/37129ddb-10cb-4eab-82c9-61bdbf7ad520n%40googlegroups.com.