@@ -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 }
117135private:
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