LF OS
Hobby operating system for amd64 with high ambitions
Loading...
Searching...
No Matches
pen.c
Go to the documentation of this file.
1#include "vterm_internal.h"
2
3#include <stdio.h>
4
9typedef struct {
10 uint8_t red, green, blue;
11} VTermRGB;
12
13static const VTermRGB ansi_colors[] = {
14 /* R G B */
15 { 0, 0, 0 }, // black
16 { 224, 0, 0 }, // red
17 { 0, 224, 0 }, // green
18 { 224, 224, 0 }, // yellow
19 { 0, 0, 224 }, // blue
20 { 224, 0, 224 }, // magenta
21 { 0, 224, 224 }, // cyan
22 { 224, 224, 224 }, // white == light grey
23
24 // high intensity
25 { 128, 128, 128 }, // black
26 { 255, 64, 64 }, // red
27 { 64, 255, 64 }, // green
28 { 255, 255, 64 }, // yellow
29 { 64, 64, 255 }, // blue
30 { 255, 64, 255 }, // magenta
31 { 64, 255, 255 }, // cyan
32 { 255, 255, 255 }, // white for real
33};
34
35static int ramp6[] = {
36 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF,
37};
38
39static int ramp24[] = {
40 0x00, 0x0B, 0x16, 0x21, 0x2C, 0x37, 0x42, 0x4D, 0x58, 0x63, 0x6E, 0x79,
41 0x85, 0x90, 0x9B, 0xA6, 0xB1, 0xBC, 0xC7, 0xD2, 0xDD, 0xE8, 0xF3, 0xFF,
42};
43
44static void lookup_default_colour_ansi(long idx, VTermColor *col)
45{
46 if (idx >= 0 && idx < 16) {
48 col,
49 ansi_colors[idx].red, ansi_colors[idx].green, ansi_colors[idx].blue);
50 }
51}
52
53static bool lookup_colour_ansi(const VTermState *state, long index, VTermColor *col)
54{
55 if(index >= 0 && index < 16) {
56 *col = state->colors[index];
57 return true;
58 }
59
60 return false;
61}
62
63static bool lookup_colour_palette(const VTermState *state, long index, VTermColor *col)
64{
65 if(index >= 0 && index < 16) {
66 // Normal 8 colours or high intensity - parse as palette 0
67 return lookup_colour_ansi(state, index, col);
68 }
69 else if(index >= 16 && index < 232) {
70 // 216-colour cube
71 index -= 16;
72
73 vterm_color_rgb(col, ramp6[index/6/6 % 6],
74 ramp6[index/6 % 6],
75 ramp6[index % 6]);
76
77 return true;
78 }
79 else if(index >= 232 && index < 256) {
80 // 24 greyscales
81 index -= 232;
82
83 vterm_color_rgb(col, ramp24[index], ramp24[index], ramp24[index]);
84
85 return true;
86 }
87
88 return false;
89}
90
91static int lookup_colour(const VTermState *state, int palette, const long args[], int argcount, VTermColor *col)
92{
93 switch(palette) {
94 case 2: // RGB mode - 3 args contain colour values directly
95 if(argcount < 3)
96 return argcount;
97
98 vterm_color_rgb(col, CSI_ARG(args[0]), CSI_ARG(args[1]), CSI_ARG(args[2]));
99
100 return 3;
101
102 case 5: // XTerm 256-colour mode
103 if (!argcount || CSI_ARG_IS_MISSING(args[0])) {
104 return argcount ? 1 : 0;
105 }
106
107 vterm_color_indexed(col, args[0]);
108
109 return argcount ? 1 : 0;
110
111 default:
112 DEBUG_LOG("Unrecognised colour palette %d\n", palette);
113 return 0;
114 }
115}
116
117// Some conveniences
118
120{
121#ifdef DEBUG
122 if(type != vterm_get_attr_type(attr)) {
123 DEBUG_LOG("Cannot set attr %d as it has type %d, not type %d\n",
124 attr, vterm_get_attr_type(attr), type);
125 return;
126 }
127#endif
129 (*state->callbacks->setpenattr)(attr, val, state->cbdata);
130}
131
132static void setpenattr_bool(VTermState *state, VTermAttr attr, int boolean)
133{
134 VTermValue val = { .boolean = boolean };
136}
137
138static void setpenattr_int(VTermState *state, VTermAttr attr, int number)
139{
140 VTermValue val = { .number = number };
142}
143
145{
146 VTermValue val = { .color = color };
148}
149
150static void set_pen_col_ansi(VTermState *state, VTermAttr attr, long col)
151{
152 VTermColor *colp = (attr == VTERM_ATTR_BACKGROUND) ? &state->pen.bg : &state->pen.fg;
153
154 vterm_color_indexed(colp, col);
155
156 setpenattr_col(state, attr, *colp);
157}
158
160{
161 // 90% grey so that pure white is brighter
162 vterm_color_rgb(&state->default_fg, 240, 240, 240);
163 vterm_color_rgb(&state->default_bg, 0, 0, 0);
165
166 for(int col = 0; col < 16; col++)
168}
169
186
210
212{
213 /* First make sure that the two colours are of the same type (RGB/Indexed) */
214 if (a->type != b->type) {
215 return false;
216 }
217
218 /* Depending on the type inspect the corresponding members */
219 if (VTERM_COLOR_IS_INDEXED(a)) {
220 return a->indexed.idx == b->indexed.idx;
221 }
222 else if (VTERM_COLOR_IS_RGB(a)) {
223 return (a->rgb.red == b->rgb.red)
224 && (a->rgb.green == b->rgb.green)
225 && (a->rgb.blue == b->rgb.blue);
226 }
227
228 return 0;
229}
230
232{
233 *default_fg = state->default_fg;
234 *default_bg = state->default_bg;
235}
236
238{
239 lookup_colour_palette(state, index, col);
240}
241
242void vterm_state_set_default_colors(VTermState *state, const VTermColor *default_fg, const VTermColor *default_bg)
243{
244 if(default_fg) {
245 state->default_fg = *default_fg;
246 state->default_fg.type = (state->default_fg.type & ~VTERM_COLOR_DEFAULT_MASK)
248 }
249
250 if(default_bg) {
251 state->default_bg = *default_bg;
252 state->default_bg.type = (state->default_bg.type & ~VTERM_COLOR_DEFAULT_MASK)
254 }
255}
256
258{
259 if(index >= 0 && index < 16)
260 state->colors[index] = *col;
261}
262
264{
265 if (VTERM_COLOR_IS_INDEXED(col)) { /* Convert indexed colors to RGB */
266 lookup_colour_palette(state, col->indexed.idx, col);
267 }
268 col->type &= VTERM_COLOR_TYPE_MASK; /* Reset any metadata but the type */
269}
270
272{
273 state->bold_is_highbright = bold_is_highbright;
274}
275
276INTERNAL void vterm_state_setpen(VTermState *state, const long args[], int argcount)
277{
278 // SGR - ECMA-48 8.3.117
279
280 int argi = 0;
281 int value;
282
283 while(argi < argcount) {
284 // This logic is easier to do 'done' backwards; set it true, and make it
285 // false again in the 'default' case
286 int done = 1;
287
288 long arg;
289 switch(arg = CSI_ARG(args[argi])) {
290 case CSI_ARG_MISSING:
291 case 0: // Reset
293 break;
294
295 case 1: { // Bold on
296 const VTermColor *fg = &state->pen.fg;
297 state->pen.bold = 1;
301 break;
302 }
303
304 case 3: // Italic on
305 state->pen.italic = 1;
307 break;
308
309 case 4: // Underline
311 if(CSI_ARG_HAS_MORE(args[argi])) {
312 argi++;
313 switch(CSI_ARG(args[argi])) {
314 case 0:
315 state->pen.underline = 0;
316 break;
317 case 1:
319 break;
320 case 2:
322 break;
323 case 3:
325 break;
326 }
327 }
329 break;
330
331 case 5: // Blink
332 state->pen.blink = 1;
334 break;
335
336 case 7: // Reverse on
337 state->pen.reverse = 1;
339 break;
340
341 case 8: // Conceal on
342 state->pen.conceal = 1;
344 break;
345
346 case 9: // Strikethrough on
347 state->pen.strike = 1;
349 break;
350
351 case 10: case 11: case 12: case 13: case 14:
352 case 15: case 16: case 17: case 18: case 19: // Select font
353 state->pen.font = CSI_ARG(args[argi]) - 10;
355 break;
356
357 case 21: // Underline double
360 break;
361
362 case 22: // Bold off
363 state->pen.bold = 0;
365 break;
366
367 case 23: // Italic and Gothic (currently unsupported) off
368 state->pen.italic = 0;
370 break;
371
372 case 24: // Underline off
373 state->pen.underline = 0;
375 break;
376
377 case 25: // Blink off
378 state->pen.blink = 0;
380 break;
381
382 case 27: // Reverse off
383 state->pen.reverse = 0;
385 break;
386
387 case 28: // Conceal off (Reveal)
388 state->pen.conceal = 0;
390 break;
391
392 case 29: // Strikethrough off
393 state->pen.strike = 0;
395 break;
396
397 case 30: case 31: case 32: case 33:
398 case 34: case 35: case 36: case 37: // Foreground colour palette
399 value = CSI_ARG(args[argi]) - 30;
401 value += 8;
403 break;
404
405 case 38: // Foreground colour alternative palette
406 if(argcount - argi < 1)
407 return;
408 argi += 1 + lookup_colour(state, CSI_ARG(args[argi+1]), args+argi+2, argcount-argi-2, &state->pen.fg);
410 break;
411
412 case 39: // Foreground colour default
415 break;
416
417 case 40: case 41: case 42: case 43:
418 case 44: case 45: case 46: case 47: // Background colour palette
419 value = CSI_ARG(args[argi]) - 40;
421 break;
422
423 case 48: // Background colour alternative palette
424 if(argcount - argi < 1)
425 return;
426 argi += 1 + lookup_colour(state, CSI_ARG(args[argi+1]), args+argi+2, argcount-argi-2, &state->pen.bg);
428 break;
429
430 case 49: // Default background
433 break;
434
435 case 73: // Superscript
436 case 74: // Subscript
437 case 75: // Superscript/subscript off
438 state->pen.small = (arg != 75);
440 (arg == 73) ? VTERM_BASELINE_RAISE :
441 (arg == 74) ? VTERM_BASELINE_LOWER :
445 break;
446
447 case 90: case 91: case 92: case 93:
448 case 94: case 95: case 96: case 97: // Foreground colour high-intensity palette
449 value = CSI_ARG(args[argi]) - 90 + 8;
451 break;
452
453 case 100: case 101: case 102: case 103:
454 case 104: case 105: case 106: case 107: // Background colour high-intensity palette
455 value = CSI_ARG(args[argi]) - 100 + 8;
457 break;
458
459 default:
460 done = 0;
461 break;
462 }
463
464 if(!done)
465 DEBUG_LOG("libvterm: Unhandled CSI SGR %ld\n", arg);
466
467 while(CSI_ARG_HAS_MORE(args[argi++]));
468 }
469}
470
471static int vterm_state_getpen_color(const VTermColor *col, int argi, long args[], int fg)
472{
473 /* Do nothing if the given color is the default color */
474 if (( fg && VTERM_COLOR_IS_DEFAULT_FG(col)) ||
475 (!fg && VTERM_COLOR_IS_DEFAULT_BG(col))) {
476 return argi;
477 }
478
479 /* Decide whether to send an indexed color or an RGB color */
480 if (VTERM_COLOR_IS_INDEXED(col)) {
481 const uint8_t idx = col->indexed.idx;
482 if (idx < 8) {
483 args[argi++] = (idx + (fg ? 30 : 40));
484 }
485 else if (idx < 16) {
486 args[argi++] = (idx - 8 + (fg ? 90 : 100));
487 }
488 else {
489 args[argi++] = CSI_ARG_FLAG_MORE | (fg ? 38 : 48);
490 args[argi++] = CSI_ARG_FLAG_MORE | 5;
491 args[argi++] = idx;
492 }
493 }
494 else if (VTERM_COLOR_IS_RGB(col)) {
495 args[argi++] = CSI_ARG_FLAG_MORE | (fg ? 38 : 48);
496 args[argi++] = CSI_ARG_FLAG_MORE | 2;
497 args[argi++] = CSI_ARG_FLAG_MORE | col->rgb.red;
498 args[argi++] = CSI_ARG_FLAG_MORE | col->rgb.green;
499 args[argi++] = col->rgb.blue;
500 }
501 return argi;
502}
503
504INTERNAL int vterm_state_getpen(VTermState *state, long args[], int argcount)
505{
506 int argi = 0;
507
508 if(state->pen.bold)
509 args[argi++] = 1;
510
511 if(state->pen.italic)
512 args[argi++] = 3;
513
515 args[argi++] = 4;
517 args[argi++] = 4 | CSI_ARG_FLAG_MORE, args[argi++] = 3;
518
519 if(state->pen.blink)
520 args[argi++] = 5;
521
522 if(state->pen.reverse)
523 args[argi++] = 7;
524
525 if(state->pen.conceal)
526 args[argi++] = 8;
527
528 if(state->pen.strike)
529 args[argi++] = 9;
530
531 if(state->pen.font)
532 args[argi++] = 10 + state->pen.font;
533
535 args[argi++] = 21;
536
537 argi = vterm_state_getpen_color(&state->pen.fg, argi, args, true);
538
539 argi = vterm_state_getpen_color(&state->pen.bg, argi, args, false);
540
541 if(state->pen.small) {
543 args[argi++] = 73;
545 args[argi++] = 74;
546 }
547
548 return argi;
549}
550
552{
553 switch(attr) {
554 case VTERM_ATTR_BOLD:
555 val->boolean = state->pen.bold;
556 return 1;
557
559 val->number = state->pen.underline;
560 return 1;
561
563 val->boolean = state->pen.italic;
564 return 1;
565
566 case VTERM_ATTR_BLINK:
567 val->boolean = state->pen.blink;
568 return 1;
569
571 val->boolean = state->pen.reverse;
572 return 1;
573
575 val->boolean = state->pen.conceal;
576 return 1;
577
579 val->boolean = state->pen.strike;
580 return 1;
581
582 case VTERM_ATTR_FONT:
583 val->number = state->pen.font;
584 return 1;
585
587 val->color = state->pen.fg;
588 return 1;
589
591 val->color = state->pen.bg;
592 return 1;
593
594 case VTERM_ATTR_SMALL:
595 val->boolean = state->pen.small;
596 return 1;
597
599 val->number = state->pen.baseline;
600 return 1;
601
602 case VTERM_N_ATTRS:
603 return 0;
604 }
605
606 return 0;
607}
unsigned char uint8_t
Definition arch.h:5
static VTermState * state
Definition harness.c:105
enum MessageType type
Type of the message.
INTERNAL void vterm_state_savepen(VTermState *state, int save)
Definition pen.c:187
static void setpenattr_bool(VTermState *state, VTermAttr attr, int boolean)
Definition pen.c:132
void vterm_state_set_palette_color(VTermState *state, int index, const VTermColor *col)
Definition pen.c:257
static int ramp24[]
Definition pen.c:39
static void lookup_default_colour_ansi(long idx, VTermColor *col)
Definition pen.c:44
void vterm_state_get_palette_color(const VTermState *state, int index, VTermColor *col)
Definition pen.c:237
static bool lookup_colour_ansi(const VTermState *state, long index, VTermColor *col)
Definition pen.c:53
void vterm_state_set_bold_highbright(VTermState *state, int bold_is_highbright)
Definition pen.c:271
void vterm_state_get_default_colors(const VTermState *state, VTermColor *default_fg, VTermColor *default_bg)
Definition pen.c:231
INTERNAL int vterm_state_getpen(VTermState *state, long args[], int argcount)
Definition pen.c:504
INTERNAL void vterm_state_resetpen(VTermState *state)
Definition pen.c:170
static void setpenattr(VTermState *state, VTermAttr attr, VTermValueType type, VTermValue *val)
Definition pen.c:119
static const VTermRGB ansi_colors[]
Definition pen.c:13
void vterm_state_convert_color_to_rgb(const VTermState *state, VTermColor *col)
Definition pen.c:263
static int ramp6[]
Definition pen.c:35
void vterm_state_set_default_colors(VTermState *state, const VTermColor *default_fg, const VTermColor *default_bg)
Definition pen.c:242
INTERNAL void vterm_state_newpen(VTermState *state)
Definition pen.c:159
static int vterm_state_getpen_color(const VTermColor *col, int argi, long args[], int fg)
Definition pen.c:471
int vterm_state_get_penattr(const VTermState *state, VTermAttr attr, VTermValue *val)
Definition pen.c:551
static bool lookup_colour_palette(const VTermState *state, long index, VTermColor *col)
Definition pen.c:63
uint8_t blue
Definition pen.c:10
static void set_pen_col_ansi(VTermState *state, VTermAttr attr, long col)
Definition pen.c:150
static void setpenattr_int(VTermState *state, VTermAttr attr, int number)
Definition pen.c:138
static void setpenattr_col(VTermState *state, VTermAttr attr, VTermColor color)
Definition pen.c:144
int vterm_color_is_equal(const VTermColor *a, const VTermColor *b)
Definition pen.c:211
static int lookup_colour(const VTermState *state, int palette, const long args[], int argcount, VTermColor *col)
Definition pen.c:91
INTERNAL void vterm_state_setpen(VTermState *state, const long args[], int argcount)
Definition pen.c:276
Definition pen.c:9
int(* setpenattr)(VTermAttr attr, VTermValue *val, void *user)
Definition vterm.h:434
VTermColor colors[16]
VTermColor default_fg
VTermColor default_bg
const VTermStateCallbacks * callbacks
struct VTermState::@17 saved
struct VTermPen pen
struct VTermColor::@11 indexed
int boolean
Definition vterm.h:228
#define VTERM_COLOR_IS_INDEXED(col)
Definition vterm.h:109
uint8_t type
Definition vterm.h:149
static void vterm_color_rgb(VTermColor *col, uint8_t red, uint8_t green, uint8_t blue)
Definition vterm.h:186
#define CSI_ARG_HAS_MORE(a)
Definition vterm.h:392
@ VTERM_COLOR_DEFAULT_BG
Definition vterm.h:97
@ VTERM_COLOR_TYPE_MASK
Definition vterm.h:81
@ VTERM_COLOR_DEFAULT_FG
Definition vterm.h:89
#define VTERM_COLOR_IS_DEFAULT_FG(col)
Definition vterm.h:124
#define VTERM_COLOR_IS_RGB(col)
Definition vterm.h:116
#define CSI_ARG_MISSING
Definition vterm.h:396
int number
Definition vterm.h:229
@ VTERM_BASELINE_NORMAL
Definition vterm.h:522
@ VTERM_BASELINE_LOWER
Definition vterm.h:524
@ VTERM_BASELINE_RAISE
Definition vterm.h:523
@ VTERM_UNDERLINE_DOUBLE
Definition vterm.h:517
@ VTERM_UNDERLINE_SINGLE
Definition vterm.h:516
@ VTERM_UNDERLINE_CURLY
Definition vterm.h:518
#define CSI_ARG(a)
Definition vterm.h:393
VTermValueType vterm_get_attr_type(VTermAttr attr)
Definition vterm.c:266
#define CSI_ARG_IS_MISSING(a)
Definition vterm.h:398
#define CSI_ARG_FLAG_MORE
Definition vterm.h:389
VTermAttr
Definition vterm.h:234
@ VTERM_ATTR_BOLD
Definition vterm.h:236
@ VTERM_N_ATTRS
Definition vterm.h:249
@ VTERM_ATTR_FOREGROUND
Definition vterm.h:244
@ VTERM_ATTR_UNDERLINE
Definition vterm.h:237
@ VTERM_ATTR_ITALIC
Definition vterm.h:238
@ VTERM_ATTR_BACKGROUND
Definition vterm.h:245
@ VTERM_ATTR_FONT
Definition vterm.h:243
@ VTERM_ATTR_BLINK
Definition vterm.h:239
@ VTERM_ATTR_STRIKE
Definition vterm.h:242
@ VTERM_ATTR_SMALL
Definition vterm.h:246
@ VTERM_ATTR_REVERSE
Definition vterm.h:240
@ VTERM_ATTR_BASELINE
Definition vterm.h:247
@ VTERM_ATTR_CONCEAL
Definition vterm.h:241
VTermColor color
Definition vterm.h:231
VTermValueType
Definition vterm.h:210
@ VTERM_VALUETYPE_INT
Definition vterm.h:213
@ VTERM_VALUETYPE_BOOL
Definition vterm.h:212
@ VTERM_VALUETYPE_COLOR
Definition vterm.h:215
static void vterm_color_indexed(VTermColor *col, uint8_t idx)
Definition vterm.h:199
#define VTERM_COLOR_IS_DEFAULT_BG(col)
Definition vterm.h:132
struct VTermColor::@10 rgb
#define INTERNAL
#define DEBUG_LOG(...)
unsigned int strike
unsigned int bold
unsigned int conceal
unsigned int blink
unsigned int small
unsigned int italic
unsigned int reverse
unsigned int font
unsigned int baseline
VTermColor bg
VTermColor fg
unsigned int underline