-
Notifications
You must be signed in to change notification settings - Fork 1
/
cansid.c
114 lines (109 loc) · 2.43 KB
/
cansid.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <stddef.h>
#include <stdint.h>
#include "cansid.h"
#define ESC '\x1B'
struct cansid_state cansid_init(void)
{
struct cansid_state rv = {
.state = CANSID_ESC,
.style = 0x0F,
.next_style = 0x0F
};
return rv;
}
static inline unsigned char cansid_convert_color(unsigned char color)
{
const unsigned char lookup_table[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
return lookup_table[(int)color];
}
struct color_char cansid_process(struct cansid_state *state, char x)
{
struct color_char rv = {
.style = state->style,
.ascii = '\0'
};
switch (state->state) {
case CANSID_ESC:
if (x == ESC)
state->state = CANSID_BRACKET;
else {
rv.ascii = x;
}
break;
case CANSID_BRACKET:
if (x == '[')
state->state = CANSID_PARSE;
else {
state->state = CANSID_ESC;
rv.ascii = x;
}
break;
case CANSID_PARSE:
if (x == '3') {
state->state = CANSID_FGCOLOR;
} else if (x == '4') {
state->state = CANSID_BGCOLOR;
} else if (x == '0') {
state->state = CANSID_ENDVAL;
state->next_style = 0x0F;
} else if (x == '1') {
state->state = CANSID_ENDVAL;
state->next_style |= (1 << 3);
} else if (x == '=') {
state->state = CANSID_EQUALS;
} else {
state->state = CANSID_ESC;
state->next_style = state->style;
rv.ascii = x;
}
break;
case CANSID_BGCOLOR:
if (x >= '0' && x <= '7') {
state->state = CANSID_ENDVAL;
state->next_style &= 0x1F;
state->next_style |= cansid_convert_color(x - '0') << 4;
} else {
state->state = CANSID_ESC;
state->next_style = state->style;
rv.ascii = x;
}
break;
case CANSID_FGCOLOR:
if (x >= '0' && x <= '7') {
state->state = CANSID_ENDVAL;
state->next_style &= 0xF8;
state->next_style |= cansid_convert_color(x - '0');
} else {
state->state = CANSID_ESC;
state->next_style = state->style;
rv.ascii = x;
}
break;
case CANSID_EQUALS:
if (x == '1') {
state->state = CANSID_ENDVAL;
state->next_style &= ~(1 << 3);
} else {
state->state = CANSID_ESC;
state->next_style = state->style;
rv.ascii = x;
}
break;
case CANSID_ENDVAL:
if (x == ';') {
state->state = CANSID_PARSE;
} else if (x == 'm') {
// Finish and apply styles
state->state = CANSID_ESC;
state->style = state->next_style;
} else {
state->state = CANSID_ESC;
state->next_style = state->style;
rv.ascii = x;
}
break;
default:
break;
}
return rv;
}