aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/interface-curses
diff options
context:
space:
mode:
Diffstat (limited to 'src/interface-curses')
-rw-r--r--src/interface-curses/curses-info-popup.c28
-rw-r--r--src/interface-curses/curses-info-popup.h2
-rw-r--r--src/interface-curses/interface.c100
3 files changed, 62 insertions, 68 deletions
diff --git a/src/interface-curses/curses-info-popup.c b/src/interface-curses/curses-info-popup.c
index edb6e15..f7d923d 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 */
@@ -106,7 +106,7 @@ teco_curses_info_popup_init_pad(teco_curses_info_popup_t *ctx, attr_t attr)
* so we use foreground attributes instead of background attributes.
* This way, we can cancel out the A_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 ^ A_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/interface.c b/src/interface-curses/interface.c
index 365a096..4f00bcf 100644
--- a/src/interface-curses/interface.c
+++ b/src/interface-curses/interface.c
@@ -233,63 +233,49 @@ static struct {
* 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 beginnig at the second half of
- * color pair space on demand (similar to what Scinterm does).
- *
- * @note Scinterm now also has scintilla_set_color_offsets(),
- * so we could use the color pairs beginning with 1 as well.
+ * 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 allocated_pairs = 0;
+ static gshort 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 |= A_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);
- /*
- * We are still adding colors with COLOR_PAIR(), which allows
- * at most 256 color pairs (1-255).
- */
- gshort new_pair = MIN(COLOR_PAIRS, 256)/2 + allocated_pairs;
- if (G_UNLIKELY(new_pair >= 256))
+ if (G_UNLIKELY(next_pair >= MIN(COLOR_PAIRS, G_MAXSHORT)))
return 0;
- allocated_pairs++;
- init_pair(new_pair, fg, bg);
- g_hash_table_insert(teco_interface.pair_table, key, GUINT_TO_POINTER(new_pair));
- return new_pair;
+ init_pair(next_pair, fg, bg);
+ g_hash_table_insert(teco_interface.pair_table, key, GUINT_TO_POINTER(next_pair));
+ return next_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)
+static inline gint
+teco_wattr_set(WINDOW *win, attr_t attr, gshort fg, gshort bg)
{
- if (has_colors())
- return COLOR_PAIR(teco_color_pair(fg, bg));
-
- /*
- * 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.
- */
- return bg != COLOR_BLACK ? A_REVERSE : 0;
+ gshort pair = teco_color_pair(&attr, fg, bg);
+ return wattr_set(win, attr, pair, NULL);
}
/**
@@ -760,6 +746,8 @@ 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 */
+ scintilla_set_color_offsets(0, MIN(COLOR_PAIRS, G_MAXSHORT)/2);
/*
* On UNIX terminals, the escape key is usually
@@ -950,7 +938,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));
@@ -972,7 +960,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);
}
@@ -983,11 +971,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);
}
@@ -1161,11 +1149,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;
@@ -1734,11 +1722,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
@@ -1938,9 +1928,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;
}