From ffbc962c0a241f7d70b48162f92f2023fe6c043f Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Wed, 2 Jun 2021 19:18:10 +0200 Subject: renamed scintilla.[ch] to symbols.[ch]: fixes builds on case-insensitive file systems * There is a "Scintilla.h" as well. * should fix macOS and builds on native Windows hosts * It wasn't practical to refer to the Scintilla includes using paths since the Scintilla location is configurable (--with-scintilla). So we'd have to write something like #include . For Scinterm we cannot avoid collisions neither as its path is also configurable (--with-scinterm). Effectively, we must prevent name clashes across SciTECO and all of Scintilla and Scinterm. --- src/Makefile.am | 2 +- src/cmdline.c | 2 +- src/core-commands.c | 2 +- src/scintilla.c | 349 ------------------------------------------------ src/scintilla.h | 64 --------- src/symbols-extract.tes | 2 +- src/symbols.c | 349 ++++++++++++++++++++++++++++++++++++++++++++++++ src/symbols.h | 64 +++++++++ 8 files changed, 417 insertions(+), 417 deletions(-) delete mode 100644 src/scintilla.c delete mode 100644 src/scintilla.h create mode 100644 src/symbols.c create mode 100644 src/symbols.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index a2990d8..17de739 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,7 +54,7 @@ libsciteco_base_la_SOURCES = main.c sciteco.h list.h \ goto-commands.c goto-commands.h \ help.c help.h \ rb3str.c rb3str.h \ - scintilla.c scintilla.h \ + symbols.c symbols.h \ view.c view.h \ interface.c interface.h # NOTE: We cannot link in Scintilla (static library) into diff --git a/src/cmdline.c b/src/cmdline.c index 85cbbdd..9e73e4e 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -47,7 +47,7 @@ #include "goto.h" #include "help.h" #include "undo.h" -#include "scintilla.h" +#include "symbols.h" #include "spawn.h" #include "eol.h" #include "error.h" diff --git a/src/core-commands.c b/src/core-commands.c index 4c5d176..0db0328 100644 --- a/src/core-commands.c +++ b/src/core-commands.c @@ -31,7 +31,7 @@ #include "expressions.h" #include "ring.h" #include "parser.h" -#include "scintilla.h" +#include "symbols.h" #include "search.h" #include "spawn.h" #include "glob.h" diff --git a/src/scintilla.c b/src/scintilla.c deleted file mode 100644 index f58b6f4..0000000 --- a/src/scintilla.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright (C) 2012-2021 Robin Haberkorn - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include - -#include "sciteco.h" -#include "string-utils.h" -#include "error.h" -#include "parser.h" -#include "core-commands.h" -#include "undo.h" -#include "expressions.h" -#include "interface.h" -#include "scintilla.h" - -teco_symbol_list_t teco_symbol_list_scintilla = {NULL, 0}; -teco_symbol_list_t teco_symbol_list_scilexer = {NULL, 0}; - -/* - * FIXME: Could be static. - */ -TECO_DEFINE_UNDO_OBJECT_OWN(scintilla_message, teco_machine_scintilla_t, /* don't delete */); - -/** @memberof teco_symbol_list_t */ -void -teco_symbol_list_init(teco_symbol_list_t *ctx, const teco_symbol_entry_t *entries, gint size, - gboolean case_sensitive) -{ - memset(ctx, 0, sizeof(*ctx)); - ctx->entries = entries; - ctx->size = size; - ctx->cmp_fnc = case_sensitive ? strncmp : g_ascii_strncasecmp; -} - -/** - * @note Since symbol lists are presorted constant arrays we can do a simple - * binary search. - * This does not use bsearch() since we'd have to prepend `prefix` in front of - * the name. - * - * @memberof teco_symbol_list_t - */ -gint -teco_symbol_list_lookup(teco_symbol_list_t *ctx, const gchar *name, const gchar *prefix) -{ - gsize name_len = strlen(name); - - gsize prefix_skip = strlen(prefix); - if (!ctx->cmp_fnc(name, prefix, prefix_skip)) - prefix_skip = 0; - - gint left = 0; - gint right = ctx->size - 1; - - while (left <= right) { - gint cur = left + (right-left)/2; - gint cmp = ctx->cmp_fnc(ctx->entries[cur].name + prefix_skip, - name, name_len + 1); - - if (!cmp) - return ctx->entries[cur].value; - - if (cmp > 0) - right = cur-1; - else /* cmp < 0 */ - left = cur+1; - } - - return -1; -} - -/** - * Auto-complete a Scintilla symbol. - * - * @param ctx The symbol list. - * @param symbol The symbol to auto-complete or NULL. - * @param insert String to initialize with the completion. - * @return TRUE in case of an unambiguous completion. - * - * @memberof teco_symbol_list_t - */ -gboolean -teco_symbol_list_auto_complete(teco_symbol_list_t *ctx, const gchar *symbol, teco_string_t *insert) -{ - memset(insert, 0, sizeof(*insert)); - - if (!symbol) - symbol = ""; - gsize symbol_len = strlen(symbol); - - if (G_UNLIKELY(!ctx->list)) - for (gint i = ctx->size; i; i--) - ctx->list = g_list_prepend(ctx->list, (gchar *)ctx->entries[i-1].name); - - /* NOTE: element data must not be freed */ - g_autoptr(GList) glist = g_list_copy(ctx->list); - guint glist_len = 0; - - gsize prefix_len = 0; - - for (GList *entry = g_list_first(glist), *next = g_list_next(entry); - entry != NULL; - entry = next, next = entry ? g_list_next(entry) : NULL) { - if (g_ascii_strncasecmp(entry->data, symbol, symbol_len) != 0) { - glist = g_list_delete_link(glist, entry); - continue; - } - - teco_string_t glist_str; - glist_str.data = (gchar *)glist->data + symbol_len; - glist_str.len = strlen(glist_str.data); - - gsize len = teco_string_casediff(&glist_str, (gchar *)entry->data + symbol_len, - strlen(entry->data) - symbol_len); - if (!prefix_len || len < prefix_len) - prefix_len = len; - - glist_len++; - } - - if (prefix_len > 0) { - teco_string_init(insert, (gchar *)glist->data + symbol_len, prefix_len); - } else if (glist_len > 1) { - for (GList *entry = g_list_first(glist); - entry != NULL; - entry = g_list_next(entry)) { - teco_interface_popup_add(TECO_POPUP_PLAIN, entry->data, - strlen(entry->data), FALSE); - } - - teco_interface_popup_show(); - } - - return glist_len == 1; -} - -/* - * Command states - */ - -/* - * FIXME: This state could be static. - */ -TECO_DECLARE_STATE(teco_state_scintilla_lparam); - -static gboolean -teco_scintilla_parse_symbols(teco_machine_scintilla_t *scintilla, const teco_string_t *str, GError **error) -{ - if (teco_string_contains(str, '\0')) { - g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED, - "Scintilla symbol names must not contain null-byte"); - return FALSE; - } - - g_auto(GStrv) symbols = g_strsplit(str->data, ",", -1); - - if (!symbols[0]) - return TRUE; - if (*symbols[0]) { - gint v = teco_symbol_list_lookup(&teco_symbol_list_scintilla, symbols[0], "SCI_"); - if (v < 0) { - g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED, - "Unknown Scintilla message symbol \"%s\"", - symbols[0]); - return FALSE; - } - scintilla->iMessage = v; - } - - if (!symbols[1]) - return TRUE; - if (*symbols[1]) { - gint v = teco_symbol_list_lookup(&teco_symbol_list_scilexer, symbols[1], ""); - if (v < 0) { - g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED, - "Unknown Scintilla Lexer symbol \"%s\"", - symbols[1]); - return FALSE; - } - scintilla->wParam = v; - } - - if (!symbols[2]) - return TRUE; - if (*symbols[2]) { - gint v = teco_symbol_list_lookup(&teco_symbol_list_scilexer, symbols[2], ""); - if (v < 0) { - g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED, - "Unknown Scintilla Lexer symbol \"%s\"", - symbols[2]); - return FALSE; - } - scintilla->lParam = v; - } - - return TRUE; -} - -static teco_state_t * -teco_state_scintilla_symbols_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) -{ - if (ctx->mode > TECO_MODE_NORMAL) - return &teco_state_scintilla_lparam; - - /* - * NOTE: This is more memory efficient than pushing the individual - * members of teco_machine_scintilla_t and we won't need to define - * undo methods for the Scintilla types. - */ - if (ctx->parent.must_undo) - teco_undo_object_scintilla_message_push(&ctx->scintilla); - memset(&ctx->scintilla, 0, sizeof(ctx->scintilla)); - - if ((str->len > 0 && !teco_scintilla_parse_symbols(&ctx->scintilla, str, error)) || - !teco_expressions_eval(FALSE, error)) - return NULL; - - teco_int_t value; - - if (!ctx->scintilla.iMessage) { - if (!teco_expressions_args()) { - g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED, - " command requires at least a message code"); - return NULL; - } - - if (!teco_expressions_pop_num_calc(&value, 0, error)) - 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; -} - -/* in cmdline.c */ -gboolean teco_state_scintilla_symbols_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error); - -/*$ ES scintilla message - * -- Send Scintilla message - * [lParam[,wParam]]ESmessage[,wParam[,lParam]]$[lParam]$ -> result - * - * Send Scintilla message with code specified by symbolic - * name , and . - * may be symbolic when specified as part of the - * first string argument. - * If not it is popped from the stack. - * may be specified as a constant string whose - * pointer is passed to Scintilla if specified as the second - * string argument. - * If the second string argument is empty, is popped - * from the stack instead. - * Parameters popped from the stack may be omitted, in which - * case 0 is implied. - * The message's return value is pushed onto the stack. - * - * All messages defined by Scintilla (as C macros) can be - * used by passing their name as a string to ES - * (e.g. ESSCI_LINESONSCREEN...). - * The \(lqSCI_\(rq prefix may be omitted and message symbols - * are case-insensitive. - * Only the Scintilla lexer symbols (SCLEX_..., SCE_...) - * may be used symbolically with the ES command as , - * other values must be passed as integers on the stack. - * In interactive mode, symbols may be auto-completed by - * pressing Tab. - * String-building characters are by default interpreted - * in the string arguments. - * - * .BR Warning : - * Almost all Scintilla messages may be dispatched using - * this command. - * \*(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 - * (position changes, deletions, etc.) or otherwise - * rub out will result in an inconsistent editor state. - * There are however exceptions: - * - In the editor profile and batch mode in general, - * the ES command may be used freely. - * - In the ED hook macro (register \(lqED\(rq), - * when a file is added to the ring, most destructive - * operations can be performed since rubbing out the - * EB command responsible for the hook execution also - * removes the buffer from the ring again. - * - As part of function key macros that immediately - * terminate the command line. - */ -TECO_DEFINE_STATE_EXPECTSTRING(teco_state_scintilla_symbols, - .process_edit_cmd_cb = (teco_state_process_edit_cmd_cb_t)teco_state_scintilla_symbols_process_edit_cmd, - .expectstring.last = FALSE -); - -static teco_state_t * -teco_state_scintilla_lparam_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) -{ - if (ctx->mode > TECO_MODE_NORMAL) - return &teco_state_start; - - if (teco_string_contains(str, '\0')) { - g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED, - "Scintilla lParam string must not contain null-byte."); - return NULL; - } - - if (!ctx->scintilla.lParam) { - if (str->len > 0) { - ctx->scintilla.lParam = (sptr_t)str->data; - } else { - teco_int_t v; - if (!teco_expressions_pop_num_calc(&v, 0, error)) - return NULL; - ctx->scintilla.lParam = v; - } - } - - teco_expressions_push(teco_interface_ssm(ctx->scintilla.iMessage, - ctx->scintilla.wParam, - ctx->scintilla.lParam)); - - return &teco_state_start; -} - -TECO_DEFINE_STATE_EXPECTSTRING(teco_state_scintilla_lparam); diff --git a/src/scintilla.h b/src/scintilla.h deleted file mode 100644 index 607a3ff..0000000 --- a/src/scintilla.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2012-2021 Robin Haberkorn - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once - -#include - -#include "sciteco.h" -#include "string-utils.h" -#include "parser.h" - -typedef struct { - const gchar *name; - gint value; -} teco_symbol_entry_t; - -typedef struct { - const teco_symbol_entry_t *entries; - gint size; - - int (*cmp_fnc)(const char *, const char *, size_t); - - /** - * For auto-completions. - * The list is allocated only ondemand. - */ - GList *list; -} teco_symbol_list_t; - -void teco_symbol_list_init(teco_symbol_list_t *ctx, const teco_symbol_entry_t *entries, gint size, - gboolean case_sensitive); - -gint teco_symbol_list_lookup(teco_symbol_list_t *ctx, const gchar *name, const gchar *prefix); - -gboolean teco_symbol_list_auto_complete(teco_symbol_list_t *ctx, const gchar *symbol, teco_string_t *insert); - -/** @memberof teco_symbol_list_t */ -static inline void -teco_symbol_list_clear(teco_symbol_list_t *ctx) -{ - g_list_free(ctx->list); -} - -extern teco_symbol_list_t teco_symbol_list_scintilla; -extern teco_symbol_list_t teco_symbol_list_scilexer; - -/* - * Command states - */ - -TECO_DECLARE_STATE(teco_state_scintilla_symbols); diff --git a/src/symbols-extract.tes b/src/symbols-extract.tes index 3f71629..356bdd1 100755 --- a/src/symbols-extract.tes +++ b/src/symbols-extract.tes @@ -33,7 +33,7 @@ I/* #include "Q#in" #include "sciteco.h" -#include "scintilla.h" +#include "symbols.h" static const teco_symbol_entry_t entries[] = {^J < diff --git a/src/symbols.c b/src/symbols.c new file mode 100644 index 0000000..003d745 --- /dev/null +++ b/src/symbols.c @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2012-2021 Robin Haberkorn + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +#include "sciteco.h" +#include "string-utils.h" +#include "error.h" +#include "parser.h" +#include "core-commands.h" +#include "undo.h" +#include "expressions.h" +#include "interface.h" +#include "symbols.h" + +teco_symbol_list_t teco_symbol_list_scintilla = {NULL, 0}; +teco_symbol_list_t teco_symbol_list_scilexer = {NULL, 0}; + +/* + * FIXME: Could be static. + */ +TECO_DEFINE_UNDO_OBJECT_OWN(scintilla_message, teco_machine_scintilla_t, /* don't delete */); + +/** @memberof teco_symbol_list_t */ +void +teco_symbol_list_init(teco_symbol_list_t *ctx, const teco_symbol_entry_t *entries, gint size, + gboolean case_sensitive) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->entries = entries; + ctx->size = size; + ctx->cmp_fnc = case_sensitive ? strncmp : g_ascii_strncasecmp; +} + +/** + * @note Since symbol lists are presorted constant arrays we can do a simple + * binary search. + * This does not use bsearch() since we'd have to prepend `prefix` in front of + * the name. + * + * @memberof teco_symbol_list_t + */ +gint +teco_symbol_list_lookup(teco_symbol_list_t *ctx, const gchar *name, const gchar *prefix) +{ + gsize name_len = strlen(name); + + gsize prefix_skip = strlen(prefix); + if (!ctx->cmp_fnc(name, prefix, prefix_skip)) + prefix_skip = 0; + + gint left = 0; + gint right = ctx->size - 1; + + while (left <= right) { + gint cur = left + (right-left)/2; + gint cmp = ctx->cmp_fnc(ctx->entries[cur].name + prefix_skip, + name, name_len + 1); + + if (!cmp) + return ctx->entries[cur].value; + + if (cmp > 0) + right = cur-1; + else /* cmp < 0 */ + left = cur+1; + } + + return -1; +} + +/** + * Auto-complete a Scintilla symbol. + * + * @param ctx The symbol list. + * @param symbol The symbol to auto-complete or NULL. + * @param insert String to initialize with the completion. + * @return TRUE in case of an unambiguous completion. + * + * @memberof teco_symbol_list_t + */ +gboolean +teco_symbol_list_auto_complete(teco_symbol_list_t *ctx, const gchar *symbol, teco_string_t *insert) +{ + memset(insert, 0, sizeof(*insert)); + + if (!symbol) + symbol = ""; + gsize symbol_len = strlen(symbol); + + if (G_UNLIKELY(!ctx->list)) + for (gint i = ctx->size; i; i--) + ctx->list = g_list_prepend(ctx->list, (gchar *)ctx->entries[i-1].name); + + /* NOTE: element data must not be freed */ + g_autoptr(GList) glist = g_list_copy(ctx->list); + guint glist_len = 0; + + gsize prefix_len = 0; + + for (GList *entry = g_list_first(glist), *next = g_list_next(entry); + entry != NULL; + entry = next, next = entry ? g_list_next(entry) : NULL) { + if (g_ascii_strncasecmp(entry->data, symbol, symbol_len) != 0) { + glist = g_list_delete_link(glist, entry); + continue; + } + + teco_string_t glist_str; + glist_str.data = (gchar *)glist->data + symbol_len; + glist_str.len = strlen(glist_str.data); + + gsize len = teco_string_casediff(&glist_str, (gchar *)entry->data + symbol_len, + strlen(entry->data) - symbol_len); + if (!prefix_len || len < prefix_len) + prefix_len = len; + + glist_len++; + } + + if (prefix_len > 0) { + teco_string_init(insert, (gchar *)glist->data + symbol_len, prefix_len); + } else if (glist_len > 1) { + for (GList *entry = g_list_first(glist); + entry != NULL; + entry = g_list_next(entry)) { + teco_interface_popup_add(TECO_POPUP_PLAIN, entry->data, + strlen(entry->data), FALSE); + } + + teco_interface_popup_show(); + } + + return glist_len == 1; +} + +/* + * Command states + */ + +/* + * FIXME: This state could be static. + */ +TECO_DECLARE_STATE(teco_state_scintilla_lparam); + +static gboolean +teco_scintilla_parse_symbols(teco_machine_scintilla_t *scintilla, const teco_string_t *str, GError **error) +{ + if (teco_string_contains(str, '\0')) { + g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED, + "Scintilla symbol names must not contain null-byte"); + return FALSE; + } + + g_auto(GStrv) symbols = g_strsplit(str->data, ",", -1); + + if (!symbols[0]) + return TRUE; + if (*symbols[0]) { + gint v = teco_symbol_list_lookup(&teco_symbol_list_scintilla, symbols[0], "SCI_"); + if (v < 0) { + g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED, + "Unknown Scintilla message symbol \"%s\"", + symbols[0]); + return FALSE; + } + scintilla->iMessage = v; + } + + if (!symbols[1]) + return TRUE; + if (*symbols[1]) { + gint v = teco_symbol_list_lookup(&teco_symbol_list_scilexer, symbols[1], ""); + if (v < 0) { + g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED, + "Unknown Scintilla Lexer symbol \"%s\"", + symbols[1]); + return FALSE; + } + scintilla->wParam = v; + } + + if (!symbols[2]) + return TRUE; + if (*symbols[2]) { + gint v = teco_symbol_list_lookup(&teco_symbol_list_scilexer, symbols[2], ""); + if (v < 0) { + g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED, + "Unknown Scintilla Lexer symbol \"%s\"", + symbols[2]); + return FALSE; + } + scintilla->lParam = v; + } + + return TRUE; +} + +static teco_state_t * +teco_state_scintilla_symbols_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) +{ + if (ctx->mode > TECO_MODE_NORMAL) + return &teco_state_scintilla_lparam; + + /* + * NOTE: This is more memory efficient than pushing the individual + * members of teco_machine_scintilla_t and we won't need to define + * undo methods for the Scintilla types. + */ + if (ctx->parent.must_undo) + teco_undo_object_scintilla_message_push(&ctx->scintilla); + memset(&ctx->scintilla, 0, sizeof(ctx->scintilla)); + + if ((str->len > 0 && !teco_scintilla_parse_symbols(&ctx->scintilla, str, error)) || + !teco_expressions_eval(FALSE, error)) + return NULL; + + teco_int_t value; + + if (!ctx->scintilla.iMessage) { + if (!teco_expressions_args()) { + g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED, + " command requires at least a message code"); + return NULL; + } + + if (!teco_expressions_pop_num_calc(&value, 0, error)) + 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; +} + +/* in cmdline.c */ +gboolean teco_state_scintilla_symbols_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error); + +/*$ ES scintilla message + * -- Send Scintilla message + * [lParam[,wParam]]ESmessage[,wParam[,lParam]]$[lParam]$ -> result + * + * Send Scintilla message with code specified by symbolic + * name , and . + * may be symbolic when specified as part of the + * first string argument. + * If not it is popped from the stack. + * may be specified as a constant string whose + * pointer is passed to Scintilla if specified as the second + * string argument. + * If the second string argument is empty, is popped + * from the stack instead. + * Parameters popped from the stack may be omitted, in which + * case 0 is implied. + * The message's return value is pushed onto the stack. + * + * All messages defined by Scintilla (as C macros) can be + * used by passing their name as a string to ES + * (e.g. ESSCI_LINESONSCREEN...). + * The \(lqSCI_\(rq prefix may be omitted and message symbols + * are case-insensitive. + * Only the Scintilla lexer symbols (SCLEX_..., SCE_...) + * may be used symbolically with the ES command as , + * other values must be passed as integers on the stack. + * In interactive mode, symbols may be auto-completed by + * pressing Tab. + * String-building characters are by default interpreted + * in the string arguments. + * + * .BR Warning : + * Almost all Scintilla messages may be dispatched using + * this command. + * \*(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 + * (position changes, deletions, etc.) or otherwise + * rub out will result in an inconsistent editor state. + * There are however exceptions: + * - In the editor profile and batch mode in general, + * the ES command may be used freely. + * - In the ED hook macro (register \(lqED\(rq), + * when a file is added to the ring, most destructive + * operations can be performed since rubbing out the + * EB command responsible for the hook execution also + * removes the buffer from the ring again. + * - As part of function key macros that immediately + * terminate the command line. + */ +TECO_DEFINE_STATE_EXPECTSTRING(teco_state_scintilla_symbols, + .process_edit_cmd_cb = (teco_state_process_edit_cmd_cb_t)teco_state_scintilla_symbols_process_edit_cmd, + .expectstring.last = FALSE +); + +static teco_state_t * +teco_state_scintilla_lparam_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) +{ + if (ctx->mode > TECO_MODE_NORMAL) + return &teco_state_start; + + if (teco_string_contains(str, '\0')) { + g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED, + "Scintilla lParam string must not contain null-byte."); + return NULL; + } + + if (!ctx->scintilla.lParam) { + if (str->len > 0) { + ctx->scintilla.lParam = (sptr_t)str->data; + } else { + teco_int_t v; + if (!teco_expressions_pop_num_calc(&v, 0, error)) + return NULL; + ctx->scintilla.lParam = v; + } + } + + teco_expressions_push(teco_interface_ssm(ctx->scintilla.iMessage, + ctx->scintilla.wParam, + ctx->scintilla.lParam)); + + return &teco_state_start; +} + +TECO_DEFINE_STATE_EXPECTSTRING(teco_state_scintilla_lparam); diff --git a/src/symbols.h b/src/symbols.h new file mode 100644 index 0000000..607a3ff --- /dev/null +++ b/src/symbols.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2012-2021 Robin Haberkorn + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include + +#include "sciteco.h" +#include "string-utils.h" +#include "parser.h" + +typedef struct { + const gchar *name; + gint value; +} teco_symbol_entry_t; + +typedef struct { + const teco_symbol_entry_t *entries; + gint size; + + int (*cmp_fnc)(const char *, const char *, size_t); + + /** + * For auto-completions. + * The list is allocated only ondemand. + */ + GList *list; +} teco_symbol_list_t; + +void teco_symbol_list_init(teco_symbol_list_t *ctx, const teco_symbol_entry_t *entries, gint size, + gboolean case_sensitive); + +gint teco_symbol_list_lookup(teco_symbol_list_t *ctx, const gchar *name, const gchar *prefix); + +gboolean teco_symbol_list_auto_complete(teco_symbol_list_t *ctx, const gchar *symbol, teco_string_t *insert); + +/** @memberof teco_symbol_list_t */ +static inline void +teco_symbol_list_clear(teco_symbol_list_t *ctx) +{ + g_list_free(ctx->list); +} + +extern teco_symbol_list_t teco_symbol_list_scintilla; +extern teco_symbol_list_t teco_symbol_list_scilexer; + +/* + * Command states + */ + +TECO_DECLARE_STATE(teco_state_scintilla_symbols); -- cgit v1.2.3