ReplaceSel doesn't immediately update cursor position?

41 views
Skip to first unread message

dail8859

unread,
Apr 8, 2018, 10:42:28 AM4/8/18
to scintilla-interest
I was testing some macro recording/playback and noticed that in some cases the cursor was not ending up where it was supposed to be. It seems unrelated to macros but instead it appears (assumably) using SCI_REPLACESEL doesn't update the cursor's position immediately.

The test case:
2345
2345
2345
If the cursor is placed at the beginning of the first line and the following actions are performed by the user (e.g. via the keyboard):
  1. SCI_REPLACESEL("1")
  2. SCI_LINEDOWN
  3. SCI_CHARLEFT

Then a "1" is inserted at the beginning of the first line and the cursor is at the beginning of the 2nd line...which is expected.

Now if these actions are preformed very quickly, such as playback of a macro, or even just simply adding this logic in C++ code, then the result is not the same. The cursor ends up at the *end of the 1st line*.

My assumption is that after the SCI_REPLACESEL the cursor still thinks it is at the beginning of the line, then SCI_LINEDOWN makes cursor ends up at the beginning of the 2nd line, then SCI_CHARLEFT moves the cursor back one position to the end of the 1st line.

Is this a bug or just a limitation? If it is a limitation of Scintilla I'd like to understand it better so I can avoid this situation in the future.

I've seen this happen on Win7 with Win32/v3.5.6 and Qt5.9.4/v3.8

Thanks,
Justin

Neil Hodgson

unread,
Apr 8, 2018, 6:16:20 PM4/8/18
to Scintilla mailing list
dail8859:

> 2345
> 2345
> If the cursor is placed at the beginning of the first line and the following actions are performed by the user (e.g. via the keyboard):
> • SCI_REPLACESEL("1")
> • SCI_LINEDOWN
> • SCI_CHARLEFT
>
> Then a "1" is inserted at the beginning of the first line and the cursor is at the beginning of the 2nd line...which is expected.
>
> Now if these actions are preformed very quickly, such as playback of a macro, or even just simply adding this logic in C++ code, then the result is not the same. The cursor ends up at the *end of the 1st line*.

For vertical movement, there is an extra variable, the last X chosen, that ensures that a sequence of up/down cursor movements doesn’t move to the left side at the first empty line and stay there.

Currently, the last X chosen is not updated in SCI_REPLACESEL so the SCI_LINEDOWN goes to the same X as last X chosen (0), the line start.

This should be fixed in SCI_REPLACESEL, but, for now, you can add a call to SCI_CHOOSECARETX after the SCI_REPLACESEL.

Neil

dail8859

unread,
Apr 8, 2018, 8:50:42 PM4/8/18
to scintilla-interest


   For vertical movement, there is an extra variable, the last X chosen, that ensures that a sequence of up/down cursor movements doesn’t move to the left side at the first empty line and stay there.

Ah ok this makes a bit more sense now.
 

   Currently, the last X chosen is not updated in SCI_REPLACESEL so the SCI_LINEDOWN goes to the same X as last X chosen (0), the line start.

When exactly does it get updated? Is it related to the UI redraw? (this would explain why it works typing the commands in via the keyboard but not when doing it with a macro or direct with code).
 

   This should be fixed in SCI_REPLACESEL, but, for now, you can add a call to SCI_CHOOSECARETX after the SCI_REPLACESEL.

Ok that should be simple enough, even when playing back a macro I'll just call SCI_CHOOSECARETX after each SCI_REPLACESEL I run across.

Thanks for the info!

Neil Hodgson

unread,
Apr 9, 2018, 6:11:57 PM4/9/18
to Scintilla mailing list
dail8859:

> When exactly does it get updated? Is it related to the UI redraw? (this would explain why it works typing the commands in via the keyboard but not when doing it with a macro or direct with code).

It is updated after each command that is seen to be caused directly by the user which deliberately changes the X of the caret. Thus, left arrow, right arrow, and typing set the last X chosen but up and down arrow don’t. This means that a call is manually added to each situation identified as appropriate.

Actions that the application takes that are not directly caused by a user command should not set the last X chosen. For example, when saving, the application may fix up inconsistent line ends, strip trailing spaces, and tidy indentation. Making the next down arrow move 20 columns right because some off-screen whitespace was modified would not be nice.

SCI_REPLACESEL was available early so appeared a good choice for applications to use. Later, SCI_REPLACETARGET was added which is the better choice in most cases.

SCI_REPLACESEL takes an argument so can’t be assigned to a key for easy access. Thus, it was not seen as a command that should change the last X chosen. However, that overlooks its use in macros, as you discovered.

Neil

Neil Hodgson

unread,
Apr 10, 2018, 8:47:26 PM4/10/18
to Scintilla mailing list
Reply all
Reply to author
Forward
0 new messages