... | ... |
@@ -69,13 +69,13 @@ redata_highlighter_register(redata_t *redata, redata_plugin_t *slot) |
69 | 69 |
if(redata==NULL || slot==NULL) |
70 | 70 |
return(-1); |
71 | 71 |
colors=hl_initcolors(&ncolors, |
72 |
- color_normal,"\x38\x17\x1e\xff", |
|
72 |
+ color_keyword,"\x38\x17\x1e\xff", |
|
73 | 73 |
color_directive,"\x38\x4b\x00\xff", |
74 | 74 |
color_directivekeyword,"\x63\x7d\x16\xff", |
75 | 75 |
color_directivestring,"\x07\x20\3b\xff", |
76 | 76 |
color_directiveinclude,"\x16\x63\x7d\xff", |
77 | 77 |
color_directiveincludestring,"\x6\x13\x2d\xff", |
78 |
- color_keyword,"\x9d\x15\x00\xff", |
|
78 |
+ color_normal,"\x9d\x15\x00\xff", |
|
79 | 79 |
color_string,"\x68\x00\x01\xff", |
80 | 80 |
color_multilinecomment,"\x4f\x40\x57\xff", |
81 | 81 |
color_linecomment,"\xc6\x8c\xa4\xff", |
... | ... |
@@ -155,6 +155,22 @@ redata_highlighter_getline(redata_t *redata, int line, int *nlinecolors) |
155 | 155 |
return((linecolor_t *) (hl->buf+hl->lines[line].off)); |
156 | 156 |
} |
157 | 157 |
|
158 |
+int |
|
159 |
+redata_highlighter_getcolorindex(redata_t *redata, int line, int nthbyte) |
|
160 |
+{ |
|
161 |
+ int i,n; |
|
162 |
+ int nlinecolors; |
|
163 |
+ linecolor_t *linecolors; |
|
164 |
+ if((linecolors=redata_highlighter_getline(redata,line,&nlinecolors))==NULL) |
|
165 |
+ return(-1); |
|
166 |
+ for(i=0,n=0;n<nlinecolors;i+=linecolors[n].len,n++) { |
|
167 |
+ if(nthbyte<(i+linecolors[n].len)) |
|
168 |
+ return(linecolors[n].color); |
|
169 |
+ } |
|
170 |
+ return(-1); |
|
171 |
+} |
|
172 |
+ |
|
173 |
+ |
|
158 | 174 |
static int |
159 | 175 |
redata_highlighter_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
160 | 176 |
{ |
... | ... |
@@ -54,4 +54,5 @@ int redata_highlighter_unregister(redata_t *redata, redata_plugin_t *slot,char * |
54 | 54 |
|
55 | 55 |
hcolor_t *redata_highlighter_getcolors(redata_t *redata, int *ncolors); |
56 | 56 |
linecolor_t *redata_highlighter_getline(redata_t *redata, int line, int *nlinecolors); |
57 |
+int redata_highlighter_getcolorindex(redata_t *redata, int line, int nthbyte); |
|
57 | 58 |
|
... | ... |
@@ -31,6 +31,9 @@ |
31 | 31 |
#define COMMAND_WARNING "(!)" |
32 | 32 |
#define COMMAND_GOTOLINE "Go to line:" |
33 | 33 |
#define COMMAND_SEARCHFORWARD "Search:" |
34 |
+#define COMMAND_REPLACEWHAT "Search for:" |
|
35 |
+#define COMMAND_REPLACEWITH "Replace with:" |
|
36 |
+#define COMMAND_REPLACEHOW "Replace options (Igncase Selected Backwards Entire All Noconfirm):" |
|
34 | 37 |
#define COMMAND_QUESTION "(?)" |
35 | 38 |
#define COMMAND_EXIT "Exit" |
36 | 39 |
|
... | ... |
@@ -88,6 +91,7 @@ int re_processcommand(re_t *re); |
88 | 91 |
int re_moveupdown(re_t *re, int totalinc); |
89 | 92 |
int re_moveleftright(re_t *re, int totalinc); |
90 | 93 |
int re_rtrim(re_t *re, long curpos, int *trimmed); |
94 |
+long re_getmatchingbracket(re_t *re,long posini, char originalchar, char *matchingchar); |
|
91 | 95 |
int re_drawheader_editing(re_t *re); |
92 | 96 |
int re_drawheader_command(re_t *re); |
93 | 97 |
int re_drawcontents(re_t *re); |
... | ... |
@@ -661,6 +665,7 @@ re_processkey_commandwait(re_t *re, SDL_Event *event) |
661 | 665 |
strncpy(re->commandbuf,re->cachelastsearch,sizeof(re->commandbuf)); |
662 | 666 |
re->commandbuf[sizeof(re->commandbuf)-1]='\0'; |
663 | 667 |
re->headerdirty=1; |
668 |
+#warning TODO: Search and replace (control+q+a) |
|
664 | 669 |
} else if(re->command_first_key=='k' && event->key.keysym.sym==SDLK_q) { |
665 | 670 |
re->command=COMMAND_EXIT; |
666 | 671 |
re->commandbuf[0]='\0'; |
... | ... |
@@ -938,6 +943,70 @@ re_rtrim(re_t *re, long curpos, int *trimmed) |
938 | 943 |
return(0); |
939 | 944 |
} |
940 | 945 |
|
946 |
+long |
|
947 |
+re_getmatchingbracket(re_t *re,long posini, char originalchar, char *matchingchar) |
|
948 |
+{ |
|
949 |
+ char *ori,*dest; |
|
950 |
+ char *pairs="[]{}<>()"; |
|
951 |
+ int is_backwards; |
|
952 |
+ int colorindex,newcolor; |
|
953 |
+ long realstart; |
|
954 |
+ int line; |
|
955 |
+ long pos; |
|
956 |
+ long posnextori,posnextdest; |
|
957 |
+ long posnext; |
|
958 |
+ int counter; |
|
959 |
+ if(re==NULL) |
|
960 |
+ return(-1); /* sanity check failed */ |
|
961 |
+ if((ori=strchr(pairs,originalchar))==NULL) |
|
962 |
+ return(-1); /* unknown char */ |
|
963 |
+ is_backwards=(ori-pairs)%2; |
|
964 |
+ dest=ori+((is_backwards)?-1:1); |
|
965 |
+ if(redata_pos2linecol(re->data,posini,&line,NULL)==-1 |
|
966 |
+ || redata_line_realstart(re->data,posini,&realstart)==-1) { |
|
967 |
+ return(-1); /* couldn't get line number or startpos */ |
|
968 |
+ } |
|
969 |
+ colorindex=redata_highlighter_getcolorindex(re->data,line,posini-realstart); |
|
970 |
+ pos=posini; |
|
971 |
+ counter=1; |
|
972 |
+ while(1) { |
|
973 |
+ /* get the next pos */ |
|
974 |
+ if(!is_backwards) { |
|
975 |
+ posnextori=redata_searchforward(re->data,pos+1,ori,1); |
|
976 |
+ posnextdest=redata_searchforward(re->data,pos+1,dest,1); |
|
977 |
+ posnext=(posnextori==-1)?posnextdest:(posnextdest==-1)?posnextori:(posnextori<posnextdest)?posnextori:posnextdest; |
|
978 |
+ } else { |
|
979 |
+ posnextori=redata_searchbackwards(re->data,pos-1,ori,1); |
|
980 |
+ posnextdest=redata_searchbackwards(re->data,pos-1,dest,1); |
|
981 |
+ posnext=(posnextori==-1)?posnextdest:(posnextdest==-1)?posnextori:(posnextori>posnextdest)?posnextori:posnextdest; |
|
982 |
+ } |
|
983 |
+ if(posnext==-1) |
|
984 |
+ break; /* search ended and couln't get the counter to zero */ |
|
985 |
+ /* check that the color index is ok */ |
|
986 |
+ if(redata_pos2linecol(re->data,posnext,&line,NULL)==-1 |
|
987 |
+ || redata_line_realstart(re->data,posnext,&realstart)==-1) { |
|
988 |
+ return(-1); /* couldn't get line number or startpos */ |
|
989 |
+ } |
|
990 |
+ newcolor=redata_highlighter_getcolorindex(re->data,line,posnext-realstart); |
|
991 |
+ if(colorindex!=newcolor) { |
|
992 |
+ pos=posnext; |
|
993 |
+ continue; /* it doesn't have the same color */ |
|
994 |
+ } |
|
995 |
+ /* do the math */ |
|
996 |
+ if(posnext==posnextori) |
|
997 |
+ counter++; |
|
998 |
+ if(posnext==posnextdest) |
|
999 |
+ counter--; |
|
1000 |
+ pos=posnext; |
|
1001 |
+ if(counter==0) { |
|
1002 |
+ if(matchingchar!=NULL) |
|
1003 |
+ *matchingchar=*dest; |
|
1004 |
+ return(posnext); /* found matching bracket */ |
|
1005 |
+ } |
|
1006 |
+ } |
|
1007 |
+ return(-1); |
|
1008 |
+} |
|
1009 |
+ |
|
941 | 1010 |
int |
942 | 1011 |
re_drawheader_editing(re_t *re) |
943 | 1012 |
{ |
... | ... |
@@ -1012,6 +1081,9 @@ re_drawcontents(re_t *re) |
1012 | 1081 |
int ncolors; |
1013 | 1082 |
linecolor_t *linecolors; |
1014 | 1083 |
int nlinecolors; |
1084 |
+ int matchingpos; |
|
1085 |
+ char matchingchar; |
|
1086 |
+ int mline,mcol; |
|
1015 | 1087 |
if(re==NULL) |
1016 | 1088 |
return(-1); |
1017 | 1089 |
reui_fill(re->ui,re->x,re->y,re->w,re->h,"\xdf\xdf\xdf\xff"); |
... | ... |
@@ -1029,8 +1101,10 @@ re_drawcontents(re_t *re) |
1029 | 1101 |
/* draw the lines */ |
1030 | 1102 |
drawn_cursor=0; |
1031 | 1103 |
colors=redata_highlighter_getcolors(re->data,&ncolors); |
1104 |
+ matchingpos=-1; |
|
1105 |
+ matchingchar='\0'; |
|
1032 | 1106 |
for(y=re->y;y<(re->y+re->h);y+=re->ui->fontheight,row++) { |
1033 |
- /* definiciton of vars for teacking linecolor usage */ |
|
1107 |
+ /* definition of vars for tracking linecolor usage */ |
|
1034 | 1108 |
int curlinecolor; /* current linecolor */ |
1035 | 1109 |
int usedlenlinecolor; /* number of bytes of current linecolor already drawn */ |
1036 | 1110 |
/* end of deifinitions */ |
... | ... |
@@ -1072,15 +1146,18 @@ re_drawcontents(re_t *re) |
1072 | 1146 |
} |
1073 | 1147 |
if(row==(re->curline-re->originline)) { |
1074 | 1148 |
if(re->curcol>=tmpcol && re->curcol<(tmpcol+availcol)) { |
1149 |
+ int utf8charlen; |
|
1150 |
+ /* draw cursor */ |
|
1075 | 1151 |
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"); |
1076 | 1152 |
drawn_cursor=1; |
1077 | 1153 |
curptr=redata_generic_utf8col(ptr,len-has_nl,re->curcol-tmpcol); |
1078 | 1154 |
curptrlen=(curptr==NULL)?0:(len-has_nl)-(curptr-ptr); |
1079 |
- reui_write(re->ui,re->x+re->ui->fontwidth*(re->curcol-re->origincol),y,"\xff\xff\xff\xff",curptr,redata_generic_utf8charlen(curptr,curptrlen)); |
|
1155 |
+ utf8charlen=redata_generic_utf8charlen(curptr,curptrlen); |
|
1156 |
+ reui_write(re->ui,re->x+re->ui->fontwidth*(re->curcol-re->origincol),y,"\xff\xff\xff\xff",curptr,utf8charlen); |
|
1157 |
+ /* get matching braces/parens/anglebracket/curlybraces for highlighting */ |
|
1158 |
+ if(utf8charlen==1 && strchr("[]{}<>()",*curptr)!=NULL) |
|
1159 |
+ matchingpos=re_getmatchingbracket(re,re->cursorpos,*curptr,&matchingchar); |
|
1080 | 1160 |
} |
1081 |
-#warning TODO: if it is one of '[','{','<','>','}',']', highlight the matching bracket/parens/anglebracket. |
|
1082 |
-#warning When searching for matching backet/..., count only the ones in the same highlighting color. |
|
1083 |
-#warning If it is ourside of the visible part of the code, put a comic baloon (with some transparency) in that dir. (up, down or right) at the correct height/position to mark the direction of where it is. |
|
1084 | 1161 |
#warning TODO: Select(control+k+b/control+k+k/...) |
1085 | 1162 |
} |
1086 | 1163 |
} |
... | ... |
@@ -1091,22 +1168,40 @@ re_drawcontents(re_t *re) |
1091 | 1168 |
pos=realend+1; |
1092 | 1169 |
/*LONG LINE LEFT FOR DEBUGGING PURPOSES: reui_write(re->ui,re->x+re->ui->fontwidth*(re->curcol-re->origincol),y,"\xff\xff\xff\xff",curptr,redata_generic_utf8charlen(ptr,curptrlen));*/ |
1093 | 1170 |
} |
1094 |
- re->contentsdirty=0; |
|
1095 |
- re->ui->rendererdirty=1; |
|
1171 |
+ /* highlight matching parens/brace/... if applicable */ |
|
1172 |
+ if(matchingpos!=-1 && redata_pos2linecol(re->data,matchingpos,&mline,&mcol)!=-1) { |
|
1173 |
+ int x,y; |
|
1174 |
+ char *fg="\xff\x00\x00\x80"; |
|
1175 |
+ char *bg="\xff\xff\xff\xaf"; |
|
1176 |
+ x=re->x+(mcol-re->origincol)*re->ui->fontwidth+(re->ui->fontwidth/2); |
|
1177 |
+ x=(x<re->x)?re->x:(x>=(re->x+re->w))?(re->x+re->w-1):x; |
|
1178 |
+ y=re->y+(mline-re->originline)*re->ui->fontheight+(re->ui->fontheight/2); |
|
1179 |
+ y=(y<re->y)?re->y:(y>=(re->y+re->h))?(re->y+re->h-1):y; |
|
1180 |
+ if(mline<re->originline) |
|
1181 |
+ reui_balloon(re->ui, 'n', x, re->y, fg, bg, &matchingchar,1); |
|
1182 |
+ else if(mline>=(re->originline+re->maxrow)) |
|
1183 |
+ reui_balloon(re->ui, 's', x, re->y+re->h-1, fg, bg, &matchingchar,1); |
|
1184 |
+ else if(mcol<re->origincol) |
|
1185 |
+ reui_balloon(re->ui, 'w', re->x, y, fg, bg, &matchingchar,1); |
|
1186 |
+ else if(mcol>=(re->origincol+re->maxcol)) |
|
1187 |
+ reui_balloon(re->ui, 'e', re->x+re->w-1,y, fg, bg, &matchingchar,1); |
|
1188 |
+ else |
|
1189 |
+ reui_balloon(re->ui, '\0', x,y, fg, bg, &matchingchar,1); |
|
1190 |
+ } |
|
1191 |
+ /* display commonprototypes info if applicable */ |
|
1096 | 1192 |
#if 1 |
1193 |
+#warning TODO: display commonprototypes info if applicable |
|
1097 | 1194 |
{ |
1098 |
-char sampletext[]={"Here is the top"}; |
|
1099 |
-char sampletextlarge[]={"void *memcpy(void *dest, const void *src, size_t n)"}; |
|
1100 |
-reui_balloon(re->ui, 'n', re->x+re->w/2, re->y, "\xff\x00\x00\xff", "\x00\x00\xff\x80",sampletext,strlen(sampletext)); |
|
1101 |
-reui_balloon(re->ui, 's', re->x+re->w/2, re->y+re->h-1, "\xff\x00\x00\x80", "\xff\xff\xff\xaf", "}",1); |
|
1102 |
-reui_balloon(re->ui, 'e', re->x+re->w-1,re->y+re->h/2, "\xff\x00\x00\x80", "\xff\xff\xff\xaf", "[",1); |
|
1103 |
-reui_balloon(re->ui, 'w', re->x, re->y+re->h/2, "\xff\x00\x00\x80", "\xff\xff\xff\xaf", "]",1); |
|
1104 |
-if((re->curline-re->originline)>=(re->maxrow/2)) |
|
1105 |
- reui_balloon(re->ui, '\0', re->x+re->w/2, re->y+re->ui->fontheight*3/2, "\x80\x80\x80\xff", "\xff\xff\xff\xcf",sampletextlarge,strlen(sampletextlarge)); |
|
1106 |
-else |
|
1107 |
- reui_balloon(re->ui, '\0', re->x+re->w/2, re->y+re->h-re->ui->fontheight*3/2, "\x80\x80\x80\xff", "\xff\xff\xff\xcf",sampletextlarge,strlen(sampletextlarge)); |
|
1195 |
+ char sampletextlarge[]={"void *memcpy(void *dest, const void *src, size_t n)"}; |
|
1196 |
+ if((re->curline-re->originline)>=(re->maxrow/2)) |
|
1197 |
+ reui_balloon(re->ui, '\0', re->x+re->w/2, re->y+re->ui->fontheight*3/2, "\x80\x80\x80\xff", "\xff\xff\xff\xcf",sampletextlarge,strlen(sampletextlarge)); |
|
1198 |
+ else |
|
1199 |
+ reui_balloon(re->ui, '\0', re->x+re->w/2, re->y+re->h-re->ui->fontheight*3/2, "\x80\x80\x80\xff", "\xff\xff\xff\xcf",sampletextlarge,strlen(sampletextlarge)); |
|
1108 | 1200 |
} |
1109 | 1201 |
#endif |
1202 |
+ /* all done */ |
|
1203 |
+ re->contentsdirty=0; |
|
1204 |
+ re->ui->rendererdirty=1; |
|
1110 | 1205 |
return(0); |
1111 | 1206 |
} |
1112 | 1207 |
|