diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core-commands.c | 150 | ||||
| -rw-r--r-- | src/interface-curses/interface.c | 417 | ||||
| -rw-r--r-- | src/interface-gtk/interface.c | 3 | ||||
| -rw-r--r-- | src/interface.h | 10 | ||||
| -rw-r--r-- | src/main.c | 14 | ||||
| -rw-r--r-- | src/search.c | 291 | ||||
| -rw-r--r-- | src/search.h | 2 | ||||
| -rw-r--r-- | src/stdio-commands.c | 37 | ||||
| -rw-r--r-- | src/view.c | 16 |
9 files changed, 573 insertions, 367 deletions
diff --git a/src/core-commands.c b/src/core-commands.c index 2dc1da7..5ca508c 100644 --- a/src/core-commands.c +++ b/src/core-commands.c @@ -2084,7 +2084,7 @@ teco_state_ecommand_flags(teco_machine_main_t *ctx, GError **error) /*$ EJ properties * [key]EJ -> value -- Get and set system properties * value,keyEJ - * rgb,color,3EJ + * [fore,]back,7EJ * -EJ -> event * -2EJ -> y, x * @@ -2110,6 +2110,7 @@ teco_state_ecommand_flags(teco_machine_main_t *ctx, GError **error) * of buffers in the ring. * (\fBread-only\fP) * .IP 2: + * .SCITECO_TOPIC "memory limit" * The current memory limit in bytes. * This limit helps to prevent dangerous out-of-memory * conditions (e.g. resulting from infinite loops) by @@ -2134,49 +2135,40 @@ teco_state_ecommand_flags(teco_machine_main_t *ctx, GError **error) * requirements are too large for the new limit \(em if * this happens you may have to clear your command-line * first. - * Memory limiting is enabled by default. + * Memory limiting is enabled by default (default: 500MB). * .IP 3: - * This \fBwrite-only\fP property allows redefining the - * first 16 entries of the terminal color palette \(em a - * feature required by some - * color schemes when using the Curses user interface. - * When setting this property, you are making a request - * to define the terminal \fIcolor\fP as the Scintilla-compatible - * RGB color value given in the \fIrgb\fP parameter. - * \fIcolor\fP must be a value between 0 and 15 - * corresponding to black, red, green, yellow, blue, magenta, - * cyan, white, bright black, bright red, etc. in that order. - * The \fIrgb\fP value has the format 0xBBGGRR, i.e. the red - * component is the least-significant byte and all other bytes - * are ignored. - * Note that on curses, RGB color values sent to Scintilla - * are actually mapped to these 16 colors by the Scinterm port - * and may represent colors with no resemblance to the \(lqRGB\(rq - * value used (depending on the current palette) \(em they should - * instead be viewed as placeholders for 16 standard terminal - * color codes. - * Please refer to the Scinterm manual for details on the allowed - * \(lqRGB\(rq values and how they map to terminal colors. - * This command provides a crude way to request exact RGB colors - * for the first 16 terminal colors. - * The color definition may be queued or be completely ignored - * on other user interfaces and no feedback is given - * if it fails. In fact feedback cannot be given reliably anyway. - * Note that on 8 color terminals, only the first 8 colors - * can be redefined (if you are lucky). - * Note that due to restrictions of most terminal emulators - * and some curses implementations, this command simply will not - * restore the original palette entry or request - * when rubbed out and should generally only be used in - * \fIbatch-mode\fP \(em typically when loading a color scheme. - * For the same reasons \(em even though \*(ST tries hard to - * restore the original palette on exit \(em palette changes may - * persist after \*(ST terminates on most terminal emulators on Unix. - * The only emulator which will restore their default palette - * on exit the author is aware of is \fBxterm\fP(1) and - * the Linux console driver. - * You have been warned. Good luck. + * .SCITECO_TOPIC palette + * This \fBwrite-only\fP property allows disabling use of + * the 16 color palette of default colors when using + * the Curses user interface. + * By default, when working with RGB values in Scintilla + * messages (and \*(ST color schemes for that matter) + * the 16 \(lqdefault\(rq colors are represented by + * special RGB placeholders (e.g. 0x000080 for \fICOLOR_RED\fP) + * as documented in the Scinterm manual. + * Any other RGB values will be automatically allocated + * in the terminal emulator if supported, giving the illusion + * of true color support, even though the actual number of + * concurrent colors on screen may be limited by the terminal + * emulator (see \fImax_colors\fP and \fImax_pairs\fP + * .B terminfo (1) + * capabilities) and other factors. + * \*(ST tries to avoid the first 16 color ids so as not to + * interfer with other terminal-based applications. + * The default palette however may be overwritten when requesting + * new colors in terminals restricted to 16 colors. + * In this case the original palette might not be restored properly on + * program termination and affect other terminal applications. + * The 16 predefined colors do not map to exact RGB values, + * though, but point into a palette at the terminal emulator. + * \*(ST therefore allows you to disable the 16 RGB placeholders + * by calling \(lq0,3EJ\(rq so that all colors are freshly initialized + * and will represent their exact RGB values. + * It has no effect when using the GTK interface. + * You are recommended to add \(lq0,3EJ\(rq to all color + * schemes that rely on exact RGB values. * .IP 4: + * .SCITECO_TOPIC caretx * The column after the last horizontal movement. * This is only used by \fBfnkeys.tes\fP and is similar to the Scintilla-internal * setting \fBSCI_CHOOSECARETX\fP. @@ -2199,6 +2191,41 @@ teco_state_ecommand_flags(teco_machine_main_t *ctx, GError **error) * After changing the interval, the new value may become * active only after the previous interval expires. * Recovery files are not dumped in batch mode. + * .IP 7: + * .SCITECO_TOPIC "default colors" + * This \fBwrite-only\fP property allows configuring the default + * foreground and background colors, given as two + * Scintilla-encoded RGB (0xBBGGRR) numbers. + * When asked to draw these colors, the terminal's native + * default colors \(em which may be some kind of white on black or + * black on white \(em are used instead. + * Therefore this command does not change any colors on screen + * \(em it just defines placeholder values for the terminal's + * default colors. + * This may be used e.g. to get a true black background where + * the terminal emulator's palette uses a different hue for + * Curses color COLOR_BLACK without having to resort to + * color redefinitions. + * With caution this may even be used to build color schemes that + * work both on white on black and black on white terminals. + * Use -1 to disable default foreground or background colors. + * It has no effect when using the GTK interface. + * .IP 8: + * .SCITECO_TOPIC "block size" + * Block size during backwards searches (e.g. \(lq-S\(rq). + * When searching backwards \*(ST will perform forward searches + * in within blocks before the search range's end. + * If not enough matches could be produced, it moves back + * another block. + * The smaller the block size the more likely that a match + * will not be the leftmost longest, but the less matching overhead. + * A negative or 0 value (\(lq0,8EJ\(rq) is the maximum block size and + * ensures forward searches over the entire search range. + * Only this setting guarantees leftmost longest matches that + * are entirely symmetric to forward searches, but can be + * unpractically slow on huge files. + * The default is 0. + * \# FIXME: Feature is currently broken! * . * .IP -1: * Type of the last mouse event (\fBread-only\fP). @@ -2250,10 +2277,12 @@ teco_state_ecommand_properties(teco_machine_main_t *ctx, GError **error) EJ_USER_INTERFACE = 0, EJ_BUFFERS, EJ_MEMORY_LIMIT, - EJ_INIT_COLOR, + EJ_PALETTE, EJ_CARETX, EJ_CMDLINE_HEIGHT, - EJ_RECOVERY_INTERVAL + EJ_RECOVERY_INTERVAL, + EJ_DEFAULT_COLORS, + EJ_SEARCH_BLOCK_SIZE }; static teco_int_t caret_x = 0; @@ -2274,19 +2303,13 @@ teco_state_ecommand_properties(teco_machine_main_t *ctx, GError **error) return; break; - case EJ_INIT_COLOR: - if (value < 0 || value >= 16) { - g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED, - "Invalid color code %" TECO_INT_FORMAT " " - "specified for <EJ>", value); - return; - } - if (!teco_expressions_args()) { - teco_error_argexpected_set(error, "EJ"); + case EJ_PALETTE: + if (teco_is_success(value)) { + g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED, + "Default color palette can only be disabled"); return; } - teco_interface_init_color((guint)value, - (guint32)teco_expressions_pop_num(0)); + teco_interface_disable_palette(); break; case EJ_CARETX: @@ -2315,6 +2338,19 @@ teco_state_ecommand_properties(teco_machine_main_t *ctx, GError **error) /* FIXME: Perhaps signal the interface to reprogram timers */ break; + case EJ_DEFAULT_COLORS: { + teco_int_t fore; + + if (!teco_expressions_pop_num_calc(&fore, -1, error)) + return; + teco_interface_set_default_colors(fore, value); + break; + } + + case EJ_SEARCH_BLOCK_SIZE: + teco_undo_gsize(teco_search_block_size) = MAX(0, value); + break; + default: g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED, "Cannot set property %" TECO_INT_FORMAT " " @@ -2378,6 +2414,10 @@ teco_state_ecommand_properties(teco_machine_main_t *ctx, GError **error) teco_expressions_push(teco_ring_recovery_interval); break; + case EJ_SEARCH_BLOCK_SIZE: + teco_expressions_push(teco_search_block_size); + break; + default: g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED, "Invalid property %" TECO_INT_FORMAT " " diff --git a/src/interface-curses/interface.c b/src/interface-curses/interface.c index 569b13a..ff6a0f2 100644 --- a/src/interface-curses/interface.c +++ b/src/interface-curses/interface.c @@ -140,6 +140,16 @@ static gint teco_xterm_version(void) G_GNUC_UNUSED; static gint teco_interface_blocking_getch(void); static inline gboolean teco_interface_check_key(gint key); +#define MAX_COLORS (MIN(COLORS, G_MAXSHORT)/2) +/** + * Maximum effective number of color pairs. + * 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. + * Half of the range is reserved to Scinterm. + */ +#define MAX_PAIRS (MIN(COLOR_PAIRS, G_MAXSHORT)/2) + /** * Get bright variant of one of the 8 standard * curses colors. @@ -156,6 +166,12 @@ static inline gboolean teco_interface_check_key(gint key); * The 8 bright colors (if terminal supports at * least 16 colors), else they are identical to * the non-bright colors (default curses colors). + * + * As a consequence a light black (grey) foreground + * on black background might be invisible on 8 color + * terminals. + * If you add in A_BOLD, there is a good chance that + * the text will still become grey. */ #define COLOR_LBLACK COLOR_LIGHT(COLOR_BLACK) #define COLOR_LRED COLOR_LIGHT(COLOR_RED) @@ -168,30 +184,28 @@ static inline gboolean teco_interface_check_key(gint key); static struct { /** + * Mapping of RGB codes (encoded into a pointer) + * to a curses color number. + */ + GHashTable *color_table; + /** * Mapping of foreground and background curses color tuples * (encoded into a pointer) to a color pair number. */ GHashTable *pair_table; - /** - * Mapping of the first 16 curses color codes (that may or may not - * correspond with the standard terminal color codes) to - * Scintilla-compatible RGB values (red is LSB) to initialize after - * Curses startup. - * Negative values mean no color redefinition (keep the original - * palette entry). + * Whether to map the 16 standard palettized colors + * in color_table. + * Should be disabled when using arbitrary RGB values, + * so every color is initialized to exact RGB values. */ - gint32 color_table[16]; - + gboolean use_palette; /** - * Mapping of the first 16 curses color codes to their - * original values for restoring them on shutdown. - * Unfortunately, this may not be supported on all - * curses ports, so this array may be unused. + * Scintilla RGB values which should be rendered + * as the terminal's default foreground/background colors. + * This is -1 if colors haven't been configured. */ - struct { - gshort r, g, b; - } orig_color_table[16]; + gint32 default_fg, default_bg; int stdin_orig, stdout_orig, stderr_orig; SCREEN *screen; @@ -229,6 +243,76 @@ static struct { } teco_interface; /** + * Translate a Scintilla-compatible RGB color value + * (0xBBGGRR) to a Curses color triple (0 to 1000 + * for each component). + */ +static inline void +teco_rgb2curses_triple(guint32 rgb, gshort *r, gshort *g, gshort *b) +{ + /* NOTE: We could also use 200/51 */ + *r = ((rgb & 0x0000FF) >> 0)*1000/0xFF; + *g = ((rgb & 0x00FF00) >> 8)*1000/0xFF; + *b = ((rgb & 0xFF0000) >> 16)*1000/0xFF; +} + +static inline void +teco_interface_insert_color(guint32 rgb, gshort color) +{ + /* + * Color ids are stored one-offset, so that COLOR_BLACK + * can be discerned from a missing entry. + */ + g_hash_table_insert(teco_interface.color_table, + GUINT_TO_POINTER(rgb), GUINT_TO_POINTER(color)+1); +} + +/** + * Convert a Scintilla-compatible RGB color value + * (0xBBGGRR) to a Curses color code (e.g. COLOR_BLACK). + * + * This will automatically initialize new curses colors + * when necessary. + * Unless the palette is disabled with + * teco_interface_disable_palette(), this will return + * the 16 "standard" colors for a predefined list of + * RGB values (just like defined by Scinterm). + */ +static gshort +teco_rgb2curses(guint32 rgb) +{ + static guint colors = 0; + + if (!has_colors()) + return COLOR_WHITE; + + gpointer value = g_hash_table_lookup(teco_interface.color_table, + GUINT_TO_POINTER(rgb)); + if (G_LIKELY(value != NULL)) + return GPOINTER_TO_UINT(value)-1; + + /* + * Even when initializing new colors, we will __try__ not to + * touch the 16 palettized colors. + * First of all, we might still need them and secondly, + * this ensures we don't have to reset them on exit + * (which is not always possible anyway). + * There can still be 16 color terminals with + * can_change_color() == TRUE, though. + */ + guint next_color = colors + (COLORS > 16 ? 16 : 0); + + if (G_UNLIKELY(next_color >= MAX_COLORS) || !can_change_color()) + return COLOR_WHITE; + gshort r, g, b; + teco_rgb2curses_triple(rgb, &r, &g, &b); + init_color(next_color, r, g, b); + teco_interface_insert_color(rgb, next_color); + colors++; + return next_color; +} + +/** * Returns the curses color pair for the given curses foreground and background colors. * Initializes a new pair if necessary. * @@ -239,12 +323,12 @@ static struct { * 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 + * @param fg curses foreground color (0xBBGGRR) + * @param bg curses background color (0xBBGGRR) * @return curses color pair number */ static gshort -teco_color_pair(attr_t *attr, gshort fg, gshort bg) +teco_color_pair(attr_t *attr, guint32 fg, guint32 bg) { static guint next_pair = 1; @@ -256,78 +340,44 @@ teco_color_pair(attr_t *attr, gshort fg, gshort bg) * color schemes. */ if (!has_colors()) { - if (bg != COLOR_BLACK) - *attr |= WA_REVERSE; + if (bg != 0x000000) + *attr ^= WA_REVERSE; return 0; } + gshort fg_id, bg_id; + + /* + * Prefer to use reverse attribute since it will work with + * the terminals default colors. + */ + if (fg == teco_interface.default_bg && bg == teco_interface.default_fg) { + fg_id = bg_id = -1; + *attr ^= WA_REVERSE; + } else { + fg_id = fg == teco_interface.default_fg ? -1 : teco_rgb2curses(fg); + bg_id = bg == teco_interface.default_bg ? -1 : teco_rgb2curses(bg); + } + G_STATIC_ASSERT(sizeof(gshort)*2 <= sizeof(guint)); - gpointer key = GUINT_TO_POINTER(((guint)fg << 8*sizeof(bg)) | bg); + gpointer key = GUINT_TO_POINTER(((guint)fg_id << 8*sizeof(bg_id)) | bg_id); 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)) + if (G_UNLIKELY(next_pair >= MAX_PAIRS)) return 0; - init_pair(next_pair, fg, bg); + init_pair(next_pair, fg_id, bg_id); 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) +teco_wattr_set(WINDOW *win, attr_t attr, guint32 fg, guint32 bg) { gshort pair = teco_color_pair(&attr, fg, bg); return wattr_set(win, attr, pair, NULL); } -/** - * Translate a Scintilla-compatible RGB color value - * (0xBBGGRR) to a Curses color triple (0 to 1000 - * for each component). - */ -static inline void -teco_rgb2curses_triple(guint32 rgb, gshort *r, gshort *g, gshort *b) -{ - /* NOTE: We could also use 200/51 */ - *r = ((rgb & 0x0000FF) >> 0)*1000/0xFF; - *g = ((rgb & 0x00FF00) >> 8)*1000/0xFF; - *b = ((rgb & 0xFF0000) >> 16)*1000/0xFF; -} - -/** - * Convert a Scintilla-compatible RGB color value - * (0xBBGGRR) to a Curses color code (e.g. COLOR_BLACK). - * This does not work with arbitrary RGB values but - * only the 16 RGB color values defined by Scinterm - * corresponding to the 16 terminal colors. - * It is equivalent to Scinterm's internal `term_color` - * function. - */ -static gshort -teco_rgb2curses(guint32 rgb) -{ - switch (rgb) { - case 0x000000: return COLOR_BLACK; - case 0x000080: return COLOR_RED; - case 0x008000: return COLOR_GREEN; - case 0x008080: return COLOR_YELLOW; - case 0x800000: return COLOR_BLUE; - case 0x800080: return COLOR_MAGENTA; - case 0x808000: return COLOR_CYAN; - case 0xC0C0C0: return COLOR_WHITE; - case 0x404040: return COLOR_LBLACK; - case 0x0000FF: return COLOR_LRED; - case 0x00FF00: return COLOR_LGREEN; - case 0x00FFFF: return COLOR_LYELLOW; - case 0xFF0000: return COLOR_LBLUE; - case 0xFF00FF: return COLOR_LMAGENTA; - case 0xFFFF00: return COLOR_LCYAN; - case 0xFFFFFF: return COLOR_LWHITE; - } - - return COLOR_WHITE; -} - static gint teco_xterm_version(void) { @@ -416,9 +466,6 @@ teco_view_free(teco_view_t *ctx) scintilla_delete(ctx); } -static void teco_interface_init_color_safe(guint color, guint32 rgb); -static void teco_interface_restore_colors(void); - static void teco_interface_init_screen(void); static gboolean teco_interface_init_interactive(GError **error); static void teco_interface_restore_batch(void); @@ -433,10 +480,9 @@ static void teco_interface_draw_info(void); 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; - for (guint i = 0; i < G_N_ELEMENTS(teco_interface.orig_color_table); i++) - teco_interface.orig_color_table[i].r = -1; + teco_interface.use_palette = TRUE; + teco_interface.default_fg = 0xC0C0C0; /* white */ + teco_interface.default_bg = 0x000000; /* black */; teco_interface.stdin_orig = teco_interface.stdout_orig = teco_interface.stderr_orig = -1; @@ -478,133 +524,17 @@ teco_interface_get_options(void) return NULL; } -static void -teco_interface_init_color_safe(guint color, guint32 rgb) -{ -#if defined(__PDCURSES__) && !defined(PDCURSES_GUI) - if (teco_interface.orig_color_table[color].r < 0) { - color_content((short)color, - &teco_interface.orig_color_table[color].r, - &teco_interface.orig_color_table[color].g, - &teco_interface.orig_color_table[color].b); - } -#endif - - gshort r, g, b; - teco_rgb2curses_triple(rgb, &r, &g, &b); - init_color((short)color, r, g, b); -} - -#if defined(__PDCURSES__) && !defined(PDCURSES_GUI) - -/* - * On PDCurses/WinCon, color_content() will actually return - * the real console color palette - or at least the default - * palette when the console started. - */ -static void -teco_interface_restore_colors(void) -{ - if (!can_change_color()) - return; - - for (guint i = 0; i < G_N_ELEMENTS(teco_interface.orig_color_table); i++) { - if (teco_interface.orig_color_table[i].r < 0) - continue; - - init_color((short)i, - teco_interface.orig_color_table[i].r, - teco_interface.orig_color_table[i].g, - teco_interface.orig_color_table[i].b); - } -} - -#elif defined(CURSES_TTY) - -/* - * FIXME: On UNIX/ncurses teco_interface_init_color_safe() __may__ - * change the terminal's palette permanently and there does not - * appear to be any portable way of restoring the original one. - * Curses has color_content(), but there is actually no terminal - * that allows querying the current palette and so color_content() - * will return bogus "default" values and only for the first 8 colors. - * It would do more damage to restore the palette returned by - * color_content() than it helps. - * xterm has the escape sequence "\e]104\a" which restores - * the palette from Xdefaults but not all terminal emulators - * claiming to be "xterm" via $TERM support this escape sequence. - * lxterminal for instance will print gibberish instead. - * So we try to look whether $XTERM_VERSION is set. - * There are hardly any other terminal emulators that support palette - * resets. - * The only emulator I'm aware of which can be identified reliably - * by $TERM supporting a palette reset is the Linux console - * (see console_codes(4)). The escape sequence "\e]R" is already - * part of its terminfo description (orig_colors capability) - * which is apparently sent by endwin(), so the palette is - * already properly restored on endwin(). - * Welcome in Curses hell. - */ -static void -teco_interface_restore_colors(void) -{ - if (teco_xterm_version() < 0) - return; - - /* - * Looks like a real XTerm - */ - fputs("\e]104\a", teco_interface.screen_tty); - fflush(teco_interface.screen_tty); -} - -#else /* (!__PDCURSES__ || PDCURSES_GUI) && !CURSES_TTY */ - -static void -teco_interface_restore_colors(void) +void +teco_interface_disable_palette(void) { - /* - * No way to restore the palette, or it's - * unnecessary (e.g. XCurses) - */ + teco_interface.use_palette = FALSE; } -#endif - void -teco_interface_init_color(guint color, guint32 rgb) +teco_interface_set_default_colors(gint32 fg, gint32 bg) { - if (color >= G_N_ELEMENTS(teco_interface.color_table)) - return; - -#if defined(__PDCURSES__) && !defined(PDC_RGB) - /* - * PDCurses will usually number color codes differently - * (least significant bit is the blue component) while - * SciTECO macros will assume a standard terminal color - * code numbering with red as the LSB. - * Therefore we have to swap the bit order of the least - * significant 3 bits here. - */ - color = (color & ~0x5) | - ((color & 0x1) << 2) | ((color & 0x4) >> 2); -#endif - - if (teco_interface.input_pad) { - /* interactive mode */ - if (!can_change_color()) - return; - - teco_interface_init_color_safe(color, rgb); - } else { - /* - * batch mode: store colors, - * they can only be initialized after start_color() - * which is called by Scinterm when interactive - * mode is initialized - */ - teco_interface.color_table[color] = (gint32)rgb; - } + teco_interface.default_fg = fg; + teco_interface.default_bg = bg; } #ifdef CURSES_TTY @@ -746,14 +676,41 @@ teco_interface_init_interactive(GError **error) teco_interface_init_screen(); + teco_interface.color_table = g_hash_table_new(g_direct_hash, g_direct_equal); 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); + scintilla_set_color_offsets(MAX_COLORS, MAX_PAIRS); + if (!teco_interface.use_palette) + scintilla_disable_color_palette(); +#ifdef HAVE_USE_DEFAULT_COLORS + /* color -1 will be the terminal's default foreground or background color */ + use_default_colors(); +#endif + scintilla_set_default_colors(teco_interface.default_fg, + teco_interface.default_bg); + + if (teco_interface.use_palette && has_colors()) { + teco_interface_insert_color(0x000000, COLOR_BLACK); + teco_interface_insert_color(0x000080, COLOR_RED); + teco_interface_insert_color(0x008000, COLOR_GREEN); + teco_interface_insert_color(0x008080, COLOR_YELLOW); + teco_interface_insert_color(0x800000, COLOR_BLUE); + teco_interface_insert_color(0x800080, COLOR_MAGENTA); + teco_interface_insert_color(0x808000, COLOR_CYAN); + teco_interface_insert_color(0xC0C0C0, COLOR_WHITE); + /* + * On 8-color terminals, we still support the + * higher (light) colors, but map them to the lower codes as well. + */ + teco_interface_insert_color(0x404040, COLOR_LBLACK); + teco_interface_insert_color(0x0000FF, COLOR_LRED); + teco_interface_insert_color(0x00FF00, COLOR_LGREEN); + teco_interface_insert_color(0x00FFFF, COLOR_LYELLOW); + teco_interface_insert_color(0xFF0000, COLOR_LBLUE); + teco_interface_insert_color(0xFF00FF, COLOR_LMAGENTA); + teco_interface_insert_color(0xFFFF00, COLOR_LCYAN); + teco_interface_insert_color(0xFFFFFF, COLOR_LWHITE); + } /* * On UNIX terminals, the escape key is usually @@ -835,19 +792,6 @@ teco_interface_init_interactive(GError **error) teco_interface_show_view(teco_interface_current_view); /* - * Only now it's safe to redefine the 16 default colors. - */ - if (can_change_color()) { - for (guint i = 0; i < G_N_ELEMENTS(teco_interface.color_table); i++) { - /* - * init_color() may still fail if COLORS < 16 - */ - if (teco_interface.color_table[i] >= 0) - teco_interface_init_color_safe(i, (guint32)teco_interface.color_table[i]); - } - } - - /* * Only now (in interactive mode), it's safe to initialize * the clipboard Q-Registers on ncurses with a compatible terminal * emulator since clipboard operations will no longer interfer @@ -879,7 +823,6 @@ teco_interface_restore_batch(void) * (i.e. return to batch mode) */ endwin(); - teco_interface_restore_colors(); /* * Restore stdin, stdout and stderr, so output goes to @@ -944,23 +887,23 @@ teco_interface_msg_literal(teco_msg_t type, const gchar *str, gsize len) teco_interface_stdio_msg(type, str, len); #endif - gshort fg, bg; + guint32 fg, bg; - fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0)); + fg = teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0); switch (type) { default: case TECO_MSG_USER: - bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0)); + bg = teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0); break; case TECO_MSG_INFO: - bg = COLOR_GREEN; + bg = 0x008000; /* green */ break; case TECO_MSG_WARNING: - bg = COLOR_YELLOW; + bg = 0x008080; /* yellow */ break; case TECO_MSG_ERROR: - bg = COLOR_RED; + bg = 0x000080; /* red */ beep(); break; } @@ -977,8 +920,8 @@ teco_interface_msg_clear(void) if (!teco_interface.input_pad) /* batch mode */ return; - gshort fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0)); - gshort bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0)); + guint32 fg = teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0); + guint32 bg = teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0); wmove(teco_interface.msg_window, 0, 0); teco_wattr_set(teco_interface.msg_window, 0, fg, bg); @@ -1170,8 +1113,8 @@ teco_interface_draw_info(void) * the current buffer's STYLE_DEFAULT. * The same style is used for MSG_USER messages. */ - gshort fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0)); - gshort bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0)); + guint32 fg = teco_interface_ssm(SCI_STYLEGETBACK, STYLE_DEFAULT, 0); + guint32 bg = teco_interface_ssm(SCI_STYLEGETFORE, STYLE_DEFAULT, 0); wmove(teco_interface.info_window, 0, 0); teco_wattr_set(teco_interface.info_window, 0, fg, bg); @@ -1743,8 +1686,8 @@ teco_interface_popup_show(gsize prefix_len) /* batch mode */ return; - gshort fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_CALLTIP, 0)); - gshort bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_CALLTIP, 0)); + guint32 fg = teco_interface_ssm(SCI_STYLEGETFORE, STYLE_CALLTIP, 0); + guint32 bg = teco_interface_ssm(SCI_STYLEGETBACK, STYLE_CALLTIP, 0); teco_interface.popup_prefix_len = prefix_len; attr_t attr = 0; @@ -1949,8 +1892,8 @@ teco_interface_process_mevent(MEVENT *event, GError **error) else if (event->bstate & BUTTON_NUM(5)) teco_curses_info_popup_scroll(&teco_interface.popup, +2); - gshort fg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETFORE, STYLE_CALLTIP, 0)); - gshort bg = teco_rgb2curses(teco_interface_ssm(SCI_STYLEGETBACK, STYLE_CALLTIP, 0)); + guint32 fg = teco_interface_ssm(SCI_STYLEGETFORE, STYLE_CALLTIP, 0); + guint32 bg = 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); @@ -2403,6 +2346,8 @@ teco_interface_cleanup(void) if (teco_interface.stdout_orig >= 0) close(teco_interface.stdout_orig); + if (teco_interface.color_table) + g_hash_table_destroy(teco_interface.color_table); if (teco_interface.pair_table) g_hash_table_destroy(teco_interface.pair_table); diff --git a/src/interface-gtk/interface.c b/src/interface-gtk/interface.c index a31790f..1f6259f 100644 --- a/src/interface-gtk/interface.c +++ b/src/interface-gtk/interface.c @@ -404,7 +404,8 @@ teco_interface_get_options(void) return group; } -void teco_interface_init_color(guint color, guint32 rgb) {} +void teco_interface_disable_palette(void) {} +void teco_interface_set_default_colors(gint32 fg, gint32 bg) {} void teco_interface_msg_literal(teco_msg_t type, const gchar *str, gsize len) diff --git a/src/interface.h b/src/interface.h index 54f807b..a7968d1 100644 --- a/src/interface.h +++ b/src/interface.h @@ -57,13 +57,17 @@ void teco_interface_init(gint argc, gchar **argv); GOptionGroup *teco_interface_get_options(void); /** @pure makes sense only on Curses */ -void teco_interface_init_color(guint color, guint32 rgb); +void teco_interface_disable_palette(void); + +/** @pure makes sense only on Curses */ +void teco_interface_set_default_colors(gint32 fg, gint32 bg); typedef enum { - TECO_MSG_USER, + TECO_MSG_USER = 0, TECO_MSG_INFO, TECO_MSG_WARNING, - TECO_MSG_ERROR + TECO_MSG_ERROR, + TECO_MSG_MAX = TECO_MSG_ERROR } teco_msg_t; extern teco_msg_t teco_interface_msg_level; @@ -388,7 +388,21 @@ main(int argc, char **argv) getchar(); #endif + /* + * FIXME: Gracefully handle SIGTERM. + * This however would require polling for the flag in Curses + * getch() loops. + * GTK already catches SIGTERM. + */ +#ifdef HAVE_SIGACTION + static const struct sigaction sigint = { + .sa_handler = teco_sigint_handler, + .sa_flags = 0 /* don't auto-restart syscalls */ + }; + sigaction(SIGINT, &sigint, NULL); +#else signal(SIGINT, teco_sigint_handler); +#endif /* * Important for Unicode handling in curses and glib. diff --git a/src/search.c b/src/search.c index 856d079..92be012 100644 --- a/src/search.c +++ b/src/search.c @@ -20,6 +20,7 @@ #endif #include <string.h> +#include <stdlib.h> #include <glib.h> #include <glib/gprintf.h> @@ -573,8 +574,46 @@ teco_get_ranges(const GMatchInfo *match_info, gsize offset, guint *count) return ranges; } +/* only keep the last `count' matches, in a circular stack */ +typedef struct { + guint num_ranges; + teco_range_t *ranges; +} teco_match_t; + +typedef struct { + guint count; + teco_match_t matches[]; +} teco_matches_t; + +static inline void +teco_matches_free(teco_matches_t *p) +{ + for (int i = 0; i < p->count; i++) + g_free(p->matches[i].ranges); + g_free(p); +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(teco_matches_t, teco_matches_free); + +/** + * Search forwards in the current buffer. + * + * If `*count == 0` after the call, the n-th match was found in + * the current document and teco_ranges/teco_ranges_count is + * set accordingly but must still be converted into glyph + * offsets. + * + * @param re Compiled regular expression. + * @param from Beginning of the range to search (in bytes). + * @param to End of the range to search (in bytes). + * @param count Pointer to an integer (n-th match to find). + * This is updated to reflect how many matches are still outstanding. + * A negative value indicates backwards searches. + * @param error A GError + * @return FALSE if an error occurred + */ static gboolean -teco_do_search(GRegex *re, gsize from, gsize to, gint *count, GError **error) +teco_do_search_forward(GRegex *re, gsize from, gsize to, gint *count, GError **error) { g_autoptr(GMatchInfo) info = NULL; /* NOTE: can return NULL pointer for completely new and empty documents */ @@ -590,63 +629,175 @@ teco_do_search(GRegex *re, gsize from, gsize to, gint *count, GError **error) return FALSE; } - guint num_ranges = 0; - teco_range_t *matched_ranges = NULL; + g_assert(*count > 0); + while (g_match_info_matches(info) && --(*count)) { + /* + * NOTE: The return boolean does NOT signal whether an error was generated. + */ + g_match_info_next(info, &tmp_error); + if (tmp_error) { + g_propagate_error(error, tmp_error); + return FALSE; + } - if (*count >= 0) { - while (g_match_info_matches(info) && --(*count)) { - /* - * NOTE: The return boolean does NOT signal whether an error was generated. - */ - g_match_info_next(info, &tmp_error); - if (tmp_error) { - g_propagate_error(error, tmp_error); - return FALSE; - } + /* + * FIXME: A single pathological match could already be excessively slow. + */ + if (G_UNLIKELY(teco_interface_is_interrupted())) { + teco_error_interrupted_set(error); + return FALSE; } + } - if (!*count) - /* successful */ - matched_ranges = teco_get_ranges(info, from, &num_ranges); - } else { - /* only keep the last `count' matches, in a circular stack */ - typedef struct { - guint num_ranges; - teco_range_t *ranges; - } teco_match_t; + if (!*count) { + /* successful */ + teco_undo_guint(teco_ranges_count); + teco_undo_ranges_own(teco_ranges) = teco_get_ranges(info, from, &teco_ranges_count); + } - guint matched_num = -*count; - gsize matched_size = sizeof(teco_match_t[matched_num]); + return TRUE; +} +/** + * Block size for backwards scanning or 0 + * + * @bug Block-wise matching is currently broken, + * so we disable this by default - see below. + */ +gsize teco_search_block_size = 0; //4*1024; + +/** + * Search backwards, in blocks of teco_search_block_size + * (within each block a forward scan is performed). + * + * This cannot always guarantee longest matches if a match is + * found at the beginning of a block. + * Only if teco_search_block_size is 0 the entire range + * if forward scanned, which ensures longest matches + * entirely symmetrical to forward searches. + * For large block sizes (or 0) even trivial backwards searches + * can be painstakingly slow on large files, though. + * + * @see teco_do_search_forward + */ +static gboolean +teco_do_search_backwards(GRegex *re, gsize from, gsize to, gint *count, GError **error) +{ + /* + * NOTE: can return NULL pointer for completely new and empty documents. + * + * Theoretically we could also get range pointers on demand which would + * be more likely to preserve the buffer gap. + */ + const gchar *buffer = (const gchar *)teco_interface_ssm(SCI_GETRANGEPOINTER, from, to-from) ? : ""; + + g_assert(*count < 0); + guint matched_num = -*count; + gsize total_size = sizeof(teco_matches_t) + sizeof(teco_match_t[matched_num]); + + /* + * matched_size could overflow. + * NOTE: Glib 2.48 has g_size_checked_mul() which uses + * compiler intrinsics. + */ + if ((gsize)matched_num > (G_MAXSIZE - sizeof(teco_matches_t))/sizeof(teco_match_t)) + /* guaranteed to fail either teco_memory_check() or g_malloc() */ + total_size = G_MAXSIZE; + + /* + * NOTE: It's theoretically possible that the allocation of the `matched` + * array causes an OOM if (-count) is large enough and regular + * memory limiting in teco_machine_main_step() wouldn't help. + * That's why we exceptionally have to check before allocating. + */ + if (!teco_memory_check(total_size, error)) + return FALSE; + + g_autoptr(teco_matches_t) matched = g_malloc0(total_size); + matched->count = matched_num; + + gint matched_total = 0; + gint i = 0; /* ring buffer pointer into the `matched->matches` array */ + + gsize to_block = to-from; + + while (to_block > 0) { + g_autoptr(GMatchInfo) info = NULL; + + gsize from_block = teco_search_block_size > 0 + ? MAX(0, to_block - teco_search_block_size) : 0; /* - * matched_size could overflow. - * NOTE: Glib 2.48 has g_size_checked_mul() which uses - * compiler intrinsics. + * FIXME: DEC TECO search semantics could actually demand + * allowing matches to extend beyond the [from,to] range. */ - if (matched_size / sizeof(teco_match_t) != matched_num) - /* guaranteed to fail either teco_memory_check() or g_malloc() */ - matched_size = G_MAXSIZE; + GRegexMatchFlags flags = to_block != to-from ? G_REGEX_MATCH_PARTIAL_HARD : 0; + + GError *tmp_error = NULL; /* - * NOTE: It's theoretically possible that the allocation of the `matched` - * array causes an OOM if (-count) is large enough and regular - * memory limiting in teco_machine_main_step() wouldn't help. - * That's why we exceptionally have to check before allocating. + * NOTE: The return boolean does NOT signal whether an error was generated. + * FIXME: Why isn't it possible to specify a start_position != 0? */ - if (!teco_memory_check(matched_size, error)) + g_regex_match_full(re, buffer+from_block, to_block-from_block, 0, + flags, &info, &tmp_error); + if (tmp_error) { + g_propagate_error(error, tmp_error); return FALSE; + } - /* - * NOTE: This needs to be deep-freed, which does not currently - * happen automatically. - */ - g_autofree teco_match_t *matched = g_malloc0(matched_size); + for (;;) { + if (G_UNLIKELY(teco_interface_is_interrupted())) { + teco_error_interrupted_set(error); + return FALSE; + } - gint matched_total = 0, i = 0; + if (g_match_info_is_partial_match(info)) { + /* + * Match may fall on the block boundary, + * so retry matching the rest of the document. + * This is the only case where we have to rescan + * the same memory more than once. + * + * FIXME FIXME FIXME: We cannot retrieve the position here + * since g_match_info_fetch_pos() treats partial matches as errors. + * This is a confirmed glib bug and fast backwards searches + * will continue to be broken until we switch to a custom regexp + * engine. + */ + gint partial_start, partial_end; + G_GNUC_UNUSED gboolean rc; + rc = g_match_info_fetch_pos(info, 0, &partial_start, &partial_end); + //g_assert(rc == TRUE); + if (!rc) + abort(); + + if (partial_end == to_block-from_block) { + g_autoptr(GMatchInfo) partial_info = NULL; + + g_regex_match_full(re, buffer+partial_start, to-from-partial_start, 0, + G_REGEX_MATCH_ANCHORED, &partial_info, &tmp_error); + if (tmp_error) { + g_propagate_error(error, tmp_error); + return FALSE; + } + + if (g_match_info_matches(partial_info)) { + g_free(matched->matches[i].ranges); + matched->matches[i].ranges = teco_get_ranges(partial_info, from+partial_start, + &matched->matches[i].num_ranges); + i = ++matched_total % matched_num; + } + } - while (g_match_info_matches(info)) { - g_free(matched[i].ranges); - matched[i].ranges = teco_get_ranges(info, from, &matched[i].num_ranges); + /* there might still be other matches within the current block */ + } else if (g_match_info_matches(info)) { + g_free(matched->matches[i].ranges); + matched->matches[i].ranges = teco_get_ranges(info, from+from_block, + &matched->matches[i].num_ranges); + i = ++matched_total % matched_num; + } else { + break; + } /* * NOTE: The return boolean does NOT signal whether an error was generated. @@ -654,30 +805,50 @@ teco_do_search(GRegex *re, gsize from, gsize to, gint *count, GError **error) g_match_info_next(info, &tmp_error); if (tmp_error) { g_propagate_error(error, tmp_error); - for (int i = 0; i < matched_num; i++) - g_free(matched[i].ranges); return FALSE; } - - i = ++matched_total % -(*count); } - *count = MIN(*count + matched_total, 0); - if (!*count) { + if (matched_total >= matched_num) { /* successful -> i points to stack bottom */ - num_ranges = matched[i].num_ranges; - matched_ranges = matched[i].ranges; - matched[i].ranges = NULL; + teco_undo_guint(teco_ranges_count) = matched->matches[i].num_ranges; + teco_undo_ranges_own(teco_ranges) = matched->matches[i].ranges; + matched->matches[i].ranges = NULL; + + *count = 0; + return TRUE; } - for (gint i = 0; i < matched_num; i++) - g_free(matched[i].ranges); + /* + * We got less matches than the required number. + * We know that the result won't be any of the existing + * matches, so we can discard them and shrink our + * circular buffer. + * This avoids merging the result lists of two blocks. + * Elements are freed when being overwritten just like + * when the buffer overflows. + */ + matched_num -= matched_total; + i = 0; + + to_block = from_block; } - if (matched_ranges) { + *count += matched_total; + g_assert(*count < 0); + return TRUE; +} + +static gboolean +teco_do_search(GRegex *re, gsize from, gsize to, gint *count, GError **error) +{ + gboolean rc = *count >= 0 ? teco_do_search_forward(re, from, to, count, error) + : teco_do_search_backwards(re, from, to, count, error); + if (!rc) + return FALSE; + + if (!*count) { /* match success */ - teco_undo_ranges_own(teco_ranges) = matched_ranges; - teco_undo_guint(teco_ranges_count) = num_ranges; g_assert(teco_ranges_count > 0); teco_interface_ssm(SCI_SETSEL, teco_ranges[0].from, teco_ranges[0].to); @@ -685,6 +856,8 @@ teco_do_search(GRegex *re, gsize from, gsize to, gint *count, GError **error) /* * teco_get_ranges() returned byte positions, * while everything else expects glyph offsets. + * They are fixed up only now to avoid unnecessary + * possibly costly teco_interface_bytes2glyphs() calls. */ for (guint i = 0; i < teco_ranges_count; i++) { teco_ranges[i].from = teco_interface_bytes2glyphs(teco_ranges[i].from); @@ -777,6 +950,7 @@ teco_state_search_process(teco_machine_main_t *ctx, teco_string_t str, gsize new teco_ring_undo_edit(); if (count > 0) { + /* search forward */ do { buffer = teco_buffer_next(buffer) ? : teco_ring_first(); teco_buffer_edit(buffer); @@ -792,6 +966,7 @@ teco_state_search_process(teco_machine_main_t *ctx, teco_string_t str, gsize new return FALSE; } while (count); } else /* count < 0 */ { + /* search backwards */ do { buffer = teco_buffer_prev(buffer) ? : teco_ring_last(); teco_buffer_edit(buffer); diff --git a/src/search.h b/src/search.h index 9bd62f7..dc6413e 100644 --- a/src/search.h +++ b/src/search.h @@ -20,6 +20,8 @@ #include "parser.h" +extern gsize teco_search_block_size; + void teco_state_control_search_mode(teco_machine_main_t *ctx, GError **error); extern teco_state_t teco_state_search; diff --git a/src/stdio-commands.c b/src/stdio-commands.c index abb6566..c2a1c16 100644 --- a/src/stdio-commands.c +++ b/src/stdio-commands.c @@ -255,17 +255,42 @@ teco_state_print_string_initial(teco_machine_main_t *ctx, GError **error) static teco_state_t * teco_state_print_string_done(teco_machine_main_t *ctx, teco_string_t str, GError **error) { - teco_interface_msg_literal(TECO_MSG_USER, str.data, str.len); + teco_int_t type; + + if (ctx->flags.mode > TECO_MODE_NORMAL) + return &teco_state_start; + + if (!teco_expressions_pop_num_calc(&type, TECO_MSG_USER, error)) + return NULL; + if (type < TECO_MSG_USER || type > TECO_MSG_MAX) { + g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED, + "Invalid message level specified for <^A>"); + return NULL; + } + + teco_interface_msg_literal(type, str.data, str.len); return &teco_state_start; } /*$ "^A" ":^A" print "print string" - * ^A<string>^A -- Print string as message - * @^A/string/ - * :^A<string>^A + * [type]^A<string>^A -- Print string as message + * [type]@^A/string/ + * [type]:^A<string>^A * - * Print <string> as a message, i.e. in the message line - * in interactive mode and if possible on the terminal (stdout) as well. + * Print <string> as a message with severity <type>, i.e. in the + * message line in interactive mode and if possible on the terminal + * as well. + * The following message levels are supported: + * .IP 0: 3 + * User-level message: + * They are written without any prefixes directly to stdout. + * This is the default if <type> is omitted. + * .IP 1: + * Info-level message + * .IP 2: + * Warnings + * .IP 3: + * Errors * * \fB^A\fP differs from all other commands in the way <string> * is terminated. @@ -109,12 +109,12 @@ teco_view_setup(teco_view_t *ctx) teco_view_ssm(ctx, SCI_SETCARETSTYLE, CARETSTYLE_BLOCK | CARETSTYLE_OVERSTRIKE_BLOCK | CARETSTYLE_BLOCK_AFTER, 0); teco_view_ssm(ctx, SCI_SETCARETPERIOD, 0, 0); - teco_view_ssm(ctx, SCI_SETCARETFORE, 0xFFFFFF, 0); + teco_view_ssm(ctx, SCI_SETCARETFORE, 0xC0C0C0, 0); teco_view_ssm(ctx, SCI_SETSELFORE, TRUE, 0x000000); - teco_view_ssm(ctx, SCI_SETSELBACK, TRUE, 0xFFFFFF); + teco_view_ssm(ctx, SCI_SETSELBACK, TRUE, 0xC0C0C0); - teco_view_ssm(ctx, SCI_STYLESETFORE, STYLE_DEFAULT, 0xFFFFFF); + teco_view_ssm(ctx, SCI_STYLESETFORE, STYLE_DEFAULT, 0xC0C0C0); teco_view_ssm(ctx, SCI_STYLESETBACK, STYLE_DEFAULT, 0x000000); teco_view_ssm(ctx, SCI_STYLESETFONT, STYLE_DEFAULT, (sptr_t)"Monospace"); teco_view_ssm(ctx, SCI_STYLECLEARALL, 0, 0); @@ -132,7 +132,7 @@ teco_view_setup(teco_view_t *ctx) * default if no color-scheme is applied (and --no-profile). */ teco_view_ssm(ctx, SCI_STYLESETFORE, STYLE_CALLTIP, 0x000000); - teco_view_ssm(ctx, SCI_STYLESETBACK, STYLE_CALLTIP, 0xFFFFFF); + teco_view_ssm(ctx, SCI_STYLESETBACK, STYLE_CALLTIP, 0xC0C0C0); /* * Since we have patched out Scintilla's original SetRepresentations(), @@ -234,8 +234,8 @@ teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel, */ guint cp = teco_view_get_codepage(ctx); if (cp == SC_CP_UTF8) - teco_interface_ssm(SCI_RELEASELINECHARACTERINDEX, - SC_LINECHARACTERINDEX_UTF32, 0); + teco_view_ssm(ctx, SCI_RELEASELINECHARACTERINDEX, + SC_LINECHARACTERINDEX_UTF32, 0); teco_view_ssm(ctx, SCI_BEGINUNDOACTION, 0, 0); if (clear) { @@ -314,8 +314,8 @@ cleanup: teco_view_ssm(ctx, SCI_ENDUNDOACTION, 0, 0); if (cp == SC_CP_UTF8) - teco_interface_ssm(SCI_ALLOCATELINECHARACTERINDEX, - SC_LINECHARACTERINDEX_UTF32, 0); + teco_view_ssm(ctx, SCI_ALLOCATELINECHARACTERINDEX, + SC_LINECHARACTERINDEX_UTF32, 0); return ret; } |
