From 48fc4afc5bb622ef98a340b31322114835b559fd Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Apr 2017 11:02:25 -0700 Subject: [PATCH 1/8] 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) From eaa71f5717c85424ada7d3f63cbff3ad58661361 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Apr 2017 11:38:49 -0700 Subject: [PATCH 2/8] GUACAMOLE-278: Move terminal palette/color definitions into dedicated files. --- src/terminal/Makefile.am | 2 + src/terminal/common.c | 20 ---- src/terminal/display.c | 25 +---- src/terminal/palette.c | 66 +++++++++++++ src/terminal/terminal.c | 1 + src/terminal/terminal/common.h | 21 ---- src/terminal/terminal/display.h | 88 +---------------- src/terminal/terminal/palette.h | 163 +++++++++++++++++++++++++++++++ src/terminal/terminal/types.h | 29 +----- src/terminal/terminal_handlers.c | 1 + 10 files changed, 236 insertions(+), 180 deletions(-) create mode 100644 src/terminal/palette.c create mode 100644 src/terminal/terminal/palette.h diff --git a/src/terminal/Makefile.am b/src/terminal/Makefile.am index 53bc74d1..b3474605 100644 --- a/src/terminal/Makefile.am +++ b/src/terminal/Makefile.am @@ -27,6 +27,7 @@ noinst_HEADERS = \ terminal/char_mappings.h \ terminal/common.h \ terminal/display.h \ + terminal/palette.h \ terminal/scrollbar.h \ terminal/terminal.h \ terminal/terminal_handlers.h \ @@ -38,6 +39,7 @@ libguac_terminal_la_SOURCES = \ char_mappings.c \ common.c \ display.c \ + palette.c \ scrollbar.c \ terminal.c \ terminal_handlers.c \ diff --git a/src/terminal/common.c b/src/terminal/common.c index 27ca3b4d..99137534 100644 --- a/src/terminal/common.c +++ b/src/terminal/common.c @@ -105,23 +105,3 @@ 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 a4995ba3..8d2b1311 100644 --- a/src/terminal/display.c +++ b/src/terminal/display.c @@ -22,6 +22,7 @@ #include "common/surface.h" #include "terminal/common.h" #include "terminal/display.h" +#include "terminal/palette.h" #include "terminal/types.h" #include @@ -36,30 +37,6 @@ #include #include -const guac_terminal_color guac_terminal_palette[16] = { - - /* Normal colors */ - {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 */ - {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 */ - -}; - /** * Clears the currently-selected region, removing the highlight. */ diff --git a/src/terminal/palette.c b/src/terminal/palette.c new file mode 100644 index 00000000..374495da --- /dev/null +++ b/src/terminal/palette.c @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "config.h" +#include "terminal/palette.h" + +const guac_terminal_color guac_terminal_palette[16] = { + + /* Normal colors */ + {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 */ + {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 */ + +}; + +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/terminal.c b/src/terminal/terminal.c index 0c1628e9..711a0fa8 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -24,6 +24,7 @@ #include "terminal/buffer.h" #include "terminal/common.h" #include "terminal/display.h" +#include "terminal/palette.h" #include "terminal/terminal.h" #include "terminal/terminal_handlers.h" #include "terminal/types.h" diff --git a/src/terminal/terminal/common.h b/src/terminal/terminal/common.h index 615779e6..ad059a87 100644 --- a/src/terminal/terminal/common.h +++ b/src/terminal/terminal/common.h @@ -50,26 +50,5 @@ 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 1e886ff4..6397fe53 100644 --- a/src/terminal/terminal/display.h +++ b/src/terminal/terminal/display.h @@ -24,6 +24,7 @@ #include "config.h" #include "common/surface.h" +#include "palette.h" #include "types.h" #include @@ -37,93 +38,6 @@ */ #define GUAC_TERMINAL_MAX_CHAR_WIDTH 2 -/** - * The index of black within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_BLACK 0 - -/** - * The index of low-intensity red within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_DARK_RED 1 - -/** - * The index of low-intensity green within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_DARK_GREEN 2 - -/** - * The index of brown within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_BROWN 3 - -/** - * The index of low-intensity blue within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_DARK_BLUE 4 - -/** - * The index of low-intensity magenta (purple) within the terminal color - * palette. - */ -#define GUAC_TERMINAL_COLOR_PURPLE 5 - -/** - * The index of low-intensity cyan (teal) within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_TEAL 6 - -/** - * The index of low-intensity white (gray) within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_GRAY 7 - -/** - * The index of bright black (dark gray) within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_DARK_GRAY 8 - -/** - * The index of bright red within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_RED 9 - -/** - * The index of bright green within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_GREEN 10 - -/** - * The index of bright brown (yellow) within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_YELLOW 11 - -/** - * The index of bright blue within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_BLUE 12 - -/** - * The index of bright magenta within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_MAGENTA 13 - -/** - * The index of bright cyan within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_CYAN 14 - -/** - * The index of bright white within the terminal color palette. - */ -#define GUAC_TERMINAL_COLOR_WHITE 15 - -/** - * The available color palette. All integer colors within structures - * here are indices into this palette. - */ -extern const guac_terminal_color guac_terminal_palette[16]; - /** * All available terminal operations which affect character cells. */ diff --git a/src/terminal/terminal/palette.h b/src/terminal/terminal/palette.h new file mode 100644 index 00000000..b0e52d13 --- /dev/null +++ b/src/terminal/terminal/palette.h @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef GUAC_TERMINAL_PALETTE_H +#define GUAC_TERMINAL_PALETTE_H + +#include "config.h" + +#include + +/** + * The index of black within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_BLACK 0 + +/** + * The index of low-intensity red within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_DARK_RED 1 + +/** + * The index of low-intensity green within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_DARK_GREEN 2 + +/** + * The index of brown within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_BROWN 3 + +/** + * The index of low-intensity blue within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_DARK_BLUE 4 + +/** + * The index of low-intensity magenta (purple) within the terminal color + * palette. + */ +#define GUAC_TERMINAL_COLOR_PURPLE 5 + +/** + * The index of low-intensity cyan (teal) within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_TEAL 6 + +/** + * The index of low-intensity white (gray) within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_GRAY 7 + +/** + * The index of bright black (dark gray) within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_DARK_GRAY 8 + +/** + * The index of bright red within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_RED 9 + +/** + * The index of bright green within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_GREEN 10 + +/** + * The index of bright brown (yellow) within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_YELLOW 11 + +/** + * The index of bright blue within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_BLUE 12 + +/** + * The index of bright magenta within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_MAGENTA 13 + +/** + * The index of bright cyan within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_CYAN 14 + +/** + * The index of bright white within the terminal color palette. + */ +#define GUAC_TERMINAL_COLOR_WHITE 15 + +/** + * An RGB color, where each component ranges from 0 to 255. + */ +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. + */ + uint8_t red; + + /** + * The green component of this color. + */ + uint8_t green; + + /** + * The blue component of this color. + */ + uint8_t blue; + +} guac_terminal_color; + +/** + * 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); + +/** + * The terminal color palette. + */ +extern const guac_terminal_color guac_terminal_palette[16]; + +#endif + diff --git a/src/terminal/terminal/types.h b/src/terminal/terminal/types.h index 47f27415..7d3cd537 100644 --- a/src/terminal/terminal/types.h +++ b/src/terminal/terminal/types.h @@ -22,6 +22,7 @@ #define _GUAC_TERMINAL_TYPES_H #include "config.h" +#include "palette.h" #include #include @@ -35,34 +36,6 @@ */ #define GUAC_CHAR_CONTINUATION -1 -/** - * An RGB color, where each component ranges from 0 to 255. - */ -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. - */ - uint8_t red; - - /** - * The green component of this color. - */ - uint8_t green; - - /** - * The blue component of this color. - */ - uint8_t blue; - -} guac_terminal_color; - /** * Terminal attributes, as can be applied to a single character. */ diff --git a/src/terminal/terminal_handlers.c b/src/terminal/terminal_handlers.c index 330774aa..a4e514c9 100644 --- a/src/terminal/terminal_handlers.c +++ b/src/terminal/terminal_handlers.c @@ -20,6 +20,7 @@ #include "config.h" #include "terminal/char_mappings.h" +#include "terminal/palette.h" #include "terminal/terminal.h" #include "terminal/terminal_handlers.h" #include "terminal/types.h" From 11bf6f05c426ff13aff3539f044bf9cba56ff4aa Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Apr 2017 12:00:45 -0700 Subject: [PATCH 3/8] GUACAMOLE-278: Expand terminal palette to 256 entries. Use xterm colors for entries 16 through 255. --- src/terminal/palette.c | 244 +++++++++++++++++++++++++++++++- src/terminal/terminal/palette.h | 2 +- 2 files changed, 244 insertions(+), 2 deletions(-) diff --git a/src/terminal/palette.c b/src/terminal/palette.c index 374495da..5c9c3b40 100644 --- a/src/terminal/palette.c +++ b/src/terminal/palette.c @@ -20,7 +20,7 @@ #include "config.h" #include "terminal/palette.h" -const guac_terminal_color guac_terminal_palette[16] = { +const guac_terminal_color guac_terminal_palette[256] = { /* Normal colors */ {0, 0x00, 0x00, 0x00}, /* Black */ @@ -42,6 +42,248 @@ const guac_terminal_color guac_terminal_palette[16] = { {14, 0x67, 0xFF, 0xFF}, /* Cyan */ {15, 0xFF, 0xFF, 0xFF}, /* White */ + /* Remainder of xterm's 256-color palette */ + {16, 0x00, 0x00, 0x00}, + {17, 0x00, 0x00, 0x5F}, + {18, 0x00, 0x00, 0x87}, + {19, 0x00, 0x00, 0xAF}, + {20, 0x00, 0x00, 0xD7}, + {21, 0x00, 0x00, 0xFF}, + {22, 0x00, 0x5F, 0x00}, + {23, 0x00, 0x5F, 0x5F}, + {24, 0x00, 0x5F, 0x87}, + {25, 0x00, 0x5F, 0xAF}, + {26, 0x00, 0x5F, 0xD7}, + {27, 0x00, 0x5F, 0xFF}, + {28, 0x00, 0x87, 0x00}, + {29, 0x00, 0x87, 0x5F}, + {30, 0x00, 0x87, 0x87}, + {31, 0x00, 0x87, 0xAF}, + {32, 0x00, 0x87, 0xD7}, + {33, 0x00, 0x87, 0xFF}, + {34, 0x00, 0xAF, 0x00}, + {35, 0x00, 0xAF, 0x5F}, + {36, 0x00, 0xAF, 0x87}, + {37, 0x00, 0xAF, 0xAF}, + {38, 0x00, 0xAF, 0xD7}, + {39, 0x00, 0xAF, 0xFF}, + {40, 0x00, 0xD7, 0x00}, + {41, 0x00, 0xD7, 0x5F}, + {42, 0x00, 0xD7, 0x87}, + {43, 0x00, 0xD7, 0xAF}, + {44, 0x00, 0xD7, 0xD7}, + {45, 0x00, 0xD7, 0xFF}, + {46, 0x00, 0xFF, 0x00}, + {47, 0x00, 0xFF, 0x5F}, + {48, 0x00, 0xFF, 0x87}, + {49, 0x00, 0xFF, 0xAF}, + {50, 0x00, 0xFF, 0xD7}, + {51, 0x00, 0xFF, 0xFF}, + {52, 0x5F, 0x00, 0x00}, + {53, 0x5F, 0x00, 0x5F}, + {54, 0x5F, 0x00, 0x87}, + {55, 0x5F, 0x00, 0xAF}, + {56, 0x5F, 0x00, 0xD7}, + {57, 0x5F, 0x00, 0xFF}, + {58, 0x5F, 0x5F, 0x00}, + {59, 0x5F, 0x5F, 0x5F}, + {60, 0x5F, 0x5F, 0x87}, + {61, 0x5F, 0x5F, 0xAF}, + {62, 0x5F, 0x5F, 0xD7}, + {63, 0x5F, 0x5F, 0xFF}, + {64, 0x5F, 0x87, 0x00}, + {65, 0x5F, 0x87, 0x5F}, + {66, 0x5F, 0x87, 0x87}, + {67, 0x5F, 0x87, 0xAF}, + {68, 0x5F, 0x87, 0xD7}, + {69, 0x5F, 0x87, 0xFF}, + {70, 0x5F, 0xAF, 0x00}, + {71, 0x5F, 0xAF, 0x5F}, + {72, 0x5F, 0xAF, 0x87}, + {73, 0x5F, 0xAF, 0xAF}, + {74, 0x5F, 0xAF, 0xD7}, + {75, 0x5F, 0xAF, 0xFF}, + {76, 0x5F, 0xD7, 0x00}, + {77, 0x5F, 0xD7, 0x5F}, + {78, 0x5F, 0xD7, 0x87}, + {79, 0x5F, 0xD7, 0xAF}, + {80, 0x5F, 0xD7, 0xD7}, + {81, 0x5F, 0xD7, 0xFF}, + {82, 0x5F, 0xFF, 0x00}, + {83, 0x5F, 0xFF, 0x5F}, + {84, 0x5F, 0xFF, 0x87}, + {85, 0x5F, 0xFF, 0xAF}, + {86, 0x5F, 0xFF, 0xD7}, + {87, 0x5F, 0xFF, 0xFF}, + {88, 0x87, 0x00, 0x00}, + {89, 0x87, 0x00, 0x5F}, + {90, 0x87, 0x00, 0x87}, + {91, 0x87, 0x00, 0xAF}, + {92, 0x87, 0x00, 0xD7}, + {93, 0x87, 0x00, 0xFF}, + {94, 0x87, 0x5F, 0x00}, + {95, 0x87, 0x5F, 0x5F}, + {96, 0x87, 0x5F, 0x87}, + {97, 0x87, 0x5F, 0xAF}, + {98, 0x87, 0x5F, 0xD7}, + {99, 0x87, 0x5F, 0xFF}, + {100, 0x87, 0x87, 0x00}, + {101, 0x87, 0x87, 0x5F}, + {102, 0x87, 0x87, 0x87}, + {103, 0x87, 0x87, 0xAF}, + {104, 0x87, 0x87, 0xD7}, + {105, 0x87, 0x87, 0xFF}, + {106, 0x87, 0xAF, 0x00}, + {107, 0x87, 0xAF, 0x5F}, + {108, 0x87, 0xAF, 0x87}, + {109, 0x87, 0xAF, 0xAF}, + {110, 0x87, 0xAF, 0xD7}, + {111, 0x87, 0xAF, 0xFF}, + {112, 0x87, 0xD7, 0x00}, + {113, 0x87, 0xD7, 0x5F}, + {114, 0x87, 0xD7, 0x87}, + {115, 0x87, 0xD7, 0xAF}, + {116, 0x87, 0xD7, 0xD7}, + {117, 0x87, 0xD7, 0xFF}, + {118, 0x87, 0xFF, 0x00}, + {119, 0x87, 0xFF, 0x5F}, + {120, 0x87, 0xFF, 0x87}, + {121, 0x87, 0xFF, 0xAF}, + {122, 0x87, 0xFF, 0xD7}, + {123, 0x87, 0xFF, 0xFF}, + {124, 0xAF, 0x00, 0x00}, + {125, 0xAF, 0x00, 0x5F}, + {126, 0xAF, 0x00, 0x87}, + {127, 0xAF, 0x00, 0xAF}, + {128, 0xAF, 0x00, 0xD7}, + {129, 0xAF, 0x00, 0xFF}, + {130, 0xAF, 0x5F, 0x00}, + {131, 0xAF, 0x5F, 0x5F}, + {132, 0xAF, 0x5F, 0x87}, + {133, 0xAF, 0x5F, 0xAF}, + {134, 0xAF, 0x5F, 0xD7}, + {135, 0xAF, 0x5F, 0xFF}, + {136, 0xAF, 0x87, 0x00}, + {137, 0xAF, 0x87, 0x5F}, + {138, 0xAF, 0x87, 0x87}, + {139, 0xAF, 0x87, 0xAF}, + {140, 0xAF, 0x87, 0xD7}, + {141, 0xAF, 0x87, 0xFF}, + {142, 0xAF, 0xAF, 0x00}, + {143, 0xAF, 0xAF, 0x5F}, + {144, 0xAF, 0xAF, 0x87}, + {145, 0xAF, 0xAF, 0xAF}, + {146, 0xAF, 0xAF, 0xD7}, + {147, 0xAF, 0xAF, 0xFF}, + {148, 0xAF, 0xD7, 0x00}, + {149, 0xAF, 0xD7, 0x5F}, + {150, 0xAF, 0xD7, 0x87}, + {151, 0xAF, 0xD7, 0xAF}, + {152, 0xAF, 0xD7, 0xD7}, + {153, 0xAF, 0xD7, 0xFF}, + {154, 0xAF, 0xFF, 0x00}, + {155, 0xAF, 0xFF, 0x5F}, + {156, 0xAF, 0xFF, 0x87}, + {157, 0xAF, 0xFF, 0xAF}, + {158, 0xAF, 0xFF, 0xD7}, + {159, 0xAF, 0xFF, 0xFF}, + {160, 0xD7, 0x00, 0x00}, + {161, 0xD7, 0x00, 0x5F}, + {162, 0xD7, 0x00, 0x87}, + {163, 0xD7, 0x00, 0xAF}, + {164, 0xD7, 0x00, 0xD7}, + {165, 0xD7, 0x00, 0xFF}, + {166, 0xD7, 0x5F, 0x00}, + {167, 0xD7, 0x5F, 0x5F}, + {168, 0xD7, 0x5F, 0x87}, + {169, 0xD7, 0x5F, 0xAF}, + {170, 0xD7, 0x5F, 0xD7}, + {171, 0xD7, 0x5F, 0xFF}, + {172, 0xD7, 0x87, 0x00}, + {173, 0xD7, 0x87, 0x5F}, + {174, 0xD7, 0x87, 0x87}, + {175, 0xD7, 0x87, 0xAF}, + {176, 0xD7, 0x87, 0xD7}, + {177, 0xD7, 0x87, 0xFF}, + {178, 0xD7, 0xAF, 0x00}, + {179, 0xD7, 0xAF, 0x5F}, + {180, 0xD7, 0xAF, 0x87}, + {181, 0xD7, 0xAF, 0xAF}, + {182, 0xD7, 0xAF, 0xD7}, + {183, 0xD7, 0xAF, 0xFF}, + {184, 0xD7, 0xD7, 0x00}, + {185, 0xD7, 0xD7, 0x5F}, + {186, 0xD7, 0xD7, 0x87}, + {187, 0xD7, 0xD7, 0xAF}, + {188, 0xD7, 0xD7, 0xD7}, + {189, 0xD7, 0xD7, 0xFF}, + {190, 0xD7, 0xFF, 0x00}, + {191, 0xD7, 0xFF, 0x5F}, + {192, 0xD7, 0xFF, 0x87}, + {193, 0xD7, 0xFF, 0xAF}, + {194, 0xD7, 0xFF, 0xD7}, + {195, 0xD7, 0xFF, 0xFF}, + {196, 0xFF, 0x00, 0x00}, + {197, 0xFF, 0x00, 0x5F}, + {198, 0xFF, 0x00, 0x87}, + {199, 0xFF, 0x00, 0xAF}, + {200, 0xFF, 0x00, 0xD7}, + {201, 0xFF, 0x00, 0xFF}, + {202, 0xFF, 0x5F, 0x00}, + {203, 0xFF, 0x5F, 0x5F}, + {204, 0xFF, 0x5F, 0x87}, + {205, 0xFF, 0x5F, 0xAF}, + {206, 0xFF, 0x5F, 0xD7}, + {207, 0xFF, 0x5F, 0xFF}, + {208, 0xFF, 0x87, 0x00}, + {209, 0xFF, 0x87, 0x5F}, + {210, 0xFF, 0x87, 0x87}, + {211, 0xFF, 0x87, 0xAF}, + {212, 0xFF, 0x87, 0xD7}, + {213, 0xFF, 0x87, 0xFF}, + {214, 0xFF, 0xAF, 0x00}, + {215, 0xFF, 0xAF, 0x5F}, + {216, 0xFF, 0xAF, 0x87}, + {217, 0xFF, 0xAF, 0xAF}, + {218, 0xFF, 0xAF, 0xD7}, + {219, 0xFF, 0xAF, 0xFF}, + {220, 0xFF, 0xD7, 0x00}, + {221, 0xFF, 0xD7, 0x5F}, + {222, 0xFF, 0xD7, 0x87}, + {223, 0xFF, 0xD7, 0xAF}, + {224, 0xFF, 0xD7, 0xD7}, + {225, 0xFF, 0xD7, 0xFF}, + {226, 0xFF, 0xFF, 0x00}, + {227, 0xFF, 0xFF, 0x5F}, + {228, 0xFF, 0xFF, 0x87}, + {229, 0xFF, 0xFF, 0xAF}, + {230, 0xFF, 0xFF, 0xD7}, + {231, 0xFF, 0xFF, 0xFF}, + {232, 0x08, 0x08, 0x08}, + {233, 0x12, 0x12, 0x12}, + {234, 0x1C, 0x1C, 0x1C}, + {235, 0x26, 0x26, 0x26}, + {236, 0x30, 0x30, 0x30}, + {237, 0x3A, 0x3A, 0x3A}, + {238, 0x44, 0x44, 0x44}, + {239, 0x4E, 0x4E, 0x4E}, + {240, 0x58, 0x58, 0x58}, + {241, 0x62, 0x62, 0x62}, + {242, 0x6C, 0x6C, 0x6C}, + {243, 0x76, 0x76, 0x76}, + {244, 0x80, 0x80, 0x80}, + {245, 0x8A, 0x8A, 0x8A}, + {246, 0x94, 0x94, 0x94}, + {247, 0x9E, 0x9E, 0x9E}, + {248, 0xA8, 0xA8, 0xA8}, + {249, 0xB2, 0xB2, 0xB2}, + {250, 0xBC, 0xBC, 0xBC}, + {251, 0xC6, 0xC6, 0xC6}, + {252, 0xD0, 0xD0, 0xD0}, + {253, 0xDA, 0xDA, 0xDA}, + {254, 0xE4, 0xE4, 0xE4}, + {255, 0xEE, 0xEE, 0xEE} + }; int guac_terminal_colorcmp(const guac_terminal_color* a, diff --git a/src/terminal/terminal/palette.h b/src/terminal/terminal/palette.h index b0e52d13..10163688 100644 --- a/src/terminal/terminal/palette.h +++ b/src/terminal/terminal/palette.h @@ -157,7 +157,7 @@ int guac_terminal_colorcmp(const guac_terminal_color* a, /** * The terminal color palette. */ -extern const guac_terminal_color guac_terminal_palette[16]; +extern const guac_terminal_color guac_terminal_palette[256]; #endif From 87fba523ee668c8f7f81d36d2df5c3c560aff8c9 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Apr 2017 12:53:47 -0700 Subject: [PATCH 4/8] GUACAMOLE-278: Handle xterm 256-color SGR sequences. --- src/terminal/terminal_handlers.c | 156 ++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 4 deletions(-) diff --git a/src/terminal/terminal_handlers.c b/src/terminal/terminal_handlers.c index a4e514c9..ecb60e97 100644 --- a/src/terminal/terminal_handlers.c +++ b/src/terminal/terminal_handlers.c @@ -435,6 +435,133 @@ static bool* __guac_terminal_get_flag(guac_terminal* term, int num, char private } +/** + * Parses an xterm SGR sequence specifying the RGB values of a color. + * + * @param argc + * The number of arguments within the argv array. + * + * @param argv + * The SGR arguments to parse, with the first relevant argument the + * red component of the RGB color. + * + * @param color + * The guac_terminal_color structure which should receive the parsed + * color values. + * + * @return + * The number of arguments parsed, or zero if argv does not contain + * enough elements to represent an RGB color. + */ +static int guac_terminal_parse_xterm256_rgb(int argc, const int* argv, + guac_terminal_color* color) { + + /* RGB color palette entries require three arguments */ + if (argc < 3) + return 0; + + /* Store RGB components */ + color->red = (uint8_t) argv[0]; + color->green = (uint8_t) argv[1]; + color->blue = (uint8_t) argv[2]; + + /* Color is not from the palette */ + color->palette_index = -1; + + /* Done */ + return 3; + +} + +/** + * Parses an xterm SGR sequence specifying the index of a color within the + * 256-color palette. + * + * @param argc + * The number of arguments within the argv array. + * + * @param argv + * The SGR arguments to parse, with the first relevant argument being + * the index of the color. + * + * @param color + * The guac_terminal_color structure which should receive the parsed + * color values. + * + * @return + * The number of arguments parsed, or zero if the palette index is + * out of range or absent. + */ +static int guac_terminal_parse_xterm256_index(int argc, const int* argv, + guac_terminal_color* color) { + + /* 256-color palette entries require only one argument */ + if (argc < 1) + return 0; + + /* Verify palette index bounds */ + int index = argv[0]; + if (index < 0 || index > 255) + return 0; + + /* Copy palette entry */ + *color = guac_terminal_palette[index]; + + /* Done */ + return 1; + +} + +/** + * Parses an xterm SGR sequence specifying the index of a color within the + * 256-color palette, or specfying the RGB values of a color. The number of + * arguments required by these sequences varies. If a 256-color sequence is + * recognized, the number of arguments parsed is returned. + * + * @param argc + * The number of arguments within the argv array. + * + * @param argv + * The SGR arguments to parse, with the first relevant argument being + * the first element of the array. In the case of an xterm 256-color + * SGR sequence, the first element here will be either 2, for an + * RGB color, or 5, for a 256-color palette index. All other values + * are invalid and will not be parsed. + * + * @param color + * The guac_terminal_color structure which should receive the parsed + * color values. + * + * @return + * The number of arguments parsed, or zero if argv does not point to + * the first element of an xterm 256-color SGR sequence. + */ +static int guac_terminal_parse_xterm256(int argc, const int* argv, + guac_terminal_color* color) { + + /* All 256-color codes must have at least a type */ + if (argc < 1) + return 0; + + switch (argv[0]) { + + /* RGB */ + case 2: + return guac_terminal_parse_xterm256_rgb( + argc - 1, &argv[1], color) + 1; + + /* Palette index */ + case 5: + return guac_terminal_parse_xterm256_index( + argc - 1, &argv[1], color) + 1; + + } + + /* Invalid type */ + return 0; + +} + int guac_terminal_csi(guac_terminal* term, unsigned char c) { /* CSI function arguments */ @@ -783,11 +910,27 @@ int guac_terminal_csi(guac_terminal* term, unsigned char c) { term->current_attributes.foreground = guac_terminal_palette[value - 30]; - /* Underscore on, default foreground */ + /* Underscore on, default foreground OR 256-color + * foreground */ else if (value == 38) { - term->current_attributes.underscore = true; - term->current_attributes.foreground = - term->default_char.attributes.foreground; + + /* Attempt to set foreground with 256-color entry */ + int xterm256_length = + guac_terminal_parse_xterm256(argc - 1, &argv[i + 1], + &term->current_attributes.foreground); + + /* If valid 256-color entry, foreground has been set */ + if (xterm256_length > 0) + i += xterm256_length; + + /* Otherwise interpret as underscore and default + * foreground */ + else { + term->current_attributes.underscore = true; + term->current_attributes.foreground = + term->default_char.attributes.foreground; + } + } /* Underscore off, default foreground */ @@ -802,6 +945,11 @@ int guac_terminal_csi(guac_terminal* term, unsigned char c) { term->current_attributes.background = guac_terminal_palette[value - 40]; + /* 256-color background */ + else if (value == 48) + i += guac_terminal_parse_xterm256(argc - 1, &argv[i + 1], + &term->current_attributes.background); + /* Reset background */ else if (value == 49) term->current_attributes.background = From 19f7424c6221f08314ba3fce2745c28162427adc Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Apr 2017 12:58:32 -0700 Subject: [PATCH 5/8] GUACAMOLE-278: Log unhandled/invalid sequences at DEBUG level. --- src/terminal/terminal_handlers.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/terminal/terminal_handlers.c b/src/terminal/terminal_handlers.c index ecb60e97..7f7aee86 100644 --- a/src/terminal/terminal_handlers.c +++ b/src/terminal/terminal_handlers.c @@ -367,7 +367,8 @@ int guac_terminal_escape(guac_terminal* term, unsigned char c) { break; default: - guac_client_log(term->client, GUAC_LOG_INFO, "Unhandled ESC sequence: %c", c); + guac_client_log(term->client, GUAC_LOG_DEBUG, + "Unhandled ESC sequence: %c", c); term->char_handler = guac_terminal_echo; } @@ -1011,11 +1012,11 @@ int guac_terminal_csi(guac_terminal* term, unsigned char c) { default: if (c != ';') { - guac_client_log(term->client, GUAC_LOG_INFO, + guac_client_log(term->client, GUAC_LOG_DEBUG, "Unhandled CSI sequence: %c", c); for (i=0; iclient, GUAC_LOG_INFO, + guac_client_log(term->client, GUAC_LOG_DEBUG, " -> argv[%i] = %i", i, argv[i]); } @@ -1182,7 +1183,8 @@ int guac_terminal_osc(guac_terminal* term, unsigned char c) { /* Stop on unrecognized character */ else { - guac_client_log(term->client, GUAC_LOG_INFO, "Unexpected character in OSC: 0x%X", c); + guac_client_log(term->client, GUAC_LOG_DEBUG, + "Unexpected character in OSC: 0x%X", c); term->char_handler = guac_terminal_echo; } From e4ce7b0eeb07b326b4fec013fcee9e90f72b0b6f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Apr 2017 13:36:46 -0700 Subject: [PATCH 6/8] GUACAMOLE-278: Ignore 256-color SGR sequences which contain out-of-range values. --- src/terminal/terminal_handlers.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/terminal/terminal_handlers.c b/src/terminal/terminal_handlers.c index 7f7aee86..defca4b4 100644 --- a/src/terminal/terminal_handlers.c +++ b/src/terminal/terminal_handlers.c @@ -461,10 +461,21 @@ static int guac_terminal_parse_xterm256_rgb(int argc, const int* argv, if (argc < 3) return 0; + /* Read RGB components from arguments */ + int red = argv[0]; + int green = argv[1]; + int blue = argv[2]; + + /* Ignore if components are out of range */ + if ( red < 0 || red > 255 + || green < 0 || green > 255 + || blue < 0 || blue > 255) + return 3; + /* Store RGB components */ - color->red = (uint8_t) argv[0]; - color->green = (uint8_t) argv[1]; - color->blue = (uint8_t) argv[2]; + color->red = (uint8_t) red; + color->green = (uint8_t) green; + color->blue = (uint8_t) blue; /* Color is not from the palette */ color->palette_index = -1; @@ -491,7 +502,7 @@ static int guac_terminal_parse_xterm256_rgb(int argc, const int* argv, * * @return * The number of arguments parsed, or zero if the palette index is - * out of range or absent. + * absent. */ static int guac_terminal_parse_xterm256_index(int argc, const int* argv, guac_terminal_color* color) { @@ -500,10 +511,10 @@ static int guac_terminal_parse_xterm256_index(int argc, const int* argv, if (argc < 1) return 0; - /* Verify palette index bounds */ + /* Ignore if palette index is out of bounds */ int index = argv[0]; if (index < 0 || index > 255) - return 0; + return 1; /* Copy palette entry */ *color = guac_terminal_palette[index]; From 10180095d8ff1618412843338ed5493c96ec2b32 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Apr 2017 13:59:03 -0700 Subject: [PATCH 7/8] GUACAMOLE-278: Handle (but ignore) xterm's 256-color palette redefinition OSC. --- src/terminal/terminal/terminal_handlers.h | 12 ++++++++++++ src/terminal/terminal_handlers.c | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/terminal/terminal/terminal_handlers.h b/src/terminal/terminal/terminal_handlers.h index cc976862..0a8fdcef 100644 --- a/src/terminal/terminal/terminal_handlers.h +++ b/src/terminal/terminal/terminal_handlers.h @@ -138,6 +138,18 @@ int guac_terminal_open_pipe_stream(guac_terminal* term, unsigned char c); */ int guac_terminal_close_pipe_stream(guac_terminal* term, unsigned char c); +/** + * Parses the remainder of xterm's OSC sequence for redefining the terminal + * emulator's palette. + * + * @param term + * The terminal that received the given character of data. + * + * @param c + * The character that was received by the given terminal. + */ +int guac_terminal_xterm_palette(guac_terminal* term, unsigned char c); + /** * Handles the remaining characters of an Operating System Code (OSC) sequence, * typically initiated with "ESC ]". diff --git a/src/terminal/terminal_handlers.c b/src/terminal/terminal_handlers.c index defca4b4..8e83fb11 100644 --- a/src/terminal/terminal_handlers.c +++ b/src/terminal/terminal_handlers.c @@ -1156,6 +1156,19 @@ int guac_terminal_close_pipe_stream(guac_terminal* term, unsigned char c) { } +int guac_terminal_xterm_palette(guac_terminal* term, unsigned char c) { + + /* NOTE: Currently unimplemented. Attempts to set the 256-color palette + * are ignored. */ + + /* Stop on ECMA-48 ST (String Terminator */ + if (c == 0x9C || c == 0x5C || c == 0x07) + term->char_handler = guac_terminal_echo; + + return 0; + +} + int guac_terminal_osc(guac_terminal* term, unsigned char c) { static int operation = 0; @@ -1183,6 +1196,10 @@ int guac_terminal_osc(guac_terminal* term, unsigned char c) { else if (operation == 482203) term->char_handler = guac_terminal_close_pipe_stream; + /* xterm 256-color palette redefinition */ + else if (operation == 4) + term->char_handler = guac_terminal_xterm_palette; + /* Reset parameter for next OSC */ operation = 0; From a04022883caaa616e4ae5334a5beccf079043a4b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Apr 2017 17:32:33 -0700 Subject: [PATCH 8/8] GUACAMOLE-278: Provide constants defining locations of dark vs. intense colors in 16-color palette. --- src/terminal/display.c | 8 +++++--- src/terminal/terminal/palette.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/terminal/display.c b/src/terminal/display.c index 8d2b1311..cd9f6a6d 100644 --- a/src/terminal/display.c +++ b/src/terminal/display.c @@ -118,9 +118,11 @@ int __guac_terminal_set_colors(guac_terminal_display* display, } /* Handle bold */ - if (attributes->bold && foreground->palette_index >= 0 - && foreground->palette_index <= 7) { - foreground = &guac_terminal_palette[foreground->palette_index + 8]; + if (attributes->bold + && foreground->palette_index >= GUAC_TERMINAL_FIRST_DARK + && foreground->palette_index <= GUAC_TERMINAL_LAST_DARK) { + foreground = &guac_terminal_palette[foreground->palette_index + + GUAC_TERMINAL_INTENSE_OFFSET]; } display->glyph_foreground = *foreground; diff --git a/src/terminal/terminal/palette.h b/src/terminal/terminal/palette.h index 10163688..b18038fb 100644 --- a/src/terminal/terminal/palette.h +++ b/src/terminal/terminal/palette.h @@ -105,6 +105,36 @@ */ #define GUAC_TERMINAL_COLOR_WHITE 15 +/** + * The index of the first low-intensity color in the 16-color portion of the + * palette. + */ +#define GUAC_TERMINAL_FIRST_DARK 0 + +/** + * The index of the last low-intensity color in the 16-color portion of the + * palette. + */ +#define GUAC_TERMINAL_LAST_DARK 7 + +/** + * The index of the first high-intensity color in the 16-color portion of the + * palette. + */ +#define GUAC_TERMINAL_FIRST_INTENSE 8 + +/** + * The index of the last high-intensity color in the 16-color portion of the + * palette. + */ +#define GUAC_TERMINAL_LAST_INTENSE 15 + +/** + * The distance between the palette indices of the dark colors (0 through 7) + * and the bright colors (8 - 15) in the 16-color portion of the palette. + */ +#define GUAC_TERMINAL_INTENSE_OFFSET 8 + /** * An RGB color, where each component ranges from 0 to 255. */