diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmdline.c | 257 | ||||
| -rw-r--r-- | src/cmdline.h | 47 | ||||
| -rw-r--r-- | src/core-commands.c | 8 | ||||
| -rw-r--r-- | src/doc.c | 3 | ||||
| -rw-r--r-- | src/interface-curses/interface.c | 187 | ||||
| -rw-r--r-- | src/interface-gtk/interface.c | 108 | ||||
| -rw-r--r-- | src/interface.h | 3 | ||||
| -rw-r--r-- | src/main.c | 1 | ||||
| -rw-r--r-- | src/stdio-commands.c | 2 |
9 files changed, 271 insertions, 345 deletions
diff --git a/src/cmdline.c b/src/cmdline.c index 089bd7a..53436fe 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -38,6 +38,7 @@ #include "file-utils.h" #include "interface.h" #include "view.h" +#include "doc.h" #include "expressions.h" #include "parser.h" #include "core-commands.h" @@ -61,11 +62,86 @@ int malloc_trim(size_t pad); #define TECO_DEFAULT_BREAK_CHARS " \t\v\r\n\f<>,;@" +/** Style used for the asterisk at the beginning of the command line */ +#define STYLE_ASTERISK 64 + teco_cmdline_t teco_cmdline = {}; -/** Last terminated command line */ +/* + * FIXME: Should perhaps be in doc.h. + * But which view should it be called on? + */ +static inline void +teco_doc_scintilla_unref(teco_doc_scintilla_t *doc) +{ + if (doc) + teco_cmdline_ssm(SCI_RELEASEDOCUMENT, 0, (sptr_t)doc); +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(teco_doc_scintilla_t, teco_doc_scintilla_unref); + +/** + * Last terminated command line. + * This is not a teco_doc_scintilla_t since we have to return it as a string + * at the end of the day. + */ static teco_string_t teco_last_cmdline = {NULL, 0}; +void +teco_cmdline_init(void) +{ + teco_cmdline.view = teco_view_new(); + teco_view_setup(teco_cmdline.view); + + teco_cmdline_ssm(SCI_SETUNDOCOLLECTION, FALSE, 0); + teco_cmdline_ssm(SCI_SETVSCROLLBAR, FALSE, 0); + teco_cmdline_ssm(SCI_STYLESETBOLD, STYLE_ASTERISK, TRUE); + teco_cmdline_ssm(SCI_SETMARGINTYPEN, 1, SC_MARGIN_TEXT); + teco_cmdline_ssm(SCI_MARGINSETSTYLE, 0, STYLE_ASTERISK); + teco_cmdline_ssm(SCI_SETMARGINWIDTHN, 1, + teco_cmdline_ssm(SCI_TEXTWIDTH, STYLE_ASTERISK, (sptr_t)"*")); + /* NOTE: might not work on all UIs */ + teco_cmdline_ssm(SCI_INDICSETSTYLE, INDICATOR_RUBBEDOUT, INDIC_STRIKE); + teco_cmdline_ssm(SCI_INDICSETFORE, INDICATOR_RUBBEDOUT, + teco_cmdline_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0)); + + /* single line mode - EOL characters won't break the line */ + teco_cmdline_ssm(SCI_SETLINEENDTYPESALLOWED, SC_LINE_END_TYPE_HIDDEN, 0); + /* render tabs as "TAB" */ + teco_cmdline_ssm(SCI_SETTABDRAWMODE, SCTD_CONTROLCHAR, 0); + teco_cmdline_ssm(SCI_SETTABWIDTH, 1, 0); + teco_cmdline_ssm(SCI_SETTABMINIMUMWIDTH, + teco_cmdline_ssm(SCI_TEXTWIDTH, STYLE_DEFAULT, (sptr_t)"TAB"), 0); + + /* + * FIXME: Something resets the margin text, so we have to set it last. + */ + teco_cmdline_ssm(SCI_MARGINSETTEXT, 0, (sptr_t)"*"); +} + +static void +teco_cmdline_update(void) +{ + /* + * Update the command line indicators. + * FIXME: Perhaps this can be avoided completely by updating the + * indicators in teco_cmdline_insert(). + */ + gsize effective_len = teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0); + gsize macro_len = teco_cmdline_ssm(SCI_GETLENGTH, 0, 0); + teco_cmdline_ssm(SCI_SETINDICATORCURRENT, INDICATOR_RUBBEDOUT, 0); + teco_cmdline_ssm(SCI_INDICATORCLEARRANGE, 0, macro_len); + teco_cmdline_ssm(SCI_INDICATORFILLRANGE, effective_len, macro_len - effective_len); + teco_cmdline_ssm(SCI_SCROLLCARET, 0, 0); + + /* + * FIXME: This gets reset repeatedly. + * Setting it once per keypress however means you can no longer customize + * the margin text. + */ + teco_cmdline_ssm(SCI_MARGINSETTEXT, 0, (sptr_t)"*"); +} + /** * Insert string into command line and execute * it immediately. @@ -80,43 +156,52 @@ static gboolean teco_cmdline_insert(const gchar *data, gsize len, GError **error) { const teco_string_t src = {(gchar *)data, len}; - g_auto(teco_string_t) old_cmdline = {NULL, 0}; + g_autoptr(teco_doc_scintilla_t) old_cmdline = NULL; gsize repl_pc = 0; - teco_cmdline.machine.macro_pc = teco_cmdline.pc = teco_cmdline.effective_len; + gsize effective_len = teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0); + teco_cmdline.machine.macro_pc = teco_cmdline.pc = effective_len; - if (len <= teco_cmdline.str.len - teco_cmdline.effective_len && - !teco_string_cmp(&src, teco_cmdline.str.data + teco_cmdline.effective_len, len)) { - teco_cmdline.effective_len += len; + const gchar *macro = (const gchar *)teco_cmdline_ssm(SCI_GETCHARACTERPOINTER, 0, 0); + gsize macro_len = teco_cmdline_ssm(SCI_GETLENGTH, 0, 0); + + if (len <= macro_len - effective_len && + !teco_string_cmp(&src, macro + effective_len, len)) { + /* extend effective command line from rubbed out part */ + teco_cmdline_ssm(SCI_GOTOPOS, effective_len+len, 0); } else { - if (teco_cmdline.effective_len < teco_cmdline.str.len) + /* discard rubbed out part of the command line */ + if (effective_len < macro_len) /* * Automatically disable immediate editing modifier. * FIXME: Should we show a message as when pressing ^G? */ teco_cmdline.modifier_enabled = FALSE; - teco_cmdline.str.len = teco_cmdline.effective_len; - teco_string_append(&teco_cmdline.str, data, len); - teco_cmdline.effective_len = teco_cmdline.str.len; + teco_cmdline_ssm(SCI_DELETERANGE, effective_len, macro_len - effective_len); + teco_cmdline_ssm(SCI_ADDTEXT, len, (sptr_t)data); + + /* the pointer shouldn't have changed... */ + macro = (const gchar *)teco_cmdline_ssm(SCI_GETCHARACTERPOINTER, 0, 0); + macro_len = teco_cmdline_ssm(SCI_GETLENGTH, 0, 0); } + effective_len += len; /* * Parse/execute characters, one at a time so * undo tokens get emitted for the corresponding characters. */ - while (teco_cmdline.pc < teco_cmdline.effective_len) { + while (teco_cmdline.pc < effective_len) { g_autoptr(GError) tmp_error = NULL; - if (!teco_machine_main_step(&teco_cmdline.machine, teco_cmdline.str.data, - teco_cmdline.pc+1, &tmp_error)) { + if (!teco_machine_main_step(&teco_cmdline.machine, macro, teco_cmdline.pc+1, &tmp_error)) { if (g_error_matches(tmp_error, TECO_ERROR, TECO_ERROR_CMDLINE)) { /* * Result of command line replacement (}): - * Exchange command lines, avoiding deep copying + * Exchange command lines */ teco_qreg_t *cmdline_reg = teco_qreg_table_find(&teco_qreg_table_globals, "\e", 1); - teco_string_t new_cmdline; + g_auto(teco_string_t) new_cmdline = {NULL, 0}; if (!cmdline_reg->vtable->get_string(cmdline_reg, &new_cmdline.data, &new_cmdline.len, NULL, error)) @@ -127,14 +212,18 @@ teco_cmdline_insert(const gchar *data, gsize len, GError **error) * new command line. This avoids unnecessary rubouts * and insertions when the command line is updated. */ - teco_cmdline.pc = teco_string_diff(&teco_cmdline.str, new_cmdline.data, new_cmdline.len); + teco_cmdline.pc = teco_string_diff(&new_cmdline, macro, effective_len); teco_undo_pop(teco_cmdline.pc); - g_assert(old_cmdline.len == 0); - old_cmdline = teco_cmdline.str; - teco_cmdline.str = new_cmdline; - teco_cmdline.effective_len = new_cmdline.len; + //g_assert(old_cmdline == NULL); + old_cmdline = (teco_doc_scintilla_t *)teco_cmdline_ssm(SCI_GETDOCPOINTER, 0, 0); + teco_cmdline_ssm(SCI_ADDREFDOCUMENT, 0, (sptr_t)old_cmdline); + /* create new document in the command line view */ + teco_cmdline_ssm(SCI_SETDOCPOINTER, 0, 0); + teco_cmdline_ssm(SCI_ADDTEXT, new_cmdline.len, (sptr_t)new_cmdline.data); + macro = (const gchar *)teco_cmdline_ssm(SCI_GETCHARACTERPOINTER, 0, 0); + macro_len = effective_len = new_cmdline.len; teco_cmdline.machine.macro_pc = repl_pc = teco_cmdline.pc; continue; @@ -144,7 +233,7 @@ teco_cmdline_insert(const gchar *data, gsize len, GError **error) teco_error_add_frame_toplevel(); teco_error_display_short(tmp_error); - if (old_cmdline.len > 0) { + if (old_cmdline) { /* * Error during command-line replacement. * Replay previous command-line. @@ -152,13 +241,16 @@ teco_cmdline_insert(const gchar *data, gsize len, GError **error) */ teco_undo_pop(repl_pc); - teco_string_clear(&teco_cmdline.str); - teco_cmdline.str = old_cmdline; - memset(&old_cmdline, 0, sizeof(old_cmdline)); + teco_cmdline_ssm(SCI_SETDOCPOINTER, 0, (sptr_t)old_cmdline); + old_cmdline = NULL; teco_cmdline.machine.macro_pc = teco_cmdline.pc = repl_pc; /* rubout cmdline replacement command */ - teco_cmdline.effective_len--; + teco_cmdline_ssm(SCI_GOTOPOS, --effective_len, 0); + + macro = (const gchar *)teco_cmdline_ssm(SCI_GETCHARACTERPOINTER, 0, 0); + macro_len = teco_cmdline_ssm(SCI_GETLENGTH, 0, 0); + continue; } } @@ -177,14 +269,18 @@ teco_cmdline_insert(const gchar *data, gsize len, GError **error) 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); + gsize macro_len = teco_cmdline_ssm(SCI_GETLENGTH, 0, 0); + gsize pos = teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0); + gchar buf[4+1]; + struct Sci_TextRangeFull range = { + .chrg = {pos, MIN(macro_len, pos+sizeof(buf)-1)}, + .lpstrText = buf + }; + gsize len = teco_cmdline_ssm(SCI_GETTEXTRANGEFULL, 0, (sptr_t)&range); + + const gchar *end = buf+len; + const gchar *next = g_utf8_find_next_char(buf, end) ? : end; + return teco_cmdline_insert(buf, next-buf, error); } /** @@ -219,7 +315,7 @@ teco_cmdline_keypress(const gchar *data, gsize len, GError **error) */ teco_interface_msg_clear(); - gsize start_pc = teco_cmdline.effective_len; + gsize start_pc = teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0); for (guint i = 0; i < len; i = g_utf8_next_char(data+i) - data) { gunichar chr = g_utf8_get_char(data+i); @@ -246,9 +342,9 @@ teco_cmdline_keypress(const gchar *data, gsize len, GError **error) * up until the insertion point. */ teco_undo_pop(start_pc); - teco_cmdline.effective_len = start_pc; + teco_cmdline_ssm(SCI_GOTOPOS, start_pc, 0); /* program counter could be messed up */ - teco_cmdline.machine.macro_pc = teco_cmdline.effective_len; + teco_cmdline.machine.macro_pc = start_pc; #ifdef HAVE_MALLOC_TRIM /* @@ -297,12 +393,16 @@ teco_cmdline_keypress(const gchar *data, gsize len, GError **error) g_array_remove_range(teco_loop_stack, 0, teco_loop_stack->len); teco_string_clear(&teco_last_cmdline); - teco_last_cmdline = teco_cmdline.str; + teco_last_cmdline.len = teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0); + teco_last_cmdline.data = g_malloc(teco_last_cmdline.len + 1); + teco_cmdline_ssm(SCI_GETTEXT, teco_last_cmdline.len, + (sptr_t)teco_last_cmdline.data); /* * FIXME: Preserve the command line after the $$. + * This would be useful for command line editing macros. + * Perhaps just call teco_cmdline_insert(). */ - memset(&teco_cmdline.str, 0, sizeof(teco_cmdline.str)); - teco_cmdline.effective_len = 0; + teco_cmdline_ssm(SCI_CLEARALL, 0, 0); #ifdef HAVE_MALLOC_TRIM /* see above */ @@ -317,10 +417,8 @@ teco_cmdline_keypress(const gchar *data, gsize len, GError **error) start_pc = 0; } - /* - * Echo command line - */ - teco_interface_cmdline_update(&teco_cmdline); + teco_cmdline_update(); + return TRUE; } @@ -377,20 +475,19 @@ teco_cmdline_keymacro(const gchar *name, gssize name_len, GError **error) 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); + gsize effective_len = teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0); + gssize p = teco_view_glyphs2bytes_relative(teco_cmdline.view, effective_len, -1); + if (p >= 0) { + teco_cmdline_ssm(SCI_GOTOPOS, p, 0); + teco_undo_pop(p); } } -static void TECO_DEBUG_CLEANUP +void teco_cmdline_cleanup(void) { teco_machine_main_clear(&teco_cmdline.machine); - teco_string_clear(&teco_cmdline.str); + teco_view_free(teco_cmdline.view); teco_string_clear(&teco_last_cmdline); } @@ -448,11 +545,12 @@ teco_state_process_edit_cmd(teco_machine_t *ctx, teco_machine_t *parent_ctx, gun if (teco_cmdline.modifier_enabled) { /* reinsert construct */ + gsize macro_len = teco_cmdline_ssm(SCI_GETLENGTH, 0, 0); do { if (!teco_cmdline_rubin(error)) return FALSE; } while (!ctx->current->is_start && - teco_cmdline.effective_len < teco_cmdline.str.len); + teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) < macro_len); } else { /* rubout construct */ do @@ -508,6 +606,9 @@ teco_state_command_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *pa case TECO_CTL_KEY('W'): /* rubout/reinsert command */ teco_interface_popup_clear(); + const gchar *macro = (const gchar *)teco_cmdline_ssm(SCI_GETCHARACTERPOINTER, 0, 0); + gsize macro_len = teco_cmdline_ssm(SCI_GETLENGTH, 0, 0); + /* * This mimics the behavior of the `Y` command, * so it also rubs out no-op commands. @@ -517,9 +618,8 @@ teco_state_command_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *pa /* reinsert command */ /* @ and : are not separate states, but practically belong to the command */ while (ctx->parent.current->is_start && - teco_cmdline.effective_len < teco_cmdline.str.len && - (teco_cmdline.str.data[teco_cmdline.effective_len] == ':' || - teco_cmdline.str.data[teco_cmdline.effective_len] == '@')) + teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) < macro_len && + strchr(":@", macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)]) != NULL) if (!teco_cmdline_rubin(error)) return FALSE; @@ -527,11 +627,11 @@ teco_state_command_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *pa if (!teco_cmdline_rubin(error)) return FALSE; } while (!ctx->parent.current->is_start && - teco_cmdline.effective_len < teco_cmdline.str.len); + teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) < macro_len); while (ctx->parent.current->is_start && - teco_cmdline.effective_len < teco_cmdline.str.len && - teco_is_noop(teco_cmdline.str.data[teco_cmdline.effective_len])) + teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) < macro_len && + teco_is_noop(macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)])) if (!teco_cmdline_rubin(error)) return FALSE; @@ -540,8 +640,8 @@ teco_state_command_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *pa /* rubout command */ while (ctx->parent.current->is_start && - teco_cmdline.effective_len > 0 && - teco_is_noop(teco_cmdline.str.data[teco_cmdline.effective_len-1])) + teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) > 0 && + teco_is_noop(macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)-1])) teco_cmdline_rubout(); do @@ -555,7 +655,7 @@ teco_state_command_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *pa */ while (ctx->parent.current->is_start && (ctx->flags.modifier_at || ctx->flags.modifier_colon) && - teco_cmdline.effective_len > 0) + teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) > 0) teco_cmdline_rubout(); return TRUE; @@ -570,6 +670,9 @@ teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t * { teco_state_t *current = ctx->parent.current; + const gchar *macro = (const gchar *)teco_cmdline_ssm(SCI_GETCHARACTERPOINTER, 0, 0); + gsize macro_len = teco_cmdline_ssm(SCI_GETLENGTH, 0, 0); + switch (key) { case TECO_CTL_KEY('W'): { /* rubout/reinsert word */ teco_interface_popup_clear(); @@ -587,15 +690,15 @@ teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t * if (teco_cmdline.modifier_enabled) { /* reinsert word chars */ while (ctx->parent.current == current && - teco_cmdline.effective_len < teco_cmdline.str.len && - teco_string_contains(&wchars, teco_cmdline.str.data[teco_cmdline.effective_len])) + teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) < macro_len && + teco_string_contains(&wchars, macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)])) if (!teco_cmdline_rubin(error)) return FALSE; /* reinsert non-word chars */ while (ctx->parent.current == current && - teco_cmdline.effective_len < teco_cmdline.str.len && - !teco_string_contains(&wchars, teco_cmdline.str.data[teco_cmdline.effective_len])) + teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) < macro_len && + !teco_string_contains(&wchars, macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)])) if (!teco_cmdline_rubin(error)) return FALSE; @@ -609,7 +712,7 @@ teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t * * a result string even in parse-only mode. */ if (ctx->result && ctx->result->len > 0) { - gboolean is_wordchar = teco_string_contains(&wchars, teco_cmdline.str.data[teco_cmdline.effective_len-1]); + gboolean is_wordchar = teco_string_contains(&wchars, macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)-1]); teco_cmdline_rubout(); if (ctx->parent.current != current) { /* rub out string building command */ @@ -625,13 +728,13 @@ teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t * */ if (!is_wordchar) { while (ctx->result->len > 0 && - !teco_string_contains(&wchars, teco_cmdline.str.data[teco_cmdline.effective_len-1])) + !teco_string_contains(&wchars, macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)-1])) teco_cmdline_rubout(); } /* rubout word chars */ while (ctx->result->len > 0 && - teco_string_contains(&wchars, teco_cmdline.str.data[teco_cmdline.effective_len-1])) + teco_string_contains(&wchars, macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)-1])) teco_cmdline_rubout(); return TRUE; @@ -648,8 +751,7 @@ teco_state_stringbuilding_start_process_edit_cmd(teco_machine_stringbuilding_t * if (teco_cmdline.modifier_enabled) { /* reinsert string */ - while (ctx->parent.current == current && - teco_cmdline.effective_len < teco_cmdline.str.len) + while (ctx->parent.current == current && teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) < macro_len) if (!teco_cmdline_rubin(error)) return FALSE; @@ -827,18 +929,21 @@ teco_state_expectfile_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t case TECO_CTL_KEY('W'): /* rubout/reinsert file names including directories */ teco_interface_popup_clear(); + const gchar *macro = (const gchar *)teco_cmdline_ssm(SCI_GETCHARACTERPOINTER, 0, 0); + gsize macro_len = teco_cmdline_ssm(SCI_GETLENGTH, 0, 0); + if (teco_cmdline.modifier_enabled) { /* reinsert one level of file name */ while (stringbuilding_ctx->parent.current == stringbuilding_current && - teco_cmdline.effective_len < teco_cmdline.str.len && - !G_IS_DIR_SEPARATOR(teco_cmdline.str.data[teco_cmdline.effective_len])) + teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) < macro_len && + !G_IS_DIR_SEPARATOR(macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)])) if (!teco_cmdline_rubin(error)) return FALSE; /* reinsert final directory separator */ if (stringbuilding_ctx->parent.current == stringbuilding_current && - teco_cmdline.effective_len < teco_cmdline.str.len && - G_IS_DIR_SEPARATOR(teco_cmdline.str.data[teco_cmdline.effective_len]) && + teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) < macro_len && + G_IS_DIR_SEPARATOR(macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)]) && !teco_cmdline_rubin(error)) return FALSE; @@ -847,12 +952,12 @@ teco_state_expectfile_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t if (ctx->expectstring.string.len > 0) { /* rubout directory separator */ - if (G_IS_DIR_SEPARATOR(teco_cmdline.str.data[teco_cmdline.effective_len-1])) + if (G_IS_DIR_SEPARATOR(macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)-1])) teco_cmdline_rubout(); /* rubout one level of file name */ while (ctx->expectstring.string.len > 0 && - !G_IS_DIR_SEPARATOR(teco_cmdline.str.data[teco_cmdline.effective_len-1])) + !G_IS_DIR_SEPARATOR(macro[teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0)-1])) teco_cmdline_rubout(); return TRUE; diff --git a/src/cmdline.h b/src/cmdline.h index abe9b53..1ec891b 100644 --- a/src/cmdline.h +++ b/src/cmdline.h @@ -19,10 +19,13 @@ #include <glib.h> #include "sciteco.h" -#include "string-utils.h" #include "parser.h" +#include "view.h" #include "undo.h" +/** Indicator number used for the rubbed out part of the command line */ +#define INDICATOR_RUBBEDOUT (INDICATOR_CONTAINER+0) + typedef struct { /** * State machine used for interactive mode (commandline macro). @@ -34,16 +37,14 @@ typedef struct { teco_machine_main_t machine; /** - * String containing the current command line - * (both effective and rubbed out). - */ - teco_string_t str; - /** - * Effective command line length. - * The length of the rubbed out part of the command line - * is (teco_cmdline.str.len - teco_cmdline.effective_len). + * Command-line Scintilla view. + * It's document contains the current command line macro. + * The current position (cursor) marks the end of the + * "effective" command line, while everything afterwards + * is the rubbed out part of the command line. + * The rubbed out part should be highlighted with an indicator. */ - gsize effective_len; + teco_view_t *view; /** Program counter within the command-line macro */ gsize pc; @@ -60,6 +61,30 @@ typedef struct { extern teco_cmdline_t teco_cmdline; +void teco_cmdline_init(void); + +static inline sptr_t +teco_cmdline_ssm(unsigned int iMessage, uptr_t wParam, sptr_t lParam) +{ + return teco_view_ssm(teco_cmdline.view, iMessage, wParam, lParam); +} + +/** + * Update scroll beavior on command line after window resizes. + * + * This should ensure that the caret jumps to the middle of the command line. + * + * @param width Window (command line view) width in pixels or columns. + * + * @fixme + * On the other hand this limits how you can customize the scroll behavior. + */ +static inline void +teco_cmdline_resize(guint width) +{ + teco_cmdline_ssm(SCI_SETXCARETPOLICY, CARET_SLOP | CARET_EVEN, width/2); +} + gboolean teco_cmdline_keypress(const gchar *data, gsize len, GError **error); typedef enum { @@ -84,6 +109,8 @@ teco_cmdline_keymacro_c(gchar key, GError **error) return TRUE; } +void teco_cmdline_cleanup(void); + /* * Command states */ diff --git a/src/core-commands.c b/src/core-commands.c index 653a40f..99fd628 100644 --- a/src/core-commands.c +++ b/src/core-commands.c @@ -551,9 +551,11 @@ teco_state_start_cmdline_push(teco_machine_main_t *ctx, GError **error) !teco_qreg_table_edit_name(&teco_qreg_table_globals, "\e", 1, error)) return; + const gchar *macro = (const gchar *)teco_cmdline_ssm(SCI_GETCHARACTERPOINTER, 0, 0); + teco_interface_ssm(SCI_BEGINUNDOACTION, 0, 0); teco_interface_ssm(SCI_CLEARALL, 0, 0); - teco_interface_ssm(SCI_ADDTEXT, teco_cmdline.pc, (sptr_t)teco_cmdline.str.data); + teco_interface_ssm(SCI_ADDTEXT, teco_cmdline.pc, (sptr_t)macro); teco_interface_ssm(SCI_ENDUNDOACTION, 0, 0); /* @@ -771,8 +773,10 @@ teco_state_start_input(teco_machine_main_t *ctx, gunichar chr, GError **error) * for beginnings of command-lines? * It could also be used for a corresponding KEYMACRO mask. */ - if (teco_cmdline.effective_len == 1 && teco_cmdline.str.data[0] == '*') + if (teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0) == 1 && + teco_cmdline_ssm(SCI_GETCHARAT, 0, 0) == '*') return &teco_state_save_cmdline; + /* treat as an operator */ break; case '<': @@ -205,7 +205,8 @@ teco_doc_get_string(teco_doc_t *ctx, gchar **str, gsize *outlen, guint *codepage gsize len = teco_view_ssm(teco_qreg_view, SCI_GETLENGTH, 0, 0); if (str) { *str = g_malloc(len + 1); - teco_view_ssm(teco_qreg_view, SCI_GETTEXT, len + 1, (sptr_t)*str); + /* null-terminates the string */ + teco_view_ssm(teco_qreg_view, SCI_GETTEXT, len, (sptr_t)*str); } if (outlen) *outlen = len; diff --git a/src/interface-curses/interface.c b/src/interface-curses/interface.c index 6c8c812..2effdb6 100644 --- a/src/interface-curses/interface.c +++ b/src/interface-curses/interface.c @@ -371,9 +371,6 @@ static struct { WINDOW *msg_window; - WINDOW *cmdline_window, *cmdline_pad; - guint cmdline_len, cmdline_rubout_len; - /** * Pad used exclusively for wgetch() as it will not * result in unwanted wrefresh(). @@ -404,7 +401,6 @@ static void teco_interface_resize_all_windows(void); static void teco_interface_set_window_title(const gchar *title); static void teco_interface_draw_info(void); -static void teco_interface_draw_cmdline(void); void teco_interface_init(void) @@ -424,6 +420,14 @@ teco_interface_init(void) */ teco_string_init(&teco_interface.info_current, PACKAGE_NAME, strlen(PACKAGE_NAME)); + teco_cmdline_init(); + /* + * The default INDIC_STRIKE wouldn't be visible. + * FIXME: INDIC_PLAIN is not yet supported by Scinterm to get underlined text. + */ + teco_cmdline_ssm(SCI_INDICSETSTYLE, INDICATOR_RUBBEDOUT, INDIC_STRAIGHTBOX); + teco_cmdline_ssm(SCI_INDICSETFORE, INDICATOR_RUBBEDOUT, 0x404040); + /* * On all platforms except Curses/XTerm, it's * safe to initialize the clipboards now. @@ -561,7 +565,7 @@ teco_interface_init_color(guint color, guint32 rgb) ((color & 0x1) << 2) | ((color & 0x4) >> 2); #endif - if (teco_interface.cmdline_window) { + if (teco_interface.input_pad) { /* interactive mode */ if (!can_change_color()) return; @@ -769,7 +773,10 @@ teco_interface_init_interactive(GError **error) teco_interface.info_window = newwin(1, 0, 0, 0); teco_interface.msg_window = newwin(1, 0, LINES - 2, 0); - teco_interface.cmdline_window = newwin(0, 0, LINES - 1, 0); + + wresize(teco_view_get_window(teco_cmdline.view), 1, COLS); + mvwin(teco_view_get_window(teco_cmdline.view), LINES - 1, 0); + teco_cmdline_resize(COLS); teco_interface.input_pad = newpad(1, 1); /* @@ -861,39 +868,36 @@ teco_interface_restore_batch(void) #endif /* - * cmdline_window determines whether we're in batch mode. + * input_pad determines whether we're in batch mode. */ - if (teco_interface.cmdline_window) { - delwin(teco_interface.cmdline_window); - teco_interface.cmdline_window = NULL; + if (teco_interface.input_pad) { + delwin(teco_interface.input_pad); + teco_interface.input_pad = NULL; } } static void teco_interface_resize_all_windows(void) { - int lines, cols; /* screen dimensions */ - - getmaxyx(stdscr, lines, cols); - - wresize(teco_interface.info_window, 1, cols); + wresize(teco_interface.info_window, 1, COLS); wresize(teco_view_get_window(teco_interface_current_view), - lines - 3, cols); - wresize(teco_interface.msg_window, 1, cols); - mvwin(teco_interface.msg_window, lines - 2, 0); - wresize(teco_interface.cmdline_window, 1, cols); - mvwin(teco_interface.cmdline_window, lines - 1, 0); + LINES - 3, COLS); + wresize(teco_interface.msg_window, 1, COLS); + mvwin(teco_interface.msg_window, LINES - 2, 0); + + wresize(teco_view_get_window(teco_cmdline.view), 1, COLS); + mvwin(teco_view_get_window(teco_cmdline.view), LINES - 1, 0); + teco_cmdline_resize(COLS); teco_interface_draw_info(); teco_interface_msg_clear(); /* FIXME: use saved message */ teco_interface_popup_clear(); - teco_interface_draw_cmdline(); } void teco_interface_msg_literal(teco_msg_t type, const gchar *str, gsize len) { - if (!teco_interface.cmdline_window) { /* batch mode */ + if (!teco_interface.input_pad) { /* batch mode */ teco_interface_stdio_msg(type, str, len); return; } @@ -936,7 +940,7 @@ teco_interface_msg_literal(teco_msg_t type, const gchar *str, gsize len) void teco_interface_msg_clear(void) { - if (!teco_interface.cmdline_window) /* batch mode */ + if (!teco_interface.input_pad) /* batch mode */ return; short fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0)); @@ -950,7 +954,7 @@ teco_interface_msg_clear(void) teco_int_t teco_interface_getch(gboolean widechar) { - if (!teco_interface.cmdline_window) /* batch mode */ + if (!teco_interface.input_pad) /* batch mode */ return teco_interface_stdio_getch(widechar); teco_interface_refresh(FALSE); @@ -996,7 +1000,7 @@ teco_interface_show_view(teco_view_t *view) { teco_interface_current_view = view; - if (!teco_interface.cmdline_window) /* batch mode */ + if (!teco_interface.input_pad) /* batch mode */ return; WINDOW *current_view_win = teco_view_get_window(teco_interface_current_view); @@ -1005,9 +1009,7 @@ teco_interface_show_view(teco_view_t *view) * screen size might have changed since * this view's WINDOW was last active */ - int lines, cols; /* screen dimensions */ - getmaxyx(stdscr, lines, cols); - wresize(current_view_win, lines - 3, cols); + wresize(current_view_win, LINES - 3, COLS); /* Set up window position: never changes */ mvwin(current_view_win, 1, 0); } @@ -1194,114 +1196,6 @@ teco_interface_info_update_buffer(const teco_buffer_t *buffer) /* NOTE: drawn in teco_interface_event_loop_iter() */ } -void -teco_interface_cmdline_update(const teco_cmdline_t *cmdline) -{ - /* - * Especially important on PDCurses, which can crash - * in newpad() when run with --fake-cmdline. - */ - if (!teco_interface.cmdline_window) /* batch mode */ - return; - - /* - * Replace entire pre-formatted command-line. - * We don't know if it is similar to the last one, - * so resizing makes no sense. - * We approximate the size of the new formatted command-line, - * wasting a few bytes for control characters and - * multi-byte Unicode sequences. - */ - if (teco_interface.cmdline_pad) - delwin(teco_interface.cmdline_pad); - - int max_cols = 1; - for (guint i = 0; i < cmdline->str.len; i++) - max_cols += TECO_IS_CTL(cmdline->str.data[i]) ? 3 : 1; - teco_interface.cmdline_pad = newpad(1, max_cols); - - short fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0)); - short bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0)); - wattrset(teco_interface.cmdline_pad, teco_color_attr(fg, bg)); - - /* format effective command line */ - teco_interface.cmdline_len = - teco_curses_format_str(teco_interface.cmdline_pad, - cmdline->str.data, cmdline->effective_len, -1); - - /* - * A_BOLD should result in either a bold font or a brighter - * color both on 8 and 16 color terminals. - * This is not quite color-scheme-agnostic, but works - * with both the `terminal` and `solarized` themes. - * This problem will be gone once we use a Scintilla view - * as command line, since we can then define a style - * for rubbed out parts of the command line which will - * be user-configurable. - * The attributes, supported by the terminal can theoretically - * be queried with term_attrs(). - */ - wattron(teco_interface.cmdline_pad, A_UNDERLINE | A_BOLD); - - /* - * Format rubbed-out command line. - * NOTE: This formatting will never be truncated since we're - * writing into the pad which is large enough. - */ - teco_interface.cmdline_rubout_len = - teco_curses_format_str(teco_interface.cmdline_pad, cmdline->str.data + cmdline->effective_len, - cmdline->str.len - cmdline->effective_len, -1); - - /* - * Highlight cursor after effective command line - * FIXME: This should use SCI_GETCARETFORE(). - */ - attr_t attr = A_NORMAL; - short pair = 0; - if (teco_interface.cmdline_rubout_len) { - wmove(teco_interface.cmdline_pad, 0, teco_interface.cmdline_len); - wattr_get(teco_interface.cmdline_pad, &attr, &pair, NULL); - wchgat(teco_interface.cmdline_pad, 1, - (attr & (A_UNDERLINE | A_REVERSE)) ^ A_REVERSE, pair, NULL); - } else { - teco_interface.cmdline_len++; - wattr_get(teco_interface.cmdline_pad, &attr, &pair, NULL); - wattr_set(teco_interface.cmdline_pad, (attr & ~(A_UNDERLINE | A_BOLD)) ^ A_REVERSE, pair, NULL); - waddch(teco_interface.cmdline_pad, ' '); - } - - teco_interface_draw_cmdline(); -} - -static void -teco_interface_draw_cmdline(void) -{ - /* total width available for command line */ - guint total_width = getmaxx(teco_interface.cmdline_window) - 1; - - /* beginning of command line to show */ - guint disp_offset = teco_interface.cmdline_len - - MIN(teco_interface.cmdline_len, - total_width/2 + teco_interface.cmdline_len % MAX(total_width/2, 1)); - /* - * length of command line to show - * - * NOTE: we do not use getmaxx(cmdline_pad) here since it may be - * larger than the text the pad contains. - */ - guint disp_len = MIN(total_width, teco_interface.cmdline_len + - teco_interface.cmdline_rubout_len - disp_offset); - - short fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0)); - short bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0)); - - wattrset(teco_interface.cmdline_window, teco_color_attr(fg, bg)); - mvwaddch(teco_interface.cmdline_window, 0, 0, '*' | A_BOLD); - teco_curses_clrtobot(teco_interface.cmdline_window); - copywin(teco_interface.cmdline_pad, teco_interface.cmdline_window, - 0, disp_offset, 0, 1, 0, disp_len, FALSE); -} - #if PDCURSES /* @@ -1771,7 +1665,7 @@ void teco_interface_popup_add(teco_popup_entry_type_t type, const gchar *name, gsize name_len, gboolean highlight) { - if (teco_interface.cmdline_window) + if (teco_interface.input_pad) /* interactive mode */ teco_curses_info_popup_add(&teco_interface.popup, type, name, name_len, highlight); } @@ -1779,7 +1673,7 @@ teco_interface_popup_add(teco_popup_entry_type_t type, const gchar *name, gsize void teco_interface_popup_show(gsize prefix_len) { - if (!teco_interface.cmdline_window) + if (!teco_interface.input_pad) /* batch mode */ return; @@ -1793,7 +1687,7 @@ teco_interface_popup_show(gsize prefix_len) void teco_interface_popup_scroll(void) { - if (!teco_interface.cmdline_window) + if (!teco_interface.input_pad) /* batch mode */ return; @@ -1880,15 +1774,13 @@ teco_interface_is_interrupted(void) void teco_interface_refresh(gboolean force) { - if (!teco_interface.cmdline_window) + if (!teco_interface.input_pad) /* batch mode */ return; #ifdef NETBSD_CURSES /* works around crashes in doupdate() */ - gint y, x; - getmaxyx(stdscr, y, x); - if (G_UNLIKELY(x <= 1 || y <= 1)) + if (G_UNLIKELY(COLS <= 1 || LINES <= 1)) return; #endif @@ -1905,7 +1797,7 @@ teco_interface_refresh(gboolean force) wnoutrefresh(teco_interface.info_window); teco_view_noutrefresh(teco_interface_current_view); wnoutrefresh(teco_interface.msg_window); - wnoutrefresh(teco_interface.cmdline_window); + teco_view_noutrefresh(teco_cmdline.view); teco_curses_info_popup_noutrefresh(&teco_interface.popup); doupdate(); } @@ -1952,7 +1844,6 @@ teco_interface_process_mevent(MEVENT *event, GError **error) teco_interface_popup_clear(); teco_interface_msg_clear(); - teco_interface_cmdline_update(&teco_cmdline); } return TRUE; @@ -2286,8 +2177,6 @@ teco_interface_event_loop(GError **error) if (!teco_interface_init_interactive(error)) return FALSE; - static const teco_cmdline_t empty_cmdline; // FIXME - teco_interface_cmdline_update(&empty_cmdline); teco_interface_msg_clear(); teco_interface_ssm(SCI_SCROLLCARET, 0, 0); /* @@ -2342,10 +2231,6 @@ teco_interface_cleanup(void) teco_string_clear(&teco_interface.info_current); if (teco_interface.input_queue) g_queue_free(teco_interface.input_queue); - if (teco_interface.cmdline_window) - delwin(teco_interface.cmdline_window); - if (teco_interface.cmdline_pad) - delwin(teco_interface.cmdline_pad); if (teco_interface.msg_window) delwin(teco_interface.msg_window); if (teco_interface.input_pad) diff --git a/src/interface-gtk/interface.c b/src/interface-gtk/interface.c index 438e6cc..665a635 100644 --- a/src/interface-gtk/interface.c +++ b/src/interface-gtk/interface.c @@ -84,12 +84,6 @@ static gchar teco_interface_get_ansi_key(GdkEventKey *event); /** printf() format for CSS RGB colors given as guint32 */ #define CSS_COLOR_FORMAT "#%06" G_GINT32_MODIFIER "X" -/** Style used for the asterisk at the beginning of the command line */ -#define STYLE_ASTERISK 16 - -/** Indicator number used for the rubbed out part of the command line */ -#define INDIC_RUBBEDOUT (INDIC_CONTAINER+0) - /** Convert Scintilla-style BGR color triple to RGB. */ static inline guint32 teco_bgr2rgb(guint32 bgr) @@ -123,7 +117,6 @@ static struct { GtkWidget *message_bar_widget; GtkWidget *message_widget; - teco_view_t *cmdline_view; GtkIMContext *input_method; GtkWidget *popup_widget; @@ -284,28 +277,9 @@ teco_interface_init(void) gtk_container_add(GTK_CONTAINER(overlay_widget), overlay_vbox); gtk_box_pack_start(GTK_BOX(vbox), overlay_widget, TRUE, TRUE, 0); - teco_interface.cmdline_view = teco_view_new(); - teco_view_setup(teco_interface.cmdline_view); - teco_view_ssm(teco_interface.cmdline_view, SCI_SETUNDOCOLLECTION, FALSE, 0); - teco_view_ssm(teco_interface.cmdline_view, SCI_SETVSCROLLBAR, FALSE, 0); - teco_view_ssm(teco_interface.cmdline_view, SCI_SETMARGINTYPEN, 1, SC_MARGIN_TEXT); - teco_view_ssm(teco_interface.cmdline_view, SCI_MARGINSETSTYLE, 0, STYLE_ASTERISK); - teco_view_ssm(teco_interface.cmdline_view, SCI_SETMARGINWIDTHN, 1, - teco_view_ssm(teco_interface.cmdline_view, SCI_TEXTWIDTH, STYLE_ASTERISK, (sptr_t)"*")); - teco_view_ssm(teco_interface.cmdline_view, SCI_MARGINSETTEXT, 0, (sptr_t)"*"); - teco_view_ssm(teco_interface.cmdline_view, SCI_INDICSETSTYLE, INDIC_RUBBEDOUT, INDIC_STRIKE); - /* we will forward key events, so the view should only react to text insertion */ - teco_view_ssm(teco_interface.cmdline_view, SCI_CLEARALLCMDKEYS, 0, 0); - - /* single line mode - EOL characters won't break the line */ - teco_view_ssm(teco_interface.cmdline_view, SCI_SETLINEENDTYPESALLOWED, SC_LINE_END_TYPE_HIDDEN, 0); - /* render tabs as "TAB" */ - teco_view_ssm(teco_interface.cmdline_view, SCI_SETTABDRAWMODE, SCTD_CONTROLCHAR, 0); - teco_view_ssm(teco_interface.cmdline_view, SCI_SETTABWIDTH, 1, 0); - teco_view_ssm(teco_interface.cmdline_view, SCI_SETTABMINIMUMWIDTH, - teco_view_ssm(teco_interface.cmdline_view, SCI_TEXTWIDTH, STYLE_DEFAULT, (sptr_t)"TAB"), 0); - - GtkWidget *cmdline_widget = GTK_WIDGET(teco_interface.cmdline_view); + teco_cmdline_init(); + + GtkWidget *cmdline_widget = GTK_WIDGET(teco_cmdline.view); gtk_widget_set_name(cmdline_widget, "sciteco-cmdline"); g_signal_connect(cmdline_widget, "size-allocate", G_CALLBACK(teco_interface_cmdline_size_allocate_cb), NULL); @@ -340,10 +314,6 @@ teco_interface_init(void) */ gtk_widget_set_can_focus(teco_interface.message_widget, FALSE); gtk_widget_set_can_focus(teco_interface.info_name_widget, FALSE); - - teco_cmdline_t empty_cmdline; - memset(&empty_cmdline, 0, sizeof(empty_cmdline)); - teco_interface_cmdline_update(&empty_cmdline); } static void @@ -607,34 +577,6 @@ teco_interface_info_update_buffer(const teco_buffer_t *buffer) : TECO_INFO_TYPE_BUFFER; } -/* - * FIXME: We no longer have to rebuild the command line. - * The view should be integrated into the teco_cmdline object. - * This would also deprecate this interface method. - */ -void -teco_interface_cmdline_update(const teco_cmdline_t *cmdline) -{ - /* - * We don't know if the new command line is similar to - * the old one, so we can just as well rebuild it. - */ - teco_view_ssm(teco_interface.cmdline_view, SCI_CLEARALL, 0, 0); - - /* add both the effective and rubbed out parts of the command line */ - teco_view_ssm(teco_interface.cmdline_view, SCI_APPENDTEXT, - cmdline->str.len, (sptr_t)cmdline->str.data); - - /* cursor should be after effective command line */ - teco_view_ssm(teco_interface.cmdline_view, SCI_GOTOPOS, cmdline->effective_len, 0); - - teco_view_ssm(teco_interface.cmdline_view, SCI_SETINDICATORCURRENT, INDIC_RUBBEDOUT, 0); - teco_view_ssm(teco_interface.cmdline_view, SCI_INDICATORFILLRANGE, cmdline->effective_len, - cmdline->str.len - cmdline->effective_len); - - teco_view_ssm(teco_interface.cmdline_view, SCI_SCROLLCARET, 0, 0); -} - static GdkAtom teco_interface_get_selection_by_name(const gchar *name) { @@ -840,37 +782,7 @@ teco_interface_set_css_variables(teco_view_t *view) guint32 calltip_fg_color = teco_view_ssm(view, SCI_STYLEGETFORE, STYLE_CALLTIP, 0); guint32 calltip_bg_color = teco_view_ssm(view, SCI_STYLEGETBACK, STYLE_CALLTIP, 0); - /* - * FIXME: Font and colors of Scintilla views cannot be set via CSS. - * But some day, there will be a way to send messages to the commandline view - * from SciTECO code via ES. - * Configuration will then be in the hands of color schemes. - * - * NOTE: We don't actually know apriori how large the font_size buffer should be, - * but luckily SCI_STYLEGETFONT with a sptr==0 will return only the size. - * This is undocumented in the Scintilla docs. - */ - g_autofree gchar *font_name = g_malloc(teco_view_ssm(view, SCI_STYLEGETFONT, STYLE_DEFAULT, 0) + 1); - teco_view_ssm(view, SCI_STYLEGETFONT, STYLE_DEFAULT, (sptr_t)font_name); - - teco_view_ssm(teco_interface.cmdline_view, SCI_STYLESETFORE, STYLE_DEFAULT, default_fg_color); - teco_view_ssm(teco_interface.cmdline_view, SCI_STYLESETBACK, STYLE_DEFAULT, default_bg_color); - teco_view_ssm(teco_interface.cmdline_view, SCI_STYLESETFONT, STYLE_DEFAULT, (sptr_t)font_name); - teco_view_ssm(teco_interface.cmdline_view, SCI_STYLESETSIZE, STYLE_DEFAULT, - teco_view_ssm(view, SCI_STYLEGETSIZE, STYLE_DEFAULT, 0)); - teco_view_ssm(teco_interface.cmdline_view, SCI_STYLECLEARALL, 0, 0); - teco_view_ssm(teco_interface.cmdline_view, SCI_STYLESETFORE, STYLE_CALLTIP, calltip_fg_color); - teco_view_ssm(teco_interface.cmdline_view, SCI_STYLESETBACK, STYLE_CALLTIP, calltip_bg_color); - teco_view_ssm(teco_interface.cmdline_view, SCI_SETCARETFORE, - teco_view_ssm(view, SCI_GETCARETFORE, 0, 0), 0); - /* used for the asterisk at the beginning of the command line */ - teco_view_ssm(teco_interface.cmdline_view, SCI_STYLESETBOLD, STYLE_ASTERISK, TRUE); - /* used for the rubbed out command line */ - teco_view_ssm(teco_interface.cmdline_view, SCI_INDICSETFORE, INDIC_RUBBEDOUT, default_fg_color); - /* this somehow gets reset */ - teco_view_ssm(teco_interface.cmdline_view, SCI_MARGINSETTEXT, 0, (sptr_t)"*"); - - guint text_height = teco_view_ssm(teco_interface.cmdline_view, SCI_TEXTHEIGHT, 0, 0); + guint text_height = teco_cmdline_ssm(SCI_TEXTHEIGHT, 0, 0); /* * Generates a CSS that sets some predefined color variables. @@ -903,7 +815,7 @@ teco_interface_set_css_variables(teco_view_t *view) * This cannot be done via CSS or Scintilla messages. * Currently, it is always exactly one line high in order to mimic the Curses UI. */ - gtk_widget_set_size_request(GTK_WIDGET(teco_interface.cmdline_view), -1, text_height); + gtk_widget_set_size_request(GTK_WIDGET(teco_cmdline.view), -1, text_height); } static void @@ -1374,17 +1286,12 @@ teco_interface_event_box_realized_cb(GtkWidget *widget, gpointer user_data) teco_interface_set_cursor(widget, "text"); } -/** - * Called when the commandline widget is resized. - * This should ensure that the caret jumps to the middle of the command line, - * imitating the behaviour of the current Curses command line. - */ +/** Called when the commandline widget is resized */ static void teco_interface_cmdline_size_allocate_cb(GtkWidget *widget, GdkRectangle *allocation, gpointer user_data) { - teco_view_ssm(teco_interface.cmdline_view, SCI_SETXCARETPOLICY, - CARET_SLOP | CARET_EVEN, allocation->width/2); + teco_cmdline_resize(allocation->width); } static gboolean @@ -1560,7 +1467,6 @@ teco_interface_popup_clicked_cb(GtkWidget *popup, gchar *str, gulong len, gpoint !machine->current->insert_completion_cb(machine, &insert, NULL)) return; teco_interface_popup_clear(); - teco_interface_cmdline_update(&teco_cmdline); teco_interface_update(teco_interface_current_view != last_view); } diff --git a/src/interface.h b/src/interface.h index 9531d37..8ab66ef 100644 --- a/src/interface.h +++ b/src/interface.h @@ -118,9 +118,6 @@ void undo__teco_interface_info_update_qreg(const teco_qreg_t *); void undo__teco_interface_info_update_buffer(const teco_buffer_t *); /** @pure */ -void teco_interface_cmdline_update(const teco_cmdline_t *cmdline); - -/** @pure */ gboolean teco_interface_set_clipboard(const gchar *name, const gchar *str, gsize str_len, GError **error); void teco_interface_undo_set_clipboard(const gchar *name, gchar *str, gsize len); @@ -640,6 +640,7 @@ cleanup: teco_qreg_table_clear(&teco_qreg_table_globals); teco_qreg_stack_clear(); teco_view_free(teco_qreg_view); + teco_cmdline_cleanup(); #endif teco_interface_cleanup(); diff --git a/src/stdio-commands.c b/src/stdio-commands.c index 3a1b320..565f442 100644 --- a/src/stdio-commands.c +++ b/src/stdio-commands.c @@ -38,7 +38,7 @@ static inline gboolean teco_cmdline_is_executing(teco_machine_main_t *ctx) { return ctx == &teco_cmdline.machine && - ctx->macro_pc == teco_cmdline.effective_len; + ctx->macro_pc == teco_cmdline_ssm(SCI_GETCURRENTPOS, 0, 0); } static gboolean is_executing = FALSE; |
