From 27cf97cb9e08e3ba4093c573b61c1a71e547c890 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 10 Jul 2017 21:38:12 -0700 Subject: [PATCH] GUACAMOLE-279: Handle xterm palette assignments, parsing each color as an X11 color spec. --- src/terminal/Makefile.am | 6 ++- src/terminal/terminal/xparsecolor.h | 48 +++++++++++++++++++ src/terminal/terminal_handlers.c | 73 ++++++++++++++++++++++++++++- src/terminal/xparsecolor.c | 70 +++++++++++++++++++++++++++ 4 files changed, 193 insertions(+), 4 deletions(-) create mode 100644 src/terminal/terminal/xparsecolor.h create mode 100644 src/terminal/xparsecolor.c diff --git a/src/terminal/Makefile.am b/src/terminal/Makefile.am index b3474605..c7cedbba 100644 --- a/src/terminal/Makefile.am +++ b/src/terminal/Makefile.am @@ -32,7 +32,8 @@ noinst_HEADERS = \ terminal/terminal.h \ terminal/terminal_handlers.h \ terminal/types.h \ - terminal/typescript.h + terminal/typescript.h \ + terminal/xparsecolor.h libguac_terminal_la_SOURCES = \ buffer.c \ @@ -43,7 +44,8 @@ libguac_terminal_la_SOURCES = \ scrollbar.c \ terminal.c \ terminal_handlers.c \ - typescript.c + typescript.c \ + xparsecolor.c libguac_terminal_la_CFLAGS = \ -Werror -Wall \ diff --git a/src/terminal/terminal/xparsecolor.h b/src/terminal/terminal/xparsecolor.h new file mode 100644 index 00000000..7cb2fcaa --- /dev/null +++ b/src/terminal/terminal/xparsecolor.h @@ -0,0 +1,48 @@ +/* + * 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_XPARSECOLOR_H +#define GUAC_TERMINAL_XPARSECOLOR_H + +#include "config.h" + +#include "terminal/palette.h" + +/** + * Parses an X11 color spec, as defined by Xlib's XParseColor(), storing the + * result in the provided guac_terminal_color structure. If the color spec is + * not valid, the provided guac_terminal_color is not touched. + * + * Currently, only the "rgb:*" format color specs are supported. + * + * @param spec + * The X11 color spec to parse. + * + * @param color + * A pointer to the guac_terminal_color structure which should receive the + * parsed result. + * + * @returns + * Zero if the color spec was successfully parsed, non-zero otherwise. + */ +int guac_terminal_xparsecolor(const char* spec, + guac_terminal_color* color); + +#endif + diff --git a/src/terminal/terminal_handlers.c b/src/terminal/terminal_handlers.c index 6f013a21..02e9f9df 100644 --- a/src/terminal/terminal_handlers.c +++ b/src/terminal/terminal_handlers.c @@ -24,6 +24,7 @@ #include "terminal/terminal.h" #include "terminal/terminal_handlers.h" #include "terminal/types.h" +#include "terminal/xparsecolor.h" #include #include @@ -1212,8 +1213,76 @@ int guac_terminal_window_title(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. */ + /** + * Whether we are currently reading the color spec. If false, we are + * currently reading the color index. + */ + static bool read_color_spec = false; + + /** + * The index of the palette entry being modified. + */ + static int index = 0; + + /** + * The color spec string, valid only if read_color_spec is true. + */ + static char color_spec[256]; + + /** + * The current position within the color spec string, valid only if + * read_color_spec is true. + */ + static int color_spec_pos = 0; + + /* If not reading the color spec, parse the index */ + if (!read_color_spec) { + + /* If digit, append to index */ + if (c >= '0' && c <= '9') + index = index * 10 + c - '0'; + + /* If end of parameter, switch to reading the color */ + else if (c == ';') { + read_color_spec = true; + color_spec_pos = 0; + } + + } + + /* Once the index has been parsed, read the color spec */ + else { + + /* Modify palette once index/spec pair has been read */ + if (c == ';' || c == 0x9C || c == 0x5C || c == 0x07) { + + guac_terminal_color color; + + /* Terminate color spec string */ + color_spec[color_spec_pos] = '\0'; + + /* Modify palette if color spec is valid */ + if (!guac_terminal_xparsecolor(color_spec, &color)) + guac_terminal_display_assign_color(term->display, + index, &color); + else + guac_client_log(term->client, GUAC_LOG_DEBUG, + "Invalid XParseColor() color spec: \"%s\"", + color_spec); + + /* Resume parsing index */ + read_color_spec = false; + index = 0; + + } + + /* Append characters to color spec as long as available space is not + * exceeded */ + else if (color_spec_pos < 255) { + color_spec[color_spec_pos++] = c; + } + + } /* Stop on ECMA-48 ST (String Terminator */ if (c == 0x9C || c == 0x5C || c == 0x07) diff --git a/src/terminal/xparsecolor.c b/src/terminal/xparsecolor.c new file mode 100644 index 00000000..740f2b41 --- /dev/null +++ b/src/terminal/xparsecolor.c @@ -0,0 +1,70 @@ +/* + * 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/named-colors.h" +#include "terminal/palette.h" + +#include + +int guac_terminal_xparsecolor(const char* spec, + guac_terminal_color* color) { + + int red; + int green; + int blue; + + /* 12-bit RGB ("rgb:h/h/h"), zero-padded to 24-bit */ + if (sscanf(spec, "rgb:%1x/%1x/%1x", &red, &green, &blue) == 3) { + color->red = red << 4; + color->green = green << 4; + color->blue = blue << 4; + return 0; + } + + /* 24-bit RGB ("rgb:hh/hh/hh") */ + if (sscanf(spec, "rgb:%2x/%2x/%2x", &red, &green, &blue) == 3) { + color->red = red; + color->green = green; + color->blue = blue; + return 0; + } + + /* 36-bit RGB ("rgb:hhh/hhh/hhh"), truncated to 24-bit */ + if (sscanf(spec, "rgb:%3x/%3x/%3x", &red, &green, &blue) == 3) { + color->red = red >> 4; + color->green = green >> 4; + color->blue = blue >> 4; + return 0; + } + + /* 48-bit RGB ("rgb:hhhh/hhhh/hhhh"), truncated to 24-bit */ + if (sscanf(spec, "rgb:%4x/%4x/%4x", &red, &green, &blue) == 3) { + color->red = red >> 8; + color->green = green >> 8; + color->blue = blue >> 8; + return 0; + } + + /* Invalid color spec */ + return 1; + +} +