/* * re_plugin_highlighter.c * * A programmers editor * * re_data plugin to support the syntax highlighter. * * Author: Dario Rodriguez antartica@whereismybit.com * This program is licensed under the terms of GNU GPL v2.1+ */ #include #include #include #include #include #include #include #include #include "re_plugin_highlighter.h" #define PLUGINNAME "highlighter" #define HLINETBLOCK (16*1024) #define BUFBLOCK (64*1024) #define HIGHLIGHTERGROWSIZE (256*1024) #define DEFAULTCOLOR "\x80\x80\x80\xff" typedef enum colorsenum_t { color_normal=0, color_directive, color_directivekeyword, color_directivestring, color_directiveinclude, color_directiveincludestring, color_keyword, color_string, color_multilinecomment, color_linecomment, color_number, color_operator, color_symbol, color_endenum, } colorsenum_t; static int redata_highlighter_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd); static int redata_highlighter_postload(redata_t *redata, redata_plugin_t *slot,char *filename); static int hl_invalidatefrom(redata_t *redata, highlighter_t *hl, int nline); hcolor_t *hl_initcolors(int *ncolors, /* int color, char *colordef, */ ...); static highlighter_t *hl_getplugin(redata_t *redata); static int hl_doline(redata_t *redata, highlighter_t *hl, int nline); int hl_C_getkeywords(char ***keywords,int *nkeywords, int *maxlen); int hl_C_getdirectives(char ***directives,int *ndirectives, int *maxlen); int hl_searchlist(char **wordlist, int wordlistlen, char *word, int wordlen, int *res); linecolor_t *hl_addtolinecolor(int *opaque, highlighter_t *hl,linecolor_t *linecolor,int posoff, int color); int redata_highlighter_register(redata_t *redata, redata_plugin_t *slot) { hcolor_t *colors; int ncolors; highlighter_t *hl; if(redata==NULL || slot==NULL) return(-1); #if 1 /* "forest" theme */ colors=hl_initcolors(&ncolors, color_keyword,"\x38\x17\x1e\xff", color_directive,"\x38\x4b\x00\xff", color_directivekeyword,"\x63\x7d\x16\xff", color_directivestring,"\x07\x20\x3b\xff", color_directiveinclude,"\x16\x63\x7d\xff", color_directiveincludestring,"\x6\x13\x2d\xff", color_normal,"\x9a\x67\x43\xff", color_string,"\x9d\x15\x00\xff", color_multilinecomment,"\x4f\x40\x57\xff", color_linecomment,"\xc6\x8c\xa4\xff", color_number,"\x3b\x10\x35\xff", color_operator,"\xaa\x8c\xcd\xff", color_symbol,"\x69\x2a\x44\xff", color_endenum,DEFAULTCOLOR, -1); #else /* "alternative" theme (dark) */ colors=hl_initcolors(&ncolors, color_keyword,"\xcc\x99\xcc\xff",// color_directive,"\x38\x4b\x00\xff", color_directivekeyword,"\x63\x7d\x16\xff", color_directivestring,"\x07\x20\x3b\xff", color_directiveinclude,"\x16\x63\x7d\xff", color_directiveincludestring,"\x6\x13\x2d\xff", color_normal,"\xf2\xf0\xec\xff",// color_string,"\x99\xcc\x99\xff",// color_multilinecomment,"\x74\x73\x69\xff",// color_linecomment,"\x74\x73\x69\xff",// color_number,"\xf9\x91\x57\xff",// color_operator,"\x66\xcc\xcc\xff",// color_symbol,"\x91\xa7\xff\xff",// color_endenum,"\xf2\xf0\xec\xff",// -1); #endif if(colors==NULL || (hl=malloc(sizeof(highlighter_t)))==NULL) { if(colors!=NULL) free(colors),colors=NULL; return(-1); /* insufficient memory */ } memset(hl,0,sizeof(highlighter_t)); hl->sizebuf=hl->usedbuf=0; hl->sizecolors=ncolors; hl->colors=colors; strncpy(slot->name,PLUGINNAME,sizeof(slot->name)); slot->name[sizeof(slot->name)-1]='\0'; slot->unregister=redata_highlighter_unregister; slot->postload=redata_highlighter_postload; slot->add_or_unadd=redata_highlighter_add_or_unadd; slot->userptr=hl; return(0); } int redata_highlighter_unregister(redata_t *redata, redata_plugin_t *slot, char *filename) { highlighter_t *hl=(highlighter_t *) ((slot!=NULL)?(slot->userptr):NULL); if(redata==NULL || slot==NULL || hl==NULL) return(-1); if(hl->buf!=NULL) free(hl->buf),hl->buf=NULL; hl->sizebuf=hl->usedbuf=0; if(hl->colors!=NULL) free(hl->colors),hl->colors=NULL; hl->sizecolors=0; if(hl->lines!=NULL) free(hl->lines),hl->lines=NULL; hl->sizelines=hl->usedlines=0; if(hl->keywordbuf!=NULL) free(hl->keywordbuf),hl->keywordbuf=NULL; hl->sizekeywordbuf=hl->usedkeywordbuf=0; if(hl->directivebuf!=NULL) free(hl->directivebuf),hl->directivebuf=NULL; hl->sizedirectivebuf=hl->useddirectivebuf=0; if(slot->userptr!=NULL) free(slot->userptr),slot->userptr=NULL; return(0); } hcolor_t * redata_highlighter_getcolors(redata_t *redata, int *ncolors) { highlighter_t *hl; if(redata==NULL || (hl=hl_getplugin(redata))==NULL) return(NULL); /* sanity check failed or plugin not found */ if(ncolors!=NULL) *ncolors=hl->sizecolors; return(hl->colors); } linecolor_t * redata_highlighter_getline(redata_t *redata, int line, int *nlinecolors) { highlighter_t *hl; if(redata==NULL || line<0 || (hl=hl_getplugin(redata))==NULL) return(NULL); /* sanity check failed or plugin not found */ if(!hl->flag_doneall) hl_doline(redata,hl,line); if(line<0 || line>=hl->usedlines) return(NULL); if(nlinecolors!=NULL) *nlinecolors=(hl->lines[line].len)/sizeof(linecolor_t); return((linecolor_t *) (hl->buf+hl->lines[line].off)); } int redata_highlighter_getcolorindex(redata_t *redata, int line, int nthbyte) { int i,n; int nlinecolors; linecolor_t *linecolors; if((linecolors=redata_highlighter_getline(redata,line,&nlinecolors))==NULL) return(-1); for(i=0,n=0;n2 || template3[1]<0 || template3[1]>2 || template3[2]<0 || template3[2]>2) return; /* sanity check error */ if(invert==0) { ((unsigned char *)color->rgba)[0]=((unsigned char *)color->origrgba)[template3[0]]; ((unsigned char *)color->rgba)[1]=((unsigned char *)color->origrgba)[template3[1]]; ((unsigned char *)color->rgba)[2]=((unsigned char *)color->origrgba)[template3[2]]; } else { ((unsigned char *)color->rgba)[0]=255-((unsigned char *)color->origrgba)[template3[0]]; ((unsigned char *)color->rgba)[1]=255-((unsigned char *)color->origrgba)[template3[1]]; ((unsigned char *)color->rgba)[2]=255-((unsigned char *)color->origrgba)[template3[2]]; } return; } int redata_highlighter_settheme(redata_t *redata, int ntheme, int invert) { int permutations[6][3]={{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,1,0},{2,0,1}}; int *permutationtemplate; hcolor_t *colors; int ncolors,i; ntheme=(ntheme<0)?0:ntheme; ntheme%=6; permutationtemplate=permutations[ntheme]; if((colors=redata_highlighter_getcolors(redata, &ncolors))==NULL) return(-1); for(i=0;iuserptr):NULL); if(redata==NULL || slot==NULL || hl==NULL || undo==NULL || slot->active==0) return(-1); /* sanity check failed */ if(hl->usedlines==0) { return(0); /* nothing to do */ } /* get the first pos of the operation */ pos=undo->posorig; if((!is_unadd && undo->type=='D') || (is_unadd && undo->type=='A')) pos-=undo->len; if(undo->type=='M' && undo->posdestposdest; /* get line of pos */ for(nline=0;nlineusedlines;nline++) { if(hl->lines[nline].pos>pos) { nline--; break; } } /* special case: check if pos is inside last line */ if(nline>=hl->usedlines) nline=hl->usedlines-1; /* invalidate from this line on */ nline=(nline<0)?0:nline; hl_invalidatefrom(redata,hl,nline); return(0); } static int redata_highlighter_postload(redata_t *redata, redata_plugin_t *slot,char *filename) { #warning XXX TODO: get the language from the filename return(-1); } static int hl_invalidatefrom(redata_t *redata, highlighter_t *hl, int nline) { if(redata==NULL || hl==NULL || nline<0) return(-1); /* sanity check failed */ if(nline>=hl->usedlines) return(0); /* nothing to do */ if(nline==0) { hl->usedbuf=0; hl->usedlines=0; } hl->usedbuf=hl->lines[nline].off; hl->usedlines=nline; hl->flag_doneall=0; return(0); } hcolor_t * hl_initcolors(int *ncolors, /* int color, char *colordef, */ ...) { int maxcolor; int color; char *colordef; int round; hcolor_t *hcolors; va_list paramlist; int i; static char defcolor[]={DEFAULTCOLOR}; if(ncolors==NULL) return(NULL); /* sanity check failed */ *ncolors=0; hcolors=NULL; for(round=0;round<2;round++) { maxcolor=-1; va_start(paramlist,ncolors); while((color=va_arg(paramlist,int))>=0) { colordef=va_arg(paramlist,char *); maxcolor=(maxcolorsizeplugins;i++) { if(strcmp(redata->plugins[i].name,PLUGINNAME)==0) break; } if(i>=redata->sizeplugins || redata->plugins[i].active==0) return(NULL); /* plugin not found or nor active */ hl=(highlighter_t *) (redata->plugins[i].userptr); if(hl==NULL) return(NULL); /* internal error */ return(hl); } static int hl_doline(redata_t *redata, highlighter_t *hl, int nline) { int i; long realpos; long pos; char *ptr; int len; hline_t *line; long redataused; int has_nl; int has_next; char **keywords; int nkeywords; char **directives; int ndirectives; int maxlenkeywords,maxlendirectives; linecolor_t *linecolor; int prev_char; int prev_char_mask; int cant_define; int cant_directivekeyword; int is_directiveinclude; int opaque; int posoffset; enum { mode_whatever=0, mode_in_multilinecomment, mode_in_linecomment, mode_in_directive, mode_in_string, mode_in_singlestring, mode_in_directivestring, } mode,mlcprevmode; if(redata==NULL || hl==NULL || nline<0) return(-1); /* sanoty check failed */ if(hl->usedlines>nline) return(0); /* nothing to do */ if(hl_C_getkeywords(&keywords,&nkeywords,&maxlenkeywords)==-1) return(-1); /* couldn't get keyword list */ if(hl_C_getdirectives(&directives,&ndirectives,&maxlendirectives)==-1) return(-1); /* couldn't get directive list */ /* make sure keywordbuf is large enough */ if(maxlenkeywords>hl->sizekeywordbuf) { char *newkeywordbuf; int newsize; newsize=maxlenkeywords; if((newkeywordbuf=realloc(hl->keywordbuf,newsize))==NULL) return(-1); /* insufficient memory */ memset(newkeywordbuf,0,newsize); hl->keywordbuf=newkeywordbuf; hl->sizekeywordbuf=newsize; hl->usedkeywordbuf=0; } /* make sure directivebuf is large enough */ if(maxlendirectives>hl->sizedirectivebuf) { char *newdirectivebuf; int newsize; newsize=maxlendirectives; if((newdirectivebuf=realloc(hl->directivebuf,newsize))==NULL) return(-1); /* insufficient memory */ memset(newdirectivebuf,0,newsize); hl->directivebuf=newdirectivebuf; hl->sizedirectivebuf=newsize; hl->useddirectivebuf=0; } /* make sure we have enough hline_t structs */ if(hl->sizelines<=nline) { hline_t *newlines; int newsize=(nline+1+HLINETBLOCK)/HLINETBLOCK; newsize*=HLINETBLOCK; if((newlines=realloc(hl->lines,newsize*sizeof(hline_t)))==NULL) return(-1); /* insufficient memory */ hl->lines=newlines; memset(hl->lines+hl->sizelines,0,(newsize-hl->sizelines)*sizeof(hline_t)); hl->sizelines=newsize; } /* make sure we have previous lines highlighted */ for(i=hl->usedlines;ilines+nline; if(redata_linecol2pos(redata,nline,0,&realpos,NULL)==-1) return(-1); /* couldn't get line pos */ /* NOTE: here comes the highlighter */ line->pos=realpos; line->off=(nline==0)?0:hl->lines[nline-1].off+hl->lines[nline-1].len; line->len=0; line->endingmode=mode_whatever; redataused=redata_getused(redata); mode=(nline>0)?line[-1].endingmode:mode_whatever; cant_define=0; cant_directivekeyword=0; is_directiveinclude=0; opaque=0; linecolor=hl_addtolinecolor(&opaque,hl,NULL,color_normal,0); posoffset=0; prev_char='\0'; prev_char_mask=0xff; hl->usedkeywordbuf=0; hl->useddirectivebuf=0; mlcprevmode=mode_whatever; do { if(redata_line_rawinfo(redata,realpos+posoffset,&pos,&ptr,&len,NULL)==-1) return(-1); /* couldn't get line data */ has_nl=((len>0 && ptr[len-1]=='\n')?1:0); has_next=(len==0)?1:(ptr[len-1]=='\n')?0:1; /* special case: line with only a newline */ if(posoffset==0 && has_nl==1 && len==1) { /* delete the existing linecolor and break */ line->len=0; break; } /* iterate */ for(i=0;i<(len-has_nl);prev_char=(ptr[i]&prev_char_mask),prev_char_mask=0xff,i++) { /* special case: keyword ends in a change of mode */ if(mode!=mode_whatever && hl->usedkeywordbuf>0) { if(hl_searchlist(keywords,nkeywords,hl->keywordbuf,hl->usedkeywordbuf,NULL)==0) { linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart,color_keyword); linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart+hl->usedkeywordbuf-1,color_keyword); } hl->usedkeywordbuf=0; } /* end of special case */ if(mode==mode_whatever) { if(prev_char=='\\' || ptr[i]=='\\') { /* escape char mark or escaped char */ continue; } if(prev_char=='/' && ptr[i]=='/') { mode=mode_in_linecomment; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i-1,color_linecomment); linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_linecomment); continue; } if(prev_char=='/' && ptr[i]=='*') { mlcprevmode=mode; mode=mode_in_multilinecomment; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i-1,color_multilinecomment); linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_multilinecomment); continue; } if(ptr[i]=='\"') { mode=mode_in_string; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_string); continue; } if(ptr[i]=='\'') { mode=mode_in_singlestring; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_string); continue; } if(!cant_define && ptr[i]=='#') { mode=mode_in_directive; is_directiveinclude=0; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_directive); continue; } /* keyword detection */ if(hl->usedkeywordbuf==0 && ((ptr[i]>='a' && ptr[i]<='z') || (ptr[i]>='A' && ptr[i]<='Z') || ptr[i]=='_')) { cant_define=1; hl->keywordbuf[hl->usedkeywordbuf++]=ptr[i]; hl->keywordbufstart=posoffset+i; } 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]=='_')) { if(hl->usedkeywordbufsizekeywordbuf) { hl->keywordbuf[hl->usedkeywordbuf++]=ptr[i]; } else { hl->keywordbuf[0]='\0'; /* too long */ } } if(hl->usedkeywordbuf>0 && !((ptr[i]>='0' && ptr[i]<='9') || (ptr[i]>='a' && ptr[i]<='z') || (ptr[i]>='A' && ptr[i]<='Z') || ptr[i]=='_')) { if(hl_searchlist(keywords,nkeywords,hl->keywordbuf,hl->usedkeywordbuf,NULL)==0) { linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart,color_keyword); linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart+hl->usedkeywordbuf-1,color_keyword); } hl->usedkeywordbuf=0; } /* keyword detection */ if(strchr("0123456789",ptr[i])!=NULL) { cant_define=1; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_number); continue; } if(strchr("<>=+-%*/!|&^",ptr[i])!=NULL) { cant_define=1; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_operator); continue; } if(strchr("(){}[],;",ptr[i])!=NULL) { cant_define=1; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_symbol); continue; } linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_normal); continue; } if(mode==mode_in_multilinecomment) { if(prev_char=='\\' || ptr[i]=='\\') { continue; } if(prev_char=='*' && ptr[i]=='/') { prev_char_mask=0x00; mode=mlcprevmode; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_multilinecomment); continue; } linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_multilinecomment); continue; } if(mode==mode_in_directive) { if(prev_char=='\\' || ptr[i]=='\\') { continue; } if(prev_char=='/' && ptr[i]=='/') { mode=mode_in_linecomment; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i-1,color_linecomment); linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_linecomment); continue; } if(prev_char=='/' && ptr[i]=='*') { mlcprevmode=mode; mode=mode_in_multilinecomment; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i-1,color_multilinecomment); linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_multilinecomment); continue; } /* directive detection */ if(!cant_directivekeyword && hl->useddirectivebuf==0 && ((ptr[i]>='a' && ptr[i]<='z') || (ptr[i]>='A' && ptr[i]<='Z') || ptr[i]=='_')) { hl->directivebuf[hl->useddirectivebuf++]=ptr[i]; hl->directivebufstart=posoffset+i; } 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]=='_')) { if(hl->useddirectivebufsizedirectivebuf) { hl->directivebuf[hl->useddirectivebuf++]=ptr[i]; } else { hl->directivebuf[0]='\0'; /* too long */ cant_directivekeyword=1; } } if(hl->useddirectivebuf>0 && !((ptr[i]>='0' && ptr[i]<='9') || (ptr[i]>='a' && ptr[i]<='z') || (ptr[i]>='A' && ptr[i]<='Z') || ptr[i]=='_')) { int nfound; if(hl_searchlist(directives,ndirectives,hl->directivebuf,hl->useddirectivebuf,&nfound)==0) { linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->directivebufstart,color_directivekeyword); linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->directivebufstart+hl->useddirectivebuf-1,color_directivekeyword); if(strcmp(directives[nfound],"include")==0) is_directiveinclude=1; } hl->useddirectivebuf=0; cant_directivekeyword=1; } if(ptr[i]!=' ' && ptr[i]!='\t') cant_directivekeyword=1; /* directive detection */ if(ptr[i]=='\"') { mode=mode_in_directivestring; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,(is_directiveinclude==0)?color_directivestring:color_directiveincludestring); continue; } linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,(is_directiveinclude==0)?color_directive:color_directiveinclude); continue; } if(mode==mode_in_directivestring) { if(prev_char=='\\' || ptr[i]=='\\') { continue; } if(ptr[i]=='\"') { mode=mode_in_directive; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,(is_directiveinclude==0)?color_directivestring:color_directiveincludestring); continue; } linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,(is_directiveinclude==0)?color_directivestring:color_directiveincludestring); continue; } if(mode==mode_in_string || mode_in_singlestring) { if(prev_char=='\\' || ptr[i]=='\\') { continue; } if((mode==mode_in_string && ptr[i]=='\"') || (mode==mode_in_singlestring && ptr[i]=='\'')) { mode=mode_whatever; linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_string); continue; } linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_string); continue; } if(mode==mode_in_linecomment) { linecolor=hl_addtolinecolor(&opaque,hl,linecolor,posoffset+i,color_linecomment); continue; } } posoffset+=len; } while(has_next!=0 && (realpos+posoffset)usedkeywordbuf>0 && hl_searchlist(keywords,nkeywords,hl->keywordbuf,hl->usedkeywordbuf,NULL)==0) { linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart,color_keyword); linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->keywordbufstart+hl->usedkeywordbuf-1,color_keyword); } /* end of special case */ /* special case: deirectivekeyword ends at end-of-line */ if(mode==mode_in_directive && hl->useddirectivebuf>0 && hl_searchlist(directives,ndirectives,hl->directivebuf,hl->useddirectivebuf,NULL)==0) { linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->directivebufstart,color_directivekeyword); linecolor=hl_addtolinecolor(&opaque,hl,linecolor,hl->directivebufstart+hl->useddirectivebuf-1,color_directivekeyword); } /* end of special case */ if(linecolor==NULL) return(-1); if((prev_char=='\\' && mode!=mode_in_linecomment) || mode==mode_in_multilinecomment) line->endingmode=mode; hl->usedlines++; return(0); } int hl_C_getkeywords(char ***keywords,int *nkeywords, int *maxlen) { static int init=0; static int staticnkeywords=0; static int staticmaxlen=0; static const char *C_keywords[]={ "auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "extern", "float", "for", "goto", "if", "inline", "int", "long", "register", "restrict", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", "union", "unsigned", "void", "volatile", "while", "_Alignas", "_Alignof", "_Atomic", "_Bool", "_Complex", "_Generic", "_Imaginary", "_Noreturn", "_Static_assert", "_Thread_local", NULL }; if(keywords==NULL || nkeywords==NULL) return(-1); if(init==0) { int k,l,maxl; for(k=0,maxl=0;C_keywords[k]!=NULL;k++) { l=strlen(C_keywords[k]); maxl=(l>maxl)?l:maxl; } staticnkeywords=k; staticmaxlen=maxl; init=1; } *keywords=(char **)C_keywords; *nkeywords=staticnkeywords; if(maxlen!=NULL) *maxlen=staticmaxlen; return(0); } int hl_C_getdirectives(char ***directives,int *ndirectives, int *maxlen) { static int init=0; static int staticndirectives=0; static int staticmaxlen=0; static const char *C_directives[]={ "define", "undef", "include", "if", "ifdef", "ifndef", "else", "elif", "endif", "line", "error", "pragma", NULL }; if(directives==NULL || ndirectives==NULL) return(-1); if(init==0) { int k,l,maxl; for(k=0,maxl=0;C_directives[k]!=NULL;k++) { l=strlen(C_directives[k]); maxl=(l>maxl)?l:maxl; } staticndirectives=k; staticmaxlen=maxl; init=1; } *directives=(char **)C_directives; *ndirectives=staticndirectives; if(maxlen!=NULL) *maxlen=staticmaxlen; return(0); } int hl_searchlist(char **wordlist, int wordlistlen, char *word, int wordlen, int *res) { int k; if(wordlist==NULL || wordlistlen<0 || word==NULL || wordlen<0) return(-1); /* sanity check failed */ for(k=0;kusedbuf+sizeof(linecolor_t))>=hl->sizebuf) { char *newbuf; int newsize=(hl->sizebuf+sizeof(linecolor_t)+BUFBLOCK-1)/BUFBLOCK; newsize*=BUFBLOCK; if((newbuf=realloc(hl->buf,newsize))==NULL) return(NULL); /* insufficient memory */ hl->buf=newbuf; memset(hl->buf+hl->sizebuf,0,(newsize-hl->sizebuf)); hl->sizebuf=newsize; } line=hl->lines+hl->usedlines; /* posoff==0 means "do init" */ if(posoff==0) { line->off=(hl->usedlines==0)?0:hl->lines[hl->usedlines-1].off+hl->lines[hl->usedlines-1].len; line->len=sizeof(linecolor_t); linecolor=(linecolor_t *) (hl->buf+line->off); linecolor->len=1; linecolor->color=color; *opaque=1; hl->usedbuf=line->off+line->len; return(linecolor); } /* if posoff was already done, truncate */ if(posoff<*opaque) { int delta,maxdelta; int l; maxdelta=line->len; line->len=0; for(delta=0,l=0;deltalen,delta+=sizeof(linecolor_t)) { linecolor=(linecolor_t *) (hl->buf+line->off+delta); line->len=delta; if((l+linecolor->len)>=posoff) { line->len+=sizeof(linecolor_t); linecolor->len=posoff-l; *opaque=posoff; break; } } hl->usedbuf=line->off+line->len; } linecolor=(linecolor_t *) (hl->buf+line->off+line->len); /* if we have not changed color, expand */ if(linecolor[-1].color==color) { int added=(posoff-*opaque)+1; linecolor[-1].len+=added; *opaque+=added; return(linecolor-1); } /* add new linecolor */ linecolor->len=1; linecolor->color=color; *opaque+=1; line->len+=sizeof(linecolor_t); hl->usedbuf=line->off+line->len; return(linecolor); }