Commit c5a32b49 authored by Egmont Koblinger's avatar Egmont Koblinger

emulation: Support 16 million colors

https://bugzilla.gnome.org/show_bug.cgi?id=704449
parent 5cf31fcc
#!/bin/bash
# Image viewer for terminals that support true colors.
# Copyright (C) 2014 Egmont Koblinger
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
if [ $# != 1 -o "$1" = "--help" ]; then
echo 'Usage: img.sh imagefile' >&2
exit 1
elif [ -z $(type -p convert) ]; then
echo 'Please install ImageMagick to run this script.' >&2
exit 1
fi
# This is so that "upper" is still visible after exiting the while loop.
shopt -s lastpipe
COLUMNS=$(tput cols)
declare -a upper lower
upper=()
lower=()
convert -thumbnail ${COLUMNS}x "$1" txt:- |
while IFS=',:() ' read col row dummy red green blue rest; do
if [ "$col" = "#" ]; then
continue
fi
if [ $((row%2)) = 0 ]; then
upper[$col]="$red;$green;$blue"
else
lower[$col]="$red;$green;$blue"
fi
# After reading every second image row, print them out.
if [ $((row%2)) = 1 -a $col = $((COLUMNS-1)) ]; then
i=0
while [ $i -lt $COLUMNS ]; do
echo -ne "\\e[38;2;${upper[$i]};48;2;${lower[$i]}m▀"
i=$((i+1))
done
# \e[K is useful when you resize the terminal while this script is still running.
echo -e "\\e[0m\e[K"
upper=()
d=()
fi
done
# Print the last half line, if required.
if [ "${upper[0]}" != "" ]; then
i=0
while [ $i -lt $COLUMNS ]; do
echo -ne "\\e[38;2;${upper[$i]}m▀"
i=$((i+1))
done
echo -e "\\e[0m\e[K"
fi
......@@ -56,11 +56,34 @@ G_BEGIN_DECLS
#define VTE_LINE_WIDTH 1
#define VTE_ROWS 24
#define VTE_COLUMNS 80
/*
* Colors are encoded in 25 bits as follows:
*
* 0 .. 255:
* Colors set by SGR 256-color extension (38/48;5;index).
* These are direct indices into the color palette.
*
* 256 .. VTE_PALETTE_SIZE - 1 (261):
* Special values, such as default colors.
* These are direct indices into the color palette.
*
* VTE_LEGACY_COLORS_OFFSET (512) .. VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_FULL_COLOR_SET_SIZE - 1 (527):
* Colors set by legacy escapes (30..37/40..47, 90..97/100..107).
* These are translated to 0 .. 15 before looking up in the palette, taking bold into account.
*
* VTE_RGB_COLOR (2^24) .. VTE_RGB_COLOR + 16Mi - 1 (2^25 - 1):
* Colors set by SGR truecolor extension (38/48;2;red;green;blue)
* These are direct RGB values.
*/
#define VTE_LEGACY_COLORS_OFFSET 512
#define VTE_LEGACY_COLOR_SET_SIZE 8
#define VTE_LEGACY_FULL_COLOR_SET_SIZE 16
#define VTE_COLOR_PLAIN_OFFSET 0
#define VTE_COLOR_BRIGHT_OFFSET 8
#define VTE_COLOR_DIM_OFFSET 16
/* More color defines in ring.h */
#define VTE_RGB_COLOR (1 << 24)
/* More color defines in vterowdata.h */
#define VTE_SCROLLBACK_INIT 512
#define VTE_SATURATION_MAX 10000
......@@ -223,19 +246,14 @@ struct _VteTerminalPrivate {
long insert_delta; /* insertion offset */
VteCell defaults; /* default characteristics
for insertion of any new
characters; colors not yet
adjusted for bold/dim/standout */
characters */
VteCell color_defaults; /* original defaults
plus the current
fore/back already adjusted for
bold/dim/standout */
fore/back */
VteCell fill_defaults; /* original defaults
plus the current
fore/back already adjusted for
bold/dim/standout with no
fore/back with no
character data */
gboolean fg_sgr_extended, bg_sgr_extended; /* whether fg/bg were set by
256 color sequences */
gboolean alternate_charset;
gboolean status_line;
GString *status_line_contents;
......
......@@ -319,6 +319,10 @@ G_DEFINE_TYPE(VteTerminal, vte_terminal, GTK_TYPE_WIDGET)
#endif
#endif /* GTK 3.0 */
/* Indexes in the "palette" color array for the dim colors.
* Only the first %VTE_LEGACY_COLOR_SET_SIZE colors have dim versions. */
static const guchar corresponding_dim_index[] = {16,88,28,100,18,90,30,102};
static void
vte_g_array_fill(GArray *array, gconstpointer item, guint final_size)
{
......@@ -371,8 +375,6 @@ _vte_terminal_set_default_attributes(VteTerminal *terminal)
screen->defaults = basic_cell.cell;
screen->color_defaults = screen->defaults;
screen->fill_defaults = screen->defaults;
screen->fg_sgr_extended = FALSE;
screen->bg_sgr_extended = FALSE;
}
/* Cause certain cells to be repainted. */
......@@ -6300,6 +6302,23 @@ vte_terminal_copy_cb(GtkClipboard *clipboard, GtkSelectionData *data,
}
}
/* Convert the internal color code (either index or RGB, see vte-private.h) into RGB. */
static void
vte_terminal_get_rgb_from_index(const VteTerminal *terminal, guint index, PangoColor *color)
{
if (index >= VTE_LEGACY_COLORS_OFFSET && index < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_FULL_COLOR_SET_SIZE)
index -= VTE_LEGACY_COLORS_OFFSET;
if (index < VTE_PALETTE_SIZE) {
memcpy(color, &terminal->pvt->palette[index], sizeof(PangoColor));
} else if (index & VTE_RGB_COLOR) {
color->red = ((index >> 16) & 0xFF) * 257;
color->green = ((index >> 8) & 0xFF) * 257;
color->blue = (index & 0xFF) * 257;
} else {
g_assert_not_reached();
}
}
/**
* VteSelectionFunc:
* @terminal: terminal in which the cell is.
......@@ -6368,7 +6387,7 @@ vte_terminal_get_text_range_maybe_wrapped(VteTerminal *terminal,
const VteCell *pcell = NULL;
GString *string;
struct _VteCharAttributes attr;
PangoColor fore, back, *palette;
PangoColor fore, back;
if (!is_selected)
is_selected = always_selected;
......@@ -6381,7 +6400,6 @@ vte_terminal_get_text_range_maybe_wrapped(VteTerminal *terminal,
string = g_string_new(NULL);
memset(&attr, 0, sizeof(attr));
palette = terminal->pvt->palette;
col = start_col;
for (row = start_row; row < end_row + 1; row++, col = 0) {
const VteRowData *row_data = _vte_terminal_find_row_data (terminal, row);
......@@ -6401,8 +6419,8 @@ vte_terminal_get_text_range_maybe_wrapped(VteTerminal *terminal,
* the selection. */
if (!pcell->attr.fragment && is_selected(terminal, col, row, data)) {
/* Store the attributes of this character. */
fore = palette[pcell->attr.fore];
back = palette[pcell->attr.back];
vte_terminal_get_rgb_from_index(terminal, pcell->attr.fore, &fore);
vte_terminal_get_rgb_from_index(terminal, pcell->attr.back, &back);
attr.fore.red = fore.red;
attr.fore.green = fore.green;
attr.fore.blue = fore.blue;
......@@ -9407,6 +9425,29 @@ vte_terminal_determine_colors_internal(VteTerminal *terminal,
back = VTE_DEF_FG;
}
/* Handle bold by using set bold color or brightening */
if (cell->attr.bold) {
if (fore == VTE_DEF_FG)
fore = VTE_BOLD_FG;
else if (fore >= VTE_LEGACY_COLORS_OFFSET && fore < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_COLOR_SET_SIZE) {
fore += VTE_COLOR_BRIGHT_OFFSET;
}
}
/* Handle half similarly */
if (cell->attr.half) {
if (fore == VTE_DEF_FG)
fore = VTE_DIM_FG;
else if (fore >= VTE_LEGACY_COLORS_OFFSET && fore < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_COLOR_SET_SIZE)
fore = corresponding_dim_index[fore - VTE_LEGACY_COLORS_OFFSET];
}
/* And standout */
if (cell->attr.standout) {
if (fore >= VTE_LEGACY_COLORS_OFFSET && back < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_COLOR_SET_SIZE)
back += VTE_COLOR_BRIGHT_OFFSET;
}
/* Reverse cell? */
if (cell->attr.reverse) {
swap (&fore, &back);
......@@ -9527,18 +9568,22 @@ vte_terminal_draw_graphic(VteTerminal *terminal, vteunistr c,
double adjust;
cairo_t *cr = _vte_draw_get_context (terminal->pvt->draw);
PangoColor fg, bg;
vte_terminal_get_rgb_from_index(terminal, fore, &fg);
vte_terminal_get_rgb_from_index(terminal, back, &bg);
width = column_width * columns;
if ((back != VTE_DEF_BG) || draw_default_bg) {
vte_terminal_fill_rectangle(terminal,
&terminal->pvt->palette[back],
&bg,
x, y, width, row_height);
}
cairo_save (cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
_vte_draw_set_source_color_alpha (terminal->pvt->draw, &terminal->pvt->palette[fore], VTE_DRAW_OPAQUE);
_vte_draw_set_source_color_alpha (terminal->pvt->draw, &fg, VTE_DRAW_OPAQUE);
// FIXME wtf!?
x += terminal->pvt->inner_border.left;
......@@ -10020,9 +10065,9 @@ vte_terminal_draw_graphic(VteTerminal *terminal, vteunistr c,
/* Now take the inside out */
cairo_set_source_rgba (cr,
terminal->pvt->palette[back].red / 65535.,
terminal->pvt->palette[back].green / 65535.,
terminal->pvt->palette[back].blue / 65535.,
bg.red / 65535.,
bg.green / 65535.,
bg.blue / 65535.,
1.);
cairo_set_line_width(cr, inner_line_width);
cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
......@@ -10177,9 +10222,9 @@ vte_terminal_draw_graphic(VteTerminal *terminal, vteunistr c,
case 0x2592: /* medium shade */
case 0x2593: /* dark shade */
cairo_set_source_rgba (cr,
terminal->pvt->palette[fore].red / 65535.,
terminal->pvt->palette[fore].green / 65535.,
terminal->pvt->palette[fore].blue / 65535.,
fg.red / 65535.,
fg.green / 65535.,
fg.blue / 65535.,
(c - 0x2590) / 4.);
cairo_rectangle(cr, x, y, width, row_height);
cairo_fill (cr);
......@@ -10284,7 +10329,7 @@ vte_terminal_draw_cells(VteTerminal *terminal,
{
int i, x, y, ascent;
gint columns = 0;
PangoColor *fg, *bg, *defbg;
PangoColor fg, bg, *defbg;
g_assert(n > 0);
_VTE_DEBUG_IF(VTE_DEBUG_CELLS) {
......@@ -10302,8 +10347,8 @@ vte_terminal_draw_cells(VteTerminal *terminal,
}
bold = bold && terminal->pvt->allow_bold;
fg = &terminal->pvt->palette[fore];
bg = &terminal->pvt->palette[back];
vte_terminal_get_rgb_from_index(terminal, fore, &fg);
vte_terminal_get_rgb_from_index(terminal, back, &bg);
defbg = &terminal->pvt->palette[VTE_DEF_BG];
ascent = terminal->char_ascent;
......@@ -10318,20 +10363,20 @@ vte_terminal_draw_cells(VteTerminal *terminal,
items[i].y += terminal->pvt->inner_border.top;
columns += items[i].columns;
}
if (clear && (draw_default_bg || bg != defbg)) {
if (clear && (draw_default_bg || back != VTE_DEF_BG)) {
gint bold_offset = _vte_draw_has_bold(terminal->pvt->draw,
VTE_DRAW_BOLD) ? 0 : bold;
_vte_draw_fill_rectangle(terminal->pvt->draw,
x + terminal->pvt->inner_border.left,
y + terminal->pvt->inner_border.top,
columns * column_width + bold_offset, row_height,
bg, VTE_DRAW_OPAQUE);
&bg, VTE_DRAW_OPAQUE);
}
} while (i < n);
_vte_draw_text(terminal->pvt->draw,
items, n,
fg, VTE_DRAW_OPAQUE,
&fg, VTE_DRAW_OPAQUE,
_vte_draw_get_style(bold, italic));
for (i = 0; i < n; i++) {
......@@ -10351,7 +10396,7 @@ vte_terminal_draw_cells(VteTerminal *terminal,
}
if (underline) {
vte_terminal_draw_line(terminal,
&terminal->pvt->palette[fore],
&fg,
x,
y + terminal->pvt->underline_position,
x + (columns * column_width) - 1,
......@@ -10359,7 +10404,7 @@ vte_terminal_draw_cells(VteTerminal *terminal,
}
if (strikethrough) {
vte_terminal_draw_line(terminal,
&terminal->pvt->palette[fore],
&fg,
x,
y + terminal->pvt->strikethrough_position,
x + (columns * column_width) - 1,
......@@ -10367,7 +10412,7 @@ vte_terminal_draw_cells(VteTerminal *terminal,
}
if (hilite) {
vte_terminal_draw_line(terminal,
&terminal->pvt->palette[fore],
&fg,
x,
y + row_height - 1,
x + (columns * column_width) - 1,
......@@ -10375,7 +10420,7 @@ vte_terminal_draw_cells(VteTerminal *terminal,
}
if (boxed) {
vte_terminal_draw_rectangle(terminal,
&terminal->pvt->palette[fore],
&fg,
x, y,
MAX(0, (columns * column_width)),
MAX(0, row_height));
......@@ -10384,44 +10429,6 @@ vte_terminal_draw_cells(VteTerminal *terminal,
}
}
/* Try to map a PangoColor to a palette entry and return its index. */
static guint
_vte_terminal_map_pango_color(VteTerminal *terminal, PangoColor *color)
{
long distance[G_N_ELEMENTS(terminal->pvt->palette)];
guint i, ret;
/* Calculate a "distance" value. Could stand to be improved a bit. */
for (i = 0; i < G_N_ELEMENTS(distance); i++) {
const PangoColor *entry = &terminal->pvt->palette[i];
distance[i] = 0;
distance[i] += ((entry->red >> 8) - (color->red >> 8)) *
((entry->red >> 8) - (color->red >> 8));
distance[i] += ((entry->blue >> 8) - (color->blue >> 8)) *
((entry->blue >> 8) - (color->blue >> 8));
distance[i] += ((entry->green >> 8) - (color->green >> 8)) *
((entry->green >> 8) - (color->green >> 8));
}
/* Find the index of the minimum value. */
ret = 0;
for (i = 1; i < G_N_ELEMENTS(distance); i++) {
if (distance[i] < distance[ret]) {
ret = i;
}
}
_vte_debug_print(VTE_DEBUG_UPDATES,
"mapped PangoColor(%04x,%04x,%04x) to "
"palette entry (%04x,%04x,%04x)\n",
color->red, color->green, color->blue,
terminal->pvt->palette[ret].red,
terminal->pvt->palette[ret].green,
terminal->pvt->palette[ret].blue);
return ret;
}
/* FIXME: we don't have a way to tell GTK+ what the default text attributes
* should be, so for now at least it's assuming white-on-black is the norm and
* is using "black-on-white" to signify "inverse". Pick up on that state and
......@@ -10510,8 +10517,10 @@ _vte_terminal_apply_pango_attr(VteTerminal *terminal, PangoAttribute *attr,
case PANGO_ATTR_FOREGROUND:
case PANGO_ATTR_BACKGROUND:
attrcolor = (PangoAttrColor*) attr;
ival = _vte_terminal_map_pango_color(terminal,
&attrcolor->color);
ival = VTE_RGB_COLOR |
((attrcolor->color.red & 0xFF00) << 8) |
((attrcolor->color.green & 0xFF00)) |
((attrcolor->color.blue & 0xFF00) >> 8);
for (i = attr->start_index;
i < attr->end_index && i < n_cells;
i++) {
......@@ -10726,15 +10735,17 @@ vte_terminal_draw_rows(VteTerminal *terminal,
j += cell ? cell->attr.columns : 1;
}
if (back != VTE_DEF_BG) {
PangoColor bg;
gint bold_offset = _vte_draw_has_bold(terminal->pvt->draw,
VTE_DRAW_BOLD) ? 0 : bold;
vte_terminal_get_rgb_from_index(terminal, back, &bg);
_vte_draw_fill_rectangle (
terminal->pvt->draw,
x + i * column_width,
y,
(j - i) * column_width + bold_offset,
row_height,
&terminal->pvt->palette[back], VTE_DRAW_OPAQUE);
&bg, VTE_DRAW_OPAQUE);
}
/* We'll need to continue at the first cell which didn't
* match the first one in this set. */
......@@ -10753,12 +10764,14 @@ vte_terminal_draw_rows(VteTerminal *terminal,
}
vte_terminal_determine_colors(terminal, NULL, selected, &fore, &back);
if (back != VTE_DEF_BG) {
PangoColor bg;
vte_terminal_get_rgb_from_index(terminal, back, &bg);
_vte_draw_fill_rectangle (terminal->pvt->draw,
x + i *column_width,
y,
(j - i) * column_width,
row_height,
&terminal->pvt->palette[back], VTE_DRAW_OPAQUE);
&bg, VTE_DRAW_OPAQUE);
}
i = j;
} while (i < end_column);
......@@ -11084,6 +11097,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
int row, drow, col;
long width, height, delta, cursor_width;
guint fore, back;
PangoColor bg;
int x, y;
gboolean blink, selected, focus;
......@@ -11133,6 +11147,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
selected = vte_cell_is_selected(terminal, col, drow, NULL);
vte_terminal_determine_cursor_colors(terminal, cell, selected, &fore, &back);
vte_terminal_get_rgb_from_index(terminal, back, &bg);
x = item.x;
y = item.y;
......@@ -11145,7 +11160,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
stem_width = (int) (((float) height) * terminal->pvt->cursor_aspect_ratio + 0.5);
stem_width = CLAMP (stem_width, VTE_LINE_WIDTH, cursor_width);
vte_terminal_fill_rectangle(terminal, &terminal->pvt->palette[back],
vte_terminal_fill_rectangle(terminal, &bg,
x, y, stem_width, height);
break;
}
......@@ -11158,7 +11173,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
line_height = (int) (((float) height) * terminal->pvt->cursor_aspect_ratio + 0.5);
line_height = CLAMP (line_height, VTE_LINE_WIDTH, height);
vte_terminal_fill_rectangle(terminal, &terminal->pvt->palette[back],
vte_terminal_fill_rectangle(terminal, &bg,
x, y + height - line_height,
cursor_width, line_height);
break;
......@@ -11169,7 +11184,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
if (focus) {
/* just reverse the character under the cursor */
vte_terminal_fill_rectangle (terminal,
&terminal->pvt->palette[back],
&bg,
x, y,
cursor_width, height);
......@@ -11211,7 +11226,7 @@ vte_terminal_paint_cursor(VteTerminal *terminal)
/* draw a box around the character */
vte_terminal_draw_rectangle (terminal,
&terminal->pvt->palette[back],
&bg,
x - VTE_LINE_WIDTH,
y - VTE_LINE_WIDTH,
cursor_width + 2*VTE_LINE_WIDTH,
......
......@@ -35,6 +35,14 @@ G_BEGIN_DECLS
#define VTE_PALETTE_SIZE 262
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6)
#define VTE_GNUC_PACKED \
__attribute__((__packed__))
#else
#define VTE_GNUC_PACKED
#endif /* !__GNUC__ */
/*
* VteCellAttr: A single cell style attributes
*
......@@ -45,32 +53,33 @@ G_BEGIN_DECLS
*/
typedef struct _VteCellAttr {
guint32 fragment: 1; /* A continuation cell. */
guint32 columns: 4; /* Number of visible columns
guint64 fragment: 1; /* A continuation cell. */
guint64 columns: 4; /* Number of visible columns
(as determined by g_unicode_iswide(c)).
Also abused for tabs; bug 353610
Keep at least 4 for tabs to work
*/
guint32 bold: 1;
guint32 italic: 1;
guint32 fore: 9; /* Index into color palette */
guint32 back: 9; /* Index into color palette. */
guint64 bold: 1;
guint64 italic: 1;
guint64 fore: 25; /* Index into color palette, or direct RGB, */
/* 4-byte boundary */
guint64 back: 25; /* see vte-private.h */
guint32 standout: 1;
guint32 underline: 1;
guint32 strikethrough: 1;
guint64 standout: 1;
guint64 underline: 1;
guint64 strikethrough: 1;
guint32 reverse: 1;
guint32 blink: 1;
guint32 half: 1;
guint64 reverse: 1;
guint64 blink: 1;
guint64 half: 1;
guint32 invisible: 1;
guint64 invisible: 1;
} VteCellAttr;
G_STATIC_ASSERT (sizeof (VteCellAttr) == 4);
G_STATIC_ASSERT (sizeof (VteCellAttr) == 8);
typedef union _VteIntCellAttr {
VteCellAttr s;
guint32 i;
guint64 i;
} VteIntCellAttr;
G_STATIC_ASSERT (sizeof (VteCellAttr) == sizeof (VteIntCellAttr));
......@@ -78,17 +87,17 @@ G_STATIC_ASSERT (sizeof (VteCellAttr) == sizeof (VteIntCellAttr));
* VteCell: A single cell's data
*/
typedef struct _VteCell {
typedef struct VTE_GNUC_PACKED _VteCell {
vteunistr c;
VteCellAttr attr;
} VteCell;
G_STATIC_ASSERT (sizeof (VteCell) == 8);
G_STATIC_ASSERT (sizeof (VteCell) == 12);
typedef union _VteIntCell {
VteCell cell;
struct {
struct VTE_GNUC_PACKED {
guint32 c;
guint32 attr;
guint64 attr;
} i;
} VteIntCell;
G_STATIC_ASSERT (sizeof (VteCell) == sizeof (VteIntCell));
......
......@@ -493,53 +493,6 @@ vte_sequence_handler_set_mode_internal(VteTerminal *terminal,
}
/* Indexes in the "palette" color array for the dim colors.
* Only the first %VTE_LEGACY_COLOR_SET_SIZE colors have dim versions. */
static const guchar corresponding_dim_index[] = {16,88,28,100,18,90,30,102};
static void
vte_adjust_colors(VteTerminal *terminal)
{
guint fore, back;
fore = terminal->pvt->screen->defaults.attr.fore;
back = terminal->pvt->screen->defaults.attr.back;
/* Handle bold by using set bold color or brightening */
if (terminal->pvt->screen->defaults.attr.bold) {
if (fore == VTE_DEF_FG) {
fore = VTE_BOLD_FG;
} else if (!terminal->pvt->screen->fg_sgr_extended
&& fore < VTE_LEGACY_COLOR_SET_SIZE) {
fore += VTE_COLOR_BRIGHT_OFFSET;
}
}
/* Handle half similarly */
if (terminal->pvt->screen->defaults.attr.half) {
if (fore == VTE_DEF_FG) {
fore = VTE_DIM_FG;
} else if (!terminal->pvt->screen->fg_sgr_extended
&& fore < VTE_LEGACY_COLOR_SET_SIZE) {
fore = corresponding_dim_index[fore];
}
}
/* And standout */
if (terminal->pvt->screen->defaults.attr.standout) {
if (!terminal->pvt->screen->bg_sgr_extended
&& back < VTE_LEGACY_COLOR_SET_SIZE) {
back += VTE_COLOR_BRIGHT_OFFSET;
}
}
/* Save the adjusted colors. */
terminal->pvt->screen->color_defaults.attr.fore = fore;
terminal->pvt->screen->color_defaults.attr.back = back;
terminal->pvt->screen->fill_defaults.attr.fore = fore;
terminal->pvt->screen->fill_defaults.attr.back = back;
}
/*
* Sequence handling boilerplate
*/
......@@ -2456,33 +2409,66 @@ vte_sequence_handler_character_attributes (VteTerminal *terminal, GValueArray *p
case 35:
case 36:
case 37:
terminal->pvt->screen->fg_sgr_extended = FALSE;
terminal->pvt->screen->defaults.attr.fore = param - 30;
terminal->pvt->screen->defaults.attr.fore = VTE_LEGACY_COLORS_OFFSET + param - 30;
break;
case 38:
case 48:
{
/* The format looks like: ^[[38;5;COLORNUMBERm,
so look for COLORNUMBER here. */
if ((i + 2) < params->n_values){
GValue *value1, *value2;
long param1, param2;
/* The format looks like: ^[[38;5;COLORNUMBERm or ^[[38;2;RED;GREEN;BLUEm
so look for the parameters here. */
if ((i + 1) < params->n_values) {
GValue *value1, *value2, *value3, *value4;
long param1, param2, param3, param4;
value1 = g_value_array_get_nth(params, i + 1);
value2 = g_value_array_get_nth(params, i + 2);
if (G_UNLIKELY (!(G_VALUE_HOLDS_LONG(value1) && G_VALUE_HOLDS_LONG(value2))))
if (G_UNLIKELY (!G_VALUE_HOLDS_LONG(value1)))
break;
param1 = g_value_get_long(value1);
param2 = g_value_get_long(value2);
if (G_LIKELY (param1 == 5 && param2 >= 0 && param2 < 256)) {
terminal->pvt->screen->fg_sgr_extended = TRUE;
terminal->pvt->screen->defaults.attr.fore = param2;
switch (param1) {
case 2:
if (G_UNLIKELY ((i + 4) >= params->n_values))
break;
value2 = g_value_array_get_nth(params, i + 2);
value3 = g_value_array_get_nth(params, i + 3);
value4 = g_value_array_get_nth(params, i + 4);
if (G_UNLIKELY (!(G_VALUE_HOLDS_LONG(value2) && G_VALUE_HOLDS_LONG(value3) && G_VALUE_HOLDS_LONG(value4))))
break;
param2 = g_value_get_long(value2);
param3 = g_value_get_long(value3);
param4 = g_value_get_long(value4);
if (G_LIKELY (param2 >= 0 && param2 < 256 && param3 >= 0 && param3 < 256 && param4 >= 0 && param4 < 256)) {
guint32 value = (1 << 24) | (param2 << 16) | (param3 << 8) | param4;
if (param == 38) {
terminal->pvt->screen->defaults.attr.fore = value;
} else {
terminal->pvt->screen->defaults.attr.back = value;
}
}
i += 4;
break;
case 5:
if (G_UNLIKELY ((i + 2) >= params->n_values))
break;
value2 = g_value_array_get_nth(params, i + 2);
if (G_UNLIKELY (!G_VALUE_HOLDS_LONG(value2)))
break;
param2 = g_value_get_long(value2);
if (G_LIKELY (param2 >= 0 && param2 < 256)) {
if (param == 38) {
terminal->pvt->screen->defaults.attr.fore = param2;
} else {
terminal->pvt->screen->defaults.attr.back = param2;
}
}
i += 2;
break;
default:
break;
}
i += 2;
}
break;
}
case 39:
/* default foreground */
terminal->pvt->screen->fg_sgr_extended = FALSE;
terminal->pvt->screen->defaults.attr.fore = VTE_DEF_FG;
break;
case 40:
......@@ -2493,33 +2479,11 @@ vte_sequence_handler_character_attributes (VteTerminal *terminal, GValueArray *p
case 45:
case 46:
case 47:
terminal->pvt->screen->bg_sgr_extended = FALSE;
terminal->pvt->screen->defaults.attr.back = param - 40;
break;
case 48:
{
/* The format looks like: ^[[48;5;COLORNUMBERm,
so look for COLORNUMBER here. */
if ((i + 2) < params->n_values){
GValue *value1, *value2;
long param1, param2;
value1 = g_value_array_get_nth(params, i + 1);
value2 = g_value_array_get_nth(params, i + 2);
if (G_UNLIKELY (!(G_VALUE_HOLDS_LONG(value1) && G_VALUE_HOLDS_LONG(value2))))
break;
param1 = g_value_get_long(value1);
param2 = g_value_get_long(value2);
if (G_LIKELY (param1 == 5 && param2 >= 0 && param2 < 256)) {