From 48fc4afc5bb622ef98a340b31322114835b559fd Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Apr 2017 11:02:25 -0700 Subject: [PATCH] GUACAMOLE-278: Copy terminal color values rather than referencing only by palette index. --- src/terminal/common.c | 20 +++++++ src/terminal/display.c | 92 ++++++++++++++++---------------- src/terminal/terminal.c | 20 +++---- src/terminal/terminal/common.h | 22 ++++++++ src/terminal/terminal/display.h | 16 +++--- src/terminal/terminal/types.h | 21 +++++--- src/terminal/terminal_handlers.c | 6 ++- 7 files changed, 124 insertions(+), 73 deletions(-) diff --git a/src/terminal/common.c b/src/terminal/common.c index 99137534..27ca3b4d 100644 --- a/src/terminal/common.c +++ b/src/terminal/common.c @@ -105,3 +105,23 @@ int guac_terminal_write_all(int fd, const char* buffer, int size) { } +int guac_terminal_colorcmp(const guac_terminal_color* a, + const guac_terminal_color* b) { + + /* Consider red component highest order ... */ + if (a->red != b->red) + return a->red - b->red; + + /* ... followed by green ... */ + if (a->green != b->green) + return a->green - b->green; + + /* ... followed by blue */ + if (a->blue != b->blue) + return a->blue - b->blue; + + /* If all components match, colors are equal */ + return 0; + +} + diff --git a/src/terminal/display.c b/src/terminal/display.c index 1a0aeb52..a4995ba3 100644 --- a/src/terminal/display.c +++ b/src/terminal/display.c @@ -39,24 +39,24 @@ const guac_terminal_color guac_terminal_palette[16] = { /* Normal colors */ - {0x00, 0x00, 0x00}, /* Black */ - {0x99, 0x3E, 0x3E}, /* Red */ - {0x3E, 0x99, 0x3E}, /* Green */ - {0x99, 0x99, 0x3E}, /* Brown */ - {0x3E, 0x3E, 0x99}, /* Blue */ - {0x99, 0x3E, 0x99}, /* Magenta */ - {0x3E, 0x99, 0x99}, /* Cyan */ - {0x99, 0x99, 0x99}, /* White */ + {0, 0x00, 0x00, 0x00}, /* Black */ + {1, 0x99, 0x3E, 0x3E}, /* Red */ + {2, 0x3E, 0x99, 0x3E}, /* Green */ + {3, 0x99, 0x99, 0x3E}, /* Brown */ + {4, 0x3E, 0x3E, 0x99}, /* Blue */ + {5, 0x99, 0x3E, 0x99}, /* Magenta */ + {6, 0x3E, 0x99, 0x99}, /* Cyan */ + {7, 0x99, 0x99, 0x99}, /* White */ /* Intense colors */ - {0x3E, 0x3E, 0x3E}, /* Black */ - {0xFF, 0x67, 0x67}, /* Red */ - {0x67, 0xFF, 0x67}, /* Green */ - {0xFF, 0xFF, 0x67}, /* Brown */ - {0x67, 0x67, 0xFF}, /* Blue */ - {0xFF, 0x67, 0xFF}, /* Magenta */ - {0x67, 0xFF, 0xFF}, /* Cyan */ - {0xFF, 0xFF, 0xFF}, /* White */ + {8, 0x3E, 0x3E, 0x3E}, /* Black */ + {9, 0xFF, 0x67, 0x67}, /* Red */ + {10, 0x67, 0xFF, 0x67}, /* Green */ + {11, 0xFF, 0xFF, 0x67}, /* Brown */ + {12, 0x67, 0x67, 0xFF}, /* Blue */ + {13, 0xFF, 0x67, 0xFF}, /* Magenta */ + {14, 0x67, 0xFF, 0xFF}, /* Cyan */ + {15, 0xFF, 0xFF, 0xFF}, /* White */ }; @@ -127,24 +127,27 @@ int __guac_terminal_hash_codepoint(int codepoint) { int __guac_terminal_set_colors(guac_terminal_display* display, guac_terminal_attributes* attributes) { - int background, foreground; + const guac_terminal_color* background; + const guac_terminal_color* foreground; /* Handle reverse video */ if (attributes->reverse != attributes->cursor) { - background = attributes->foreground; - foreground = attributes->background; + background = &attributes->foreground; + foreground = &attributes->background; } else { - foreground = attributes->foreground; - background = attributes->background; + foreground = &attributes->foreground; + background = &attributes->background; } /* Handle bold */ - if (attributes->bold && foreground <= 7) - foreground += 8; + if (attributes->bold && foreground->palette_index >= 0 + && foreground->palette_index <= 7) { + foreground = &guac_terminal_palette[foreground->palette_index + 8]; + } - display->glyph_foreground = foreground; - display->glyph_background = background; + display->glyph_foreground = *foreground; + display->glyph_background = *background; return 0; @@ -163,12 +166,10 @@ int __guac_terminal_set(guac_terminal_display* display, int row, int col, int co char utf8[4]; /* Use foreground color */ - const guac_terminal_color* color = - &guac_terminal_palette[display->glyph_foreground]; + const guac_terminal_color* color = &display->glyph_foreground; /* Use background color */ - const guac_terminal_color* background = - &guac_terminal_palette[display->glyph_background]; + const guac_terminal_color* background = &display->glyph_background; cairo_surface_t* surface; cairo_t* cairo; @@ -259,7 +260,7 @@ int __guac_terminal_set(guac_terminal_display* display, int row, int col, int co guac_terminal_display* guac_terminal_display_alloc(guac_client* client, const char* font_name, int font_size, int dpi, - int foreground, int background) { + guac_terminal_color* foreground, guac_terminal_color* background) { PangoFontMap* font_map; PangoFont* font; @@ -303,8 +304,8 @@ guac_terminal_display* guac_terminal_display_alloc(guac_client* client, return NULL; } - display->default_foreground = display->glyph_foreground = foreground; - display->default_background = display->glyph_background = background; + display->default_foreground = display->glyph_foreground = *foreground; + display->default_background = display->glyph_background = *background; /* Calculate character dimensions */ display->char_width = @@ -688,14 +689,11 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) { int rect_width, rect_height; /* Color of the rectangle to draw */ - int color; + const guac_terminal_color* color; if (current->character.attributes.reverse != current->character.attributes.cursor) - color = current->character.attributes.foreground; + color = ¤t->character.attributes.foreground; else - color = current->character.attributes.background; - - const guac_terminal_color* guac_color = - &guac_terminal_palette[color]; + color = ¤t->character.attributes.background; /* Current row within a subrect */ guac_terminal_operation* rect_current_row; @@ -709,16 +707,16 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) { /* Find width */ for (rect_col=col; rect_colwidth; rect_col++) { - int joining_color; + const guac_terminal_color* joining_color; if (rect_current->character.attributes.reverse != rect_current->character.attributes.cursor) - joining_color = rect_current->character.attributes.foreground; + joining_color = &rect_current->character.attributes.foreground; else - joining_color = rect_current->character.attributes.background; + joining_color = &rect_current->character.attributes.background; /* If not identical operation, stop */ if (rect_current->type != GUAC_CHAR_SET || guac_terminal_has_glyph(rect_current->character.value) - || joining_color != color) + || guac_terminal_colorcmp(joining_color, color) != 0) break; /* Next column */ @@ -754,16 +752,16 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) { for (rect_col=0; rect_colcharacter.attributes.reverse != rect_current->character.attributes.cursor) - joining_color = rect_current->character.attributes.foreground; + joining_color = &rect_current->character.attributes.foreground; else - joining_color = rect_current->character.attributes.background; + joining_color = &rect_current->character.attributes.background; /* Mark clear operations as NOP */ if (rect_current->type == GUAC_CHAR_SET && !guac_terminal_has_glyph(rect_current->character.value) - && joining_color == color) + && guac_terminal_colorcmp(joining_color, color) == 0) rect_current->type = GUAC_CHAR_NOP; /* Next column */ @@ -783,7 +781,7 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) { row * display->char_height, rect_width * display->char_width, rect_height * display->char_height, - guac_color->red, guac_color->green, guac_color->blue, + color->red, color->green, color->blue, 0xFF); } /* end if clear operation */ diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index 758b72d7..0c1628e9 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -205,8 +205,7 @@ static void guac_terminal_repaint_default_layer(guac_terminal* terminal, guac_terminal_display* display = terminal->display; /* Get background color */ - const guac_terminal_color* color = - &guac_terminal_palette[display->default_background]; + const guac_terminal_color* color = &display->default_background; /* Reset size */ guac_protocol_send_size(socket, GUAC_DEFAULT_LAYER, width, height); @@ -296,8 +295,8 @@ guac_terminal* guac_terminal_create(guac_client* client, guac_terminal_char default_char = { .value = 0, .attributes = { - .foreground = default_foreground, - .background = default_background, + .foreground = guac_terminal_palette[default_foreground], + .background = guac_terminal_palette[default_background], .bold = false, .reverse = false, .underscore = false @@ -326,8 +325,8 @@ guac_terminal* guac_terminal_create(guac_client* client, /* Init display */ term->display = guac_terminal_display_alloc(client, font_name, font_size, dpi, - default_char.attributes.foreground, - default_char.attributes.background); + &default_char.attributes.foreground, + &default_char.attributes.background); /* Fail if display init failed */ if (term->display == NULL) { @@ -875,17 +874,18 @@ static bool guac_terminal_is_visible(guac_terminal* term, if (guac_terminal_has_glyph(c->value)) return true; - int background; + const guac_terminal_color* background; /* Determine actual background color of character */ if (c->attributes.reverse != c->attributes.cursor) - background = c->attributes.foreground; + background = &c->attributes.foreground; else - background = c->attributes.background; + background = &c->attributes.background; /* Blank characters are visible if their background color differs from that * of the terminal */ - return background != term->default_char.attributes.background; + return guac_terminal_colorcmp(background, + &term->default_char.attributes.background) != 0; } diff --git a/src/terminal/terminal/common.h b/src/terminal/terminal/common.h index f7eda619..615779e6 100644 --- a/src/terminal/terminal/common.h +++ b/src/terminal/terminal/common.h @@ -22,6 +22,7 @@ #define _GUAC_TERMINAL_COMMON_H #include "config.h" +#include "types.h" #include @@ -49,5 +50,26 @@ bool guac_terminal_has_glyph(int codepoint); */ int guac_terminal_write_all(int fd, const char* buffer, int size); +/** + * Compares two colors, returning a negative value if the first color is less + * than the second, a positive value if the first color is greater than the + * second, and zero if the colors are identical. Only the color components are + * compared (not the palette index). The red component is considered the + * highest order component, followed by green, followed by blue. + * + * @param a + * The first color to compare. + * + * @param b + * The second color to compare. + * + * @return + * A negative value if the first color is less than the second, a positive + * value if the first color is greater than the second, and zero if the + * colors are identical. + */ +int guac_terminal_colorcmp(const guac_terminal_color* a, + const guac_terminal_color* b); + #endif diff --git a/src/terminal/terminal/display.h b/src/terminal/terminal/display.h index 655d1aa0..1e886ff4 100644 --- a/src/terminal/terminal/display.h +++ b/src/terminal/terminal/display.h @@ -220,22 +220,24 @@ typedef struct guac_terminal_display { /** * Default foreground color for all glyphs. */ - int default_foreground; + guac_terminal_color default_foreground; /** * Default background color for all glyphs and the terminal itself. */ - int default_background; + guac_terminal_color default_background; /** - * Color of glyphs in copy buffer + * The foreground color to be used for the next glyph rendered to the + * terminal. */ - int glyph_foreground; + guac_terminal_color glyph_foreground; /** - * Color of glyphs in copy buffer + * The background color to be used for the next glyph rendered to the + * terminal. */ - int glyph_background; + guac_terminal_color glyph_background; /** * The surface containing the actual terminal. @@ -292,7 +294,7 @@ typedef struct guac_terminal_display { */ guac_terminal_display* guac_terminal_display_alloc(guac_client* client, const char* font_name, int font_size, int dpi, - int foreground, int background); + guac_terminal_color* foreground, guac_terminal_color* background); /** * Frees the given display. diff --git a/src/terminal/terminal/types.h b/src/terminal/terminal/types.h index ccb862ff..47f27415 100644 --- a/src/terminal/terminal/types.h +++ b/src/terminal/terminal/types.h @@ -24,6 +24,7 @@ #include "config.h" #include +#include /** * A character which is not truly a character, but rather part of an @@ -39,20 +40,26 @@ */ typedef struct guac_terminal_color { + /** + * The index of this color within the terminal palette, or -1 if the color + * does not exist within the terminal palette. + */ + int palette_index; + /** * The red component of this color. */ - int red; + uint8_t red; /** * The green component of this color. */ - int green; + uint8_t green; /** * The blue component of this color. */ - int blue; + uint8_t blue; } guac_terminal_color; @@ -83,14 +90,14 @@ typedef struct guac_terminal_attributes { bool underscore; /** - * The foreground color of this character, as a palette index. + * The foreground color of this character. */ - int foreground; + guac_terminal_color foreground; /** - * The background color of this character, as a palette index. + * The background color of this character. */ - int background; + guac_terminal_color background; } guac_terminal_attributes; diff --git a/src/terminal/terminal_handlers.c b/src/terminal/terminal_handlers.c index 328400cc..330774aa 100644 --- a/src/terminal/terminal_handlers.c +++ b/src/terminal/terminal_handlers.c @@ -779,7 +779,8 @@ int guac_terminal_csi(guac_terminal* term, unsigned char c) { /* Foreground */ else if (value >= 30 && value <= 37) - term->current_attributes.foreground = value - 30; + term->current_attributes.foreground = + guac_terminal_palette[value - 30]; /* Underscore on, default foreground */ else if (value == 38) { @@ -797,7 +798,8 @@ int guac_terminal_csi(guac_terminal* term, unsigned char c) { /* Background */ else if (value >= 40 && value <= 47) - term->current_attributes.background = value - 40; + term->current_attributes.background = + guac_terminal_palette[value - 40]; /* Reset background */ else if (value == 49)