From 507005ca549a4f6b7c45c1c27b4a219ca6b03f7e Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Mon, 2 Dec 2013 22:38:11 +0100 Subject: [PATCH 1/4] Rename utils_strtod() to utils_parse_color() Rename the function to a more sensible name, and remove unnecessary arguments. Now, format (# or 0x) is auto-detected. --- src/highlighting.c | 2 +- src/sciwrappers.c | 2 +- src/utils.c | 33 ++++++++++++++------------------- src/utils.h | 2 +- src/win32.c | 2 +- 5 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/highlighting.c b/src/highlighting.c index de7cd431..b45816ab 100644 --- a/src/highlighting.c +++ b/src/highlighting.c @@ -253,7 +253,7 @@ static void parse_color(GKeyFile *kf, const gchar *str, gint *clr) g_free(named_color); - c = utils_strtod(hex_clr, NULL, FALSE); + c = utils_parse_color(hex_clr); if (c > -1) { diff --git a/src/sciwrappers.c b/src/sciwrappers.c index 5baa8edd..80a63665 100644 --- a/src/sciwrappers.c +++ b/src/sciwrappers.c @@ -69,7 +69,7 @@ void sci_set_line_numbers(ScintillaObject *sci, gboolean set, gint extra_width) void sci_set_mark_long_lines(ScintillaObject *sci, gint type, gint column, const gchar *colour) { - glong colour_val = utils_strtod(colour, NULL, TRUE); /* Scintilla uses a "long" value */ + glong colour_val = utils_parse_color(colour); /* Scintilla uses a "long" value */ if (column == 0) type = 2; diff --git a/src/utils.c b/src/utils.c index 9cb7c7ee..3a2b998d 100644 --- a/src/utils.c +++ b/src/utils.c @@ -977,35 +977,30 @@ gchar *utils_make_human_readable_str(guint64 size, gulong block_size, } -/* utils_strtod() converts a string containing a hex colour ("0x00ff00") into an integer. - * Basically, it is the same as strtod() would do, but it does not understand hex colour values, - * before ANSI-C99. With with_route set, it takes strings of the format "#00ff00". - * Returns -1 on failure. */ -gint utils_strtod(const gchar *source, gchar **end, gboolean with_route) +/* Converts a string containing a hex colour ("0x00ff00") into an integer. + * Returns an integer color in the format BBGGRR or -1 on failure. */ +gint utils_parse_color(const gchar *source) { - guint red, green, blue, offset = 0; + guint red, green, blue; g_return_val_if_fail(source != NULL, -1); - if (with_route && (strlen(source) != 7 || source[0] != '#')) + if (source[0] == '#') + source++; + else if (source[0] == '0' && (source[1] == 'x' || source[1] == 'X')) + source += 2; + else return -1; - else if (! with_route && (strlen(source) != 8 || source[0] != '0' || - (source[1] != 'x' && source[1] != 'X'))) - { - return -1; - } - /* offset is set to 1 when the string starts with 0x, otherwise it starts with # - * and we don't need to increase the index */ - if (! with_route) - offset = 1; + if (strlen(source) != 6) + return -1; red = utils_get_value_of_hex( - source[1 + offset]) * 16 + utils_get_value_of_hex(source[2 + offset]); + source[0]) * 16 + utils_get_value_of_hex(source[1]); green = utils_get_value_of_hex( - source[3 + offset]) * 16 + utils_get_value_of_hex(source[4 + offset]); + source[2]) * 16 + utils_get_value_of_hex(source[3]); blue = utils_get_value_of_hex( - source[5 + offset]) * 16 + utils_get_value_of_hex(source[6 + offset]); + source[4]) * 16 + utils_get_value_of_hex(source[5]); return (red | (green << 8) | (blue << 16)); } diff --git a/src/utils.h b/src/utils.h index 4219e65e..c5b8c58c 100644 --- a/src/utils.h +++ b/src/utils.h @@ -220,7 +220,7 @@ void utils_beep(void); gchar *utils_make_human_readable_str(guint64 size, gulong block_size, gulong display_unit); -gint utils_strtod(const gchar *source, gchar **end, gboolean with_route); +gint utils_parse_color(const gchar *source); gchar *utils_get_current_time_string(void); diff --git a/src/win32.c b/src/win32.c index b6aa9c4a..b5a51427 100644 --- a/src/win32.c +++ b/src/win32.c @@ -565,7 +565,7 @@ void win32_show_color_dialog(const gchar *colour) cc.lStructSize = sizeof(cc); cc.hwndOwner = GDK_WINDOW_HWND(gtk_widget_get_window(main_widgets.window)); cc.lpCustColors = (LPDWORD) acr_cust_clr; - cc.rgbResult = (colour != NULL) ? utils_strtod(colour, NULL, colour[0] == '#') : 0; + cc.rgbResult = (colour != NULL) ? utils_parse_color(colour) : 0; cc.Flags = CC_FULLOPEN | CC_RGBINIT; if (ChooseColor(&cc)) From 11a2f0ee91be81991c9d1b3dfe9b8b9680ca3abf Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Mon, 2 Dec 2013 22:44:40 +0100 Subject: [PATCH 2/4] Properly validate input in utils_parse_color() --- src/utils.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/utils.c b/src/utils.c index 3a2b998d..330e79bb 100644 --- a/src/utils.c +++ b/src/utils.c @@ -964,16 +964,17 @@ gchar *utils_make_human_readable_str(guint64 size, gulong block_size, } - static guint utils_get_value_of_hex(const gchar ch) +static gboolean read_hex(const gchar *s, guint len, gint *h) { - if (ch >= '0' && ch <= '9') - return ch - '0'; - else if (ch >= 'A' && ch <= 'F') - return ch - 'A' + 10; - else if (ch >= 'a' && ch <= 'f') - return ch - 'a' + 10; - else - return 0; + guint i; + *h = 0; + for (i = 0; i < len; i++) + { + if (! g_ascii_isxdigit(s[i])) + return FALSE; + *h = (*h << 4) | g_ascii_xdigit_value(s[i]); + } + return TRUE; } @@ -981,7 +982,7 @@ gchar *utils_make_human_readable_str(guint64 size, gulong block_size, * Returns an integer color in the format BBGGRR or -1 on failure. */ gint utils_parse_color(const gchar *source) { - guint red, green, blue; + gint red, green, blue; g_return_val_if_fail(source != NULL, -1); @@ -995,12 +996,10 @@ gint utils_parse_color(const gchar *source) if (strlen(source) != 6) return -1; - red = utils_get_value_of_hex( - source[0]) * 16 + utils_get_value_of_hex(source[1]); - green = utils_get_value_of_hex( - source[2]) * 16 + utils_get_value_of_hex(source[3]); - blue = utils_get_value_of_hex( - source[4]) * 16 + utils_get_value_of_hex(source[5]); + if (! read_hex(source, 2, &red) || + ! read_hex(source + 2, 2, &green) || + ! read_hex(source + 4, 2, &blue)) + return -1; return (red | (green << 8) | (blue << 16)); } From ebde42617a5c4e57ae0d717b56a03201f51e0988 Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Mon, 2 Dec 2013 22:53:35 +0100 Subject: [PATCH 3/4] Accept colors with only 1 digit per channel in utils_parse_color() AKA short HTML color notation. --- src/utils.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/utils.c b/src/utils.c index 330e79bb..279c0169 100644 --- a/src/utils.c +++ b/src/utils.c @@ -978,11 +978,13 @@ static gboolean read_hex(const gchar *s, guint len, gint *h) } -/* Converts a string containing a hex colour ("0x00ff00") into an integer. +/* Converts a string containing an hex or HTML RGB color with 1 or 2 digits per + * channel (0x00ff11, 0x0f1, #00ff11, #0f1) to an integer. * Returns an integer color in the format BBGGRR or -1 on failure. */ gint utils_parse_color(const gchar *source) { - gint red, green, blue; + gint r, g, b; + guint len; g_return_val_if_fail(source != NULL, -1); @@ -993,15 +995,24 @@ gint utils_parse_color(const gchar *source) else return -1; - if (strlen(source) != 6) + len = strlen(source); + if (len % 3 || len < 3 || len > 6) + return -1; + len /= 3; + + if (! read_hex(source, len, &r) || + ! read_hex(source + len, len, &g) || + ! read_hex(source + len * 2, len, &b)) return -1; - if (! read_hex(source, 2, &red) || - ! read_hex(source + 2, 2, &green) || - ! read_hex(source + 4, 2, &blue)) - return -1; + if (len < 2) + { + r |= r << 4; + g |= g << 4; + b |= b << 4; + } - return (red | (green << 8) | (blue << 16)); + return (r | (g << 8) | (b << 16)); } From 3759562d7c3b53b19f363a47413a8b04b75661a7 Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Mon, 2 Dec 2013 22:58:54 +0100 Subject: [PATCH 4/4] Simplify reading highlighting colors with new utils_parse_color() Drop redundant code converting # and short formats to hex colors now utils_parse_color() can parse them. --- src/highlighting.c | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/src/highlighting.c b/src/highlighting.c index b45816ab..ae72cde0 100644 --- a/src/highlighting.c +++ b/src/highlighting.c @@ -219,9 +219,7 @@ static gboolean read_named_style(const gchar *named_style, GeanyLexerStyle *styl static void parse_color(GKeyFile *kf, const gchar *str, gint *clr) { gint c; - gchar hex_clr[9] = { 0 }; gchar *named_color = NULL; - const gchar *start; g_return_if_fail(clr != NULL); @@ -229,38 +227,16 @@ static void parse_color(GKeyFile *kf, const gchar *str, gint *clr) return; named_color = g_key_file_get_string(kf, "named_colors", str, NULL); - if (named_color) + if (named_color) str = named_color; - if (str[0] == '#') - start = str + 1; - else if (strlen(str) > 1 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) - start = str + 2; - else - { + c = utils_parse_color(str); + if (c == -1) geany_debug("Bad color '%s'", str); - g_free(named_color); - return; - } - - if (strlen(start) == 3) - { - g_snprintf(hex_clr, 9, "0x%c%c%c%c%c%c", start[0], start[0], - start[1], start[1], start[2], start[2]); - } else - g_snprintf(hex_clr, 9, "0x%s", start); + *clr = c; g_free(named_color); - - c = utils_parse_color(hex_clr); - - if (c > -1) - { - *clr = c; - return; - } - geany_debug("Bad color '%s'", str); }