diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-03-23 18:31:09 +0300 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-03-23 18:42:07 +0300 |
commit | 9e101ec36e0bf45f294f63015e0352d1d08d641d (patch) | |
tree | 786dd994465a48d038d48889af4678bf87d09614 | |
parent | 8f0fea5b17025a424474bc78c668ae3bfb0e2661 (diff) | |
download | sciteco-9e101ec36e0bf45f294f63015e0352d1d08d641d.tar.gz |
the ES command (send Scintilla message) now supports passing both wParam and lParam as null-terminated strings
* Being able to embed null bytes into the lParam string is
practically useless - there aren't any messages where this is useful
and where there are no native SciTECO counterparts - so this case is now catched
and the null-byte separates wParam from lParam.
* wParam can be the empty string, but it is not supported to pass wParam as a
string and lParam as the empty string.
If the second string argument ends in ^@, lParam is popped from the stack instead.
* This is a temporary workaround until we can properly parse the Scintilla.iface and
generate more elegant per-message wrappers.
* It in particular unlocks the SCI_SETREPRESENTATION and SCI_SETPROPERTY messages.
The former allows us to write a special hex-editor macro which sets hexadecimal
character representations, while the latter allows you to set lexer properties.
* The C-based lexers ("cpp" in Lexilla) can now take preprocessor definitions into account.
This is disabled by default, unless you set lexer.c.defines before opening a file.
You can also set it interactively and re-set the lexer. For instance:
^U[lexer.c.defines]NDEBUG$ M[lexer.set.c]
-rw-r--r-- | lib/lexers/c.tes | bin | 2440 -> 2705 bytes | |||
-rw-r--r-- | lib/lexers/cpp.tes | bin | 1279 -> 1410 bytes | |||
-rw-r--r-- | lib/lexers/devicetree.tes | bin | 612 -> 743 bytes | |||
-rw-r--r-- | lib/lexers/sciteco.tes | bin | 637 -> 697 bytes | |||
-rw-r--r-- | src/lexer.c | 6 | ||||
-rw-r--r-- | src/symbols.c | 56 |
6 files changed, 44 insertions, 18 deletions
diff --git a/lib/lexers/c.tes b/lib/lexers/c.tes Binary files differindex c0acea2..0f2b68d 100644 --- a/lib/lexers/c.tes +++ b/lib/lexers/c.tes diff --git a/lib/lexers/cpp.tes b/lib/lexers/cpp.tes Binary files differindex 0f6a01a..7ac177f 100644 --- a/lib/lexers/cpp.tes +++ b/lib/lexers/cpp.tes diff --git a/lib/lexers/devicetree.tes b/lib/lexers/devicetree.tes Binary files differindex 7551458..da6d876 100644 --- a/lib/lexers/devicetree.tes +++ b/lib/lexers/devicetree.tes diff --git a/lib/lexers/sciteco.tes b/lib/lexers/sciteco.tes Binary files differindex ec023d7..7ca9c70 100644 --- a/lib/lexers/sciteco.tes +++ b/lib/lexers/sciteco.tes diff --git a/src/lexer.c b/src/lexer.c index 1124b99..84ddcc3 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -133,9 +133,9 @@ teco_lexer_step(teco_view_t *view, teco_machine_main_t *machine, * The curly braces will be styled like regular commands. * * FIXME: This will not work with nested macro definitions. - * FIXME: This cannot currently be disabled since SCI_SETPROPERTY - * cannot be accessed with ES. - * We could only map it to an ED flag. + * FIXME: This cannot currently be disabled, not even with SCI_SETPROPERTY. + * We could only map it to an ED flag or + * rewrite the lexer against the ILexer5 interface, which requires C++. */ if ((escape_char == '{' || machine->expectstring.machine.escape_char == '{') && teco_view_ssm(view, SCI_GETPROPERTYINT, (uptr_t)"lexer.sciteco.macrodef", TRUE)) diff --git a/src/symbols.c b/src/symbols.c index 32a33da..66edd90 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -243,11 +243,6 @@ teco_state_scintilla_symbols_done(teco_machine_main_t *ctx, const teco_string_t return NULL; ctx->scintilla.iMessage = value; } - if (!ctx->scintilla.wParam) { - if (!teco_expressions_pop_num_calc(&value, 0, error)) - return NULL; - ctx->scintilla.wParam = value; - } return &teco_state_scintilla_lparam; } @@ -259,8 +254,11 @@ gboolean teco_state_scintilla_symbols_insert_completion(teco_machine_main_t *ctx GError **error); /*$ ES scintilla message - * -- Send Scintilla message - * [lParam,][wParam,][message]ES[message][,wParam]$[lParam]$ -> result + * [lParam,][wParam,][message]ES$ -> result -- Send Scintilla message + * [lParam,][wParam]ES[message]$$ -> result + * [lParam]ES[message][,wParam]$$ -> result + * [wParam]ES[message]$[lParam]$ -> result + * [lParam]ES[message]$[wParam]^@[lParam]$ -> result * * Send Scintilla message with code specified by * <message>, <wParam> and <lParam>. @@ -273,9 +271,15 @@ gboolean teco_state_scintilla_symbols_insert_completion(teco_machine_main_t *ctx * It is automatically null-terminated. * If the second string argument is empty, <lParam> is popped * from the stack instead. + * If the second string argument contains a null-byte (\fB^@\fP), + * both <wParam> and <lParam> are passed as null-terminated + * string pointers to Scintilla. + * If the second string ends in a null-byte, <lParam> is still + * popped from the stack. * Parameters popped from the stack may be omitted, in which * case 0 is implied. - * The message's return value is pushed onto the stack. + * The message's return value is always pushed onto the stack + * (0 if the message has no documented return values). * * All messages defined by Scintilla (as C macros in Scintilla.h) * can be used by passing their name as a string to ES @@ -283,7 +287,8 @@ gboolean teco_state_scintilla_symbols_insert_completion(teco_machine_main_t *ctx * The \(lqSCI_\(rq prefix may be omitted and message symbols * are case-insensitive. * Only the Lexilla style names (SCE_...) - * may be used symbolically with the ES command as <wParam>. + * may be used symbolically with the ES command as <wParam> in + * the first string argument. * In interactive mode, symbols may be auto-completed by * pressing Tab. * String-building characters are by default interpreted @@ -299,7 +304,7 @@ gboolean teco_state_scintilla_symbols_insert_completion(teco_machine_main_t *ctx * (shared library or DLL) is expected, * that implements the Lexilla protocol. * The \(lq.so\(rq or \(lq.dll\(rq extension is optional. - * The concrete lexer name is the remaining of the string after + * The concrete lexer name is the remainder of the string after * the null-byte. * This allows you to use lexers from external lexer libraries * like Scintillua. @@ -318,6 +323,8 @@ gboolean teco_state_scintilla_symbols_insert_completion(teco_machine_main_t *ctx * .BR Warning : * Almost all Scintilla messages may be dispatched using * this command. + * If called wrongly, you can easily crash the editor. + * Therefore it is not recommended to invoke ES interactively. * \*(ST does not keep track of the editor state changes * performed by these commands and cannot undo them. * You should never use it to change the editor state @@ -458,12 +465,31 @@ teco_state_scintilla_lparam_done(teco_machine_main_t *ctx, const teco_string_t * return NULL; } else if (str->len > 0) { /* - * NOTE: There may even be messages that read strings - * with embedded nulls. + * Theoretically, Scintilla could use null bytes from the string specified. + * This could only be the case for messages where the string length is + * passed in wParam. In practice however, there are no such messages, + * we would possible want to call. + * Therefore we pass the first null-terminated string as wParam, + * which unlocks useful messages like + * SCI_SETREPRESENTATIONS and SCI_SETPROPERTY. */ - lParam = (sptr_t)str->data; - } else { - teco_int_t v; + const gchar *p = memchr(str->data, '\0', str->len); + if (p) { + ctx->scintilla.wParam = (uptr_t)str->data; + if (str->len > p - str->data + 1) + lParam = (sptr_t)(p+1); + } else { + lParam = (sptr_t)str->data; + } + } + + teco_int_t v; + if (!ctx->scintilla.wParam) { + if (!teco_expressions_pop_num_calc(&v, 0, error)) + return NULL; + ctx->scintilla.wParam = v; + } + if (!lParam) { if (!teco_expressions_pop_num_calc(&v, 0, error)) return NULL; lParam = v; |