aboutsummaryrefslogtreecommitdiffhomepage
path: root/output.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'output.cpp')
-rw-r--r--output.cpp294
1 files changed, 91 insertions, 203 deletions
diff --git a/output.cpp b/output.cpp
index 855eecdf..5a0d221b 100644
--- a/output.cpp
+++ b/output.cpp
@@ -22,6 +22,8 @@
#if HAVE_NCURSES_H
#include <ncurses.h>
+#elif HAVE_NCURSES_CURSES_H
+#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
@@ -52,49 +54,10 @@
/**
Number of color names in the col array
*/
-#define COLORS (sizeof(col)/sizeof(wchar_t *))
+#define FISH_COLORS (sizeof(col)/sizeof(wchar_t *))
static int writeb_internal(char c);
-/**
- Names of different colors.
- */
-static const wchar_t *col[]=
-{
- L"black",
- L"red",
- L"green",
- L"brown",
- L"yellow",
- L"blue",
- L"magenta",
- L"purple",
- L"cyan",
- L"white"
- L"normal"
-}
-;
-
-/**
- Mapping from color name (the 'col' array) to color index as used in
- ANSI color terminals, and also the fish_color_* constants defined
- in highlight.h. Non-ANSI terminals will display the wrong colors,
- since they use a different mapping.
- */
-static const int col_idx[]=
-{
- 0,
- 1,
- 2,
- 3,
- 3,
- 4,
- 5,
- 5,
- 6,
- 7,
- FISH_COLOR_NORMAL,
-};
/**
The function used for output
@@ -107,8 +70,8 @@ static int (*out)(char c) = &writeb_internal;
*/
static wcstring current_term;
-/* Whether term256 is supported */
-static bool support_term256 = false;
+/* Whether term256 and term24bit are supported */
+static color_support_t color_support = 0;
void output_set_writer(int (*writer)(char))
@@ -125,22 +88,22 @@ int (*output_get_writer())(char)
static bool term256_support_is_native(void)
{
/* Return YES if we think the term256 support is "native" as opposed to forced. */
- return max_colors == 256;
+ return max_colors >= 256;
}
-bool output_get_supports_term256(void)
+color_support_t output_get_color_support(void)
{
- return support_term256;
+ return color_support;
}
-void output_set_supports_term256(bool val)
+void output_set_color_support(color_support_t val)
{
- support_term256 = val;
+ color_support = val;
}
unsigned char index_for_color(rgb_color_t c)
{
- if (c.is_named() || ! output_get_supports_term256())
+ if (c.is_named() || ! (output_get_color_support() & color_support_term256))
{
return c.to_name_index();
}
@@ -151,7 +114,7 @@ unsigned char index_for_color(rgb_color_t c)
}
-static bool write_color(char *todo, unsigned char idx, bool is_fg)
+static bool write_color_escape(char *todo, unsigned char idx, bool is_fg)
{
bool result = false;
if (idx < 16 || term256_support_is_native())
@@ -184,15 +147,15 @@ static bool write_color(char *todo, unsigned char idx, bool is_fg)
return result;
}
-bool write_foreground_color(unsigned char idx)
+static bool write_foreground_color(unsigned char idx)
{
if (set_a_foreground && set_a_foreground[0])
{
- return write_color(set_a_foreground, idx, true);
+ return write_color_escape(set_a_foreground, idx, true);
}
else if (set_foreground && set_foreground[0])
{
- return write_color(set_foreground, idx, true);
+ return write_color_escape(set_foreground, idx, true);
}
else
{
@@ -200,15 +163,15 @@ bool write_foreground_color(unsigned char idx)
}
}
-bool write_background_color(unsigned char idx)
+static bool write_background_color(unsigned char idx)
{
if (set_a_background && set_a_background[0])
{
- return write_color(set_a_background, idx, false);
+ return write_color_escape(set_a_background, idx, false);
}
else if (set_background && set_background[0])
{
- return write_color(set_background, idx, false);
+ return write_color_escape(set_background, idx, false);
}
else
{
@@ -216,6 +179,34 @@ bool write_background_color(unsigned char idx)
}
}
+void write_color(rgb_color_t color, bool is_fg)
+{
+ bool supports_term24bit = !! (output_get_color_support() & color_support_term24bit);
+ if (! supports_term24bit || ! color.is_rgb())
+ {
+ /* Indexed or non-24 bit color */
+ unsigned char idx = index_for_color(color);
+ (is_fg ? write_foreground_color : write_background_color)(idx);
+ }
+ else
+ {
+ /* 24 bit! No tparm here, just ANSI escape sequences.
+ Foreground: ^[38;2;<r>;<g>;<b>m
+ Background: ^[48;2;<r>;<g>;<b>m
+ */
+ color24_t rgb = color.to_color24();
+ char buff[128];
+ snprintf(buff, sizeof buff, "\x1b[%u;2;%u;%u;%um", is_fg ? 38 : 48, rgb.rgb[0], rgb.rgb[1], rgb.rgb[2]);
+ int (*writer)(char) = output_get_writer();
+ if (writer)
+ {
+ for (size_t i=0; buff[i]; i++)
+ {
+ writer(buff[i]);
+ }
+ }
+ }
+}
void set_color(rgb_color_t c, rgb_color_t c2)
{
@@ -345,7 +336,7 @@ void set_color(rgb_color_t c, rgb_color_t c2)
}
else if (! c.is_special())
{
- write_foreground_color(index_for_color(c));
+ write_color(c, true /* foreground */);
}
}
@@ -360,7 +351,7 @@ void set_color(rgb_color_t c, rgb_color_t c2)
writembs(exit_attribute_mode);
if (! last_color.is_normal())
{
- write_foreground_color(index_for_color(last_color));
+ write_color(last_color, true /* foreground */);
}
@@ -370,7 +361,7 @@ void set_color(rgb_color_t c, rgb_color_t c2)
}
else if (! c2.is_special())
{
- write_background_color(index_for_color(c2));
+ write_color(c2, false /* not foreground */);
last_color2 = c2;
}
}
@@ -418,13 +409,6 @@ int writeb(tputs_arg_t b)
return 0;
}
-int writembs_internal(char *str)
-{
- CHECK(str, 1);
-
- return tputs(str,1,&writeb)==ERR?1:0;
-}
-
int writech(wint_t ch)
{
mbstate_t state;
@@ -506,137 +490,45 @@ void writestr(const wchar_t *str)
delete[] buffer;
}
-
-void writestr_ellipsis(const wchar_t *str, int max_width)
+rgb_color_t best_color(const std::vector<rgb_color_t> &candidates, color_support_t support)
{
- int written=0;
- int tot;
-
- CHECK(str,);
-
- tot = my_wcswidth(str);
-
- if (tot <= max_width)
- {
- writestr(str);
- return;
- }
-
- while (*str != 0)
- {
- int w = fish_wcwidth(*str);
- if (written+w+fish_wcwidth(ellipsis_char)>max_width)
- {
- break;
- }
- written+=w;
- writech(*(str++));
- }
-
- written += fish_wcwidth(ellipsis_char);
- writech(ellipsis_char);
-
- while (written < max_width)
+ if (candidates.empty())
{
- written++;
- writestr(L" ");
+ return rgb_color_t::none();
}
-}
-
-int write_escaped_str(const wchar_t *str, int max_len)
-{
-
- wchar_t *out;
- int i;
- int len;
- int written=0;
-
- CHECK(str, 0);
-
- out = escape(str, 1);
- len = my_wcswidth(out);
-
- if (max_len && (max_len < len))
+
+ rgb_color_t first_rgb = rgb_color_t::none(), first_named = rgb_color_t::none();
+ for (size_t i=0; i < candidates.size(); i++)
{
- for (i=0; (written+fish_wcwidth(out[i]))<=(max_len-1); i++)
+ const rgb_color_t &color = candidates.at(i);
+ if (first_rgb.is_none() && color.is_rgb())
{
- writech(out[i]);
- written += fish_wcwidth(out[i]);
+ first_rgb = color;
}
- writech(ellipsis_char);
- written += fish_wcwidth(ellipsis_char);
-
- for (i=written; i<max_len; i++)
+ if (first_named.is_none() && color.is_named())
{
- writech(L' ');
- written++;
+ first_named = color;
}
}
+ // If we have both RGB and named colors, then prefer rgb if term256 is supported
+ rgb_color_t result = rgb_color_t::none();
+ bool has_term256 = !! (support & color_support_term256);
+ if ((!first_rgb.is_none() && has_term256) || first_named.is_none())
+ {
+ result = first_rgb;
+ }
else
{
- written = len;
- writestr(out);
+ result = first_named;
}
-
- free(out);
- return written;
-}
-
-
-int output_color_code(const wcstring &val, bool is_background)
-{
- size_t i;
- int color=FISH_COLOR_NORMAL;
- int is_bold=0;
- int is_underline=0;
-
- if (val.empty())
- return FISH_COLOR_NORMAL;
-
- wcstring_list_t el;
- tokenize_variable_array(val, el);
-
- for (size_t j=0; j < el.size(); j++)
+ if (result.is_none())
{
- const wcstring &next = el.at(j);
- wcstring color_name;
- if (is_background)
- {
- // look for something like "--background=red"
- const wcstring prefix = L"--background=";
- if (string_prefixes_string(prefix, next))
- {
- color_name = wcstring(next, prefix.size());
- }
-
- }
- else
- {
- if (next == L"--bold" || next == L"-o")
- is_bold = true;
- else if (next == L"--underline" || next == L"-u")
- is_underline = true;
- else
- color_name = next;
- }
-
- if (! color_name.empty())
- {
- for (i=0; i<COLORS; i++)
- {
- if (wcscasecmp(col[i], color_name.c_str()) == 0)
- {
- color = col_idx[i];
- break;
- }
- }
- }
-
+ result = candidates.at(0);
}
-
- return color | (is_bold?FISH_COLOR_BOLD:0) | (is_underline?FISH_COLOR_UNDERLINE:0);
+ return result;
}
+/* This code should be refactored to enable sharing with builtin_set_color */
rgb_color_t parse_color(const wcstring &val, bool is_background)
{
int is_bold=0;
@@ -679,29 +571,8 @@ rgb_color_t parse_color(const wcstring &val, bool is_background)
}
}
}
-
- // Pick the best candidate
- rgb_color_t first_rgb = rgb_color_t::none(), first_named = rgb_color_t::none();
- for (size_t i=0; i < candidates.size(); i++)
- {
- const rgb_color_t &color = candidates.at(i);
- if (color.is_rgb() && first_rgb.is_none())
- first_rgb = color;
- if (color.is_named() && first_named.is_none())
- first_named = color;
- }
-
- // If we have both RGB and named colors, then prefer rgb if term256 is supported
- rgb_color_t result;
- if ((!first_rgb.is_none() && output_get_supports_term256()) || first_named.is_none())
- {
- result = first_rgb;
- }
- else
- {
- result = first_named;
- }
-
+ rgb_color_t result = best_color(candidates, output_get_color_support());
+
if (result.is_none())
result = rgb_color_t::normal();
@@ -725,3 +596,20 @@ const wchar_t *output_get_term()
{
return current_term.empty() ? L"<unknown>" : current_term.c_str();
}
+
+void writembs_check(char *mbs, const char *mbs_name, const char *file, long line)
+{
+ if (mbs != NULL)
+ {
+ tputs(mbs, 1, &writeb);
+ }
+ else
+ {
+ debug( 0, _(L"Tried to use terminfo string %s on line %ld of %s, which is undefined in terminal of type \"%ls\". Please report this error to %s"),
+ mbs_name,
+ line,
+ file,
+ output_get_term(),
+ PACKAGE_BUGREPORT);
+ }
+}