diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmdline.c | 32 | ||||
| -rw-r--r-- | src/interface-curses/curses-info-popup.c | 32 | ||||
| -rw-r--r-- | src/interface-curses/curses-info-popup.h | 2 | ||||
| -rw-r--r-- | src/interface-curses/curses-utils.c | 16 | ||||
| -rw-r--r-- | src/interface-curses/curses-utils.h | 9 | ||||
| -rw-r--r-- | src/interface-curses/interface.c | 133 | ||||
| -rw-r--r-- | src/interface-gtk/interface.c | 31 | ||||
| -rw-r--r-- | src/interface.h | 2 | ||||
| -rw-r--r-- | src/main.c | 7 | ||||
| -rw-r--r-- | src/qreg.c | 6 | ||||
| -rw-r--r-- | src/ring.c | 7 | ||||
| -rw-r--r-- | src/string-utils.c | 10 |
12 files changed, 172 insertions, 115 deletions
diff --git a/src/cmdline.c b/src/cmdline.c index fa69d91..b944b5e 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -99,6 +99,14 @@ teco_cmdline_init(void) teco_cmdline_ssm(SCI_SETTABDRAWMODE, SCTD_CONTROLCHAR, 0); /* + * FIXME: This works around a problem where the caret is not + * scrolled in multi-line mode after it wraps at the end of the + * line. You cannot scroll the command-line with the mouse, so the + * user won't see any difference. + */ + teco_cmdline_ssm(SCI_SETENDATLASTLINE, FALSE, 0); + + /* * FIXME: Something resets the margin text, so we have to set it last. */ teco_cmdline_ssm(SCI_MARGINSETTEXT, 0, (sptr_t)"*"); @@ -162,12 +170,32 @@ teco_cmdline_insert(const gchar *data, gsize len, GError **error) * Result of command line replacement (}): * Exchange command lines */ + g_clear_error(&tmp_error); + teco_qreg_t *cmdline_reg = teco_qreg_table_find(&teco_qreg_table_globals, "\e", 1); 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)) + NULL, &tmp_error)) { + teco_error_add_frame_toplevel(); + teco_error_display_short(tmp_error); + g_propagate_error(error, g_steal_pointer(&tmp_error)); + return FALSE; + } + + /* + * SciTECO code must always be UTF-8, but you can smuggle arbitrary bytes + * into the "\e" register. + * This would be cumbersome to test for in teco_state_start_cmdline_pop(). + */ + if (!teco_string_validate_utf8(new_cmdline)) { + g_set_error_literal(&tmp_error, TECO_ERROR, TECO_ERROR_CODEPOINT, + "Invalid UTF-8 byte sequence in command-line replacement"); + teco_error_add_frame_toplevel(); + teco_error_display_short(tmp_error); + g_propagate_error(error, g_steal_pointer(&tmp_error)); return FALSE; + } /* * Search for first differing character in old and @@ -229,7 +257,7 @@ teco_cmdline_insert(const gchar *data, gsize len, GError **error) } } - /* error is handled in teco_cmdline_keypress_c() */ + /* error is handled in teco_cmdline_keypress() */ g_propagate_error(error, g_steal_pointer(&tmp_error)); return FALSE; } diff --git a/src/interface-curses/curses-info-popup.c b/src/interface-curses/curses-info-popup.c index edb6e15..83d4665 100644 --- a/src/interface-curses/curses-info-popup.c +++ b/src/interface-curses/curses-info-popup.c @@ -73,7 +73,7 @@ teco_curses_info_popup_add(teco_curses_info_popup_t *ctx, teco_popup_entry_type_ } static void -teco_curses_info_popup_init_pad(teco_curses_info_popup_t *ctx, attr_t attr) +teco_curses_info_popup_init_pad(teco_curses_info_popup_t *ctx, attr_t attr, gshort pair) { int pad_lines; /**! pad height */ gint pad_cols; /**! entry columns */ @@ -102,11 +102,11 @@ teco_curses_info_popup_init_pad(teco_curses_info_popup_t *ctx, attr_t attr) ctx->pad = newpad(pad_lines, COLS - 2); /* - * NOTE: attr could contain A_REVERSE on monochrome terminals, + * NOTE: attr could contain WA_REVERSE on monochrome terminals, * so we use foreground attributes instead of background attributes. - * This way, we can cancel out the A_REVERSE if necessary. + * This way, we can cancel out the WA_REVERSE if necessary. */ - wattrset(ctx->pad, attr); + wattr_set(ctx->pad, attr, pair, NULL); teco_curses_clrtobot(ctx->pad); /* @@ -161,7 +161,7 @@ teco_curses_info_popup_init_pad(teco_curses_info_popup_t *ctx, attr_t attr) } void -teco_curses_info_popup_show(teco_curses_info_popup_t *ctx, attr_t attr) +teco_curses_info_popup_show(teco_curses_info_popup_t *ctx, attr_t attr, gshort pair) { if (!ctx->length) /* nothing to display */ @@ -171,7 +171,7 @@ teco_curses_info_popup_show(teco_curses_info_popup_t *ctx, attr_t attr) delwin(ctx->window); if (!ctx->pad) - teco_curses_info_popup_init_pad(ctx, attr); + teco_curses_info_popup_init_pad(ctx, attr, pair); gint pad_lines = getmaxy(ctx->pad); /* @@ -183,15 +183,17 @@ teco_curses_info_popup_show(teco_curses_info_popup_t *ctx, attr_t attr) /* window covers message, scintilla and info windows */ ctx->window = newwin(popup_lines, 0, LINES - teco_cmdline.height - popup_lines, 0); - wattrset(ctx->window, attr); + wattr_set(ctx->window, attr, pair, NULL); - wborder(ctx->window, - ACS_VLINE, - ACS_VLINE, /* may be overwritten with scrollbar */ - ACS_HLINE, - ' ', /* no bottom line */ - ACS_ULCORNER, ACS_URCORNER, - ACS_VLINE, ACS_VLINE); + /* + * NOTE: wborder() is broken for large pair numbers, at least on ncurses. + */ + waddch(ctx->window, ACS_ULCORNER); + whline(ctx->window, ACS_HLINE, COLS - 2); + mvwaddch(ctx->window, 0, COLS - 1, ACS_URCORNER); + mvwvline(ctx->window, 1, 0, ACS_VLINE, getmaxy(ctx->window)-1); + /* may be overwritten with scrollbar */ + mvwvline(ctx->window, 1, COLS - 1, ACS_VLINE, getmaxy(ctx->window)-1); copywin(ctx->pad, ctx->window, ctx->pad_first_line, 0, @@ -214,7 +216,7 @@ teco_curses_info_popup_show(teco_curses_info_popup_t *ctx, attr_t attr) * Instead, simply draw reverse blanks. */ wmove(ctx->window, bar_y, COLS-1); - wattrset(ctx->window, attr ^ A_REVERSE); + wattr_set(ctx->window, attr ^ WA_REVERSE, pair, NULL); wvline(ctx->window, ' ', bar_height); } diff --git a/src/interface-curses/curses-info-popup.h b/src/interface-curses/curses-info-popup.h index fd923e9..898ba70 100644 --- a/src/interface-curses/curses-info-popup.h +++ b/src/interface-curses/curses-info-popup.h @@ -49,7 +49,7 @@ teco_curses_info_popup_init(teco_curses_info_popup_t *ctx) void teco_curses_info_popup_add(teco_curses_info_popup_t *ctx, teco_popup_entry_type_t type, const gchar *name, gsize name_len, gboolean highlight); -void teco_curses_info_popup_show(teco_curses_info_popup_t *ctx, attr_t attr); +void teco_curses_info_popup_show(teco_curses_info_popup_t *ctx, attr_t attr, gshort pair); const teco_string_t *teco_curses_info_popup_getentry(teco_curses_info_popup_t *ctx, gint y, gint x); void teco_curses_info_popup_scroll_page(teco_curses_info_popup_t *ctx); void teco_curses_info_popup_scroll(teco_curses_info_popup_t *ctx, gint delta); diff --git a/src/interface-curses/curses-utils.c b/src/interface-curses/curses-utils.c index 875c332..3b25d56 100644 --- a/src/interface-curses/curses-utils.c +++ b/src/interface-curses/curses-utils.c @@ -53,9 +53,9 @@ teco_curses_format_str(WINDOW *win, const gchar *str, gsize len, gint max_width) /* * The entire background might be in reverse, especially * on monochrome terminals. - * In those cases, we have to __remove__ the A_REVERSE flag. + * In those cases, we have to __remove__ the WA_REVERSE flag. */ - attr_t attrs = A_NORMAL; + attr_t attrs = WA_NORMAL; short pair = 0; wattr_get(win, &attrs, &pair, NULL); @@ -81,28 +81,28 @@ teco_curses_format_str(WINDOW *win, const gchar *str, gsize len, gint max_width) chars_added++; if (chars_added > max_width) goto truncate; - wattr_set(win, attrs ^ A_REVERSE, pair, NULL); + wattr_set(win, attrs ^ WA_REVERSE, pair, NULL); waddch(win, '$'); break; case '\r': chars_added += 2; if (chars_added > max_width) goto truncate; - wattr_set(win, attrs ^ A_REVERSE, pair, NULL); + wattr_set(win, attrs ^ WA_REVERSE, pair, NULL); waddstr(win, "CR"); break; case '\n': chars_added += 2; if (chars_added > max_width) goto truncate; - wattr_set(win, attrs ^ A_REVERSE, pair, NULL); + wattr_set(win, attrs ^ WA_REVERSE, pair, NULL); waddstr(win, "LF"); break; case '\t': chars_added += 3; if (chars_added > max_width) goto truncate; - wattr_set(win, attrs ^ A_REVERSE, pair, NULL); + wattr_set(win, attrs ^ WA_REVERSE, pair, NULL); waddstr(win, "TAB"); break; default: @@ -110,7 +110,7 @@ teco_curses_format_str(WINDOW *win, const gchar *str, gsize len, gint max_width) chars_added += 2; if (chars_added > max_width) goto truncate; - wattr_set(win, attrs ^ A_REVERSE, pair, NULL); + wattr_set(win, attrs ^ WA_REVERSE, pair, NULL); waddch(win, '^'); waddch(win, TECO_CTL_ECHO(*str)); } else { @@ -126,7 +126,7 @@ teco_curses_format_str(WINDOW *win, const gchar *str, gsize len, gint max_width) waddnstr(win, str, clen); } } - /* restore original state of A_REVERSE */ + /* restore original state of WA_REVERSE */ wattr_set(win, attrs, pair, NULL); str += clen; diff --git a/src/interface-curses/curses-utils.h b/src/interface-curses/curses-utils.h index 97fc1cc..c6d9d8d 100644 --- a/src/interface-curses/curses-utils.h +++ b/src/interface-curses/curses-utils.h @@ -27,15 +27,12 @@ guint teco_curses_format_str(WINDOW *win, const gchar *str, gsize len, gint max_ guint teco_curses_format_filename(WINDOW *win, const gchar *filename, gint max_width); -/** - * Add Unicode character to window. - * This is just like wadd_wch(), but does not require wide-char APIs. - */ +/** Add Unicode character to window. */ static inline void teco_curses_add_wc(WINDOW *win, gunichar chr) { - gchar buf[6]; - waddnstr(win, buf, g_unichar_to_utf8(chr, buf)); + wchar_t wc = chr; + waddnwstr(win, &wc, 1); } /** diff --git a/src/interface-curses/interface.c b/src/interface-curses/interface.c index 94501cb..45821f9 100644 --- a/src/interface-curses/interface.c +++ b/src/interface-curses/interface.c @@ -232,47 +232,19 @@ static struct { * * Scinterm no longer initializes all color pairs for all combinations of * the builtin foreground and background colors. - * Since curses guarantees only 256 color pairs, we cannot do that either. - * Instead we allocate color pairs beginnig at 128 on demand - * (similar to what Scinterm does). - * - * @note Scinterm now also has scintilla_set_color_offsets(), - * so we could use the lower 127 color pairs as well. + * Since curses does not guarantee any number of color pairs, we cannot do that either. + * Instead we allocate color pairs in the first half of + * color pair space on demand, while the second half is reserved to Scinterm. * + * @param attr attributes to modify (for supporting monochrome terminals) * @param fg curses foreground color * @param bg curses background color * @return curses color pair number */ static gshort -teco_color_pair(gshort fg, gshort bg) +teco_color_pair(attr_t *attr, gshort fg, gshort bg) { - static gshort last_pair = 127; - - G_STATIC_ASSERT(sizeof(gshort)*2 <= sizeof(guint)); - gpointer key = GUINT_TO_POINTER(((guint)fg << 16) | bg); - gpointer value = g_hash_table_lookup(teco_interface.pair_table, key); - if (G_LIKELY(value != NULL)) - return GPOINTER_TO_UINT(value); - init_pair(++last_pair, fg, bg); - g_hash_table_insert(teco_interface.pair_table, key, GUINT_TO_POINTER(last_pair)); - return last_pair; -} - -/** - * Curses attribute for the color combination - * according to the color pairs initialized by - * Scinterm. - * This is equivalent to Scinterm's internal term_color_attr(). - * - * @param fg foreground color - * @param bg background color - * @return curses attribute - */ -static inline attr_t -teco_color_attr(gshort fg, gshort bg) -{ - if (has_colors()) - return COLOR_PAIR(teco_color_pair(fg, bg)); + static guint next_pair = 1; /* * Basic support for monochrome terminals: @@ -281,7 +253,29 @@ teco_color_attr(gshort fg, gshort bg) * This will at least work with the terminal.tes and contrast.tes * color schemes. */ - return bg != COLOR_BLACK ? A_REVERSE : 0; + if (!has_colors()) { + if (bg != COLOR_BLACK) + *attr |= WA_REVERSE; + return 0; + } + + G_STATIC_ASSERT(sizeof(gshort)*2 <= sizeof(guint)); + gpointer key = GUINT_TO_POINTER(((guint)fg << 8*sizeof(bg)) | bg); + gpointer value = g_hash_table_lookup(teco_interface.pair_table, key); + if (G_LIKELY(value != NULL)) + return GPOINTER_TO_UINT(value); + if (G_UNLIKELY(next_pair >= COLOR_PAIRS || next_pair > G_MAXSHORT)) + return 0; + init_pair(next_pair, fg, bg); + g_hash_table_insert(teco_interface.pair_table, key, GUINT_TO_POINTER(next_pair)); + return next_pair++; +} + +static inline gint +teco_wattr_set(WINDOW *win, attr_t attr, gshort fg, gshort bg) +{ + gshort pair = teco_color_pair(&attr, fg, bg); + return wattr_set(win, attr, pair, NULL); } /** @@ -435,7 +429,7 @@ static void teco_interface_set_window_title(const gchar *title); static void teco_interface_draw_info(void); void -teco_interface_init(void) +teco_interface_init(gint argc, gchar **argv) { for (guint i = 0; i < G_N_ELEMENTS(teco_interface.color_table); i++) teco_interface.color_table[i] = -1; @@ -449,7 +443,7 @@ teco_interface_init(void) teco_cmdline_init(); /* * The default INDIC_STRIKE wouldn't be visible. - * Instead we use INDIC_SQUIGGLE, which is rendered as A_UNDERLINE. + * Instead we use INDIC_SQUIGGLE, which is rendered as WA_UNDERLINE. */ teco_cmdline_ssm(SCI_INDICSETSTYLE, INDICATOR_RUBBEDOUT, INDIC_SQUIGGLE); /* @@ -752,6 +746,12 @@ teco_interface_init_interactive(GError **error) teco_interface.pair_table = g_hash_table_new(g_direct_hash, g_direct_equal); start_color(); + /* + * Scinterm uses shorts for color pairs, so G_MAXSHORT is the maximum. + * Some Curses implementations (NetBSD, PDCurses) may support less, + * but set COLOR_PAIRS accordingly. + */ + scintilla_set_color_offsets(0, MIN(COLOR_PAIRS, G_MAXSHORT)/2); /* * On UNIX terminals, the escape key is usually @@ -942,7 +942,7 @@ teco_interface_msg_literal(teco_msg_t type, const gchar *str, gsize len) teco_interface_stdio_msg(type, str, len); #endif - short fg, bg; + gshort fg, bg; fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0)); @@ -964,7 +964,7 @@ teco_interface_msg_literal(teco_msg_t type, const gchar *str, gsize len) } wmove(teco_interface.msg_window, 0, 0); - wattrset(teco_interface.msg_window, teco_color_attr(fg, bg)); + teco_wattr_set(teco_interface.msg_window, 0, fg, bg); teco_curses_format_str(teco_interface.msg_window, str, len, -1); teco_curses_clrtobot(teco_interface.msg_window); } @@ -975,11 +975,11 @@ teco_interface_msg_clear(void) if (!teco_interface.input_pad) /* batch mode */ return; - short fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0)); - short bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0)); + gshort fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0)); + gshort bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0)); wmove(teco_interface.msg_window, 0, 0); - wattrset(teco_interface.msg_window, teco_color_attr(fg, bg)); + teco_wattr_set(teco_interface.msg_window, 0, fg, bg); teco_curses_clrtobot(teco_interface.msg_window); } @@ -993,10 +993,11 @@ teco_interface_getch(gboolean widechar) /* * Signal that we accept input by drawing a real cursor in the message bar. + * FIXME: curs_set(2) would be better, but isn't always visible. */ wmove(teco_interface.msg_window, 0, 0); - curs_set(1); wrefresh(teco_interface.msg_window); + curs_set(1); gchar buf[4]; gint i = 0; @@ -1023,7 +1024,6 @@ teco_interface_getch(gboolean widechar) i = 0; } while (cp < 0); - curs_set(0); return cp; } @@ -1153,11 +1153,11 @@ teco_interface_draw_info(void) * the current buffer's STYLE_DEFAULT. * The same style is used for MSG_USER messages. */ - short fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0)); - short bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0)); + gshort fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0)); + gshort bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0)); wmove(teco_interface.info_window, 0, 0); - wattrset(teco_interface.info_window, teco_color_attr(fg, bg)); + teco_wattr_set(teco_interface.info_window, 0, fg, bg); const gchar *info_type_str; @@ -1726,11 +1726,13 @@ teco_interface_popup_show(gsize prefix_len) /* batch mode */ return; - short fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_CALLTIP, 0)); - short bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_CALLTIP, 0)); + gshort fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_CALLTIP, 0)); + gshort bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_CALLTIP, 0)); teco_interface.popup_prefix_len = prefix_len; - teco_curses_info_popup_show(&teco_interface.popup, teco_color_attr(fg, bg)); + attr_t attr = 0; + gshort pair = teco_color_pair(&attr, fg, bg); + teco_curses_info_popup_show(&teco_interface.popup, attr, pair); } void @@ -1837,16 +1839,6 @@ teco_interface_refresh(gboolean force) clearok(curscr, TRUE); /* - * Let Scinterm enable/disable the hardware cursor - * based on the CARETSTYLE_CURSES. - * Doing this repeatedly ensures you can change the - * caret style interactively. - * Also, window resizes enable the cursor on PDCurses/wincon - * sometimes (FIXME). - */ - curs_set(0); - - /* * Info window is updated very often which is very * costly, especially when using PDC_set_title(), * so we redraw it here, where the overhead does @@ -1870,6 +1862,19 @@ teco_interface_refresh(gboolean force) */ teco_view_update_cursor(teco_cmdline.view); doupdate(); + + /* + * Scinterm enables/disables the hardware cursor, + * but only if CARETSTYLE_CURSES is used. + * Disabling the cursor repeatedly ensures you can change + * the caret style interactively. + * It also makes sure the cursor is reset after + * teco_interface_getch(). + * Also, window resizes sometimes enable the hardware cursor on + * PDCurses/wincon (FIXME). + */ + if (!(teco_view_ssm(teco_cmdline.view, SCI_GETCARETSTYLE, 0, 0) & CARETSTYLE_CURSES)) + curs_set(0); } #if NCURSES_MOUSE_VERSION >= 2 @@ -1927,9 +1932,11 @@ teco_interface_process_mevent(MEVENT *event, GError **error) else if (event->bstate & BUTTON_NUM(5)) teco_curses_info_popup_scroll(&teco_interface.popup, +2); - short fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_CALLTIP, 0)); - short bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_CALLTIP, 0)); - teco_curses_info_popup_show(&teco_interface.popup, teco_color_attr(fg, bg)); + gshort fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_CALLTIP, 0)); + gshort bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_CALLTIP, 0)); + attr_t attr = 0; + gshort pair = teco_color_pair(&attr, fg, bg); + teco_curses_info_popup_show(&teco_interface.popup, attr, pair); return TRUE; } diff --git a/src/interface-gtk/interface.c b/src/interface-gtk/interface.c index ace3a2f..08ccf5d 100644 --- a/src/interface-gtk/interface.c +++ b/src/interface-gtk/interface.c @@ -22,6 +22,7 @@ #include <stdlib.h> #include <string.h> #include <signal.h> +#include <unistd.h> #include <glib.h> #include <glib/gprintf.h> @@ -132,10 +133,10 @@ static struct { } teco_interface; void -teco_interface_init(void) +teco_interface_init(gint argc, gchar **argv) { #ifdef G_OS_UNIX - if (teco_interface.detach) { + if (teco_interface.detach && !g_getenv("__SCITECO_DETACHED")) { /* * NOTE: There is also daemon() on BSD/Linux, * but the following should be more portable. @@ -148,9 +149,29 @@ teco_interface_init(void) setsid(); - g_freopen("/dev/null", "r", stdin); - g_freopen("/dev/null", "a+", stdout); - g_freopen("/dev/null", "a+", stderr); + if (isatty(0)) { + G_GNUC_UNUSED FILE *stdin_new = g_freopen("/dev/null", "r", stdin); + g_assert(stdin_new != NULL); + } + if (isatty(1)) { + G_GNUC_UNUSED FILE *stdout_new = g_freopen("/dev/null", "a+", stdout); + g_assert(stdout_new != NULL); + } + if (isatty(2)) { + G_GNUC_UNUSED FILE *stderr_new = g_freopen("/dev/null", "a+", stderr); + g_assert(stderr_new != NULL); + } + + /* + * gtk_get_option_group() already initialized GTK and even though the + * display is not yet opened, it's unsafe to continue. + * Instead, we re-exec already in the child process. + * We cannot easily remove --detach from argv, but still guard against + * recursive forks by using an environment variable. + */ + g_setenv("__SCITECO_DETACHED", "1", TRUE); + execv(argv[0], argv); + g_assert_not_reached(); } #endif diff --git a/src/interface.h b/src/interface.h index f196a83..54f807b 100644 --- a/src/interface.h +++ b/src/interface.h @@ -51,7 +51,7 @@ extern teco_view_t *teco_interface_current_view; /** @pure */ -void teco_interface_init(void); +void teco_interface_init(gint argc, gchar **argv); /** @pure */ GOptionGroup *teco_interface_get_options(void); @@ -54,7 +54,7 @@ /* * Define this to pause the program at the beginning - * of main() (Windows only). + * of main(). * This is a useful hack on Windows, where gdbserver * sometimes refuses to start SciTECO but attaches * to a running process just fine. @@ -382,8 +382,7 @@ main(int argc, char **argv) #endif #ifdef DEBUG_PAUSE - /* Windows debugging hack (see above) */ - system("pause"); + getchar(); #endif signal(SIGINT, teco_sigint_handler); @@ -445,7 +444,7 @@ main(int argc, char **argv) */ teco_qreg_table_init(&teco_qreg_table_globals, TRUE); - teco_interface_init(); + teco_interface_init(argc, argv); /* * QRegister view must be initialized only now @@ -1694,11 +1694,7 @@ teco_machine_qregspec_auto_complete(teco_machine_qregspec_t *ctx, teco_string_t /* two-letter Q-Reg */ restrict_len = 2; - /* - * FIXME: This is not quite right as it will propose even - * lower case single or two-letter Q-Register names. - */ - return teco_rb3str_auto_complete(&ctx->result_table->tree, !restrict_len, + return teco_rb3str_auto_complete(&ctx->result_table->tree, TRUE, ctx->name.data, ctx->name.len, restrict_len, insert) && ctx->nesting == 1; } @@ -731,13 +731,18 @@ teco_state_read_file_done(teco_machine_main_t *ctx, teco_string_t str, GError ** return &teco_state_start; sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0); + teco_undo_int(teco_ranges[0].from) = teco_interface_bytes2glyphs(pos); g_autofree gchar *filename = teco_file_expand_path(str.data); /* FIXME: Add wrapper to interface.h? */ if (!teco_view_load(teco_interface_current_view, filename, FALSE, error)) return NULL; - if (teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0) != pos) { + pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0); + teco_undo_int(teco_ranges[0].to) = teco_interface_bytes2glyphs(pos); + teco_undo_guint(teco_ranges_count) = 1; + + if (teco_ranges[0].from != teco_ranges[0].to) { teco_ring_dirtify(); if (teco_current_doc_must_undo()) diff --git a/src/string-utils.c b/src/string-utils.c index e9dd148..d98b6b0 100644 --- a/src/string-utils.c +++ b/src/string-utils.c @@ -87,8 +87,10 @@ teco_string_get_coord(const gchar *str, gsize off, guint *pos, guint *line, guin } /** - * Get the length of the prefix common to two strings. - * Works with UTF-8 and single-byte encodings. + * Get the length of the prefix common to two UTF-8 strings. + * + * The UTF-8 strings must be validated, which should be the case + * for help labels and short Q-Register names. * * @param a Left string. * @param b Right string. @@ -103,8 +105,8 @@ teco_string_diff(teco_string_t a, const gchar *b, gsize b_len) gsize len = 0; while (len < a.len && len < b_len && - a.data[len] == b[len]) - len++; + g_utf8_get_char(a.data+len) == g_utf8_get_char(b+len)) + len = g_utf8_next_char(b+len) - b; return len; } |
