[vte/vte-0-36] emulation: Support 16 million colors



commit c5a32b491afe783b02eec49b1f02241163ba4367
Author: Egmont Koblinger <egmont gmail com>
Date:   Thu Jan 9 00:12:33 2014 +0100

    emulation: Support 16 million colors
    
    https://bugzilla.gnome.org/show_bug.cgi?id=704449

 perf/img.sh       |   71 ++++++++++++++++++++++++
 src/vte-private.h |   36 +++++++++---
 src/vte.c         |  155 +++++++++++++++++++++++++++++------------------------
 src/vterowdata.h  |   47 ++++++++++-------
 src/vteseq.c      |  151 ++++++++++++++++++++-------------------------------
 5 files changed, 271 insertions(+), 189 deletions(-)
---
diff --git a/perf/img.sh b/perf/img.sh
new file mode 100755
index 0000000..7cc8254
--- /dev/null
+++ b/perf/img.sh
@@ -0,0 +1,71 @@
+#!/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
diff --git a/src/vte-private.h b/src/vte-private.h
index 3b40060..c2c215d 100644
--- a/src/vte-private.h
+++ b/src/vte-private.h
@@ -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;
diff --git a/src/vte.c b/src/vte.c
index b01a036..8d04ea6 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -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,
diff --git a/src/vterowdata.h b/src/vterowdata.h
index a37302e..d8f833f 100644
--- a/src/vterowdata.h
+++ b/src/vterowdata.h
@@ -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));
diff --git a/src/vteseq.c b/src/vteseq.c
index ed0c75d..d0c6ac4 100644
--- a/src/vteseq.c
+++ b/src/vteseq.c
@@ -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)) {
-                                       terminal->pvt->screen->bg_sgr_extended = TRUE;
-                                       terminal->pvt->screen->defaults.attr.back = param2;
-                               }
-                               i += 2;
-                       }
+                       terminal->pvt->screen->defaults.attr.back = VTE_LEGACY_COLORS_OFFSET + param - 40;
                        break;
-               }
+            /* case 48: was handled above at 38 to avoid code duplication */
                case 49:
                        /* default background */
-                       terminal->pvt->screen->bg_sgr_extended = FALSE;
                        terminal->pvt->screen->defaults.attr.back = VTE_DEF_BG;
                        break;
                case 90:
@@ -2530,8 +2494,7 @@ vte_sequence_handler_character_attributes (VteTerminal *terminal, GValueArray *p
                case 95:
                case 96:
                case 97:
-                       terminal->pvt->screen->fg_sgr_extended = FALSE;
-                       terminal->pvt->screen->defaults.attr.fore = param - 90 + VTE_COLOR_BRIGHT_OFFSET;
+                       terminal->pvt->screen->defaults.attr.fore = VTE_LEGACY_COLORS_OFFSET + param - 90 + 
VTE_COLOR_BRIGHT_OFFSET;
                        break;
                case 100:
                case 101:
@@ -2541,8 +2504,7 @@ vte_sequence_handler_character_attributes (VteTerminal *terminal, GValueArray *p
                case 105:
                case 106:
                case 107:
-                       terminal->pvt->screen->bg_sgr_extended = FALSE;
-                       terminal->pvt->screen->defaults.attr.back = param - 100 + VTE_COLOR_BRIGHT_OFFSET;
+                       terminal->pvt->screen->defaults.attr.back = VTE_LEGACY_COLORS_OFFSET + param - 100 + 
VTE_COLOR_BRIGHT_OFFSET;
                        break;
                }
        }
@@ -2551,7 +2513,14 @@ vte_sequence_handler_character_attributes (VteTerminal *terminal, GValueArray *p
                _vte_terminal_set_default_attributes(terminal);
        }
        /* Save the new colors. */
-       vte_adjust_colors(terminal);
+       terminal->pvt->screen->color_defaults.attr.fore =
+               terminal->pvt->screen->defaults.attr.fore;
+       terminal->pvt->screen->color_defaults.attr.back =
+               terminal->pvt->screen->defaults.attr.back;
+       terminal->pvt->screen->fill_defaults.attr.fore =
+               terminal->pvt->screen->defaults.attr.fore;
+       terminal->pvt->screen->fill_defaults.attr.back =
+               terminal->pvt->screen->defaults.attr.back;
 }
 
 /* Move the cursor to the given column, 1-based. */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]