Skip to content

Commit

Permalink
Factor out a function to parse color from string
Browse files Browse the repository at this point in the history
Also add some minimum effort error checking/correction as this will soon
be processing a user-entered value. The extant code path should not be
affected as input color values are correctly specified.

Color values can be words or hex values.

Accepted:
- 'black'
- 'white'
- 'blue'
- 'dark blue'
- '0x0000ff'

Rejected with logged error + exit:
- 'nonsense color'
- '0xZZZZZZ'

Related to: QubesOS/qubes-issues#9304
  • Loading branch information
Euwiiwueir committed Jun 22, 2024
1 parent 122f9b4 commit 7e85df2
Showing 1 changed file with 47 additions and 15 deletions.
62 changes: 47 additions & 15 deletions gui-daemon/xside.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,27 +283,59 @@ static int x11_io_error_handler(Display * dpy)
exit(1);
}

/*
* Infer a color value from the provided string using strtoul for
* hex-like input or for a name Xlib by way of /etc/X11/rgb.txt.
*/
static XColor parse_color(const char *str, Display *dpy, int screen)
{
XColor xcolor;
Status status;
char *trimmed = (char *) str;
while (trimmed[0] == ' ') { /* skip any leading spaces */
trimmed++;
}
if (trimmed[0] == '0' && (trimmed[1] == 'x' || trimmed[1] == 'X')) {
char *endptr;
unsigned int rgb;
errno = 0;
rgb = strtoul(trimmed, &endptr, 16);
if (errno) {
perror("strtoul");
fprintf(stderr, "Failed to parse color '%s'\n", trimmed);
exit(1);
} else if (endptr == trimmed ||
/* Note: this check incorrectly rejects the
specific case of trailing space on hex black,
i.e. '0x000000 ' */
(endptr[0] != '\0' && rgb == 0)) {
fprintf(stderr, "Failed to parse color '%s'\n", trimmed);
exit(1);
}
xcolor.blue = (rgb & 0xff) * 257;
rgb >>= 8;
xcolor.green = (rgb & 0xff) * 257;
rgb >>= 8;
xcolor.red = (rgb & 0xff) * 257;
status = XAllocColor(dpy, XDefaultColormap(dpy, screen), &xcolor);
} else {
XColor dummy;
status = XAllocNamedColor(dpy, XDefaultColormap(dpy, screen), trimmed,
&xcolor, &dummy);
}
if (status == 0) {
fprintf(stderr, "Failed to allocate color when parsing '%s'\n", trimmed);
exit(1);
}
return xcolor;
}

/* prepare graphic context for painting colorful frame and set RGB value of the
* color */
static void get_frame_gc(Ghandles * g, const char *name)
{
XGCValues values;
XColor fcolor, dummy;
if (name[0] == '0' && (name[1] == 'x' || name[1] == 'X')) {
unsigned int rgb = strtoul(name, 0, 16);
fcolor.blue = (rgb & 0xff) * 257;
rgb >>= 8;
fcolor.green = (rgb & 0xff) * 257;
rgb >>= 8;
fcolor.red = (rgb & 0xff) * 257;
XAllocColor(g->display,
XDefaultColormap(g->display, g->screen),
&fcolor);
} else
XAllocNamedColor(g->display,
XDefaultColormap(g->display, g->screen),
name, &fcolor, &dummy);
XColor fcolor = parse_color(name, g->display, g->screen);
g->label_color_rgb =
(fcolor.red >> 8) << 16 |
(fcolor.green >> 8) << 8 |
Expand Down

0 comments on commit 7e85df2

Please sign in to comment.