chiark / gitweb /
@@@ more mess
[mLib] / ui / ttycolour.h
1 /* -*-c-*-
2  *
3  * Configurable terminal colour support
4  *
5  * (c) 2024 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the mLib utilities library.
11  *
12  * mLib is free software: you can redistribute it and/or modify it under
13  * the terms of the GNU Library General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or (at
15  * your option) any later version.
16  *
17  * mLib is distributed in the hope that it will be useful, but WITHOUT
18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
20  * License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with mLib.  If not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25  * USA.
26  */
27
28 #ifndef MLIB_TTYCOLOUR_H
29 #define MLIB_TTYCOLOUR_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #ifndef MLIB_GPRINTF_H
38 #  include "gprintf.h"
39 #endif
40
41 #ifndef MLIB_MACROS_H
42 #  include "macros.h"
43 #endif
44
45 /*----- Functions provided ------------------------------------------------*/
46
47 /* Attributes for colour output.
48  *
49  * An attribute word holds a foreground colour in the low nibble, a
50  * background colour in the next nibble, and some flags in the next few bits.
51  * A colour is expressed in classic 1-bit-per-channel style, with red, green,
52  * and blue in bits 0, 1, and 2, and a `bright' flag in bit 3.
53  */
54 typedef unsigned short ttycolour_attr;  /* type of an attribute */
55
56 #define TCAF_FGMASK 0x0f                /* foreground colour mask */
57 #define TCAF_FGSHIFT 0                  /* foreground colour shift */
58 #define TCAF_BGMASK 0xf0                /* background colour mask */
59 #define TCAF_BGSHIFT 4                  /* background colour shift */
60 #define TCAF_FG 256u                    /* set foreground? */
61 #define TCAF_BG 512u                    /* set background? */
62 #define TCAF_BOLD 1024u                 /* set bold? */
63
64 #define TCCF_RED 1u                     /* red channel */
65 #define TCCF_GREEN 2u                   /* green channel */
66 #define TCCF_BLUE 4u                    /* blue channel */
67 #define TCCF_RGBMASK (TCCF_RED | TCCF_GREEN | TCCF_BLUE)
68 #define TCCF_BRIGHT 8u                  /* bright colour flag */
69
70 #define TTYCOL_BLACK 0u                 /* colour codes... */
71 #define TTYCOL_RED (TCCF_RED)
72 #define TTYCOL_GREEN (TCCF_GREEN)
73 #define TTYCOL_YELLOW (TCCF_RED | TCCF_GREEN)
74 #define TTYCOL_BLUE (TCCF_BLUE)
75 #define TTYCOL_MAGENTA (TCCF_RED | TCCF_BLUE)
76 #define TTYCOL_CYAN (TCCF_GREEN | TCCF_BLUE)
77 #define TTYCOL_WHITE (TCCF_RED | TCCF_GREEN | TCCF_BLUE)
78
79 #define TTYCOL_BRBLACK (TTYCOL_BLACK | TCCF_BRIGHT)
80 #define TTYCOL_BRRED (TTYCOL_RED | TCCF_BRIGHT)
81 #define TTYCOL_BRGREEN (TTYCOL_GREEN | TCCF_BRIGHT)
82 #define TTYCOL_BRYELLOW (TTYCOL_YELLOW | TCCF_BRIGHT)
83 #define TTYCOL_BRBLUE (TTYCOL_BLUE | TCCF_BRIGHT)
84 #define TTYCOL_BRMAGENTA (TTYCOL_MAGENTA | TCCF_BRIGHT)
85 #define TTYCOL_BRCYAN (TTYCOL_CYAN | TCCF_BRIGHT)
86 #define TTYCOL_BRWHITE (TTYCOL_WHITE | TCCF_BRIGHT)
87
88 #define TC_FG(col) (TCAF_FG | (TTYCOL_##col) << TCAF_FGSHIFT) /* set fg */
89 #define TC_BG(col) (TCAF_BG | (TTYCOL_##col) << TCAF_BGSHIFT) /* set bg */
90
91 struct ttycolour_style {
92   /* Table of style tokens and their defaults.  The table is terminated with
93    * a null @tok@ pointer.
94    */
95
96   const char *tok;                      /* style token name */
97   ttycolour_attr dflt;                  /* default attribute value */
98 };
99
100 struct ttycolour_state {
101   /* State maintained by @ttycolour_setattr@. */
102
103   ttycolour_attr attr;                  /* current attribute value */
104 };
105 #define TTYCOLOUR_STATE_INIT { 0 }      /* initializer for state */
106
107 /* Machinery for building the constants and tables.
108  *
109  * The caller should define the styles it supports in a macro taking two
110  * arguments, conventionally named @_st@ and @_@.  It should apply the second
111  * argument, @_@, to quadruples @(_st, tag, tok, dflt)@, where @_st@ is the
112  * argument provided, @tag@ is a constant-name suffix, @tok@ is a string
113  * naming the capability token to be read from the user string, and @dflt@ is
114  * the default attribute for the style.
115  */
116
117 /* --- @TTYCOLOUR_DEFENUM@ --- *
118  *
119  * Arguments:   @styles@ = style-list macro, as described above
120  *              @pre@ = prefix for constant names
121  *
122  * Use:         Define constants @pretag@ for each @tag@ listed in the list
123  *              macro @styles@, having sequential values starting from zero,
124  *              in the same order as the list macro.
125  */
126
127 #define TTYCOLOUR__ENUMPREFIX(pre) pre
128 #define TTYCOLOUR__FULLENUM(_st, tag) GLUE(TTYCOLOUR__ENUMPREFIX _st, tag)
129
130 #define TTYCOLOUR__DEFENUM(_st, tag, tok, dflt)                         \
131   TTYCOLOUR__FULLENUM(_st, tag),
132 #define TTYCOLOUR_DEFENUM(styles, pre) enum {                           \
133   styles((pre), TTYCOLOUR__DEFENUM)                                     \
134   pre##_LIMIT                                                           \
135 }
136
137 /* --- @TTYCOLOUR_INITTAB@ --- *
138  *
139  * Arguments:   @styles@ = style-list macro, as described above
140  *
141  * Use:         Expand to an initializer for a table of
142  *              @struct ttycolour_style@ values.  The table entries
143  *              correspond one-for-one with the entries in the list macro, in
144  *              the same order.
145  */
146
147 #define TTYCOLOUR__DEFENTRY(_st, tag, tok, dflt) { tok, dflt },
148 #define TTYCOLOUR_INITTAB(styles) {                                     \
149   styles((pre), TTYCOLOUR__DEFENTRY)                                    \
150   { 0, 0 }                                                              \
151 }
152
153 /* --- @ttycolour_config@ --- *
154  *
155  * Arguments:   @ttycolour_attr *attr@ = pointer to attribute table
156  *              @const char *user@ = the user-specified string or environment
157  *                      variable name
158  *              @unsigned f@ = flags (@TCIF_...@)
159  *              @const struct ttycolour_style *tab@ = table initialized using
160  *                      @TTYCOLOUR_INITTAB@
161  *
162  * Returns:     Zero on success, %$-1$% on error.
163  *
164  * Use:         Initialize the table @attr@ with the attributes configured
165  *              for the styles defined in the table.
166  *
167  *              A user string is determined.  If @f@ has @TCIF_GETENV@ set,
168  *              then the user string is the value of the environment variable
169  *              named by @user@; otherwise, the user string is @user@ itself.
170  *              The user string consists of a sequence of capability
171  *              defintiions separated by colons.  Each definition has the
172  *              form %%\syntax{<tok>"="<codes>}%%,                      
173  */
174
175 #define TCIF_GETENV 1u
176 #define TCIF_REPORT 2u
177 extern int ttycolour_config(ttycolour_attr */*attr*/,
178                             const char */*user*/, unsigned /*f*/,
179                             const struct ttycolour_style */*tab*/);
180
181 extern void ttycolour_init(struct ttycolour_state */*tc*/);
182
183 extern int ttycolour_setattr
184   (const struct gprintf_ops */*gops*/, void */*go*/,
185    struct ttycolour_state */*tc*/, ttycolour_attr /*attr*/);
186
187 /*----- That's all, folks -------------------------------------------------*/
188
189 #ifdef __cplusplus
190   }
191 #endif
192
193 #endif