From c871e6fab6382d4a46ec0c410386041a8aadef65 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Wed, 9 Mar 2022 20:29:53 -0500 Subject: [PATCH] Make tile colours configurable via X resources. --- Makefile.am | 2 +- src/colour.h | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/ewmhicon.c | 1 + src/ewmhicon.h | 2 -- src/motif.c | 2 +- src/motif.h | 3 +- src/x11.c | 72 +++++++++++++++++++++++++++++++------------- t/ewmhicon.c | 24 ++++++++++----- 8 files changed, 153 insertions(+), 34 deletions(-) create mode 100644 src/colour.h diff --git a/Makefile.am b/Makefile.am index cab8d28..26111a3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,7 @@ bin_PROGRAMS = rrace-motif endif rrace_motif_SOURCES = src/game.c src/x11.c src/game.h src/motif.h \ - src/ewmhicon.c src/ewmhicon.h + src/colour.h src/ewmhicon.c src/ewmhicon.h rrace_motif_LDADD = $(libmotifmain_a_OBJECTS) $(libmotifui_a_OBJECTS) \ $(libglohelp_a_OBJECTS) libgnu.a $(MOTIF_LIBS) $(rrace_motif_OBJECTS): $(gnulib_headers) diff --git a/src/colour.h b/src/colour.h new file mode 100644 index 0000000..1bad607 --- /dev/null +++ b/src/colour.h @@ -0,0 +1,81 @@ +/* + * Colour definitions for slide puzzle game. + * Copyright © 2022 Nick Bowler + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef RRACE_COLOUR_H_ +#define RRACE_COLOUR_H_ + +enum { COLOUR_PRIMARY, COLOUR_DARK, COLOUR_LIGHT, COLOUR_MAX }; + +#define COLOUR_X11_(r, g, b) "#"#r#g#b +#define COLOUR_X11(c) COLOUR_X11_ c + +/* red */ +#define COLOUR0_PRIMARY_RGB_ (8d, 2e, 28) +#define COLOUR0_LIGHT_RGB_ (a1, 48, 42) +#define COLOUR0_DARK_RGB_ (6a, 1b, 17) + +#define COLOUR0_PRIMARY COLOUR_X11(COLOUR0_PRIMARY_RGB_) +#define COLOUR0_LIGHT COLOUR_X11(COLOUR0_LIGHT_RGB_) +#define COLOUR0_DARK COLOUR_X11(COLOUR0_DARK_RGB_) + +/* orange */ +#define COLOUR1_PRIMARY_RGB_ (b4, 6e, 28) +#define COLOUR1_LIGHT_RGB_ (c7, 90, 4f) +#define COLOUR1_DARK_RGB_ (92, 4a, 16) + +#define COLOUR1_PRIMARY COLOUR_X11(COLOUR1_PRIMARY_RGB_) +#define COLOUR1_LIGHT COLOUR_X11(COLOUR1_LIGHT_RGB_) +#define COLOUR1_DARK COLOUR_X11(COLOUR1_DARK_RGB_) + +/* yellow */ +#define COLOUR2_PRIMARY_RGB_ (d8, b7, 40) +#define COLOUR2_LIGHT_RGB_ (e2, c6, 5d) +#define COLOUR2_DARK_RGB_ (c5, 9f, 39) + +#define COLOUR2_PRIMARY COLOUR_X11(COLOUR2_PRIMARY_RGB_) +#define COLOUR2_LIGHT COLOUR_X11(COLOUR2_LIGHT_RGB_) +#define COLOUR2_DARK COLOUR_X11(COLOUR2_DARK_RGB_) + +/* green */ +#define COLOUR3_PRIMARY_RGB_ (28, 64, 28) +#define COLOUR3_DARK_RGB_ (19, 47, 19) +#define COLOUR3_LIGHT_RGB_ (4e, 87, 4e) + +#define COLOUR3_PRIMARY COLOUR_X11(COLOUR3_PRIMARY_RGB_) +#define COLOUR3_LIGHT COLOUR_X11(COLOUR3_LIGHT_RGB_) +#define COLOUR3_DARK COLOUR_X11(COLOUR3_DARK_RGB_) + +/* blue */ +#define COLOUR4_PRIMARY_RGB_ (00, 34, 71) +#define COLOUR4_DARK_RGB_ (00, 1f, 4f) +#define COLOUR4_LIGHT_RGB_ (00, 52, 8b) + +#define COLOUR4_PRIMARY COLOUR_X11(COLOUR4_PRIMARY_RGB_) +#define COLOUR4_LIGHT COLOUR_X11(COLOUR4_LIGHT_RGB_) +#define COLOUR4_DARK COLOUR_X11(COLOUR4_DARK_RGB_) + +/* white */ +#define COLOUR5_PRIMARY_RGB_ (dc, dc, dc) +#define COLOUR5_LIGHT_RGB_ (ea, ea, ea) +#define COLOUR5_DARK_RGB_ (c0, c0, c0) + +#define COLOUR5_PRIMARY COLOUR_X11(COLOUR5_PRIMARY_RGB_) +#define COLOUR5_LIGHT COLOUR_X11(COLOUR5_LIGHT_RGB_) +#define COLOUR5_DARK COLOUR_X11(COLOUR5_DARK_RGB_) + +#endif diff --git a/src/ewmhicon.c b/src/ewmhicon.c index 087dc46..6bdf8e9 100644 --- a/src/ewmhicon.c +++ b/src/ewmhicon.c @@ -26,6 +26,7 @@ # include #endif #include "ewmhicon.h" +#include "colour.h" static unsigned long scale16to8(unsigned x) { diff --git a/src/ewmhicon.h b/src/ewmhicon.h index d073067..bf0dfd6 100644 --- a/src/ewmhicon.h +++ b/src/ewmhicon.h @@ -36,8 +36,6 @@ typedef struct stub_widget *Widget; #endif -enum { COLOUR_PRIMARY, COLOUR_DARK, COLOUR_LIGHT, COLOUR_MAX }; - /* * Helpers for drawing window icons in various sizes. The tileXX functions * draw one (out of 9) tiles at a particular size using a particular colour diff --git a/src/motif.c b/src/motif.c index a829cf7..75a985b 100644 --- a/src/motif.c +++ b/src/motif.c @@ -162,7 +162,7 @@ static XtAppContext app_initialize(int argc, char **argv) shell = early_setup(&app, argc, argv); XtAppAddActions(app, (void *)menu_actions, XtNumber(menu_actions)); ui_initialize(&state, shell); - x11_initialize(&state, XtScreen(shell)); + x11_initialize(&state, shell); game_reset(&state.board); state.use_ewmh_icons = ewmh_probe_wm_icon(shell); XtRealizeWidget(shell); diff --git a/src/motif.h b/src/motif.h index 3e85277..406b087 100644 --- a/src/motif.h +++ b/src/motif.h @@ -21,6 +21,7 @@ #include #include "ewmhicon.h" +#include "colour.h" #include "game.h" struct app_state { @@ -37,7 +38,7 @@ struct app_state { }; void ui_initialize(struct app_state *state, Widget shell); -void x11_initialize(struct app_state *state, Screen *screen); +void x11_initialize(struct app_state *state, Widget shell); void x11_redraw_icon(struct app_state *state, Widget shell); void x11_redraw_goal(struct app_state *state, uint_fast32_t mask); void x11_redraw_game(struct app_state *state, uint_fast32_t mask); diff --git a/src/x11.c b/src/x11.c index caf3518..ea0fdba 100644 --- a/src/x11.c +++ b/src/x11.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -30,40 +31,69 @@ /* Size of the traditional icon pixmap (multiple of 3) */ #define ICON_SIZE 48 -/* TODO user-selectable colours */ -static const char * const colours[][3] = { - /*primary bottom top */ - "#8d2e28", "#6a1b17", "#a14842", /* red */ - "#b46e28", "#924a16", "#c7904f", /* orange */ - "#d8b740", "#c59f39", "#e2c65d", /* yellow */ - "#286428", "#194719", "#4e874e", /* green */ - "#003471", "#001f4f", "#00528b", /* blue */ - "#dcdcdc", "#c0c0c0", "#eaeaea", /* white */ +typedef String colour_tab[COLOUR_MAX*(TILE_MAX-1)]; + +#define COLOURRES(name, index, def) { \ + (name), (NULL), XtRString, sizeof (String), \ + offsetof(struct { colour_tab t; }, t[index]), \ + XtRString, (def) } + +static XtResource colour_resources[] = { + COLOURRES("colour0", 0, COLOUR0_PRIMARY), + COLOURRES("colour1", 1, COLOUR1_PRIMARY), + COLOURRES("colour2", 2, COLOUR2_PRIMARY), + COLOURRES("colour3", 3, COLOUR3_PRIMARY), + COLOURRES("colour4", 4, COLOUR4_PRIMARY), + COLOURRES("colour5", 5, COLOUR5_PRIMARY), + + COLOURRES("colourDark0", 6, COLOUR0_DARK), + COLOURRES("colourDark1", 7, COLOUR1_DARK), + COLOURRES("colourDark2", 8, COLOUR2_DARK), + COLOURRES("colourDark3", 9, COLOUR3_DARK), + COLOURRES("colourDark4", 10, COLOUR4_DARK), + COLOURRES("colourDark5", 11, COLOUR5_DARK), + + COLOURRES("colourLight0", 12, COLOUR0_LIGHT), + COLOURRES("colourLight1", 13, COLOUR1_LIGHT), + COLOURRES("colourLight2", 14, COLOUR2_LIGHT), + COLOURRES("colourLight3", 15, COLOUR3_LIGHT), + COLOURRES("colourLight4", 16, COLOUR4_LIGHT), + COLOURRES("colourLight5", 17, COLOUR5_LIGHT), }; -static void init_colours(struct app_state *state, Screen *screen) +static void init_colours(struct app_state *state, Widget shell) { - Display *display = DisplayOfScreen(screen); + Display *display = XtDisplay(shell); + Screen *screen = XtScreen(shell); Colormap cmap = DefaultColormapOfScreen(screen); - XColor colour, junk; - unsigned i, j; + unsigned i; - for (j = 0; j < COLOUR_MAX; j++) { - for (i = 0; i < TILE_MAX-1; i++) { - XAllocNamedColor(display, cmap, colours[i][j], - &colour, &junk); - state->tile_colour[i][j] = colour.pixel; + colour_tab names; + XtGetApplicationResources(shell, &names, colour_resources, + XtNumber(colour_resources), NULL, 0); + + for (i = 0; i < XtNumber(names); i++) { + unsigned tile = i % (TILE_MAX-1), shade = i / (TILE_MAX-1); + XColor c; + + assert(names[i]); + if (!XAllocNamedColor(display, cmap, names[i], &c, &c)) { + printf("warning: could not allocate colour: %s\n", + names[i]); + c.pixel = 0; } + state->tile_colour[tile][shade] = c.pixel; } } -void x11_initialize(struct app_state *state, Screen *screen) +void x11_initialize(struct app_state *state, Widget shell) { - Display *display = DisplayOfScreen(screen); + Display *display = XtDisplay(shell); + Screen *screen = XtScreen(shell); Window root = RootWindowOfScreen(screen); XGCValues gcv; - init_colours(state, screen); + init_colours(state, shell); gcv.line_width = 1; state->tile_gc = XCreateGC(display, root, GCLineWidth, &gcv); diff --git a/t/ewmhicon.c b/t/ewmhicon.c index 2ce721c..fd92e32 100644 --- a/t/ewmhicon.c +++ b/t/ewmhicon.c @@ -27,6 +27,7 @@ #include #include "ewmhicon.h" +#include "colour.h" #include "help.h" static const char *progname = "ewmhicon"; @@ -38,23 +39,30 @@ static const struct option lopts[] = { { 0 } }; +#define PASTE(a, b) a ## b +#define INDIR(a) a + #define S8TO16(x) ((x) * 0xfffful / 0xff) -#define RGB8(r, g, b) { \ - 0xff000000|(r ## ul)<<16|(g ## ul)<<8|(b ## ul), \ + +#define RGB8_(r, g, b) { \ + 0xff000000 | (r << 16) | (g << 8) | b, \ S8TO16(r), S8TO16(g), S8TO16(b) } +#define RGB8(r, g, b) RGB8_(0x ## r ## ul, 0x ## g ## ul, 0x ## b ## ul) + +#define COLOURTAB(n) { \ + INDIR(RGB8 PASTE(COLOUR ## n, _PRIMARY_RGB_)), \ + INDIR(RGB8 PASTE(COLOUR ## n, _DARK_RGB_)), \ + INDIR(RGB8 PASTE(COLOUR ## n, _LIGHT_RGB_)) } + static const XColor colours[7][3] = { { { 0xffff0000, 0xffff }, { 0xff00ff00, 0, 0xffff }, { 0xff0000ff, 0, 0, 0xffff } }, - { RGB8(0x8d,0x2e,0x28), RGB8(0x6a,0x1b,0x17), RGB8(0xa1,0x48,0x42) }, - { RGB8(0xb4,0x6e,0x28), RGB8(0x92,0x4a,0x16), RGB8(0xc7,0x90,0x4f) }, - { RGB8(0xd8,0xb7,0x40), RGB8(0xc5,0x9f,0x39), RGB8(0xe2,0xc6,0x5d) }, - { RGB8(0x28,0x64,0x28), RGB8(0x19,0x47,0x19), RGB8(0x4e,0x87,0x4e) }, - { RGB8(0x00,0x34,0x71), RGB8(0x00,0x1f,0x4f), RGB8(0x00,0x52,0x8b) }, - { RGB8(0xdc,0xdc,0xdc), RGB8(0xc0,0xc0,0xc0), RGB8(0xea,0xea,0xea) } + COLOURTAB(0), COLOURTAB(1), COLOURTAB(2), + COLOURTAB(3), COLOURTAB(4), COLOURTAB(5) }; static void print_usage(FILE *f) -- 2.43.2