diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/interface-curses/interface.c | 146 |
1 files changed, 86 insertions, 60 deletions
diff --git a/src/interface-curses/interface.c b/src/interface-curses/interface.c index ed376c2..a9f24dd 100644 --- a/src/interface-curses/interface.c +++ b/src/interface-curses/interface.c @@ -166,19 +166,91 @@ static gint teco_interface_blocking_getch(void); #define COLOR_LCYAN COLOR_LIGHT(COLOR_CYAN) #define COLOR_LWHITE COLOR_LIGHT(COLOR_WHITE) +static struct { + /** + * 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). + */ + gint32 color_table[16]; + + /** + * 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. + */ + struct { + gshort r, g, b; + } orig_color_table[16]; + + int stdin_orig, stdout_orig, stderr_orig; + SCREEN *screen; + FILE *screen_tty; + + WINDOW *info_window; + enum { + TECO_INFO_TYPE_BUFFER = 0, + TECO_INFO_TYPE_QREG + } info_type; + teco_string_t info_current; + gboolean info_dirty; + + WINDOW *msg_window; + + /** + * Pad used exclusively for wgetch() as it will not + * result in unwanted wrefresh(). + */ + WINDOW *input_pad; + GQueue *input_queue; + + teco_curses_info_popup_t popup; + gsize popup_prefix_len; + + /** + * GError "thrown" by teco_interface_event_loop_iter(). + * Having this in a variable avoids problems with EMScripten. + */ + GError *event_loop_error; +} teco_interface; + /** - * Returns the curses `COLOR_PAIR` for the given curses foreground and background `COLOR`s. - * This is used simply to enumerate every possible color combination. - * Note: only 256 combinations are possible due to curses portability. + * Returns the curses color pair for the given curses foreground and background colors. + * Initializes a new pair if necessary. + * + * 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). * - * @param fg The curses foreground `COLOR`. - * @param bg The curses background `COLOR`. - * @return number for defining a curses `COLOR_PAIR`. + * @param fg curses foreground color + * @param bg curses background color + * @return curses color pair number */ -static inline gshort +static gshort teco_color_pair(gshort fg, gshort bg) { - return bg * (COLORS < 16 ? 8 : 16) + fg + 1; + 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; } /** @@ -336,58 +408,6 @@ teco_view_free(teco_view_t *ctx) scintilla_delete(ctx); } -static struct { - /** - * 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). - */ - gint32 color_table[16]; - - /** - * 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. - */ - struct { - gshort r, g, b; - } orig_color_table[16]; - - int stdin_orig, stdout_orig, stderr_orig; - SCREEN *screen; - FILE *screen_tty; - - WINDOW *info_window; - enum { - TECO_INFO_TYPE_BUFFER = 0, - TECO_INFO_TYPE_QREG - } info_type; - teco_string_t info_current; - gboolean info_dirty; - - WINDOW *msg_window; - - /** - * Pad used exclusively for wgetch() as it will not - * result in unwanted wrefresh(). - */ - WINDOW *input_pad; - GQueue *input_queue; - - teco_curses_info_popup_t popup; - gsize popup_prefix_len; - - /** - * GError "thrown" by teco_interface_event_loop_iter(). - * Having this in a variable avoids problems with EMScripten. - */ - GError *event_loop_error; -} teco_interface; - static void teco_interface_init_color_safe(guint color, guint32 rgb); static void teco_interface_restore_colors(void); @@ -721,6 +741,9 @@ teco_interface_init_interactive(GError **error) teco_interface_init_screen(); + teco_interface.pair_table = g_hash_table_new(g_direct_hash, g_direct_equal); + start_color(); + /* * On UNIX terminals, the escape key is usually * delivered as the escape character even though function @@ -2262,4 +2285,7 @@ teco_interface_cleanup(void) close(teco_interface.stderr_orig); if (teco_interface.stdout_orig >= 0) close(teco_interface.stdout_orig); + + if (teco_interface.pair_table) + g_hash_table_destroy(teco_interface.pair_table); } |
