aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmdline.c257
-rw-r--r--src/cmdline.h47
-rw-r--r--src/core-commands.c8
-rw-r--r--src/doc.c3
-rw-r--r--src/interface-curses/interface.c187
-rw-r--r--src/interface-gtk/interface.c108
-rw-r--r--src/interface.h3
-rw-r--r--src/main.c1
-rw-r--r--src/stdio-commands.c2
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 '<':
diff --git a/src/doc.c b/src/doc.c
index 4ac96c8..1ec4d80 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -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);
diff --git a/src/main.c b/src/main.c
index b615e78..620455a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;