NeoMutt  2025-09-05-55-g97fc89
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
attr.c
Go to the documentation of this file.
1
22
29
30#include "config.h"
31#include <string.h>
32#include "mutt/lib.h"
33#include "config/lib.h"
34#include "core/lib.h"
35#include "gui/lib.h"
36#include "attr.h"
37#include "color.h"
38#include "curses2.h"
39#include "debug.h"
40
48{
49 if (!ac)
50 return;
51
52 if (ac->curses_color)
53 color_debug(LL_DEBUG5, "clear %p\n", (void *) ac);
55
56 memset(&ac->fg, 0, sizeof(ac->fg));
57 memset(&ac->bg, 0, sizeof(ac->bg));
58
61 ac->attrs = A_NORMAL;
62}
63
68void attr_color_free(struct AttrColor **ptr)
69{
70 if (!ptr || !*ptr)
71 return;
72
73 struct AttrColor *ac = *ptr;
74 if (ac->ref_count > 1)
75 {
76 ac->ref_count--;
77 *ptr = NULL;
78 return;
79 }
80
82 FREE(ptr);
83}
84
90{
91 struct AttrColor *ac = MUTT_MEM_CALLOC(1, struct AttrColor);
92
94 ac->fg.type = CT_SIMPLE;
96
98 ac->bg.type = CT_SIMPLE;
100
101 ac->attrs = A_NORMAL;
102
103 ac->ref_count = 1;
104
105 return ac;
106}
107
116void attr_color_list_clear(struct AttrColorList *acl)
117{
118 if (!acl)
119 return;
120
121 struct AttrColor *ac = NULL;
122 struct AttrColor *tmp = NULL;
123 TAILQ_FOREACH_SAFE(ac, acl, entries, tmp)
124 {
125 TAILQ_REMOVE(acl, ac, entries);
126 attr_color_free(&ac);
127 }
128}
129
138struct AttrColor *attr_color_list_find(struct AttrColorList *acl, color_t fg,
139 color_t bg, int attrs)
140{
141 if (!acl)
142 return NULL;
143
144 struct AttrColor *ac = NULL;
145 TAILQ_FOREACH(ac, acl, entries)
146 {
147 if (ac->attrs != attrs)
148 continue;
149
150 struct CursesColor *cc = ac->curses_color;
151 if (!cc)
152 continue;
153
154 if ((cc->fg == fg) && (cc->bg == bg))
155 return ac;
156 }
157 return NULL;
158}
159
165struct AttrColor attr_color_copy(const struct AttrColor *ac)
166{
167 if (ac)
168 return *ac;
169 else
170 return (struct AttrColor) { 0 };
171}
172
178bool attr_color_is_set(const struct AttrColor *ac)
179{
180 if (!ac)
181 return false;
182
183 return ((ac->attrs != A_NORMAL) || ac->curses_color);
184}
185
192bool attr_color_match(struct AttrColor *ac1, struct AttrColor *ac2)
193{
194 if ((!ac1) ^ (!ac2)) // One is set, but not the other
195 return false;
196
197 if (!ac1) // Two empty colours match
198 return true;
199
200 return ((ac1->curses_color == ac2->curses_color) && (ac1->attrs == ac2->attrs));
201}
202
210void modify_color_by_prefix(enum ColorPrefix prefix, bool is_fg, color_t *col, int *attrs)
211{
212 if (prefix == COLOR_PREFIX_NONE)
213 return; // nothing to do here
214
215 if (prefix == COLOR_PREFIX_ALERT)
216 {
217 *attrs |= A_BOLD;
218 *attrs |= A_BLINK;
219 }
220 else if (is_fg)
221 {
222 if ((COLORS >= 16) && (prefix == COLOR_PREFIX_LIGHT))
223 {
224 if (*col <= 7)
225 {
226 /* Advance the color 0-7 by 8 to get the light version */
227 *col += 8;
228 }
229 }
230 else
231 {
232 *attrs |= A_BOLD;
233 }
234 }
235 else
236 {
237 if (COLORS >= 16)
238 {
239 if (*col <= 7)
240 {
241 /* Advance the color 0-7 by 8 to get the light version */
242 *col += 8;
243 }
244 }
245 }
246}
247
248#ifdef NEOMUTT_DIRECT_COLORS
320{
321 static const color_t basic[] = {
322 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080,
323 0x008080, 0xc0c0c0, 0x808080, 0xff0000, 0x00ff00, 0xffff00,
324 0x0000ff, 0xff00ff, 0x00ffff, 0xffffff,
325 };
326
327 ASSERT(color < 256);
328
329 if (color < 0)
330 return color;
331
332 const bool c_color_directcolor = cs_subset_bool(NeoMutt->sub, "color_directcolor");
333 if (!c_color_directcolor)
334 {
335 return color;
336 }
337
338 if (color < 16)
339 {
340 color_debug(LL_DEBUG5, "Converted color 0-15: %d\n", color);
341 /* The first 16 colours are the "usual" terminal colours */
342 return basic[color];
343 }
344
345 if (color < 232)
346 {
347 /* The Color palette is divided in 6x6x6 colours, i.e. each R, G, B channel
348 * has six values:
349 *
350 * value: 1 2 3 4 5 6
351 * color: 0x00 0x5f 0x87 0xaf 0xd7 0xff
352 *
353 * The steps between the values is 0x28 = 40, the EXCEPT for the first one
354 * where it is 0x5f = 95.
355 *
356 * If we express the xterm color number minus 16 to base 6, i.e.
357 *
358 * color - 16 = (vr * 36) + (vg * 6) + (vb * 1)
359 *
360 * with vr, vg, vb integers between 0 and 5, then vr, vg, vb is the channel
361 * value for red, green, and blue, respectively.
362 */
363
364 color_t normalised_color = color - 16;
365 color_t vr = (normalised_color % 216) / 36; /* 216 = 6*6*6 */
366 color_t vg = (normalised_color % 36) / 6;
367 color_t vb = (normalised_color % 6) / 1;
368
369 /* First step is wider than the other ones, so add the difference if needed */
370 color_t r = (vr * 0x28) + ((vr > 0) ? (0x5f - 0x28) : 0);
371 color_t g = (vg * 0x28) + ((vg > 0) ? (0x5f - 0x28) : 0);
372 color_t b = (vb * 0x28) + ((vb > 0) ? (0x5f - 0x28) : 0);
373
374 color_t rgb = (r << 16) + (g << 8) + (b << 0);
375 color_debug(LL_DEBUG5, "Converted xterm color %d to RGB #%x:\n", color, rgb);
376 return rgb;
377 }
378
379 /* Grey scale starts at 0x08 and adds 0xa = 10 in very step ending in 0xee.
380 * There are a total of 6*4 = 24 grey colors in total. */
381 color_t steps = color - 232;
382 color_t grey = (steps * 0x0a) + 0x08;
383 color_t rgb = (grey << 16) + (grey << 8) + (grey << 0);
384 color_debug(LL_DEBUG5, "Converted xterm color %d to RGB #%x:\n", color, rgb);
385 return rgb;
386}
387#endif
388
394void attr_color_overwrite(struct AttrColor *ac_old, const struct AttrColor *ac_new)
395{
396 if (!ac_old || !ac_new)
397 return;
398
399 color_t fg = ac_new->fg.color;
400 color_t bg = ac_new->bg.color;
401 int attrs = ac_new->attrs;
402
403 modify_color_by_prefix(ac_new->fg.prefix, true, &fg, &attrs);
404 modify_color_by_prefix(ac_new->bg.prefix, false, &bg, &attrs);
405
406#ifdef NEOMUTT_DIRECT_COLORS
407 if ((ac_new->fg.type == CT_SIMPLE) || (ac_new->fg.type == CT_PALETTE))
409 else if (fg < 8)
410 fg = 8;
411 if ((ac_new->bg.type == CT_SIMPLE) || (ac_new->bg.type == CT_PALETTE))
413 else if (bg < 8)
414 bg = 8;
415#endif
416
417 struct CursesColor *cc = curses_color_new(fg, bg);
419 ac_old->fg = ac_new->fg;
420 ac_old->bg = ac_new->bg;
421 ac_old->attrs = attrs;
422 ac_old->curses_color = cc;
423}
struct AttrColor * attr_color_list_find(struct AttrColorList *acl, color_t fg, color_t bg, int attrs)
Find an AttrColor in a list.
Definition attr.c:138
void attr_color_clear(struct AttrColor *ac)
Free the contents of an AttrColor.
Definition attr.c:47
color_t color_xterm256_to_24bit(const color_t color)
Convert a xterm color to its RGB value.
Definition attr.c:319
void attr_color_overwrite(struct AttrColor *ac_old, const struct AttrColor *ac_new)
Update an AttrColor in-place.
Definition attr.c:394
bool attr_color_match(struct AttrColor *ac1, struct AttrColor *ac2)
Do the colours match?
Definition attr.c:192
struct AttrColor attr_color_copy(const struct AttrColor *ac)
Copy a colour.
Definition attr.c:165
struct AttrColor * attr_color_new(void)
Create a new AttrColor.
Definition attr.c:89
void attr_color_free(struct AttrColor **ptr)
Free an AttrColor.
Definition attr.c:68
void modify_color_by_prefix(enum ColorPrefix prefix, bool is_fg, color_t *col, int *attrs)
Modify a colour/attributes based on a prefix, e.g.
Definition attr.c:210
void attr_color_list_clear(struct AttrColorList *acl)
Free the contents of an AttrColorList.
Definition attr.c:116
bool attr_color_is_set(const struct AttrColor *ac)
Is the object coloured?
Definition attr.c:178
Colour and attributes.
ColorPrefix
Constants for colour prefixes of named colours.
Definition attr.h:45
@ COLOR_PREFIX_NONE
no prefix
Definition attr.h:46
@ COLOR_PREFIX_ALERT
"alert" colour prefix
Definition attr.h:47
@ COLOR_PREFIX_LIGHT
"light" colour prefix
Definition attr.h:49
@ CT_SIMPLE
Simple colour, e.g. "Red".
Definition attr.h:36
@ CT_PALETTE
Palette colour, e.g. "color207".
Definition attr.h:37
Color and attribute parsing.
#define COLOR_DEFAULT
Definition color.h:103
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
Curses Colour.
int32_t color_t
Type for 24-bit colour value.
Definition curses2.h:31
struct CursesColor * curses_color_new(color_t fg, color_t bg)
Create a new CursesColor.
Definition curses.c:151
void curses_color_free(struct CursesColor **ptr)
Free a CursesColor.
Definition curses.c:120
Colour Debugging.
static int color_debug(enum LogLevel level, const char *format,...)
Definition debug.h:52
Convenience wrapper for the gui headers.
@ LL_DEBUG5
Log at debug level 5.
Definition logging2.h:48
#define FREE(x)
Definition memory.h:62
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:47
Convenience wrapper for the library headers.
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:782
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition queue.h:792
#define TAILQ_REMOVE(head, elm, field)
Definition queue.h:901
#define ASSERT(COND)
Definition signal2.h:60
A curses colour and its attributes.
Definition attr.h:66
struct ColorElement bg
Background colour.
Definition attr.h:68
struct ColorElement fg
Foreground colour.
Definition attr.h:67
short ref_count
Number of users.
Definition attr.h:71
int attrs
Text attributes, e.g. A_BOLD.
Definition attr.h:69
struct CursesColor * curses_color
Underlying Curses colour.
Definition attr.h:70
enum ColorType type
Type of Colour.
Definition attr.h:58
color_t color
Colour.
Definition attr.h:57
enum ColorPrefix prefix
Optional Colour Modifier.
Definition attr.h:59
Colour in the ncurses palette.
Definition curses2.h:41
color_t fg
Foreground colour.
Definition curses2.h:42
color_t bg
Background colour.
Definition curses2.h:43
Container for Accounts, Notifications.
Definition neomutt.h:43
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47