GUACAMOLE-278: Copy terminal color values rather than referencing only by palette index.

This commit is contained in:
Michael Jumper 2017-04-23 11:02:25 -07:00
parent 69caa9936b
commit 48fc4afc5b
7 changed files with 124 additions and 73 deletions

View File

@ -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;
}

View File

@ -39,24 +39,24 @@
const guac_terminal_color guac_terminal_palette[16] = { const guac_terminal_color guac_terminal_palette[16] = {
/* Normal colors */ /* Normal colors */
{0x00, 0x00, 0x00}, /* Black */ {0, 0x00, 0x00, 0x00}, /* Black */
{0x99, 0x3E, 0x3E}, /* Red */ {1, 0x99, 0x3E, 0x3E}, /* Red */
{0x3E, 0x99, 0x3E}, /* Green */ {2, 0x3E, 0x99, 0x3E}, /* Green */
{0x99, 0x99, 0x3E}, /* Brown */ {3, 0x99, 0x99, 0x3E}, /* Brown */
{0x3E, 0x3E, 0x99}, /* Blue */ {4, 0x3E, 0x3E, 0x99}, /* Blue */
{0x99, 0x3E, 0x99}, /* Magenta */ {5, 0x99, 0x3E, 0x99}, /* Magenta */
{0x3E, 0x99, 0x99}, /* Cyan */ {6, 0x3E, 0x99, 0x99}, /* Cyan */
{0x99, 0x99, 0x99}, /* White */ {7, 0x99, 0x99, 0x99}, /* White */
/* Intense colors */ /* Intense colors */
{0x3E, 0x3E, 0x3E}, /* Black */ {8, 0x3E, 0x3E, 0x3E}, /* Black */
{0xFF, 0x67, 0x67}, /* Red */ {9, 0xFF, 0x67, 0x67}, /* Red */
{0x67, 0xFF, 0x67}, /* Green */ {10, 0x67, 0xFF, 0x67}, /* Green */
{0xFF, 0xFF, 0x67}, /* Brown */ {11, 0xFF, 0xFF, 0x67}, /* Brown */
{0x67, 0x67, 0xFF}, /* Blue */ {12, 0x67, 0x67, 0xFF}, /* Blue */
{0xFF, 0x67, 0xFF}, /* Magenta */ {13, 0xFF, 0x67, 0xFF}, /* Magenta */
{0x67, 0xFF, 0xFF}, /* Cyan */ {14, 0x67, 0xFF, 0xFF}, /* Cyan */
{0xFF, 0xFF, 0xFF}, /* White */ {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, int __guac_terminal_set_colors(guac_terminal_display* display,
guac_terminal_attributes* attributes) { guac_terminal_attributes* attributes) {
int background, foreground; const guac_terminal_color* background;
const guac_terminal_color* foreground;
/* Handle reverse video */ /* Handle reverse video */
if (attributes->reverse != attributes->cursor) { if (attributes->reverse != attributes->cursor) {
background = attributes->foreground; background = &attributes->foreground;
foreground = attributes->background; foreground = &attributes->background;
} }
else { else {
foreground = attributes->foreground; foreground = &attributes->foreground;
background = attributes->background; background = &attributes->background;
} }
/* Handle bold */ /* Handle bold */
if (attributes->bold && foreground <= 7) if (attributes->bold && foreground->palette_index >= 0
foreground += 8; && foreground->palette_index <= 7) {
foreground = &guac_terminal_palette[foreground->palette_index + 8];
}
display->glyph_foreground = foreground; display->glyph_foreground = *foreground;
display->glyph_background = background; display->glyph_background = *background;
return 0; return 0;
@ -163,12 +166,10 @@ int __guac_terminal_set(guac_terminal_display* display, int row, int col, int co
char utf8[4]; char utf8[4];
/* Use foreground color */ /* Use foreground color */
const guac_terminal_color* color = const guac_terminal_color* color = &display->glyph_foreground;
&guac_terminal_palette[display->glyph_foreground];
/* Use background color */ /* Use background color */
const guac_terminal_color* background = const guac_terminal_color* background = &display->glyph_background;
&guac_terminal_palette[display->glyph_background];
cairo_surface_t* surface; cairo_surface_t* surface;
cairo_t* cairo; 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, guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
const char* font_name, int font_size, int dpi, const char* font_name, int font_size, int dpi,
int foreground, int background) { guac_terminal_color* foreground, guac_terminal_color* background) {
PangoFontMap* font_map; PangoFontMap* font_map;
PangoFont* font; PangoFont* font;
@ -303,8 +304,8 @@ guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
return NULL; return NULL;
} }
display->default_foreground = display->glyph_foreground = foreground; display->default_foreground = display->glyph_foreground = *foreground;
display->default_background = display->glyph_background = background; display->default_background = display->glyph_background = *background;
/* Calculate character dimensions */ /* Calculate character dimensions */
display->char_width = display->char_width =
@ -688,14 +689,11 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) {
int rect_width, rect_height; int rect_width, rect_height;
/* Color of the rectangle to draw */ /* Color of the rectangle to draw */
int color; const guac_terminal_color* color;
if (current->character.attributes.reverse != current->character.attributes.cursor) if (current->character.attributes.reverse != current->character.attributes.cursor)
color = current->character.attributes.foreground; color = &current->character.attributes.foreground;
else else
color = current->character.attributes.background; color = &current->character.attributes.background;
const guac_terminal_color* guac_color =
&guac_terminal_palette[color];
/* Current row within a subrect */ /* Current row within a subrect */
guac_terminal_operation* rect_current_row; guac_terminal_operation* rect_current_row;
@ -709,16 +707,16 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) {
/* Find width */ /* Find width */
for (rect_col=col; rect_col<display->width; rect_col++) { for (rect_col=col; rect_col<display->width; rect_col++) {
int joining_color; const guac_terminal_color* joining_color;
if (rect_current->character.attributes.reverse != rect_current->character.attributes.cursor) 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 else
joining_color = rect_current->character.attributes.background; joining_color = &rect_current->character.attributes.background;
/* If not identical operation, stop */ /* If not identical operation, stop */
if (rect_current->type != GUAC_CHAR_SET if (rect_current->type != GUAC_CHAR_SET
|| guac_terminal_has_glyph(rect_current->character.value) || guac_terminal_has_glyph(rect_current->character.value)
|| joining_color != color) || guac_terminal_colorcmp(joining_color, color) != 0)
break; break;
/* Next column */ /* Next column */
@ -754,16 +752,16 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) {
for (rect_col=0; rect_col<rect_width; rect_col++) { for (rect_col=0; rect_col<rect_width; rect_col++) {
int joining_color; const guac_terminal_color* joining_color;
if (rect_current->character.attributes.reverse != rect_current->character.attributes.cursor) 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 else
joining_color = rect_current->character.attributes.background; joining_color = &rect_current->character.attributes.background;
/* Mark clear operations as NOP */ /* Mark clear operations as NOP */
if (rect_current->type == GUAC_CHAR_SET if (rect_current->type == GUAC_CHAR_SET
&& !guac_terminal_has_glyph(rect_current->character.value) && !guac_terminal_has_glyph(rect_current->character.value)
&& joining_color == color) && guac_terminal_colorcmp(joining_color, color) == 0)
rect_current->type = GUAC_CHAR_NOP; rect_current->type = GUAC_CHAR_NOP;
/* Next column */ /* Next column */
@ -783,7 +781,7 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) {
row * display->char_height, row * display->char_height,
rect_width * display->char_width, rect_width * display->char_width,
rect_height * display->char_height, rect_height * display->char_height,
guac_color->red, guac_color->green, guac_color->blue, color->red, color->green, color->blue,
0xFF); 0xFF);
} /* end if clear operation */ } /* end if clear operation */

View File

@ -205,8 +205,7 @@ static void guac_terminal_repaint_default_layer(guac_terminal* terminal,
guac_terminal_display* display = terminal->display; guac_terminal_display* display = terminal->display;
/* Get background color */ /* Get background color */
const guac_terminal_color* color = const guac_terminal_color* color = &display->default_background;
&guac_terminal_palette[display->default_background];
/* Reset size */ /* Reset size */
guac_protocol_send_size(socket, GUAC_DEFAULT_LAYER, width, height); 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 = { guac_terminal_char default_char = {
.value = 0, .value = 0,
.attributes = { .attributes = {
.foreground = default_foreground, .foreground = guac_terminal_palette[default_foreground],
.background = default_background, .background = guac_terminal_palette[default_background],
.bold = false, .bold = false,
.reverse = false, .reverse = false,
.underscore = false .underscore = false
@ -326,8 +325,8 @@ guac_terminal* guac_terminal_create(guac_client* client,
/* Init display */ /* Init display */
term->display = guac_terminal_display_alloc(client, term->display = guac_terminal_display_alloc(client,
font_name, font_size, dpi, font_name, font_size, dpi,
default_char.attributes.foreground, &default_char.attributes.foreground,
default_char.attributes.background); &default_char.attributes.background);
/* Fail if display init failed */ /* Fail if display init failed */
if (term->display == NULL) { if (term->display == NULL) {
@ -875,17 +874,18 @@ static bool guac_terminal_is_visible(guac_terminal* term,
if (guac_terminal_has_glyph(c->value)) if (guac_terminal_has_glyph(c->value))
return true; return true;
int background; const guac_terminal_color* background;
/* Determine actual background color of character */ /* Determine actual background color of character */
if (c->attributes.reverse != c->attributes.cursor) if (c->attributes.reverse != c->attributes.cursor)
background = c->attributes.foreground; background = &c->attributes.foreground;
else else
background = c->attributes.background; background = &c->attributes.background;
/* Blank characters are visible if their background color differs from that /* Blank characters are visible if their background color differs from that
* of the terminal */ * of the terminal */
return background != term->default_char.attributes.background; return guac_terminal_colorcmp(background,
&term->default_char.attributes.background) != 0;
} }

View File

@ -22,6 +22,7 @@
#define _GUAC_TERMINAL_COMMON_H #define _GUAC_TERMINAL_COMMON_H
#include "config.h" #include "config.h"
#include "types.h"
#include <stdbool.h> #include <stdbool.h>
@ -49,5 +50,26 @@ bool guac_terminal_has_glyph(int codepoint);
*/ */
int guac_terminal_write_all(int fd, const char* buffer, int size); 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 #endif

View File

@ -220,22 +220,24 @@ typedef struct guac_terminal_display {
/** /**
* Default foreground color for all glyphs. * Default foreground color for all glyphs.
*/ */
int default_foreground; guac_terminal_color default_foreground;
/** /**
* Default background color for all glyphs and the terminal itself. * 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. * 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, guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
const char* font_name, int font_size, int dpi, 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. * Frees the given display.

View File

@ -24,6 +24,7 @@
#include "config.h" #include "config.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
/** /**
* A character which is not truly a character, but rather part of an * A character which is not truly a character, but rather part of an
@ -39,20 +40,26 @@
*/ */
typedef struct guac_terminal_color { 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. * The red component of this color.
*/ */
int red; uint8_t red;
/** /**
* The green component of this color. * The green component of this color.
*/ */
int green; uint8_t green;
/** /**
* The blue component of this color. * The blue component of this color.
*/ */
int blue; uint8_t blue;
} guac_terminal_color; } guac_terminal_color;
@ -83,14 +90,14 @@ typedef struct guac_terminal_attributes {
bool underscore; 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; } guac_terminal_attributes;

View File

@ -779,7 +779,8 @@ int guac_terminal_csi(guac_terminal* term, unsigned char c) {
/* Foreground */ /* Foreground */
else if (value >= 30 && value <= 37) 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 */ /* Underscore on, default foreground */
else if (value == 38) { else if (value == 38) {
@ -797,7 +798,8 @@ int guac_terminal_csi(guac_terminal* term, unsigned char c) {
/* Background */ /* Background */
else if (value >= 40 && value <= 47) else if (value >= 40 && value <= 47)
term->current_attributes.background = value - 40; term->current_attributes.background =
guac_terminal_palette[value - 40];
/* Reset background */ /* Reset background */
else if (value == 49) else if (value == 49)