Browse code

Add a simple C-language highlighter as a plugin (and lots of temp. debug code; to be cleaned later)

Dario Rodriguez authored on 17/10/2020 22:30:36
Showing 6 changed files
... ...
@@ -5,3 +5,5 @@ tests_utf8
5 5
 *.log
6 6
 re.valgrind
7 7
 sdl.supp
8
+NormalizationTest.txt
9
+reference*.png
... ...
@@ -23,11 +23,13 @@
23 23
 #include "re_data.h"
24 24
 #include "sha3/sha3.h"
25 25
 
26
+/* DEFAULT CHUNKSIZE: 1024 */
27
+//#define CHUNKSIZE 65536
26 28
 //#define CHUNKSIZE 32768
27 29
 //#define CHUNKSIZE 4096
28
-#define CHUNKSIZE 1024
30
+//#define CHUNKSIZE 1024
29 31
 //#define CHUNKSIZE 160
30
-//#define CHUNKSIZE 16
32
+#define CHUNKSIZE 16
31 33
 #define UNDOBLOCK 1024
32 34
 #define ADDNBLOCK 1024
33 35
 #define UNDOGROWSIZE (256*1024)
... ...
@@ -100,7 +100,6 @@ typedef struct redata_t {
100 100
 
101 101
 redata_t *redata_init( int (*pluginregisterfn)(redata_t *redata, redata_plugin_t *slot), ...);
102 102
 void redata_free(redata_t *redata);
103
-
104 103
 void redata_idleproc(redata_t *redata, char *filename);
105 104
 
106 105
 int redata_config_chunkdatasize(redata_t *redata, int chunkdatasize);
... ...
@@ -22,19 +22,26 @@
22 22
 #include "re_plugin_highlighter.h"
23 23
 
24 24
 #define PLUGINNAME "highlighter"
25
+#define HLINETBLOCK (16*1024)
26
+#define BUFBLOCK (64*1024)
25 27
 #define HIGHLIGHTERGROWSIZE (256*1024)
26 28
 #define DEFAULTCOLOR "\x80\x80\x80\xff"
27 29
 
28 30
 
29 31
 typedef enum colorsenum_t {
30 32
         color_normal=0,
31
-        color_define,
32
-        color_definestring,
33
+        color_directive,
34
+        color_directivekeyword,
35
+        color_directivestring,
36
+        color_directiveinclude,
37
+        color_directiveincludestring,
33 38
         color_keyword,
34 39
         color_string,
35 40
         color_multilinecomment,
36 41
         color_linecomment,
37 42
         color_number,
43
+        color_operator,
44
+        color_symbol,
38 45
         color_endenum,
39 46
 } colorsenum_t;
40 47
 
... ...
@@ -42,13 +49,16 @@ typedef enum colorsenum_t {
42 49
 static int redata_highlighter_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo);
43 50
 static int redata_highlighter_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo);
44 51
 static int redata_highlighter_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd);
45
-static int redata_highlighter_commit(redata_t *redata, redata_plugin_t *slot,char *filename);
46 52
 static int redata_highlighter_postload(redata_t *redata, redata_plugin_t *slot,char *filename);
47 53
 
48 54
 static int hl_invalidatefrom(redata_t *redata, highlighter_t *hl, int nline);
49 55
 hcolor_t *hl_initcolors(int *ncolors, /* int color, char *colordef, */ ...);
50 56
 static highlighter_t *hl_getplugin(redata_t *redata);
51 57
 static int hl_doline(redata_t *redata, highlighter_t *hl, int nline);
58
+int hl_C_getkeywords(char ***keywords,int *nkeywords, int *maxlen);
59
+int hl_C_getdirectives(char ***directives,int *ndirectives, int *maxlen);
60
+int hl_searchlist(char **wordlist, int wordlistlen, char *word, int wordlen, int *res);
61
+linecolor_t *hl_addtolinecolor(int *opaque, highlighter_t *hl,linecolor_t *linecolor,int posoff, int color);
52 62
 
53 63
 int
54 64
 redata_highlighter_register(redata_t *redata, redata_plugin_t *slot)
... ...
@@ -60,13 +70,18 @@ redata_highlighter_register(redata_t *redata, redata_plugin_t *slot)
60 70
                 return(-1);
61 71
         colors=hl_initcolors(&ncolors,
62 72
                              color_normal,"\x38\x17\x1e\xff",
63
-                             color_define,"\x0d\x2b\x04\xff",
64
-                             color_definestring,"\x07\x20\3b\xff",
73
+                             color_directive,"\x38\x4b\x00\xff",
74
+                             color_directivekeyword,"\x63\x7d\x16\xff",
75
+                             color_directivestring,"\x07\x20\3b\xff",
76
+                             color_directiveinclude,"\x16\x63\x7d\xff",
77
+                             color_directiveincludestring,"\x6\x13\x2d\xff",
65 78
                              color_keyword,"\x9d\x15\x00\xff",
66 79
                              color_string,"\x68\x00\x01\xff",
67 80
                              color_multilinecomment,"\x4f\x40\x57\xff",
68
-                             color_linecomment,"\xaa\x8c\xcd\xff",
81
+                             color_linecomment,"\xc6\x8c\xa4\xff",
69 82
                              color_number,"\x3b\x10\x35\xff",
83
+                             color_operator,"\xaa\x8c\xcd\xff",
84
+                             color_symbol,"\x69\x2a\x44\xff",
70 85
                              color_endenum,DEFAULTCOLOR,
71 86
                              -1);
72 87
         if(colors==NULL || (hl=malloc(sizeof(highlighter_t)))==NULL) {
... ...
@@ -84,7 +99,6 @@ redata_highlighter_register(redata_t *redata, redata_plugin_t *slot)
84 99
         slot->postload=redata_highlighter_postload;
85 100
         slot->add=redata_highlighter_add;
86 101
         slot->unadd=redata_highlighter_unadd;
87
-        slot->commit=redata_highlighter_commit;
88 102
         slot->userptr=hl;
89 103
         return(0);
90 104
 }
... ...
@@ -104,6 +118,12 @@ redata_highlighter_unregister(redata_t *redata, redata_plugin_t *slot, char *fil
104 118
         if(hl->lines!=NULL)
105 119
                 free(hl->lines),hl->lines=NULL;
106 120
         hl->sizelines=hl->usedlines=0;
121
+        if(hl->keywordbuf!=NULL)
122
+                free(hl->keywordbuf),hl->keywordbuf=NULL;
123
+        hl->sizekeywordbuf=hl->usedkeywordbuf=0;
124
+        if(hl->directivebuf!=NULL)
125
+                free(hl->directivebuf),hl->directivebuf=NULL;
126
+        hl->sizedirectivebuf=hl->useddirectivebuf=0;
107 127
         if(slot->userptr!=NULL)
108 128
                 free(slot->userptr),slot->userptr=NULL;
109 129
         return(0);
... ...
@@ -131,7 +151,7 @@ redata_highlighter_getline(redata_t *redata, int line, int *nlinecolors)
131 151
         if(line<0 || line>=hl->usedlines)
132 152
                 return(NULL);
133 153
         if(nlinecolors!=NULL)
134
-                *nlinecolors=(hl->lines[line].len)/sizeof(hcolor_t);
154
+                *nlinecolors=(hl->lines[line].len)/sizeof(linecolor_t);
135 155
         return((linecolor_t *) (hl->buf+hl->lines[line].off));
136 156
 }
137 157
 
... ...
@@ -158,6 +178,12 @@ redata_highlighter_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t
158 178
         stack=redata_getstack(redata,undo);
159 179
         if(redata==NULL || slot==NULL || hl==NULL || undo==NULL || stack==NULL || slot->active==0)
160 180
                 return(-1); /* sanity check failed */
181
+        if(hl->usedlines==0) {
182
+#if 1
183
+fprintf(stderr,"INVALIDATING USEDLINELINES==0 (nothing to do)\n");
184
+#endif
185
+                return(0); /* nothing to do */
186
+        }
161 187
         /* get the first pos of the operation */
162 188
         pos=undo->posorig;
163 189
         if(undo->type=='D')
... ...
@@ -171,21 +197,15 @@ redata_highlighter_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t
171 197
                         break;
172 198
                 }
173 199
         }
200
+        /* special case: check if pos is inside last line */
201
+        if(nline>=hl->usedlines && (hl->lines[hl->usedlines-1].pos+hl->lines[hl->usedlines-1].len)>=pos)
202
+                nline=hl->usedlines-1;
174 203
         /* invalidate from this line on */
204
+        nline=(nline<0)?0:nline;
175 205
         hl_invalidatefrom(redata,hl,nline);
176
-        return(0);
177
-}
178
-
179
-static int
180
-redata_highlighter_commit(redata_t *redata, redata_plugin_t *slot,char *filename)
181
-{
182
-        highlighter_t *hl=(highlighter_t *) ((slot!=NULL)?(slot->userptr):NULL);
183
-        if(redata==NULL || hl==NULL || filename==NULL)
184
-                return(-1); /* sanity check failed */
185
-        if(hl->flag_doneall)
186
-                return(0);
187
-        /* calc highlight of one additional line */
188
-        hl_doline(redata, hl, hl->usedlines);
206
+#if 1
207
+fprintf(stderr,"INVALIDATING LINE %i\n",nline);
208
+#endif
189 209
         return(0);
190 210
 }
191 211
 
... ...
@@ -274,12 +294,582 @@ hl_getplugin(redata_t *redata)
274 294
         return(hl);
275 295
 }
276 296
 
277
-
278 297
 static int
279 298
 hl_doline(redata_t *redata, highlighter_t *hl, int nline)
280 299
 {
300
+        int i;
301
+        long realpos;
302
+        long pos;
303
+        char *ptr;
304
+        int len;
305
+        hline_t *line;
306
+        long redataused;
307
+        int has_nl;
308
+        int has_next;
309
+        char **keywords;
310
+        int nkeywords;
311
+        char **directives;
312
+        int ndirectives;
313
+        int maxlenkeywords,maxlendirectives;
314
+        linecolor_t *linecolor;
315
+        int prev_char;
316
+        int prev_char_mask;
317
+        int cant_define;
318
+        int cant_directivekeyword;
319
+        int is_directiveinclude;
320
+        int opaque;
321
+        int posoffset;
322
+        enum {
323
+                mode_whatever=0,
324
+                mode_in_multilinecomment,
325
+                mode_in_linecomment,
326
+                mode_in_directive,
327
+                mode_in_string,
328
+                mode_in_directivestring,
329
+        } mode,mlcprevmode;
330
+        if(redata==NULL || hl==NULL || nline<0)
331
+                return(-1); /* sanoty check failed */
332
+        if(hl->usedlines>nline)
333
+                return(0); /* nothing to do */
334
+        if(hl_C_getkeywords(&keywords,&nkeywords,&maxlenkeywords)==-1)
335
+                return(-1); /* couldn't get keyword list */
336
+        if(hl_C_getdirectives(&directives,&ndirectives,&maxlendirectives)==-1)
337
+                return(-1); /* couldn't get directive list */
338
+        /* make sure keywordbuf is large enough */
339
+        if(maxlenkeywords>hl->sizekeywordbuf) {
340
+                char *newkeywordbuf;
341
+                int newsize;
342
+                newsize=maxlenkeywords;
343
+                if((newkeywordbuf=realloc(hl->keywordbuf,newsize))==NULL)
344
+                        return(-1); /* insufficient memory */
345
+                memset(newkeywordbuf,0,newsize);
346
+                hl->keywordbuf=newkeywordbuf;
347
+                hl->sizekeywordbuf=newsize;
348
+                hl->usedkeywordbuf=0;
349
+        }
350
+        /* make sure directivebuf is large enough */
351
+        if(maxlendirectives>hl->sizedirectivebuf) {
352
+                char *newdirectivebuf;
353
+                int newsize;
354
+                newsize=maxlendirectives;
355
+                if((newdirectivebuf=realloc(hl->directivebuf,newsize))==NULL)
356
+                        return(-1); /* insufficient memory */
357
+                memset(newdirectivebuf,0,newsize);
358
+                hl->directivebuf=newdirectivebuf;
359
+                hl->sizedirectivebuf=newsize;
360
+                hl->useddirectivebuf=0;
361
+        }
362
+        /* make sure we have enough hline_t structs */
363
+        if(hl->sizelines<=nline) {
364
+                hline_t *newlines;
365
+                int newsize=(nline+1+HLINETBLOCK)/HLINETBLOCK;
366
+                newsize*=HLINETBLOCK;
367
+                if((newlines=realloc(hl->lines,newsize*sizeof(hline_t)))==NULL)
368
+                        return(-1); /* insufficient memory */
369
+                hl->lines=newlines;
370
+                memset(hl->lines+hl->sizelines,0,(newsize-hl->sizelines)*sizeof(hline_t));
371
+                hl->sizelines=newsize;
372
+        }
373
+        /* make sure we have previous lines highlighted */
374
+        for(i=hl->usedlines;i<nline;i++) {
375
+#if 0
376
+fprintf(stderr,"Recursing from %i to %i\n",nline,i);
377
+#endif
378
+                if(hl_doline(redata,hl,i)==-1)
379
+                        return(-1); /* error highlighting line */
380
+        }
381
+        hl_invalidatefrom(redata,hl,nline);
382
+        line=hl->lines+nline;
383
+        if(redata_linecol2pos(redata,nline,0,&realpos,NULL)==-1)
384
+                return(-1); /* couldn't get line pos */
281 385
         /* NOTE: here comes the highlighter */
282
-#warning XXX TODO: implement this
283
-        return(-1);
386
+        line->pos=realpos;
387
+        line->off=(nline==0)?0:hl->lines[nline-1].off+hl->lines[nline-1].len;
388
+        line->len=0;
389
+        line->endingmode=mode_whatever;
390
+        redataused=redata_getused(redata);
391
+        mode=(nline>0)?line[-1].endingmode:mode_whatever;
392
+        cant_define=0;
393
+        cant_directivekeyword=0;
394
+        is_directiveinclude=0;
395
+        opaque=0;
396
+        linecolor=hl_addtolinecolor(&opaque,hl,NULL,color_normal,0);
397
+        posoffset=0;
398
+#if 0
399
+fprintf(stderr,"Doing line %i pos:%li\n",nline,line->pos);
400
+#endif
401
+        prev_char='\0';
402
+        prev_char_mask=0xff;
403
+        hl->usedkeywordbuf=0;
404
+        hl->useddirectivebuf=0;
405
+        mlcprevmode=mode_whatever;
406
+        do {
407
+                if(redata_line_rawinfo(redata,realpos+posoffset,&pos,&ptr,&len,NULL)==-1)
408
+                        return(-1); /* couldn't get line data */
409
+                has_nl=((len>0 && ptr[len-1]=='\n')?1:0);
410
+                has_next=(len==0)?1:(ptr[len-1]=='\n')?0:1;
411
+                /* special case: line with only a newline */
412
+                if(posoffset==0 && has_nl==1 && len==1) {
413
+                        /* delete the existing linecolor and break */
414
+                        line->len=0;
415
+                        break;
416
+                }
417
+                /* iterate */
418
+#if 0
419
+fprintf(stderr,"Line %i chunk at posoffset %i\n",nline, posoffset);
420
+#endif
421
+#warning FALTA PONER DE UN COLOR DIFERENTE lo de <nombre.h> de los #include (pero no de los #define!)
422
+                for(i=0;i<(len-has_nl);prev_char=(ptr[i]&prev_char_mask),prev_char_mask=0xff,i++) {
423
+#if 0
424
+if(nline==1)
425
+        fprintf(stderr,"ptr[%i]='%c' prev_char='%s%c'\n",i,ptr[i],(prev_char=='\0')?"\\":"",(prev_char=='\0')?'0':prev_char);
426
+#endif
427
+                        /* special case: keyword ends in a change of mode */
428
+                        if(mode!=mode_whatever && hl->usedkeywordbuf>0) {
429
+                                if(hl_searchlist(keywords,nkeywords,hl->keywordbuf,hl->usedkeywordbuf,NULL)==0) {
430
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart,color_keyword);
431
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart+hl->usedkeywordbuf-1,color_keyword);
432
+                                }
433
+                                hl->usedkeywordbuf=0;
434
+                        }
435
+                        /* end of special case */
436
+                        if(mode==mode_whatever) {
437
+                                if(prev_char=='\\' || ptr[i]=='\\') {
438
+                                        /* escape char mark or escaped char */
439
+                                        continue;
440
+                                }
441
+                                if(prev_char=='/' && ptr[i]=='/') {
442
+                                        mode=mode_in_linecomment;
443
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i-1,color_linecomment);
444
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_linecomment);
445
+                                        continue;
446
+                                }
447
+                                if(prev_char=='/' && ptr[i]=='*') {
448
+                                        mlcprevmode=mode;
449
+                                        mode=mode_in_multilinecomment;
450
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i-1,color_multilinecomment);
451
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_multilinecomment);
452
+                                        continue;
453
+                                }
454
+                                if(ptr[i]=='\"') {
455
+                                        mode=mode_in_string;
456
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_string);
457
+                                        continue;
458
+                                }
459
+                                if(!cant_define && ptr[i]=='#') {
460
+                                        mode=mode_in_directive;
461
+                                        is_directiveinclude=0;
462
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_directive);
463
+                                        continue;
464
+                                }
465
+                                /* keyword detection */
466
+                                if(hl->usedkeywordbuf==0 && ((ptr[i]>='a' && ptr[i]<='z') || (ptr[i]>='A' && ptr[i]<='Z') || ptr[i]=='_')) {
467
+                                        cant_define=1;
468
+                                        hl->keywordbuf[hl->usedkeywordbuf++]=ptr[i];
469
+                                        hl->keywordbufstart=posoffset+i;
470
+                                } else if(hl->usedkeywordbuf>0 && ((ptr[i]>='0' && ptr[i]<='9') || (ptr[i]>='a' && ptr[i]<='z') || (ptr[i]>='A' && ptr[i]<='Z') || ptr[i]=='_')) {
471
+                                        if(hl->usedkeywordbuf<hl->sizekeywordbuf) {
472
+                                                hl->keywordbuf[hl->usedkeywordbuf++]=ptr[i];
473
+                                        } else {
474
+                                                hl->keywordbuf[0]='\0'; /* too long */
475
+                                        }
476
+                                }
477
+                                if(hl->usedkeywordbuf>0 && !((ptr[i]>='0' && ptr[i]<='9') || (ptr[i]>='a' && ptr[i]<='z') || (ptr[i]>='A' && ptr[i]<='Z') || ptr[i]=='_')) {
478
+                                        if(hl_searchlist(keywords,nkeywords,hl->keywordbuf,hl->usedkeywordbuf,NULL)==0) {
479
+                                                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart,color_keyword);
480
+                                                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart+hl->usedkeywordbuf-1,color_keyword);
481
+                                        }
482
+                                        hl->usedkeywordbuf=0;
483
+
484
+                                }
485
+                                /* keyword detection */
486
+                                if(strchr("0123456789",ptr[i])!=NULL) {
487
+                                        cant_define=1;
488
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_number);
489
+                                        continue;
490
+                                }
491
+                                if(strchr("<>=+-%*/!|&^",ptr[i])!=NULL) {
492
+                                        cant_define=1;
493
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_operator);
494
+                                        continue;
495
+                                }
496
+                                if(strchr("(){}[],;",ptr[i])!=NULL) {
497
+                                        cant_define=1;
498
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_symbol);
499
+                                        continue;
500
+                                }
501
+                                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_normal);
502
+                                continue;
503
+                        }
504
+                        if(mode==mode_in_multilinecomment) {
505
+                                if(prev_char=='\\' || ptr[i]=='\\') {
506
+                                        continue;
507
+                                }
508
+                                if(prev_char=='*' && ptr[i]=='/') {
509
+                                        prev_char_mask=0x00;
510
+                                        mode=mlcprevmode;
511
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_multilinecomment);
512
+                                        continue;
513
+                                }
514
+                                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_multilinecomment);
515
+                                continue;
516
+                        }
517
+                        if(mode==mode_in_directive) {
518
+                                if(prev_char=='\\' || ptr[i]=='\\') {
519
+                                        continue;
520
+                                }
521
+                                if(prev_char=='/' && ptr[i]=='/') {
522
+                                        mode=mode_in_linecomment;
523
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i-1,color_linecomment);
524
+                                         linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_linecomment);
525
+                                        continue;
526
+                                }
527
+                                if(prev_char=='/' && ptr[i]=='*') {
528
+                                        mlcprevmode=mode;
529
+                                        mode=mode_in_multilinecomment;
530
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i-1,color_multilinecomment);
531
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_multilinecomment);
532
+                                        continue;
533
+                                }
534
+                                /* directive detection */
535
+                                if(!cant_directivekeyword && hl->useddirectivebuf==0 && ((ptr[i]>='a' && ptr[i]<='z') || (ptr[i]>='A' && ptr[i]<='Z') || ptr[i]=='_')) {
536
+                                        hl->directivebuf[hl->useddirectivebuf++]=ptr[i];
537
+                                        hl->directivebufstart=posoffset+i;
538
+                                } else if(hl->useddirectivebuf>0 && ((ptr[i]>='0' && ptr[i]<='9') || (ptr[i]>='a' && ptr[i]<='z') || (ptr[i]>='A' && ptr[i]<='Z') || ptr[i]=='_')) {
539
+                                        if(hl->useddirectivebuf<hl->sizedirectivebuf) {
540
+                                                hl->directivebuf[hl->useddirectivebuf++]=ptr[i];
541
+                                        } else {
542
+                                                hl->directivebuf[0]='\0'; /* too long */
543
+                                                cant_directivekeyword=1;
544
+                                        }
545
+                                }
546
+                                if(hl->useddirectivebuf>0 && !((ptr[i]>='0' && ptr[i]<='9') || (ptr[i]>='a' && ptr[i]<='z') || (ptr[i]>='A' && ptr[i]<='Z') || ptr[i]=='_')) {
547
+                                        int nfound;
548
+                                        if(hl_searchlist(directives,ndirectives,hl->directivebuf,hl->useddirectivebuf,&nfound)==0) {
549
+                                                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->directivebufstart,color_directivekeyword);
550
+                                                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->directivebufstart+hl->useddirectivebuf-1,color_directivekeyword);
551
+                                                if(strcmp(directives[nfound],"include")==0)
552
+                                                        is_directiveinclude=1;
553
+                                        }
554
+                                        hl->useddirectivebuf=0;
555
+                                        cant_directivekeyword=1;
556
+                                }
557
+                                if(ptr[i]!=' ' && ptr[i]!='\t')
558
+                                        cant_directivekeyword=1;
559
+                                /* directive detection */
560
+                                if(ptr[i]=='\"') {
561
+                                        mode=mode_in_directivestring;
562
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,(is_directiveinclude==0)?color_directivestring:color_directiveincludestring);
563
+                                        continue;
564
+                                }
565
+                                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,(is_directiveinclude==0)?color_directive:color_directiveinclude);
566
+                                continue;
567
+                        }
568
+                        if(mode==mode_in_directivestring) {
569
+                                if(prev_char=='\\' || ptr[i]=='\\') {
570
+                                        continue;
571
+                                }
572
+                                if(ptr[i]=='\"') {
573
+                                        mode=mode_in_directive;
574
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,(is_directiveinclude==0)?color_directivestring:color_directiveincludestring);
575
+                                        continue;
576
+                                }
577
+                                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,(is_directiveinclude==0)?color_directivestring:color_directiveincludestring);
578
+                                continue;
579
+                        }
580
+                        if(mode==mode_in_string) {
581
+                                if(prev_char=='\\' || ptr[i]=='\\') {
582
+                                        continue;
583
+                                }
584
+                                if(ptr[i]=='\"') {
585
+                                        mode=mode_whatever;
586
+                                        linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_string);
587
+                                        continue;
588
+                                }
589
+                                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_string);
590
+                                continue;
591
+                        }
592
+                        if(mode==mode_in_linecomment) {
593
+                                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_linecomment);
594
+                                continue;
595
+                        }
596
+                }
597
+                posoffset+=len;
598
+        } while(has_next!=0 && (pos+posoffset)<redataused);
599
+        /* special case: keyword ends at end-of-line */
600
+        if(mode==mode_whatever && hl->usedkeywordbuf>0 && hl_searchlist(keywords,nkeywords,hl->keywordbuf,hl->usedkeywordbuf,NULL)==0) {
601
+                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart,color_keyword);
602
+                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart+hl->usedkeywordbuf-1,color_keyword);
603
+        }
604
+        /* end of special case */
605
+        /* special case: deirectivekeyword ends at end-of-line */
606
+        if(mode==mode_in_directive && hl->useddirectivebuf>0 && hl_searchlist(directives,ndirectives,hl->directivebuf,hl->useddirectivebuf,NULL)==0) {
607
+                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->directivebufstart,color_directivekeyword);
608
+                linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->directivebufstart+hl->useddirectivebuf-1,color_directivekeyword);
609
+        }
610
+        /* end of special case */
611
+        if(linecolor==NULL)
612
+                return(-1);
613
+        if((prev_char=='\\' && mode!=mode_in_linecomment) || mode==mode_in_multilinecomment)
614
+                line->endingmode=mode;
615
+        hl->usedlines++;
616
+        return(0);
617
+}
618
+
619
+
620
+int
621
+hl_C_getkeywords(char ***keywords,int *nkeywords, int *maxlen)
622
+{
623
+        static int init=0;
624
+        static int staticnkeywords=0;
625
+        static int staticmaxlen=0;
626
+        static const char *C_keywords[]={
627
+"auto",
628
+"break",
629
+"case",
630
+"char",
631
+"const",
632
+"continue",
633
+"default",
634
+"do",
635
+"double",
636
+"else",
637
+"enum",
638
+"extern",
639
+"float",
640
+"for",
641
+"goto",
642
+"if",
643
+"inline",
644
+"int",
645
+"long",
646
+"register",
647
+"restrict",
648
+"return",
649
+"short",
650
+"signed",
651
+"sizeof",
652
+"static",
653
+"struct",
654
+"switch",
655
+"typedef",
656
+"union",
657
+"unsigned",
658
+"void",
659
+"volatile",
660
+"while",
661
+"_Alignas",
662
+"_Alignof",
663
+"_Atomic",
664
+"_Bool",
665
+"_Complex",
666
+"_Generic",
667
+"_Imaginary",
668
+"_Noreturn",
669
+"_Static_assert",
670
+"_Thread_local",
671
+NULL
672
+};
673
+        if(keywords==NULL || nkeywords==NULL)
674
+                return(-1);
675
+        if(init==0) {
676
+                int k,l,maxl;
677
+                for(k=0,maxl=0;C_keywords[k]!=NULL;k++) {
678
+                        l=strlen(C_keywords[k]);
679
+                        maxl=(l>maxl)?l:maxl;
680
+                }
681
+                staticnkeywords=k;
682
+                staticmaxlen=maxl;
683
+                init=1;
684
+        }
685
+        *keywords=(char **)C_keywords;
686
+        *nkeywords=staticnkeywords;
687
+        if(maxlen!=NULL)
688
+                *maxlen=staticmaxlen;
689
+        return(0);
690
+}
691
+
692
+int
693
+hl_C_getdirectives(char ***directives,int *ndirectives, int *maxlen)
694
+{
695
+        static int init=0;
696
+        static int staticndirectives=0;
697
+        static int staticmaxlen=0;
698
+        static const char *C_directives[]={
699
+"define",
700
+"undef",
701
+"include",
702
+"if",
703
+"ifdef",
704
+"ifndef",
705
+"else",
706
+"elif",
707
+"endif",
708
+"line",
709
+"error",
710
+"pragma",
711
+};
712
+        if(directives==NULL || ndirectives==NULL)
713
+                return(-1);
714
+        if(init==0) {
715
+                int k,l,maxl;
716
+                for(k=0,maxl=0;C_directives[k]!=NULL;k++) {
717
+                        l=strlen(C_directives[k]);
718
+                        maxl=(l>maxl)?l:maxl;
719
+                }
720
+                staticndirectives=k;
721
+                staticmaxlen=maxl;
722
+                init=1;
723
+        }
724
+        *directives=(char **)C_directives;
725
+        *ndirectives=staticndirectives;
726
+        if(maxlen!=NULL)
727
+                *maxlen=staticmaxlen;
728
+        return(0);
729
+}
730
+
731
+int
732
+hl_searchlist(char **wordlist, int wordlistlen, char *word, int wordlen, int *res)
733
+{
734
+        int k;
735
+        if(wordlist==NULL || wordlistlen<0 || word==NULL || wordlen<0)
736
+                return(-1); /* sanity check failed */
737
+        for(k=0;k<wordlistlen;k++) {
738
+                if(memcmp(wordlist[k],word,wordlen)==0 && (wordlist[k])[wordlen]=='\0') {
739
+                        if(res!=NULL)
740
+                                *res=k;
741
+                        return(0); /* word found */
742
+                }
743
+        }
744
+        return(-1); /* word not found */
745
+}
746
+
747
+
748
+linecolor_t *
749
+hl_addtolinecolor(int *opaque, highlighter_t *hl,linecolor_t *linecolor,int posoff,int color)
750
+{
751
+        hline_t *line;
752
+        if(opaque==NULL || *opaque<0 || hl==NULL || (posoff!=0 && linecolor==NULL) || color<0 || posoff<0)
753
+                return(NULL); /* sanity check failed */
754
+#if 0
755
+#define DEBUGLINE 12
756
+if(hl->usedlines==DEBUGLINE) {
757
+int i,k;
758
+int l=hl->lines[hl->usedlines].len;
759
+linecolor_t *lc=(linecolor_t *) (hl->buf+hl->lines[hl->usedlines].off);
760
+fprintf(stderr,"addtolinecolor pre.: nline:%i *opaque:%i posoff:%i color:%i current:\"",hl->usedlines,*opaque,posoff,color);
761
+for(k=0;k<l;k+=sizeof(linecolor_t),lc++) {
762
+        for(i=0;i<lc->len;i++)
763
+                fprintf(stderr,"%x",lc->color);
764
+}
765
+hl->keywordbuf[hl->usedkeywordbuf]='\0';
766
+hl->directivebuf[hl->useddirectivebuf]='\0';
767
+fprintf(stderr,"\" (%i%s%s%s,%i%s%s%s)\n",
768
+hl->usedkeywordbuf,
769
+(hl->usedkeywordbuf==0)?"":" \"",
770
+(hl->usedkeywordbuf==0)?"":hl->keywordbuf,
771
+(hl->usedkeywordbuf==0)?"":"\"",
772
+hl->useddirectivebuf,
773
+(hl->useddirectivebuf==0)?"":" \"",
774
+(hl->useddirectivebuf==0)?"":hl->directivebuf,
775
+(hl->useddirectivebuf==0)?"":"\""
776
+);
777
+}
778
+#endif
779
+        /* make sure there is a space for a linecolor_t in buf */
780
+        if((hl->usedbuf+sizeof(linecolor_t))>=hl->sizebuf) {
781
+                char *newbuf;
782
+                int newsize=(hl->sizebuf+sizeof(linecolor_t)+BUFBLOCK-1)/BUFBLOCK;
783
+                newsize*=BUFBLOCK;
784
+                if((newbuf=realloc(hl->buf,newsize))==NULL)
785
+                        return(NULL); /* insufficient memory */
786
+                hl->buf=newbuf;
787
+                memset(hl->buf+hl->sizebuf,0,(newsize-hl->sizebuf));
788
+                hl->sizebuf=newsize;
789
+        }
790
+        line=hl->lines+hl->usedlines;
791
+        /* posoff==0 means "do init" */
792
+        if(posoff==0) {
793
+                line->off=(hl->usedlines==0)?0:hl->lines[hl->usedlines-1].off+hl->lines[hl->usedlines-1].len;
794
+                line->len=sizeof(linecolor_t);
795
+                linecolor=(linecolor_t *) (hl->buf+line->off);
796
+                linecolor->len=1;
797
+                linecolor->color=color;
798
+                *opaque=1;
799
+#if 0
800
+if(hl->usedlines==DEBUGLINE) {
801
+int i,k;
802
+int l=hl->lines[hl->usedlines].len;
803
+linecolor_t *lc=(linecolor_t *) (hl->buf+hl->lines[hl->usedlines].off);
804
+fprintf(stderr,"addtolinecolor post: nline:%i *opaque:%i posoff:%i color:%i         \"",hl->usedlines,*opaque,posoff,color);
805
+for(k=0;k<l;k+=sizeof(linecolor_t),lc++) {
806
+        for(i=0;i<lc->len;i++)
807
+                fprintf(stderr,"%x",lc->color);
808
+}
809
+fprintf(stderr,"\"\n");
810
+}
811
+#endif
812
+                return(linecolor);
813
+        }
814
+        /* if posoff was already done, truncate */
815
+        if(posoff<*opaque) {
816
+                int delta,maxdelta;
817
+                int l;
818
+                maxdelta=line->len;
819
+                line->len=0;
820
+                for(delta=0,l=0;delta<maxdelta;l+=linecolor->len,delta+=sizeof(linecolor_t)) {
821
+                        linecolor=(linecolor_t *) (hl->buf+line->off+delta);
822
+                        line->len=delta;
823
+                        if((l+linecolor->len)>=posoff) {
824
+                                line->len+=sizeof(linecolor_t);
825
+                                linecolor->len=posoff-l;
826
+                                *opaque=posoff;
827
+                                break;
828
+                        }
829
+                }
830
+                hl->usedbuf=line->off+line->len;
831
+        }
832
+        linecolor=(linecolor_t *) (hl->buf+line->off+line->len);
833
+        /* if we have not changed color, expand */
834
+        if(linecolor[-1].color==color) {
835
+                int added=(posoff-*opaque)+1;
836
+                linecolor[-1].len+=added;
837
+                *opaque+=added;
838
+#if 0
839
+if(hl->usedlines==DEBUGLINE) {
840
+int i,k;
841
+int l=hl->lines[hl->usedlines].len;
842
+linecolor_t *lc=(linecolor_t *) (hl->buf+hl->lines[hl->usedlines].off);
843
+fprintf(stderr,"addtolinecolor post: nline:%i *opaque:%i posoff:%i color:%i         \"",hl->usedlines,*opaque,posoff,color);
844
+for(k=0;k<l;k+=sizeof(linecolor_t),lc++) {
845
+        for(i=0;i<lc->len;i++)
846
+                fprintf(stderr,"%x",lc->color);
847
+}
848
+fprintf(stderr,"\"\n");
284 849
 }
850
+#endif
851
+                return(linecolor-1);
852
+        }
853
+        /* add new linecolor */
854
+        linecolor->len=1;
855
+        linecolor->color=color;
856
+        *opaque+=1;
857
+        line->len+=sizeof(linecolor_t);
858
+        hl->usedbuf+=sizeof(linecolor_t);
859
+#if 0
860
+if(hl->usedlines==DEBUGLINE) {
861
+int i,k;
862
+int l=hl->lines[hl->usedlines].len;
863
+linecolor_t *lc=(linecolor_t *) (hl->buf+hl->lines[hl->usedlines].off);
864
+fprintf(stderr,"addtolinecolor post: nline:%i *opaque:%i posoff:%i color:%i         \"",hl->usedlines,*opaque,posoff,color);
865
+for(k=0;k<l;k+=sizeof(linecolor_t),lc++) {
866
+        for(i=0;i<lc->len;i++)
867
+                fprintf(stderr,"%x",lc->color);
868
+}
869
+fprintf(stderr,"\"\n");
870
+}
871
+#endif
872
+        return(linecolor);
873
+}
874
+
285 875
 
... ...
@@ -22,6 +22,7 @@ typedef struct line_t {
22 22
         long pos;
23 23
         int off; /* offset int buf */
24 24
         int len; /* size used in buf */
25
+        int endingmode;
25 26
 } hline_t;
26 27
 
27 28
 typedef struct hcolor_t {
... ...
@@ -38,6 +39,14 @@ typedef struct highlighter_t {
38 39
         int sizecolors;
39 40
         hcolor_t *colors;
40 41
         int flag_doneall;
42
+        int sizekeywordbuf;
43
+        int usedkeywordbuf;
44
+        char *keywordbuf;
45
+        int keywordbufstart;
46
+        int sizedirectivebuf;
47
+        int useddirectivebuf;
48
+        char *directivebuf;
49
+        int directivebufstart;
41 50
 } highlighter_t;
42 51
 
43 52
 int redata_highlighter_register(redata_t *redata, redata_plugin_t *slot);
... ...
@@ -16,6 +16,35 @@
16 16
 #include <time.h>
17 17
 
18 18
 #include "re_data.h"
19
+#if 0
20
+#define INITIALCHUNK 20
21
+#define MAXDUMP 25
22
+static void
23
+redata_debug_chunkdump(redata_t *redata, char *title)
24
+{
25
+        int m,k;
26
+        char c;
27
+        title=(title==NULL)?"":title;
28
+        fprintf(stderr,"%s:CHUNKDUMP (sizechunks:%i)\n",title,redata->sizechunks);
29
+        for(m=INITIALCHUNK;m<redata->sizechunks && m<MAXDUMP;m++) {
30
+                fprintf(stderr,"%s:chunk[%i] len:%-5i data:\"",title,m,redata->chunks[m]->useddata);
31
+                for(k=0;k<redata->chunks[m]->useddata;k++) {
32
+                        c=redata->chunks[m]->data[k];
33
+                        if(c=='\n' || c=='\0')
34
+                                fprintf(stderr,"\\%c",(c=='\n')?'n':'0');
35
+                        else if(c<' ' || c>'~' || c=='\\')
36
+                                fprintf(stderr,"\\x%02X",((unsigned char *)redata->chunks[m]->data)[k]);
37
+                        else
38
+                                fprintf(stderr,"%c",c);
39
+                }
40
+                fprintf(stderr,"\"\n");
41
+        }
42
+}
43
+#define CHUNKDEBUG(a) redata_debug_chunkdump a
44
+#else
45
+#define CHUNKDEBUG(a)
46
+#endif
47
+
19 48
 #include "re_plugin_unsaved.h"
20 49
 #include "re_plugin_highlighter.h"
21 50
 #include "re_ui.h"
... ...
@@ -416,7 +445,7 @@ re_processkey_editing(re_t *re, SDL_Event *event)
416 445
                 strncpy(event->text.text,spaces+(re->curcol%8),sizeof(event->text.text));
417 446
                 event->text.text[sizeof(event->text.text)-1]='\0';
418 447
         } else if(event->type==SDL_KEYDOWN && event->key.keysym.sym==SDLK_DELETE) {
419
-#if 1
448
+#if 0
420 449
 fprintf(stderr,"SDL_KEYDOWN: DELETE\n");
421 450
 #endif
422 451
                 long realend;
... ...
@@ -969,6 +998,10 @@ re_drawcontents(re_t *re)
969 998
         int in_error;
970 999
         long realstart,realend;
971 1000
         int drawn_cursor;
1001
+        hcolor_t *colors;
1002
+        int ncolors;
1003
+        linecolor_t *linecolors;
1004
+        int nlinecolors;
972 1005
         if(re==NULL)
973 1006
                 return(-1);
974 1007
         reui_fill(re->ui,re->x,re->y,re->w,re->h,"\xdf\xdf\xdf\xff");
... ...
@@ -985,11 +1018,35 @@ re_drawcontents(re_t *re)
985 1018
         reui_fill(re->ui,re->x,re->y+(re->curline-re->originline)*re->ui->fontheight,re->w,re->ui->fontheight+1,"\xef\xef\xef\xff");
986 1019
         /* draw the lines */
987 1020
         drawn_cursor=0;
1021
+        colors=redata_highlighter_getcolors(re->data,&ncolors);
1022
+#if 0
1023
+CHUNKDEBUG((re->data,"Pre-display"));
1024
+#endif
988 1025
         for(y=re->y;y<(re->y+re->h);y+=re->ui->fontheight,row++) {
1026
+                /* definiciton of vars for teacking linecolor usage */
1027
+                int curlinecolor; /* current linecolor */
1028
+                int usedlenlinecolor; /* number of bytes of current linecolor already drawn */
1029
+                /* end of deifinitions */
989 1030
                 if(redata_line_realstart(re->data,pos,&realstart)==-1 || redata_line_realend(re->data,pos,&realend)==-1) {
990 1031
                         break; /* couldn't get real start/end */
991 1032
                 }
992 1033
                 in_error=0;
1034
+                linecolors=(colors==NULL)?NULL:redata_highlighter_getline(re->data,re->originline+row,&nlinecolors);
1035
+#if 0
1036
+#define DEBUGLINE 12
1037
+if((re->origincol+row)==DEBUGLINE) {
1038
+int i,k,l=nlinecolors*sizeof(linecolor_t);
1039
+linecolor_t *lc=linecolors;
1040
+fprintf(stderr,"linecolors for line:%i \"",re->origincol+row);
1041
+for(k=0;k<l;k+=sizeof(linecolor_t),lc++) {
1042
+        for(i=0;i<lc->len;i++)
1043
+                fprintf(stderr,"%x",lc->color);
1044
+}
1045
+fprintf(stderr,"\"\n");
1046
+}
1047
+#endif
1048
+                curlinecolor=0;
1049
+                usedlenlinecolor=0;
993 1050
                 for(tmpcol=0,pos=realstart,availcol=0;tmpcol<(re->origincol+re->maxcol) && pos<=realend;pos=newpos+len,tmpcol+=availcol) {
994 1051
                         if(redata_line_rawinfo(re->data,pos,&newpos,&ptr,&len,&is_continuation)==-1) {
995 1052
                                 in_error=1;
... ...
@@ -998,7 +1055,53 @@ re_drawcontents(re_t *re)
998 1055
                         has_nl=((len>0 && ptr[len-1]=='\n')?1:0);
999 1056
                         availcol=redata_generic_utf8len(ptr,len-has_nl);
1000 1057
 #warning TODO: consider tabs
1001
-                        reui_write(re->ui,re->x+(tmpcol-re->origincol)*re->ui->fontwidth,y,"\x00\x00\x00\xff",ptr,len-has_nl);
1058
+                        if(linecolors!=NULL) {
1059
+                                int used,usedcol; /* number of bytes/columns used of redata chunk (those are already drawn) */
1060
+                                used=usedcol=0;
1061
+                                /* while the avail text is larger than the linecolor len */
1062
+                                while((len-has_nl-used)>=(linecolors[curlinecolor].len-usedlenlinecolor)) {
1063
+#if 0
1064
+if((re->origincol+row)==DEBUGLINE) {
1065
+int i,l;
1066
+fprintf(stderr,"ui_write (full) for line:%i curlinecolor:%i color:%i at:%i str:\"",(re->origincol+row),curlinecolor,linecolors[curlinecolor].color,(tmpcol-re->origincol+usedcol));
1067
+l=linecolors[curlinecolor].len-usedlenlinecolor;
1068
+for(i=0;i<l;i++)
1069
+fprintf(stderr,"%c",ptr[used+i]);
1070
+fprintf(stderr,"\" (used:%i)\n",used);
1071
+}
1072
+#endif
1073
+                                        reui_write(re->ui,re->x+(tmpcol-re->origincol+usedcol)*re->ui->fontwidth,y,colors[linecolors[curlinecolor].color].rgba,ptr+used,linecolors[curlinecolor].len-usedlenlinecolor);
1074
+                                        usedcol+=redata_generic_utf8len(ptr+used,linecolors[curlinecolor].len-usedlenlinecolor);
1075
+                                        used+=linecolors[curlinecolor].len-usedlenlinecolor;
1076
+                                        curlinecolor++;
1077
+                                        usedlenlinecolor=0;
1078
+                                }
1079
+                                /* for the last bytes of avail text, after writing them we save how many bytes we have processed of that linecolor to be able to continue later */
1080
+                                if((len-has_nl-used)>0 && (linecolors[curlinecolor].len-usedlenlinecolor)>(len-has_nl-used)) {
1081
+#if 0
1082
+if((re->origincol+row)==DEBUGLINE) {
1083
+int i,l;
1084
+fprintf(stderr,"ui_write (last) for line:%i curlinecolor:%i color:%i at:%i str:\"",(re->origincol+row),curlinecolor,linecolors[curlinecolor].color,(tmpcol-re->origincol+usedcol));
1085
+l=(len-has_nl-used);
1086
+for(i=0;i<l;i++)
1087
+fprintf(stderr,"%c",ptr[used+i]);
1088
+fprintf(stderr,"\" (used:%i)\n",used);
1089
+}
1090
+#endif
1091
+                                        reui_write(re->ui,re->x+(tmpcol-re->origincol+usedcol)*re->ui->fontwidth,y,colors[linecolors[curlinecolor].color].rgba,ptr+used,(len-has_nl-used));
1092
+                                        usedcol+=redata_generic_utf8len(ptr+used,(len-has_nl-used));
1093
+                                        usedlenlinecolor+=(len-has_nl-used);
1094
+                                        used+=(len-has_nl-used);
1095
+                                }
1096
+#if 0
1097
+if((re->origincol+row)==DEBUGLINE) {
1098
+fprintf(stderr,"AFTER (used:%i)\n",used);
1099
+}
1100
+#endif
1101
+
1102
+                        } else {
1103
+                                reui_write(re->ui,re->x+(tmpcol-re->origincol)*re->ui->fontwidth,y,"\x00\x00\x00\xff",ptr,len-has_nl);
1104
+                        }
1002 1105
                         if(row==(re->curline-re->originline)) {
1003 1106
                                 if(re->curcol>=tmpcol && re->curcol<(tmpcol+availcol)) {
1004 1107
                                         reui_fill(re->ui,re->x+re->ui->fontwidth*(re->curcol-re->origincol),y,re->ui->fontwidth,re->ui->fontheight+1,"\x00\x00\x00\xff");