Optimize Notification processing

45 views
Skip to first unread message

Jean Lalonde

unread,
May 18, 2025, 3:40:12 PMMay 18
to scintilla-interest
Hi,

I'd like to check with you if I have the optimal setting to minimize the number of notifications but get all those I need to update the status bar with the length of text in the editor, length of selected text, position of the caret (line, column), etc. and to process line auto-indentation (as explained in Scintilla Usage Notes).

I'm setting this event mask:

o_Sci.SETMODEVENTMASK(SCN_MODIFIED) ; eventMask can be SCN_MODIFIED or SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT

I'm setting the notification handler with this:

o_Sci.NOTIFY := "SciOnNotify"

And inside SciOnNotify(), I first update the status bar:

if (obj.SCNCode == SCN_CHARADDED and obj.Modifiers = 10) ; SCN_CHARADDED:=2001, 10 for LF
{
Gosub, AutoIndent
}


... and update the status bar:

if (obj.SCNCode = SCN_MODIFIED) ; SCN_MODIFIED:=2008
and (obj.ModType != 20) ; SC_MOD_CHANGESTYLE := 0x4 | SC_PERFORMED_USER := 0x10 = 0x14 = 20
{
Gosub, UpdateStatusbar
}


This works for what I need. But can it be optimized?

Thanks you for your input.

Mitchell

unread,
May 18, 2025, 3:57:04 PMMay 18
to scintilla...@googlegroups.com
Hi,

> On May 18, 2025, at 3:40 PM, Jean Lalonde <jlalo...@gmail.com> wrote:
>
> Hi,
>
> I'd like to check with you if I have the optimal setting to minimize the number of notifications but get all those I need to update the status bar with the length of text in the editor, length of selected text, position of the caret (line, column), etc. and to process line auto-indentation (as explained in Scintilla Usage Notes).
>
> I'm setting this event mask:
>
> o_Sci.SETMODEVENTMASK(SCN_MODIFIED) ; eventMask can be SCN_MODIFIED or SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT

I could be wrong, but you may be able to get away with just listening for `SCN_UPDATEUI` and `SCN_CHARADDED` and setting the mod mask to 0 to ignore them all:
- For `SCN_UPDATEUI`, `updated & (SC_UPDATE_CONTENT | SC_UPDATE_SELECTION) > 0` can be used for detecting position, content and selection changes.
- For `SCN_CHARADDED`, if `ch` is 10, the user pressed enter and you can perform auto-indent.

Cheers,
Mitchell

>
> I'm setting the notification handler with this:
>
> o_Sci.NOTIFY := "SciOnNotify"
>
> And inside SciOnNotify(), I first update the status bar:
>
> if (obj.SCNCode == SCN_CHARADDED and obj.Modifiers = 10) ; SCN_CHARADDED:=2001, 10 for LF
> {
> Gosub, AutoIndent
> }
>
> ... and update the status bar:
>
> if (obj.SCNCode = SCN_MODIFIED) ; SCN_MODIFIED:=2008
> and (obj.ModType != 20) ; SC_MOD_CHANGESTYLE := 0x4 | SC_PERFORMED_USER := 0x10 = 0x14 = 20
> {
> Gosub, UpdateStatusbar
> }
>
> This works for what I need. But can it be optimized?
>
> Thanks you for your input.
>
> --
> 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 scintilla-inter...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/ea0c2cfa-4f75-450a-bf53-6ca85121e586n%40googlegroups.com.

Jean Lalonde

unread,
May 18, 2025, 5:40:40 PMMay 18
to scintilla-interest
Thanks for the help Mitchell.

Sorry but I'm (easily) confused. And I'm not very familiar with events and masks...


> I could be wrong, but you may be able to get away with just listening for `SCN_UPDATEUI` and `SCN_CHARADDED` and setting the mod mask to 0 to ignore them all:
> - For `SCN_UPDATEUI`, `updated & (SC_UPDATE_CONTENT | SC_UPDATE_SELECTION) > 0` can be used for detecting position, content and selection changes.
> - For `SCN_CHARADDED`, if `ch` is 10, the user pressed enter and you can perform auto-indent.

How would you translate this into pseudo code? What does mean " setting the mod mask to 0 to ignore them all"?

I tested the mask o_Sci.SETMODEVENTMASK(SCN_UPDATEUI|SCN_CHARADDED) and logged the events.  I'm getting SCN_UPDATEUI and SCN_CHARADDED events but also other types as shown by the following extracts (only one by type) from my log file:

20250518@17:17:20.199 SciOnNotify obj.SCNCode 2007 SCN_UPDATEUI
20250518@17:17:20.200 SciOnNotify obj.modType 0
20250518@17:17:20.205 SciOnNotify obj.Ch 0
20250518@17:17:20.210 SciOnNotify obj.modifiers 0

20250518@17:17:21.039 SciOnNotify obj.SCNCode 2000 SCN_STYLENEEDED
20250518@17:17:21.039 SciOnNotify obj.modType 0
20250518@17:17:21.045 SciOnNotify obj.Ch 0
20250518@17:17:21.050 SciOnNotify obj.modifiers 0

20250518@17:17:21.204 SciOnNotify obj.SCNCode 2028 UNKNOWN_2028
20250518@17:17:21.204 SciOnNotify obj.modType 0
20250518@17:17:21.211 SciOnNotify obj.Ch 0
20250518@17:17:21.217 SciOnNotify obj.modifiers 0

20250518@17:17:21.279 SciOnNotify obj.SCNCode 2013 SCN_PAINTED
20250518@17:17:21.284 SciOnNotify obj.modType 0
20250518@17:17:21.290 SciOnNotify obj.Ch 0
20250518@17:17:21.297 SciOnNotify obj.modifiers 0

20250518@17:17:23.662 SciOnNotify obj.SCNCode 2008 SCN_MODIFIED
20250518@17:17:23.662 SciOnNotify obj.modType 4466765987840
20250518@17:17:23.669 SciOnNotify obj.Ch 0
20250518@17:17:23.675 SciOnNotify obj.modifiers 0

When adding a new line:

20250518@17:17:23.740 SciOnNotify obj.SCNCode 2001 SCN_CHARADDED
20250518@17:17:23.744 SciOnNotify obj.modType 0
20250518@17:17:23.750 SciOnNotify obj.Ch 55834574848
20250518@17:17:23.756 SciOnNotify obj.modifiers 13
20250518@17:17:23.763 SciOnNotify obj.SCNCode 2001 SCN_CHARADDED
20250518@17:17:23.768 SciOnNotify obj.modType 0
20250518@17:17:23.773 SciOnNotify obj.Ch 42949672960
20250518@17:17:23.779 SciOnNotify obj.modifiers 10

20250518@17:17:26.345 SciOnNotify obj.SCNCode 2029 UNKNOWN_2029
20250518@17:17:26.345 SciOnNotify obj.modType 0
20250518@17:17:26.352 SciOnNotify obj.Ch 0
20250518@17:17:26.358 SciOnNotify obj.modifiers 0

20250518@17:17:27.710 SciOnNotify obj.SCNCode 2028 UNKNOWN_2028
20250518@17:17:27.710 SciOnNotify obj.modType 0
20250518@17:17:27.717 SciOnNotify obj.Ch 0
20250518@17:17:27.723 SciOnNotify obj.modifiers 0

FYI, I'm using Scintilla.DLL v3.7.6 with a wrapper written in AutoHotkey v1.

Mitchell

unread,
May 18, 2025, 6:28:31 PMMay 18
to scintilla...@googlegroups.com
Hi,

> On May 18, 2025, at 5:40 PM, Jean Lalonde <jlalo...@gmail.com> wrote:
>
> Thanks for the help Mitchell.
>
> Sorry but I'm (easily) confused. And I'm not very familiar with events and masks...
>
>> I could be wrong, but you may be able to get away with just listening for `SCN_UPDATEUI` and `SCN_CHARADDED` and setting the mod mask to 0 to ignore them all:
>> - For `SCN_UPDATEUI`, `updated & (SC_UPDATE_CONTENT | SC_UPDATE_SELECTION) > 0` can be used for detecting position, content and selection changes.
>> - For `SCN_CHARADDED`, if `ch` is 10, the user pressed enter and you can perform auto-indent.
>
> How would you translate this into pseudo code? What does mean " setting the mod mask to 0 to ignore them all"?

Yes, this can all be tricky to understand and get right. I’ve been there, and I could still be wrong :)

`os_Sci.SETMODEVENTMASK(0)` turns off all `SCN_MODIFIED` events. Those are the insert text, delete text, etc. It can be very noisy, which is why Scintilla provides this message for you to pick and choose the modifications you care about. If you don’t care about any of them, you can use set to 0 as an optimization.

You don’t use `SETMODEVENTMASK` with `SCN_UPDATEUI` or `SCN_CHARADDED`. Your `SciOnNotify` handler will always receive them (e.g. code 2007 for SCN_UPDATEUI, 2001 for SCN_CHARADDED), as you can see in your log.

Using my suggestions, your SciOnNotify handler might look like this:

```
if (obj.SCNCode == SCN_UPDATEUI && (obj.updated & (SC_UPDATE_CONTENT | SC_UPDATE_SELECTION) > 0)) {
// Either the document’s content or selection changed.
// You can query its length, selection position, etc. to update your status bar.
} else if (obj.SCNCode == SCN_CHARADDED && obj.char == 10) {
// The user pressed enter, so you can do auto-indent.
}
```

I hope that helps.

Cheers,
Mitchell
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/e284991d-c5ec-42bd-880a-804a0b02cca6n%40googlegroups.com.

Jean Lalonde

unread,
May 18, 2025, 10:27:39 PMMay 18
to scintilla-interest
Thanks for the clarification. There is progress.

My code is now:

o_Sci.SETMODEVENTMASK(0)

if (obj.SCNCode == SCN_UPDATEUI
  and (obj.Updated & (SC_UPDATE_CONTENT | SC_UPDATE_SELECTION) > 0))
  Gosub, EditorContentChanged

if (o_Settings.EditorWindow.blnAutoIndent.IniValue
  and obj.SCNCode == SCN_CHARADDED and obj.Modifier = 10)
  ; Auto-Indent

Event triggered are (from my log):

SciOnNotify obj.SCNCode 2000 SCN_STYLENEEDED
SciOnNotify obj.SCNCode 2001 SCN_CHARADDED
SciOnNotify obj.SCNCode 2007 SCN_UPDATEUI
SciOnNotify obj.SCNCode 2013 SCN_PAINTED
SciOnNotify obj.SCNCode 2028 UNKNOWN_2028

But the issue is that the obj.Updated value is always false (even if I select or insert text). Maybe there is something to look at in the wrapper? Here is an  abstracts from the code setting the .Updated value (full code here):

__SciNotify(wParam, lParam, msg, hWnd) {
...
    Static OffUpdated := x64 ? 116 : 88

    __SciObj := __SCI(NumGet(lParam + 0, 0, "UPtr")) ; Returns original object ; JL: UPtr changed 2025-05-18 see https://www.autohotkey.com/boards/viewtopic.php?f=76&t=137269
...
    __SciObj.Updated := NumGet(lParam + OffUpdated)

    ; Call user defined Notify function and passes object to it as last parameter
    __SciObj.Notify(wParam, lParam, msg, hWnd, __SciObj)


On the other hand:

obj.Ch is updated with very large values (looking like mod type?)
obj.modifiers is updated with ASCII code of characters I typed.

Could it be that the offset values when processing lParam are incorrect?

Mitchell

unread,
May 18, 2025, 10:34:33 PMMay 18
to scintilla...@googlegroups.com
Hi,
Yeah, those offsets are probably not right. I don’t know what they should be (since I work with the C/C++ struct directly), but `code` being a large number does not make sense, so its offset is probably wrong. `updated` should never be zero either.

Cheers,
Mitchell
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/350693a8-c8e9-41b0-8218-cc0540b0aa47n%40googlegroups.com.

Jean Lalonde

unread,
May 19, 2025, 3:30:04 PMMay 19
to scintilla-interest
Hi Mitchell,

Yes, the offsets were wrong. I got them fixed (thanks to AHK users in this thread).

With this in the Scintilla creation:

o_Sci.SETMODEVENTMASK(0)
o_Sci.NOTIFY := "SciOnNotify"


And this in SciOnNotify():

if (obj.SCNCode == SCN_UPDATEUI
and (obj.Updated & (SC_UPDATE_CONTENT | SC_UPDATE_SELECTION) > 0))
{
  Diag(A_ThisFunc, aaScnCodes[obj.SCNCode] . " obj.Updated / obj.Ch", obj.Updated . " / " . obj.Ch)
  Gosub, EditorContentChanged
}

What I get in the log file is now correct for the .Updated values. But I .Ch is always empty even when .Updated contains 1 (SC_UPDATE_CONTENT):

20250519@15:19:24.889 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 9 / 0
20250519@15:19:25.727 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 1 / 0
20250519@15:19:27.338 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 2 / 0
20250519@15:19:29.731 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 1 / 0
20250519@15:19:30.048 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 1 / 0
20250519@15:19:30.388 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 1 / 0
20250519@15:19:31.298 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 3 / 0


From what I read in the Scintilla doc, the .Ch value is only returned for these SCNCode values:

int ch;
/* SCN_CHARADDED, SCN_KEY, SCN_AUTOCCOMPLETED, SCN_AUTOCSELECTION, */
/* SCN_USERLISTSELECTION */

What should I change in the mask or if to get the .Ch info (neeeded to handle auto-indentation)?

Thanks again for your support.

Mitchell

unread,
May 19, 2025, 3:58:16 PMMay 19
to scintilla...@googlegroups.com
Hi,

> On May 19, 2025, at 3:30 PM, Jean Lalonde <jlalo...@gmail.com> wrote:
>
> Hi Mitchell,
>
> Yes, the offsets were wrong. I got them fixed (thanks to AHK users in this thread).
>
> With this in the Scintilla creation:
>
> o_Sci.SETMODEVENTMASK(0)
> o_Sci.NOTIFY := "SciOnNotify"
>
> And this in SciOnNotify():
>
> if (obj.SCNCode == SCN_UPDATEUI
> and (obj.Updated & (SC_UPDATE_CONTENT | SC_UPDATE_SELECTION) > 0))
> {
> Diag(A_ThisFunc, aaScnCodes[obj.SCNCode] . " obj.Updated / obj.Ch", obj.Updated . " / " . obj.Ch)
> Gosub, EditorContentChanged
> }
>
> What I get in the log file is now correct for the .Updated values. But I .Ch is always empty even when .Updated contains 1 (SC_UPDATE_CONTENT):
>
> 20250519@15:19:24.889 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 9 / 0
> 20250519@15:19:25.727 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 1 / 0
> 20250519@15:19:27.338 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 2 / 0
> 20250519@15:19:29.731 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 1 / 0
> 20250519@15:19:30.048 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 1 / 0
> 20250519@15:19:30.388 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 1 / 0
> 20250519@15:19:31.298 SciOnNotify SCN_UPDATEUI obj.Updated / obj.Ch 3 / 0
>
> From what I read in the Scintilla doc, the .Ch value is only returned for these SCNCode values:
>
> int ch;
> /* SCN_CHARADDED, SCN_KEY, SCN_AUTOCCOMPLETED, SCN_AUTOCSELECTION, */
> /* SCN_USERLISTSELECTION */
>
> What should I change in the mask or if to get the .Ch info (neeeded to handle auto-indentation)?

I think you would have an `} else if (obj.SCNCode == SCN_CHARADDED && obj.Ch == 10) {` block.

The mask only applies to `SCN_MODIFIED` notifications, which any no other notification is.

Cheers,
Mitchell
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/b4b216fe-0018-457a-9b6f-eec02c38c917n%40googlegroups.com.

Jean Lalonde

unread,
May 19, 2025, 5:19:22 PMMay 19
to scintilla-interest
>  I think you would have an `} else if (obj.SCNCode == SCN_CHARADDED && obj.Ch == 10) {` block.

Yes that's what I needed to do. Everything works as desired now! Thank you Mitchell.

My code now looks like:

if (obj.SCNCode == SCN_UPDATEUI
  and (obj.Updated & (SC_UPDATE_CONTENT | SC_UPDATE_SELECTION) > 0))
{
  Diag(A_ThisFunc, aaScnCodes[obj.SCNCode] . " obj.Updated", obj.Updated)
   Gosub, EditorContentChanged

    }
else if (obj.SCNCode == SCN_CHARADDED && obj.Ch == 10)
{
    Diag(A_ThisFunc, aaScnCodes[obj.SCNCode] . " obj.Ch", obj.Ch)
    Gosub, ProcessAutoIndent
}

As a last improvement, I would like to receive notifications when the caret position or selection change (to update the app's status bar with current line, column, etc.). Should I use SCN_MODIFIED and change the mask accordingly?

Jean

Mitchell

unread,
May 19, 2025, 5:28:58 PMMay 19
to scintilla...@googlegroups.com
Hi,

> On May 19, 2025, at 5:19 PM, Jean Lalonde <jlalo...@gmail.com> wrote:
>
> > I think you would have an `} else if (obj.SCNCode == SCN_CHARADDED && obj.Ch == 10) {` block.
>
> Yes that's what I needed to do. Everything works as desired now! Thank you Mitchell.
>
> My code now looks like:
>
> if (obj.SCNCode == SCN_UPDATEUI
> and (obj.Updated & (SC_UPDATE_CONTENT | SC_UPDATE_SELECTION) > 0))
> {
> Diag(A_ThisFunc, aaScnCodes[obj.SCNCode] . " obj.Updated", obj.Updated)
> Gosub, EditorContentChanged
> }
> else if (obj.SCNCode == SCN_CHARADDED && obj.Ch == 10)
> {
> Diag(A_ThisFunc, aaScnCodes[obj.SCNCode] . " obj.Ch", obj.Ch)
> Gosub, ProcessAutoIndent
> }
>
> As a last improvement, I would like to receive notifications when the caret position or selection change (to update the app's status bar with current line, column, etc.). Should I use SCN_MODIFIED and change the mask accordingly?

No, SCN_UPDATEUI lets you know one or both happened. Presumably your `EditorContentChanged` will be sending Scintilla messages to get that information. For example, SCI_GETCURRENTPOS and SCI_GETANCHOR will give you the current selection (or the current position if they are the same; i.e. no selection), SCI_LINEFROMPOSITION will give you the current line, SCI_GETCOLUMN will give you the current column, etc.

Cheers,
Mitchell
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/08e0b662-e80c-4d1e-9778-93f5ef585aeen%40googlegroups.com.

Jean Lalonde

unread,
May 19, 2025, 5:38:35 PMMay 19
to scintilla-interest
Yes,  EditorContentChanged already contains these commands ( SCI_GETCURRENTPOS, etc).  At this time,  it runs every 0.5 sec with timer.  What I'm looking for, if possible, is to trigger EditorContentChanged with Scintilla notifications instead of a timer.

Jean

Mitchell

unread,
May 19, 2025, 5:49:01 PMMay 19
to scintilla...@googlegroups.com
Hi,

> On May 19, 2025, at 5:38 PM, Jean Lalonde <jlalo...@gmail.com> wrote:
>
> Yes, EditorContentChanged already contains these commands ( SCI_GETCURRENTPOS, etc). At this time, it runs every 0.5 sec with timer. What I'm looking for, if possible, is to trigger EditorContentChanged with Scintilla notifications instead of a timer.

Well, whenever you move the caret position or make a selection, Scintilla will send SCN_UPDATEUI. Your handler’s first if branch should be hit, and then call `EditorContentChanged`. Is that not what happens? Maybe I’m not understanding something.
> To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/4de610e5-ab82-4932-8ef1-24efd1ac1249n%40googlegroups.com.

Jean Lalonde

unread,
May 19, 2025, 11:01:48 PMMay 19
to scintilla-interest
Yeah... My bad. I was confused by the fact that SCN_UPDATEUI does not update the .Position value.  But of course, I don't need it in the notification function itself. I call  SCI_GETCURRENTPOS(), etc. in  EditorContentChanged.

Thanks Mitchell.

Jean

Reply all
Reply to author
Forward
0 new messages