aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/cmdline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmdline.c')
-rw-r--r--src/cmdline.c382
1 files changed, 266 insertions, 116 deletions
diff --git a/src/cmdline.c b/src/cmdline.c
index 58d48b4..816816c 100644
--- a/src/cmdline.c
+++ b/src/cmdline.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2023 Robin Haberkorn
+ * Copyright (C) 2012-2024 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
@@ -52,6 +52,7 @@
#include "eol.h"
#include "error.h"
#include "qreg.h"
+#include "glob.h"
#include "cmdline.h"
#if defined(HAVE_MALLOC_TRIM) && !defined(HAVE_DECL_MALLOC_TRIM)
@@ -81,12 +82,12 @@ static teco_string_t teco_last_cmdline = {NULL, 0};
* @param error A GError.
* @return FALSE to throw a GError
*/
-gboolean
+static gboolean
teco_cmdline_insert(const gchar *data, gsize len, GError **error)
{
const teco_string_t src = {(gchar *)data, len};
- teco_string_t old_cmdline = {NULL, 0};
- guint repl_pc = 0;
+ g_auto(teco_string_t) old_cmdline = {NULL, 0};
+ gsize repl_pc = 0;
teco_cmdline.machine.macro_pc = teco_cmdline.pc = teco_cmdline.effective_len;
@@ -109,8 +110,6 @@ teco_cmdline_insert(const gchar *data, gsize len, GError **error)
/*
* Parse/execute characters, one at a time so
* undo tokens get emitted for the corresponding characters.
- *
- * FIXME: The inner loop should be factored out.
*/
while (teco_cmdline.pc < teco_cmdline.effective_len) {
g_autoptr(GError) tmp_error = NULL;
@@ -125,7 +124,8 @@ teco_cmdline_insert(const gchar *data, gsize len, GError **error)
teco_qreg_t *cmdline_reg = teco_qreg_table_find(&teco_qreg_table_globals, "\e", 1);
teco_string_t new_cmdline;
- if (!cmdline_reg->vtable->get_string(cmdline_reg, &new_cmdline.data, &new_cmdline.len, error))
+ if (!cmdline_reg->vtable->get_string(cmdline_reg, &new_cmdline.data, &new_cmdline.len,
+ NULL, error))
return FALSE;
/*
@@ -160,6 +160,7 @@ teco_cmdline_insert(const gchar *data, gsize len, GError **error)
teco_string_clear(&teco_cmdline.str);
teco_cmdline.str = old_cmdline;
+ memset(&old_cmdline, 0, sizeof(old_cmdline));
teco_cmdline.machine.macro_pc = teco_cmdline.pc = repl_pc;
/* rubout cmdline replacement command */
@@ -179,55 +180,65 @@ teco_cmdline_insert(const gchar *data, gsize len, GError **error)
return TRUE;
}
+static gboolean
+teco_cmdline_rubin(GError **error)
+{
+ if (!teco_cmdline.str.len)
+ return TRUE;
+
+ const gchar *start, *end, *next;
+ start = teco_cmdline.str.data+teco_cmdline.effective_len;
+ end = teco_cmdline.str.data+teco_cmdline.str.len;
+ next = g_utf8_find_next_char(start, end) ? : end;
+ return teco_cmdline_insert(start, next-start, error);
+}
+
+/**
+ * Process key press or expansion of key macro.
+ *
+ * Should be called only with the results of a single keypress.
+ * They are considered an unity and in case of errors, we
+ * rubout the entire sequence (unless there was a $$ return in the
+ * middle).
+ *
+ * @param data Key presses in UTF-8.
+ * @param len Length of data.
+ * @param error A GError.
+ * @return FALSE if error was set.
+ * If TRUE was returned, there could still have been an error,
+ * but it has already been handled.
+ */
gboolean
-teco_cmdline_keypress_c(gchar key, GError **error)
+teco_cmdline_keypress(const gchar *data, gsize len, GError **error)
{
+ const teco_string_t str = {(gchar *)data, len};
teco_machine_t *machine = &teco_cmdline.machine.parent;
- g_autoptr(GError) tmp_error = NULL;
+
+ if (!teco_string_validate_utf8(&str)) {
+ g_set_error_literal(error, TECO_ERROR, TECO_ERROR_CODEPOINT,
+ "Invalid UTF-8 sequence");
+ return FALSE;
+ }
/*
- * Cleanup messages,etc...
+ * Cleanup messages, etc...
*/
teco_interface_msg_clear();
- /*
- * Process immediate editing commands, inserting
- * characters as necessary into the command line.
- */
- if (!machine->current->process_edit_cmd_cb(machine, NULL, key, &tmp_error)) {
- if (g_error_matches(tmp_error, TECO_ERROR, TECO_ERROR_RETURN)) {
- /*
- * Return from top-level macro, results
- * in command line termination.
- * The return "arguments" are currently
- * ignored.
- */
- g_assert(machine->current == &teco_state_start);
+ gsize start_pc = teco_cmdline.effective_len;
- teco_interface_popup_clear();
+ for (guint i = 0; i < len; i = g_utf8_next_char(data+i) - data) {
+ gunichar chr = g_utf8_get_char(data+i);
+ g_autoptr(GError) tmp_error = NULL;
- if (teco_quit_requested) {
- /* cought by user interface */
- g_set_error_literal(error, TECO_ERROR, TECO_ERROR_QUIT, "");
- return FALSE;
- }
+ /*
+ * Process immediate editing commands, inserting
+ * characters as necessary into the command line.
+ */
+ if (machine->current->process_edit_cmd_cb(machine, NULL, chr, &tmp_error))
+ continue;
- teco_undo_clear();
- /* also empties all Scintilla undo buffers */
- teco_ring_set_scintilla_undo(TRUE);
- teco_view_set_scintilla_undo(teco_qreg_view, TRUE);
- /*
- * FIXME: Reset main machine?
- */
- teco_goto_table_clear(&teco_cmdline.machine.goto_table);
- teco_expressions_clear();
- g_array_remove_range(teco_loop_stack, 0, teco_loop_stack->len);
-
- teco_string_clear(&teco_last_cmdline);
- teco_last_cmdline = teco_cmdline.str;
- memset(&teco_cmdline.str, 0, sizeof(teco_cmdline.str));
- teco_cmdline.effective_len = 0;
- } else {
+ if (!g_error_matches(tmp_error, TECO_ERROR, TECO_ERROR_RETURN)) {
/*
* NOTE: Error message already displayed in
* teco_cmdline_insert().
@@ -237,29 +248,76 @@ teco_cmdline_keypress_c(gchar key, GError **error)
* is thrown. They must be executed so
* as if the character had never been
* inserted.
+ * Actually we rub out the entire command line
+ * up until the insertion point.
*/
- teco_undo_pop(teco_cmdline.pc);
- teco_cmdline.effective_len = teco_cmdline.pc;
+ teco_undo_pop(start_pc);
+ teco_cmdline.effective_len = start_pc;
/* program counter could be messed up */
teco_cmdline.machine.macro_pc = teco_cmdline.effective_len;
- }
#ifdef HAVE_MALLOC_TRIM
+ /*
+ * Undo stacks can grow very large - sometimes large enough to
+ * make the system swap and become unresponsive.
+ * This shrinks the program break after lots of memory has
+ * been freed, reducing the virtual memory size and aiding
+ * in recovering from swapping issues.
+ *
+ * This is particularily important with some memory limiting backends
+ * after hitting the memory limit* as otherwise the program's resident
+ * size won't shrink and it would be impossible to recover.
+ */
+ if (g_error_matches(tmp_error, TECO_ERROR, TECO_ERROR_MEMLIMIT))
+ malloc_trim(0);
+#endif
+
+ break;
+ }
+
/*
- * Undo stacks can grow very large - sometimes large enough to
- * make the system swap and become unresponsive.
- * This shrinks the program break after lots of memory has
- * been freed, reducing the virtual memory size and aiding
- * in recovering from swapping issues.
- *
- * This is particularily important with some memory limiting backends
- * after hitting the memory limit* as otherwise the program's resident
- * size won't shrink and it would be impossible to recover.
+ * Return from top-level macro, results
+ * in command line termination.
+ * The return "arguments" are currently
+ * ignored.
+ */
+ g_assert(machine->current == &teco_state_start);
+
+ teco_interface_popup_clear();
+
+ if (teco_quit_requested) {
+ /* caught by user interface */
+ g_set_error_literal(error, TECO_ERROR, TECO_ERROR_QUIT, "");
+ return FALSE;
+ }
+
+ teco_undo_clear();
+ /* also empties all Scintilla undo buffers */
+ teco_ring_set_scintilla_undo(TRUE);
+ teco_view_set_scintilla_undo(teco_qreg_view, TRUE);
+ /*
+ * FIXME: Reset main machine?
*/
- if (g_error_matches(tmp_error, TECO_ERROR, TECO_ERROR_RETURN) ||
- g_error_matches(tmp_error, TECO_ERROR, TECO_ERROR_MEMLIMIT))
- malloc_trim(0);
+ teco_goto_table_clear(&teco_cmdline.machine.goto_table);
+ teco_expressions_clear();
+ g_array_remove_range(teco_loop_stack, 0, teco_loop_stack->len);
+
+ teco_string_clear(&teco_last_cmdline);
+ teco_last_cmdline = teco_cmdline.str;
+ memset(&teco_cmdline.str, 0, sizeof(teco_cmdline.str));
+ teco_cmdline.effective_len = 0;
+
+#ifdef HAVE_MALLOC_TRIM
+ /* see above */
+ malloc_trim(0);
#endif
+
+ /*
+ * Continue with the other keys,
+ * but we obviously can't rub out beyond the return if any
+ * error occurs later on.
+ */
+ start_pc = 0;
}
/*
@@ -269,33 +327,40 @@ teco_cmdline_keypress_c(gchar key, GError **error)
return TRUE;
}
-gboolean
-teco_cmdline_fnmacro(const gchar *name, GError **error)
+teco_keymacro_status_t
+teco_cmdline_keymacro(const gchar *name, gssize name_len, GError **error)
{
g_assert(name != NULL);
+ if (name_len < 0)
+ name_len = strlen(name);
+
/*
* NOTE: It should be safe to allocate on the stack since
* there are only a limited number of possible function key macros.
*/
- gchar macro_name[1 + strlen(name)];
- macro_name[0] = TECO_CTL_KEY('F');
- memcpy(macro_name+1, name, sizeof(macro_name)-1);
+ gchar macro_name[1 + name_len];
+ macro_name[0] = TECO_CTL_KEY('K');
+ memcpy(macro_name+1, name, name_len);
- teco_qreg_t *macro_reg;
-
- if (teco_ed & TECO_ED_FNKEYS &&
- (macro_reg = teco_qreg_table_find(&teco_qreg_table_globals, macro_name, sizeof(macro_name)))) {
+ teco_qreg_t *macro_reg = teco_qreg_table_find(&teco_qreg_table_globals, macro_name, sizeof(macro_name));
+ if (macro_reg) {
teco_int_t macro_mask;
if (!macro_reg->vtable->get_integer(macro_reg, &macro_mask, error))
- return FALSE;
+ return TECO_KEYMACRO_ERROR;
- if (macro_mask & teco_cmdline.machine.parent.current->fnmacro_mask)
- return TRUE;
+ /*
+ * FIXME: This does not work with Q-Register specs embedded into string arguments.
+ * There should be a keymacro_mask_cb() instead.
+ */
+ if (!((teco_cmdline.machine.parent.current->keymacro_mask |
+ teco_cmdline.machine.expectstring.machine.parent.current->keymacro_mask) & ~macro_mask))
+ return TECO_KEYMACRO_UNDEFINED;
g_auto(teco_string_t) macro_str = {NULL, 0};
- return macro_reg->vtable->get_string(macro_reg, &macro_str.data, &macro_str.len, error) &&
- teco_cmdline_keypress(macro_str.data, macro_str.len, error);
+ return macro_reg->vtable->get_string(macro_reg, &macro_str.data, &macro_str.len, NULL, error) &&
+ teco_cmdline_keypress(macro_str.data, macro_str.len, error)
+ ? TECO_KEYMACRO_SUCCESS : TECO_KEYMACRO_ERROR;
}
/*
@@ -303,28 +368,34 @@ teco_cmdline_fnmacro(const gchar *name, GError **error)
* except "CLOSE" which quits the application
* (this may loose unsaved data but is better than
* not doing anything if the user closes the window).
- * NOTE: Doing the check here is less efficient than
- * doing it in the UI implementations, but defines
- * the default actions centrally.
- * Also, fnmacros are only handled after key presses.
*/
- if (!strcmp(name, "CLOSE")) {
+ if (name_len == 5 && !strncmp(name, "CLOSE", name_len)) {
g_set_error_literal(error, TECO_ERROR, TECO_ERROR_QUIT, "");
- return FALSE;
+ return TECO_KEYMACRO_ERROR;
}
- return TRUE;
+ return TECO_KEYMACRO_UNDEFINED;
+}
+
+static void
+teco_cmdline_rubout(void)
+{
+ const gchar *p;
+ p = g_utf8_find_prev_char(teco_cmdline.str.data,
+ teco_cmdline.str.data+teco_cmdline.effective_len);
+ if (p) {
+ teco_cmdline.effective_len = p - teco_cmdline.str.data;
+ teco_undo_pop(teco_cmdline.effective_len);
+ }
}
-#ifndef NDEBUG
-static void __attribute__((destructor))
+static void TECO_DEBUG_CLEANUP
teco_cmdline_cleanup(void)
{
teco_machine_main_clear(&teco_cmdline.machine);
teco_string_clear(&teco_cmdline.str);
teco_string_clear(&teco_last_cmdline);
}
-#endif
/*
* Commandline key processing.
@@ -337,7 +408,7 @@ teco_cmdline_cleanup(void)
*/
gboolean
-teco_state_process_edit_cmd(teco_machine_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_process_edit_cmd(teco_machine_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
switch (key) {
case '\n': /* insert EOL sequence */
@@ -407,23 +478,30 @@ teco_state_process_edit_cmd(teco_machine_t *ctx, teco_machine_t *parent_ctx, gch
}
teco_interface_popup_clear();
- return teco_cmdline_insert(&key, sizeof(key), error);
+
+ gchar buf[6];
+ gsize len = g_unichar_to_utf8(key, buf);
+ return teco_cmdline_insert(buf, len, error);
}
gboolean
-teco_state_caseinsensitive_process_edit_cmd(teco_machine_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_caseinsensitive_process_edit_cmd(teco_machine_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
+ /*
+ * Auto case folding is for syntactic characters,
+ * so this could be done by working only with a-z and A-Z.
+ * However, it's also not speed critical.
+ */
if (teco_ed & TECO_ED_AUTOCASEFOLD)
- /* will not modify non-letter keys */
- key = g_ascii_islower(key) ? g_ascii_toupper(key)
- : g_ascii_tolower(key);
+ key = g_unichar_islower(key) ? g_unichar_toupper(key)
+ : g_unichar_tolower(key);
return teco_state_process_edit_cmd(ctx, parent_ctx, key, error);
}
gboolean
teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t *ctx, teco_machine_t *parent_ctx,
- gchar key, GError **error)
+ gunichar key, GError **error)
{
teco_state_t *current = ctx->parent.current;
@@ -460,20 +538,15 @@ teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t *
* get the default behaviour of teco_state_process_edit_cmd().
* This may not be a real-life issue serious enough to maintain
* a result string even in parse-only mode.
- *
- * FIXME: Does not properly rubout string-building commands at the
- * start of the string argument -- ctx->result->len is not
- * a valid indicator of argument emptyness.
- * Since it chains to teco_state_process_edit_cmd() we will instead
- * rubout the entire command.
*/
if (ctx->result && ctx->result->len > 0) {
gboolean is_wordchar = teco_string_contains(&wchars, teco_cmdline.str.data[teco_cmdline.effective_len-1]);
teco_cmdline_rubout();
if (ctx->parent.current != current) {
/* rub out string building command */
- while (ctx->result->len > 0 && ctx->parent.current != current)
+ do
teco_cmdline_rubout();
+ while (ctx->parent.current != current);
return TRUE;
}
@@ -572,8 +645,29 @@ teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t *
}
gboolean
+teco_state_stringbuilding_escaped_process_edit_cmd(teco_machine_stringbuilding_t *ctx, teco_machine_t *parent_ctx,
+ gunichar key, GError **error)
+{
+ /*
+ * Allow insertion of characters that would otherwise be interpreted as
+ * immediate editing commands after ^Q/^R.
+ */
+ switch (key) {
+ //case TECO_CTL_KEY('G'):
+ case TECO_CTL_KEY('W'):
+ case TECO_CTL_KEY('U'):
+ teco_interface_popup_clear();
+
+ gchar c = key;
+ return teco_cmdline_insert(&c, sizeof(c), error);
+ }
+
+ return teco_state_process_edit_cmd(parent_ctx, NULL, key, error);
+}
+
+gboolean
teco_state_stringbuilding_qreg_process_edit_cmd(teco_machine_stringbuilding_t *ctx, teco_machine_t *parent_ctx,
- gchar chr, GError **error)
+ gunichar chr, GError **error)
{
g_assert(ctx->machine_qregspec != NULL);
/* We downcast since teco_machine_qregspec_t is private in qreg.c */
@@ -582,7 +676,7 @@ teco_state_stringbuilding_qreg_process_edit_cmd(teco_machine_stringbuilding_t *c
}
gboolean
-teco_state_expectstring_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_expectstring_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
teco_machine_stringbuilding_t *stringbuilding_ctx = &ctx->expectstring.machine;
teco_state_t *stringbuilding_current = stringbuilding_ctx->parent.current;
@@ -590,7 +684,7 @@ teco_state_expectstring_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_
}
gboolean
-teco_state_insert_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_insert_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
teco_machine_stringbuilding_t *stringbuilding_ctx = &ctx->expectstring.machine;
teco_state_t *stringbuilding_current = stringbuilding_ctx->parent.current;
@@ -626,7 +720,7 @@ teco_state_insert_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *par
}
gboolean
-teco_state_expectfile_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_expectfile_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
teco_machine_stringbuilding_t *stringbuilding_ctx = &ctx->expectstring.machine;
teco_state_t *stringbuilding_current = stringbuilding_ctx->parent.current;
@@ -696,8 +790,8 @@ teco_state_expectfile_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t
gboolean unambiguous = teco_file_auto_complete(ctx->expectstring.string.data, G_FILE_TEST_EXISTS, &new_chars);
teco_machine_stringbuilding_escape(stringbuilding_ctx, new_chars.data, new_chars.len, &new_chars_escaped);
if (unambiguous && ctx->expectstring.nesting == 1)
- teco_string_append_c(&new_chars_escaped,
- ctx->expectstring.machine.escape_char == '{' ? '}' : ctx->expectstring.machine.escape_char);
+ teco_string_append_wc(&new_chars_escaped,
+ ctx->expectstring.machine.escape_char == '{' ? '}' : ctx->expectstring.machine.escape_char);
return teco_cmdline_insert(new_chars_escaped.data, new_chars_escaped.len, error);
}
@@ -707,7 +801,61 @@ teco_state_expectfile_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t
}
gboolean
-teco_state_expectdir_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_expectglob_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
+{
+ teco_machine_stringbuilding_t *stringbuilding_ctx = &ctx->expectstring.machine;
+ teco_state_t *stringbuilding_current = stringbuilding_ctx->parent.current;
+
+ /*
+ * NOTE: We don't just define teco_state_stringbuilding_start_process_edit_cmd(),
+ * as it would be hard to subclass/overwrite for different main machine states.
+ */
+ if (!stringbuilding_current->is_start)
+ return stringbuilding_current->process_edit_cmd_cb(&stringbuilding_ctx->parent, &ctx->parent, key, error);
+
+ switch (key) {
+ case '\t': { /* autocomplete file name */
+ if (teco_cmdline.modifier_enabled)
+ break;
+
+ if (teco_interface_popup_is_shown()) {
+ /* cycle through popup pages */
+ teco_interface_popup_show();
+ return TRUE;
+ }
+
+ if (teco_string_contains(&ctx->expectstring.string, '\0'))
+ /* null-byte not allowed in file names */
+ return TRUE;
+
+ /*
+ * We do not support autocompleting glob patterns.
+ *
+ * FIXME: What if the last autocompletion inserted escaped glob
+ * characters?
+ * Perhaps teco_file_auto_complete() should natively support glob patterns.
+ */
+ if (teco_globber_is_pattern(ctx->expectstring.string.data))
+ return TRUE;
+
+ g_auto(teco_string_t) new_chars, new_chars_escaped;
+ gboolean unambiguous = teco_file_auto_complete(ctx->expectstring.string.data, G_FILE_TEST_EXISTS, &new_chars);
+ g_autofree gchar *pattern_escaped = teco_globber_escape_pattern(new_chars.data);
+ teco_machine_stringbuilding_escape(stringbuilding_ctx, pattern_escaped, strlen(pattern_escaped), &new_chars_escaped);
+ if (unambiguous && ctx->expectstring.nesting == 1)
+ teco_string_append_wc(&new_chars_escaped,
+ ctx->expectstring.machine.escape_char == '{' ? '}' : ctx->expectstring.machine.escape_char);
+
+ return teco_cmdline_insert(new_chars_escaped.data, new_chars_escaped.len, error);
+ }
+ }
+
+ /* ^W should behave like in commands accepting files */
+ return teco_state_expectfile_process_edit_cmd(ctx, parent_ctx, key, error);
+}
+
+gboolean
+teco_state_expectdir_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
teco_machine_stringbuilding_t *stringbuilding_ctx = &ctx->expectstring.machine;
teco_state_t *stringbuilding_current = stringbuilding_ctx->parent.current;
@@ -745,11 +893,12 @@ teco_state_expectdir_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *
}
}
- return stringbuilding_current->process_edit_cmd_cb(&stringbuilding_ctx->parent, &ctx->parent, key, error);
+ /* ^W should behave like in commands accepting files */
+ return teco_state_expectfile_process_edit_cmd(ctx, parent_ctx, key, error);
}
gboolean
-teco_state_expectqreg_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_expectqreg_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
g_assert(ctx->expectqreg != NULL);
/*
@@ -761,7 +910,7 @@ teco_state_expectqreg_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t
}
gboolean
-teco_state_qregspec_process_edit_cmd(teco_machine_qregspec_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_qregspec_process_edit_cmd(teco_machine_qregspec_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
switch (key) {
case '\t': { /* autocomplete Q-Register name */
@@ -796,7 +945,7 @@ teco_state_qregspec_process_edit_cmd(teco_machine_qregspec_t *ctx, teco_machine_
}
gboolean
-teco_state_qregspec_string_process_edit_cmd(teco_machine_qregspec_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_qregspec_string_process_edit_cmd(teco_machine_qregspec_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
teco_machine_stringbuilding_t *stringbuilding_ctx = teco_machine_qregspec_get_stringbuilding(ctx);
teco_state_t *stringbuilding_current = stringbuilding_ctx->parent.current;
@@ -836,7 +985,7 @@ teco_state_qregspec_string_process_edit_cmd(teco_machine_qregspec_t *ctx, teco_m
}
gboolean
-teco_state_execute_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_execute_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
teco_machine_stringbuilding_t *stringbuilding_ctx = &ctx->expectstring.machine;
teco_state_t *stringbuilding_current = stringbuilding_ctx->parent.current;
@@ -881,7 +1030,7 @@ teco_state_execute_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *pa
}
gboolean
-teco_state_scintilla_symbols_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_scintilla_symbols_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
teco_machine_stringbuilding_t *stringbuilding_ctx = &ctx->expectstring.machine;
teco_state_t *stringbuilding_current = stringbuilding_ctx->parent.current;
@@ -926,7 +1075,7 @@ teco_state_scintilla_symbols_process_edit_cmd(teco_machine_main_t *ctx, teco_mac
}
gboolean
-teco_state_goto_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_goto_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
teco_machine_stringbuilding_t *stringbuilding_ctx = &ctx->expectstring.machine;
teco_state_t *stringbuilding_current = stringbuilding_ctx->parent.current;
@@ -973,7 +1122,7 @@ teco_state_goto_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *paren
}
gboolean
-teco_state_help_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error)
+teco_state_help_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error)
{
teco_machine_stringbuilding_t *stringbuilding_ctx = &ctx->expectstring.machine;
teco_state_t *stringbuilding_current = stringbuilding_ctx->parent.current;
@@ -1004,8 +1153,8 @@ teco_state_help_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *paren
gboolean unambiguous = teco_help_auto_complete(ctx->expectstring.string.data, &new_chars);
teco_machine_stringbuilding_escape(stringbuilding_ctx, new_chars.data, new_chars.len, &new_chars_escaped);
if (unambiguous && ctx->expectstring.nesting == 1)
- teco_string_append_c(&new_chars_escaped,
- ctx->expectstring.machine.escape_char == '{' ? '}' : ctx->expectstring.machine.escape_char);
+ teco_string_append_wc(&new_chars_escaped,
+ ctx->expectstring.machine.escape_char == '{' ? '}' : ctx->expectstring.machine.escape_char);
return new_chars_escaped.len ? teco_cmdline_insert(new_chars_escaped.data, new_chars_escaped.len, error) : TRUE;
}
@@ -1028,7 +1177,8 @@ teco_state_save_cmdline_got_register(teco_machine_main_t *ctx, teco_qreg_t *qreg
return &teco_state_start;
if (!qreg->vtable->undo_set_string(qreg, error) ||
- !qreg->vtable->set_string(qreg, teco_last_cmdline.data, teco_last_cmdline.len, error))
+ !qreg->vtable->set_string(qreg, teco_last_cmdline.data, teco_last_cmdline.len,
+ teco_default_codepage(), error))
return NULL;
return &teco_state_start;