aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/interface-curses
diff options
context:
space:
mode:
Diffstat (limited to 'src/interface-curses')
-rw-r--r--src/interface-curses/interface.c170
1 files changed, 103 insertions, 67 deletions
diff --git a/src/interface-curses/interface.c b/src/interface-curses/interface.c
index 21e728f..ff6a0f2 100644
--- a/src/interface-curses/interface.c
+++ b/src/interface-curses/interface.c
@@ -200,6 +200,12 @@ static struct {
* so every color is initialized to exact RGB values.
*/
gboolean use_palette;
+ /**
+ * Scintilla RGB values which should be rendered
+ * as the terminal's default foreground/background colors.
+ * This is -1 if colors haven't been configured.
+ */
+ gint32 default_fg, default_bg;
int stdin_orig, stdout_orig, stderr_orig;
SCREEN *screen;
@@ -237,58 +243,6 @@ static struct {
} teco_interface;
/**
- * 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 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(attr_t *attr, gshort fg, gshort bg)
-{
- static guint next_pair = 1;
-
- /*
- * Basic support for monochrome terminals:
- * Every background, that is not black is assumed to be a
- * dark-on-bright area, rendered in reverse.
- * This will at least work with the terminal.tes and contrast.tes
- * color schemes.
- */
- 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 >= MAX_PAIRS))
- 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);
-}
-
-/**
* Translate a Scintilla-compatible RGB color value
* (0xBBGGRR) to a Curses color triple (0 to 1000
* for each component).
@@ -358,6 +312,72 @@ teco_rgb2curses(guint32 rgb)
return next_color;
}
+/**
+ * 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 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 (0xBBGGRR)
+ * @param bg curses background color (0xBBGGRR)
+ * @return curses color pair number
+ */
+static gshort
+teco_color_pair(attr_t *attr, guint32 fg, guint32 bg)
+{
+ static guint next_pair = 1;
+
+ /*
+ * Basic support for monochrome terminals:
+ * Every background, that is not black is assumed to be a
+ * dark-on-bright area, rendered in reverse.
+ * This will at least work with the terminal.tes and contrast.tes
+ * color schemes.
+ */
+ if (!has_colors()) {
+ 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_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 >= MAX_PAIRS))
+ return 0;
+ 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, guint32 fg, guint32 bg)
+{
+ gshort pair = teco_color_pair(&attr, fg, bg);
+ return wattr_set(win, attr, pair, NULL);
+}
+
static gint
teco_xterm_version(void)
{
@@ -461,6 +481,8 @@ void
teco_interface_init(gint argc, gchar **argv)
{
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;
@@ -506,7 +528,13 @@ void
teco_interface_disable_palette(void)
{
teco_interface.use_palette = FALSE;
- scintilla_disable_color_palette();
+}
+
+void
+teco_interface_set_default_colors(gint32 fg, gint32 bg)
+{
+ teco_interface.default_fg = fg;
+ teco_interface.default_bg = bg;
}
#ifdef CURSES_TTY
@@ -652,6 +680,14 @@ teco_interface_init_interactive(GError **error)
teco_interface.pair_table = g_hash_table_new(g_direct_hash, g_direct_equal);
start_color();
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);
@@ -851,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;
}
@@ -884,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);
@@ -1077,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);
@@ -1650,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;
@@ -1856,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);