/* * re_plugin_highlighter.c * * A programmers editor * * re_data plugin to support the syntax highlighter. * * Author: Dario Rodriguez dario@softhome.net * This program is licensed under the terms of GNU GPL v2.1+ */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <stdarg.h> #include <sys/types.h> #include <sys/stat.h> #include "re_plugin_highlighter.h" #define PLUGINNAME "highlighter" #define HIGHLIGHTERGROWSIZE (256*1024) #define DEFAULTCOLOR "\x80\x80\x80\xff" typedef enum colorsenum_t { color_normal=0, color_define, color_definestring, color_keyword, color_string, color_multilinecomment, color_linecomment, color_number, color_endenum, } colorsenum_t; static int redata_highlighter_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo); static int redata_highlighter_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo); static int redata_highlighter_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd); static int redata_highlighter_commit(redata_t *redata, redata_plugin_t *slot,char *filename); 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 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); colors=hl_initcolors(&ncolors, color_normal,"\x38\x17\x1e\xff", color_define,"\x0d\x2b\x04\xff", color_definestring,"\x07\x20\3b\xff", color_keyword,"\x9d\x15\x00\xff", color_string,"\x68\x00\x01\xff", color_multilinecomment,"\x4f\x40\x57\xff", color_linecomment,"\xaa\x8c\xcd\xff", color_number,"\x3b\x10\x35\xff", color_endenum,DEFAULTCOLOR, -1); 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=redata_highlighter_add; slot->unadd=redata_highlighter_unadd; slot->commit=redata_highlighter_commit; 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(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(hcolor_t); return((linecolor_t *) (hl->buf+hl->lines[line].off)); } static int redata_highlighter_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo) { return(redata_highlighter_add_or_unadd(redata, slot, undo, 0)); } static int redata_highlighter_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo) { return(redata_highlighter_add_or_unadd(redata, slot, undo, 1)); } static int redata_highlighter_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd) { long pos; int nline; undostack_t *stack; highlighter_t *hl=(highlighter_t *) ((slot!=NULL)?(slot->userptr):NULL); stack=redata_getstack(redata,undo); if(redata==NULL || slot==NULL || hl==NULL || undo==NULL || stack==NULL || slot->active==0) return(-1); /* sanity check failed */ /* get the first pos of the operation */ pos=undo->posorig; if(undo->type=='D') pos-=undo->len; if(undo->type=='M' && undo->posdest<pos) pos=undo->posdest; /* get line of pos */ for(nline=0;nline<hl->usedlines;nline++) { if(hl->lines[nline].pos>pos) { nline--; break; } } /* invalidate from this line on */ hl_invalidatefrom(redata,hl,nline); return(0); } static int redata_highlighter_commit(redata_t *redata, redata_plugin_t *slot,char *filename) { highlighter_t *hl=(highlighter_t *) ((slot!=NULL)?(slot->userptr):NULL); if(redata==NULL || hl==NULL || filename==NULL) return(-1); /* sanity check failed */ if(hl->flag_doneall) return(0); /* calc highlight of one additional line */ hl_doline(redata, hl, hl->usedlines); 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=(maxcolor<color)?color:maxcolor; if(round==1) { strncpy(hcolors[color].rgba,colordef,sizeof(hcolors[color].rgba)); hcolors[color].rgba[sizeof(hcolors[color].rgba)-1]='\0'; } } va_end(paramlist); if(maxcolor<0) return(NULL); /* no colors were defined */ if(round==0) { if((hcolors=malloc(sizeof(hcolor_t)*(maxcolor+1)))==NULL) return(NULL); /* insufficient memory */ memset(hcolors,0,sizeof(hcolor_t)*(maxcolor+1)); for(i=0;i<=maxcolor;i++) memcpy(hcolors[i].rgba,defcolor,sizeof(defcolor)); } } *ncolors=maxcolor+1; return(hcolors); } static highlighter_t * hl_getplugin(redata_t *redata) { highlighter_t *hl; int i; if(redata==NULL) return(NULL); /* sanity check failed */ for(i=0;i<redata->sizeplugins;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) { /* NOTE: here comes the highlighter */ #warning XXX TODO: implement this return(-1); }