Skip to content

Commit 7321f15

Browse files
committed
Support for 256 colors in xterm style
1 parent 78e093a commit 7321f15

9 files changed

Lines changed: 2882 additions & 2656 deletions

File tree

8x32.inc

Lines changed: 128 additions & 512 deletions
Large diffs are not rendered by default.

c.jsf

Lines changed: 499 additions & 116 deletions
Large diffs are not rendered by default.

jsf.hh

Lines changed: 132 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,34 @@ public:
1818
{
1919
char Buf[512]={0};
2020
fprintf(stdout, "Parsing syntax file... "); fflush(stdout);
21-
TabType cc;
21+
TabType colortable;
2222
char colors_sorted = 0;
2323
states = 0; // NOTE: THIS LEAKS MEMORY
2424
while(fgets(Buf, sizeof(Buf), fp))
2525
{
2626
cleanup(Buf);
27-
if(Buf[0] == '=') { colors_sorted=0; ParseColorDeclaration(Buf+1, cc); }
27+
if(Buf[0] == '=')
28+
{
29+
colors_sorted = 0;
30+
ParseColorDeclaration(Buf+1, colortable);
31+
}
2832
else if(Buf[0] == ':')
2933
{
3034
if(!colors_sorted)
3135
{
32-
sort(cc);
36+
/* Sort the color table when the first state is encountered */
37+
sort(colortable);
3338
colors_sorted = 1;
3439
}
35-
ParseStateStart(Buf+1, cc);
40+
ParseStateStart(Buf+1, colortable);
3641
}
3742
else if(Buf[0] == ' ' || Buf[0] == '\t')
3843
ParseStateLine(Buf, fp);
3944
}
4045
fprintf(stdout, "Binding... "); fflush(stdout);
4146
BindStates();
4247

43-
for(unsigned n=0; n<cc.size(); ++n) free(cc[n].token);
48+
for(unsigned n=0; n<colortable.size(); ++n) free(colortable[n].token);
4449

4550
fprintf(stdout, "Done\n"); fflush(stdout);
4651
}
@@ -50,21 +55,23 @@ public:
5055
/* std::vector<unsigned char> */
5156
CharVecType buffer;
5257
int buffering;
53-
int recolor, noeat;
58+
int recolor, markbegin, markend;
59+
int recolormark:1, noeat:1;
5460
unsigned char c;
5561
state* s;
5662
};
5763
void ApplyInit(ApplyState& state)
5864
{
5965
state.buffer.clear();
6066
state.buffering = state.recolor = state.noeat = 0;
67+
state.markbegin = state.markend = 0;
6168
state.c = '?';
6269
state.s = states;
6370
}
6471
struct Applier
6572
{
6673
virtual cdecl int Get(void) = 0;
67-
virtual cdecl void Recolor(register unsigned n, register unsigned attr) = 0;
74+
virtual cdecl void Recolor(register unsigned distance, register unsigned n, register unsigned long attr) = 0;
6875
};
6976
void Apply( ApplyState& state, Applier& app)
7077
{
@@ -80,16 +87,25 @@ public:
8087
{
8188
int ch = app.Get();
8289
if(ch < 0) break;
83-
state.c = ch;
90+
state.c = ch;
8491
state.recolor += 1;
92+
++state.markbegin;
93+
++state.markend;
94+
}
95+
if(state.recolor)
96+
{
97+
app.Recolor(0, state.recolor, state.s->attr);
98+
}
99+
if(state.recolormark)
100+
{
101+
app.Recolor(state.markend, state.markbegin - state.markend, state.s->attr);
85102
}
86-
app.Recolor(state.recolor, state.s->attr);
87-
state.recolor = 0;
88103

89104
option *o = state.s->options[state.c];
90-
state.recolor = o->recolor;
91-
state.noeat = o->noeat;
92-
state.s = o->state;
105+
state.recolor = o->recolor;
106+
state.recolormark = o->recolormark;
107+
state.noeat = o->noeat;
108+
state.s = o->state;
93109
if(o->strings)
94110
{
95111
const char* k = (const char*) &state.buffer[0];
@@ -112,15 +128,17 @@ public:
112128
if(o->buffer)
113129
{ state.buffering = 1;
114130
state.buffer.assign(&state.c, &state.c + 1); }
131+
if(o->mark) { state.markbegin = 0; }
132+
if(o->markend) { state.markend = 0; }
115133
}
116134
}
117135
private:
118136
struct option;
119137
struct state
120138
{
121-
state* next;
122-
char* name;
123-
int attr;
139+
state* next;
140+
char* name;
141+
unsigned long attr;
124142
option* options[256];
125143
}* states;
126144
struct table_item
@@ -164,20 +182,80 @@ private:
164182
unsigned buffer: 1;
165183
unsigned strings:2; // 0=no strings, 1=strings, 2=istrings
166184
unsigned name_mapped:1; // whether state(1) or state_name(0) is valid
185+
unsigned mark:1, markend:1, recolormark:1;
167186
};
168187
inline void ParseColorDeclaration(char* line, TabType& colortable)
169188
{
170189
while(*line==' '||*line=='\t') ++line;
171190
char* namebegin = line;
172191
while(*line && *line != ' ' && *line!='\t') ++line;
173192
char* nameend = line;
174-
while(*line==' '||*line=='\t') ++line;
175-
int attr = strtol(line, 0, 16);
193+
char* line_end = NULL;
194+
unsigned char fg256 = 0;
195+
unsigned char bg256 = 0;
196+
unsigned char flags = 0x00; // underline=1 dim=2 italic=4 bold=8 inverse=16 blink=32
197+
for(;;)
198+
{
199+
while(*line==' '||*line=='\t') ++line;
200+
if(!*line) break;
201+
char* line_end = NULL;
202+
int attr = strtol(line, &line_end, 16);
203+
if(line_end >= line+2) // Two-digit hex?
204+
{
205+
line = line_end;
206+
fg256 = attr & 0x0F;
207+
bg256 = (attr >> 4) & 0x0F;
208+
continue;
209+
}
210+
if(strncmp(line, "fg_", 3) == 0)
211+
{
212+
if(line[5] >= '0' && line[5] <= '5') fg256 = 16 + strtol(line+3, &line, 6);
213+
else fg256 = 232 + strtol(line+3, &line, 10);
214+
continue;
215+
}
216+
if(strncmp(line, "bg_", 3) == 0)
217+
{
218+
if(line[5] >= '0' && line[5] <= '5') bg256 = 16 + strtol(line+3, &line, 6);
219+
else bg256 = 232 + strtol(line+3, &line, 10);
220+
continue;
221+
}
222+
/* Words: black blue cyan green red yellow magenta white
223+
* BLACK BLUE CYAN GREEN RED YELLOW MAGENTA WHITE
224+
* bg_black bg_blue bg_cyan bg_green bg_red bg_yellow bg_magenta bg_white
225+
* BG_BLACK BG_BLUE BG_CYAN BG_GREEN BG_RED BG_YELLOW BG_MAGENTA BG_WHITE
226+
* underline dim italic bold inverse blink
227+
*/
228+
unsigned short c=0, i=0;
229+
while(*line && *line != ' ' && *line != '\t') { c += 90u*(unsigned char)*line + i; i+=28; ++line; }
230+
unsigned char code = ((c + 22u) / 26u) % 46u;
231+
static const signed char actions[46] = { 11,30,3,1,31,18,29,23,13,36,15,25,7,2,28,-1,20,-1,24,9,16,26,-1,8,35,0,12,21,-1,5,10,17,22,33,32,34,4,14,-1,-1,6,27,-1,-1,19,37};
232+
/*if(code >= 0 && code <= 45)*/ code = actions[code - 0];
233+
switch(code >> 4) { case 0: fg256 = code&15; break;
234+
case 1: bg256 = code&15; break;
235+
default:flags |= 1u << (code&7); }
236+
}
237+
if(flags & 0x10) { unsigned tmp=fg256; fg256=bg256; bg256=tmp; flags &= ~0x10; } // inverse
238+
239+
unsigned short attrlo = fg256;
240+
unsigned char attrhi = flags & 0xF;
241+
if(fg256 < 16 && bg256 < 16)
242+
{
243+
// Create a 8-bit CGA/EGA/VGA attribute
244+
attrlo |= (bg256 << 4) | ((flags & 0x20) << 2) | (flags & 0x08);
245+
}
246+
else
247+
{
248+
// Create an extended attribute
249+
attrhi |= 0x80u | ((fg256 & 0x80) >> 1);
250+
attrlo |= (bg256 << 8u) | 0x80u;
251+
}
252+
unsigned long attr = attrlo | (((unsigned long)attrhi) << 16u);
253+
176254
*nameend = '\0';
177255
table_item tmp;
178256
tmp.token = strdup(namebegin);
179257
if(!tmp.token) fprintf(stdout, "strdup: failed to allocate string for %s\n", namebegin);
180-
tmp.state = (struct state*) attr;
258+
tmp.state = (struct state *) attr;
181259
colortable.push_back(tmp);
182260
}
183261
inline void ParseStateStart(char* line, const TabType& colortable)
@@ -192,10 +270,25 @@ private:
192270
if(!s) fprintf(stdout, "failed to allocate new jsf state\n");
193271
memset(s, 0, sizeof(*s));
194272
s->name = strdup(namebegin);
195-
if(!s->name) fprintf(stdout, "strdup: failed to allocate string for %s\n", namebegin);
196-
{state* c = findstate(colortable, line);
197-
if(!c) { s->attr = 0x4A; fprintf(stdout,"Unknown color: '%s'\n", line); }
198-
else s->attr = (long) c;}
273+
if(!s->name)
274+
{
275+
fprintf(stdout, "strdup: failed to allocate string for %s\n", namebegin);
276+
s->attr = 0x4A;
277+
}
278+
else
279+
{
280+
state* c = findstate(colortable, line);
281+
// The value in the table is a pointer type, but it actually is a color code (integer).
282+
if(!c)
283+
{
284+
fprintf(stdout,"Unknown color: '%s'\n", line);
285+
s->attr = 0x4A;
286+
}
287+
else
288+
{
289+
s->attr = (long) c;
290+
}
291+
}
199292
s->next = states;
200293
states = s;
201294
}
@@ -268,22 +361,32 @@ private:
268361
switch(*opt_begin)
269362
{
270363
case 'n':
271-
if(strcmp(opt_begin+1, /*"n"*/"oeat") == 0) { o->noeat = 1; break; }
364+
if(strcmp(opt_begin+1, "oeat") == 0) { o->noeat = 1; break; }
365+
goto ukw;
272366
case 'b':
273-
if(strcmp(opt_begin, "buffer") == 0) { o->buffer = 1; break; }
367+
if(strcmp(opt_begin+1, "uffer") == 0) { o->buffer = 1; break; }
368+
goto ukw;
369+
case 'm':
370+
if(strcmp(opt_begin+1, "arkend") == 0) { o->markend = 1; break; }
371+
if(strcmp(opt_begin+1, "ark") == 0) { o->mark = 1; break; }
372+
goto ukw;
274373
case 's':
275-
if(strcmp(opt_begin, "strings") == 0) { o->strings = 1; break; }
374+
if(strcmp(opt_begin+1, "trings") == 0) { o->strings = 1; break; }
375+
goto ukw;
276376
case 'i':
277-
if(strcmp(opt_begin, "istrings") == 0) { o->strings = 2; break; }
377+
if(strcmp(opt_begin+1, /*i*/"strings") == 0) { o->strings = 2; break; }
378+
goto ukw;
278379
case 'r':
279-
if(strncmp(opt_begin, "recolor=", 8) == 0)
380+
if(strcmp(opt_begin+1, "ecolormark") == 0) { o->recolormark = 1; break; }
381+
if(strncmp(opt_begin+1, "ecolor=", 7) == 0)
280382
{
281383
int r = atoi(opt_begin+8);
282384
if(r < 0) r = -r;
283385
o->recolor = r;
284386
break;
285387
}
286-
default:
388+
goto ukw;
389+
default: ukw:
287390
fprintf(stdout,"Unknown keyword '%s' in '%s'\n", opt_begin, namebegin);
288391
}
289392
}

0 commit comments

Comments
 (0)