Browse code

Implement a primitive function navigator when clicking on the status line

Dario Rodriguez authored on 17/02/2022 22:52:05
Showing 3 changed files
... ...
@@ -258,6 +258,26 @@ redata_getchar(redata_t *redata, long pos)
258 258
         return(-1); /* not found */
259 259
 }
260 260
 
261
+int
262
+redata_getdata(redata_t *redata, long frompos, long size, char *dest)
263
+{
264
+        int nchunk,off,avail;
265
+        long n;
266
+        if(redata==NULL || frompos<0 || size<0 || dest==NULL || (frompos+size)>redata_getused(redata) || redata_getposptr(redata,frompos,&nchunk,&off)!=0)
267
+                return(-1); /* sanity check failed */
268
+        for(n=0;n<size && nchunk<redata->sizechunks;nchunk++,off=0) {
269
+                avail=redata->chunks[nchunk]->useddata-off;
270
+                if(avail<=0)
271
+                        continue;
272
+                if(avail>(size-n))
273
+                        avail=size-n;
274
+                memcpy(dest+n,redata->chunks[nchunk]->data+off,avail);
275
+                n+=avail;
276
+        }
277
+        return(0);
278
+}
279
+
280
+
261 281
 int
262 282
 redata_wipe(redata_t *redata)
263 283
 {
... ...
@@ -647,7 +667,6 @@ redata_load(redata_t *redata, char *filename, char **errordesc)
647 667
         struct stat statbuf;
648 668
         rechunk_t *chunk;
649 669
         int i;
650
-        int reply;
651 670
         if(redata==NULL || filename==NULL) {
652 671
                 if(errordesc!=NULL)
653 672
                         *errordesc="Internal error";
... ...
@@ -2157,6 +2176,107 @@ redata_linecol2pos(redata_t *redata, int line, int colrequest, long *pos, int *c
2157 2176
         return(0);
2158 2177
 }
2159 2178
 
2179
+int
2180
+redata_line_total(redata_t *redata)
2181
+{
2182
+        long chunkpos;
2183
+        int nchunk;
2184
+        int startline;
2185
+        rechunk_t *chunk,*lastchunkwithdata;
2186
+        if(redata==NULL)
2187
+                return(-1);
2188
+        /* find line */
2189
+        lastchunkwithdata=NULL;
2190
+        for(nchunk=0,chunkpos=0,startline=0
2191
+          ;nchunk<redata->sizechunks
2192
+          ;chunkpos+=(chunk!=NULL)?chunk->useddata:0
2193
+            ,startline+=(chunk!=NULL)?chunk->whatin.nlcount:0,nchunk++) {
2194
+                if((chunk=redata->chunks[nchunk])==NULL)
2195
+                        continue;
2196
+                if(!(chunk->whatin_fresh))
2197
+                        redata_whatin_refresh(redata,nchunk);
2198
+                if(chunk->useddata>0)
2199
+                        lastchunkwithdata=chunk;
2200
+        }
2201
+        if(lastchunkwithdata!=NULL && lastchunkwithdata->data[lastchunkwithdata->useddata-1]!='\n')
2202
+                startline++;
2203
+        return(startline);
2204
+}
2205
+
2206
+int
2207
+redata_line_getendstr(redata_t *redata, int line, char *buf, int sizebuf)
2208
+{
2209
+        return(redata_line_getendstrtrimmed(redata,line,buf,sizebuf,NULL));
2210
+}
2211
+
2212
+int
2213
+redata_line_getendstrtrimmed(redata_t *redata, int line, char *buf, int sizebuf, char *trimchars)
2214
+{
2215
+        long startpos,endpos;
2216
+        int coldone;
2217
+        if(redata==NULL || line<0 || buf==NULL || sizebuf<1)
2218
+                return(-1); /* sanity check error */
2219
+        if(redata_linecol2pos(redata,line,0,&startpos,&coldone)!=0
2220
+          || redata_line_realend(redata,startpos,&endpos)!=0) {
2221
+                return(-1); /* line not found */
2222
+        }
2223
+        if(endpos>startpos && redata_getchar(redata,endpos-1)=='\n')
2224
+                endpos--;
2225
+        if(trimchars!=NULL) {
2226
+                while(endpos>startpos && strchr(trimchars,redata_getchar(redata,endpos))!=NULL)
2227
+                        endpos--;
2228
+        }
2229
+        if((endpos-startpos)>(sizebuf-1))
2230
+                startpos=endpos-(sizebuf-1);
2231
+        redata_getdata(redata,startpos,endpos-startpos,buf);
2232
+        buf[endpos-startpos]='\0';
2233
+        return(0);
2234
+}
2235
+
2236
+int
2237
+redata_line_getsize(redata_t *redata, int line) /* includes the \n */
2238
+{
2239
+        long startpos,endpos;
2240
+        int coldone;
2241
+        if(redata==NULL || line<0)
2242
+                return(-1); /* sanity check error */
2243
+        if(redata_linecol2pos(redata,line,0,&startpos,&coldone)!=0
2244
+          || redata_line_realend(redata,startpos,&endpos)!=0) {
2245
+                return(-1); /* line not found */
2246
+        }
2247
+        return(endpos-startpos);
2248
+}
2249
+
2250
+int
2251
+redata_line_getstartstr(redata_t *redata, int line, char *buf, int sizebuf)
2252
+{
2253
+        return(redata_line_getstartstrtrimmed(redata,line,buf,sizebuf,NULL));
2254
+}
2255
+
2256
+int
2257
+redata_line_getstartstrtrimmed(redata_t *redata, int line, char *buf, int sizebuf, char *trimchars)
2258
+{
2259
+        long startpos,endpos;
2260
+        int coldone;
2261
+        if(redata==NULL || line<0 || buf==NULL || sizebuf<1)
2262
+                return(-1); /* sanity check error */
2263
+        if(redata_linecol2pos(redata,line,0,&startpos,&coldone)!=0
2264
+          || redata_line_realend(redata,startpos,&endpos)!=0) {
2265
+                return(-1); /* line not found */
2266
+        }
2267
+        if(endpos>startpos && redata_getchar(redata,endpos-1)=='\n')
2268
+                endpos--;
2269
+        if(trimchars!=NULL) {
2270
+                while(startpos<endpos && strchr(trimchars,redata_getchar(redata,startpos))!=NULL)
2271
+                        startpos++;
2272
+        }
2273
+        if((endpos-startpos)>(sizebuf-1))
2274
+                endpos=startpos+(sizebuf-1);
2275
+        redata_getdata(redata,startpos,endpos-startpos,buf);
2276
+        buf[endpos-startpos]='\0';
2277
+        return(0);
2278
+}
2279
+
2160 2280
 static char *
2161 2281
 securesave_genname(char *filename, char *buf, int bufsize)
2162 2282
 {
... ...
@@ -109,6 +109,7 @@ long redata_getused(redata_t *redata);
109 109
 long redata_getavailable(redata_t *redata);
110 110
 int redata_getposptr(redata_t *redata, long pos, int *numchunk, int *offset);
111 111
 int redata_getchar(redata_t *redata, long pos);
112
+int redata_getdata(redata_t *redata, long frompos, long size, char *dest);
112 113
  
113 114
 /* low level stuff */
114 115
 int redata_wipe(redata_t *redata);
... ...
@@ -209,4 +210,11 @@ int redata_pos2linecol(redata_t *redata, long pos, int *line, int *col);
209 210
 /* get the pos of that line/col (calculated using the utf8 convenience functions) */
210 211
 int redata_linecol2pos(redata_t *redata, int line, int colrequest, long *pos, int *coldone);
211 212
 
213
+int redata_line_total(redata_t *redata);
214
+int redata_line_getendstr(redata_t *redata, int line, char *buf, int sizebuf);
215
+int redata_line_getendstrtrimmed(redata_t *redata, int line, char *buf, int sizebuf, char *trimchars);
216
+int redata_line_getsize(redata_t *redata, int line); /* includes the \n */
217
+int redata_line_getstartstr(redata_t *redata, int line, char *buf, int sizebuf);
218
+int redata_line_getstartstrtrimmed(redata_t *redata, int line, char *buf, int sizebuf, char *trimchars);
219
+
212 220
 #endif
... ...
@@ -107,6 +107,9 @@ typedef struct re_t {
107 107
         int sizeprints;
108 108
         int usedprints;
109 109
         printout_t *prints;
110
+        redata_t *funclisting;
111
+        int originlinefunclisting;
112
+        int curlinefunclisting;
110 113
 } re_t;
111 114
 
112 115
 volatile int flag_sigint;
... ...
@@ -153,6 +156,9 @@ long re_getmatchingbracket(re_t *re,long posini, char originalchar, char *matchi
153 156
 int re_drawheader_editing(re_t *re);
154 157
 int re_drawheader_command(re_t *re);
155 158
 int re_drawcontents(re_t *re, printout_t *printout);
159
+redata_t *re_getfunclisting(re_t *re);
160
+int re_funclistingxy2line(re_t *re,int mx,int my);
161
+
156 162
 
157 163
 int
158 164
 main(int argc, char *argv[])
... ...
@@ -437,11 +443,65 @@ fprintf(stderr,"Resizing from %ix%i to %ix%i...\n",re->ui->w,re->ui->h,(int)even
437 443
                                 case SDL_MOUSEBUTTONUP:
438 444
                                 case SDL_MOUSEMOTION:
439 445
                                         {
440
-#warning TODO
446
+#warning TODO: select with mouse
441 447
                                                 int mx,my;
442 448
                                                 mx=(event.type!=SDL_MOUSEMOTION)?event.button.x:event.motion.x;
443 449
                                                 my=(event.type!=SDL_MOUSEMOTION)?event.button.y:event.motion.y;
444
-                                                if(!(event.type==SDL_MOUSEMOTION && (re->mouseselactive==0 || my<re->y || mx<re->x))) {
450
+                                                if(re->mouseselactive==0 && event.type==SDL_MOUSEBUTTONDOWN && my<re->y && re->funclisting==NULL) {
451
+                                                        redata_t *funclisting;
452
+                                                        if((funclisting=re_getfunclisting(re))==NULL)
453
+                                                                break; /* mem. insuf. */
454
+                                                        if(re->funclisting!=NULL)
455
+                                                                redata_free(re->funclisting),re->funclisting=NULL;
456
+                                                        re->funclisting=funclisting;
457
+                                                        re->originlinefunclisting=0;
458
+                                                        re->curlinefunclisting=-1;
459
+                                                        re->contentsdirty=1;
460
+                                                } else if(event.type==SDL_MOUSEBUTTONUP && re->funclisting!=NULL) {
461
+                                                        char linebuf[32],*cmdend;
462
+                                                        if(redata_line_getstartstrtrimmed(re->funclisting,re->curlinefunclisting,linebuf,sizeof(linebuf)," ")==0) {
463
+                                                                int oldline;
464
+                                                                if((cmdend=strchr(linebuf,':'))!=NULL)
465
+                                                                        *cmdend='\0';
466
+                                                                re->command=COMMAND_GOTOLINE;
467
+                                                                strncpy(re->commandbuf,linebuf,sizeof(re->commandbuf));
468
+                                                                re->commandbuf[sizeof(re->commandbuf)-1]='\0';
469
+                                                                oldline=re->curline;
470
+                                                                re_processcommand(re);
471
+                                                                if(oldline!=re->curline) {
472
+                                                                        /* position the cursor near the top of the window */
473
+                                                                        re->originline=re->curline-3;
474
+                                                                        re->originline=(re->originline<0)?0:re->originline;
475
+                                                                }
476
+                                                        }
477
+                                                        redata_free(re->funclisting),re->funclisting=NULL;
478
+                                                        re->contentsdirty=1;
479
+                                                } else if(event.type==SDL_MOUSEMOTION && re->funclisting!=NULL) {
480
+                                                        if(mx<re->ui->fontwidth*10) {
481
+                                                                /* scroll */
482
+                                                                int total;
483
+                                                                total=redata_line_total(re->funclisting);
484
+                                                                if(my<re->y) {
485
+                                                                        if(re->originlinefunclisting!=0) {
486
+                                                                                re->originlinefunclisting=0;
487
+                                                                                re->contentsdirty=1;
488
+                                                                        }
489
+                                                                } else if(my>re->y && re->h>re->y) {
490
+                                                                        int old;
491
+                                                                        old=re->originlinefunclisting;
492
+                                                                        re->originlinefunclisting=total*(my-re->y)/(re->h-re->y);
493
+                                                                        if(old!=re->originlinefunclisting)
494
+                                                                                re->contentsdirty=1;
495
+                                                                }
496
+                                                        } else {
497
+                                                                /* select */
498
+                                                                int oldlinefunclisting;
499
+                                                                oldlinefunclisting=re->curlinefunclisting;
500
+                                                                re->curlinefunclisting=re_funclistingxy2line(re,mx,my);
501
+                                                                if(oldlinefunclisting!=re->curlinefunclisting)
502
+                                                                        re->contentsdirty=1;
503
+                                                        }
504
+                                                } else if(!(event.type==SDL_MOUSEMOTION && (re->mouseselactive==0 || my<re->y || mx<re->x))) {
445 505
                                                         int newposx,newposy;
446 506
                                                         long tmppos;
447 507
                                                         if(event.type==SDL_MOUSEBUTTONDOWN && event.button.button==SDL_BUTTON_LEFT) {
... ...
@@ -557,6 +617,8 @@ re_free(re_t *re)
557 617
         int i;
558 618
         if(re==NULL)
559 619
                 return; /* all done */
620
+        if(re->funclisting!=NULL)
621
+                redata_free(re->funclisting),re->funclisting=NULL;
560 622
         for(i=0;i<re->sizeprints;i++) {
561 623
                 if(re->prints[i].ui!=NULL)
562 624
                         re_delprint(re,i);
... ...
@@ -1771,25 +1833,18 @@ re_selectbuf_resize(re_t *re,long size)
1771 1833
 int
1772 1834
 re_selectbuf_fill(re_t *re,long frompos,long size, int nadditionalspaces)
1773 1835
 {
1774
-        int nchunk,off,avail;
1775
-        long n;
1776
-        if(re==NULL || size<0 || nadditionalspaces<0 || (frompos+size)>redata_getused(re->data) || redata_getposptr(re->data,frompos,&nchunk,&off)!=0)
1836
+        if(re==NULL || size<0 || nadditionalspaces<0 || (frompos+size)>redata_getused(re->data))
1777 1837
                 return(-1); /* sanity check failed */
1778 1838
         re->usedselectbuf=0;
1779 1839
         if((size+nadditionalspaces+1)>re->sizeselectbuf
1780 1840
           && re_selectbuf_resize(re,size+nadditionalspaces+1)!=0) {
1781 1841
                 return(-1); /* insuf. mem. */
1782 1842
         }
1783
-        for(n=0;n<size && nchunk<re->data->sizechunks;nchunk++,off=0) {
1784
-                avail=re->data->chunks[nchunk]->useddata-off;
1785
-                if(avail<=0)
1786
-                        continue;
1787
-                if(avail>(size-n))
1788
-                        avail=size-n;
1789
-                memcpy(re->selectbuf+n,re->data->chunks[nchunk]->data+off,avail);
1790
-                n+=avail;
1843
+        if(redata_getdata(re->data,frompos,size,re->selectbuf)!=0) {
1844
+                re->usedselectbuf=0;
1845
+                return(-1); /* internal error */
1791 1846
         }
1792
-        re->usedselectbuf=n;
1847
+        re->usedselectbuf=size;
1793 1848
         if(nadditionalspaces>0) {
1794 1849
                 memset(re->selectbuf+re->usedselectbuf,' ',nadditionalspaces);
1795 1850
                 re->usedselectbuf+=nadditionalspaces;
... ...
@@ -2315,6 +2370,23 @@ re_drawcontents(re_t *re, printout_t *printout)
2315 2370
                                 reui_balloon(ui, '\0', x0+w/2, y0+ui->fontheight*((curline-originline)*2+5)/2, "\x80\x80\x80\xff", "\xff\xff\xff\xcf",(char *) hint,strlen(hint));
2316 2371
                 }
2317 2372
         }
2373
+        /* show func listing if requested */
2374
+        if(printout==NULL && re->funclisting!=NULL) {
2375
+                int total,i,ypos;
2376
+                char linebuf[1024];
2377
+                char *fg;
2378
+                reui_fill(ui,x0,y0,w,re->h-y0,"\x44\x33\x22\x7f");
2379
+                for(total=redata_line_total(re->funclisting),i=re->originlinefunclisting,ypos=y0;i<total && ypos<re->h;i++,ypos+=(ui->fontheight/((linebuf[0]=='\0')?2:1))) {
2380
+                        fg="\xff\xff\xff\xff";
2381
+                        if(i==re->curlinefunclisting) {
2382
+                                reui_fill(ui,x0+ui->fontwidth*3,ypos,w-ui->fontwidth*6,ui->fontheight,"\xdf\xdf\xdf\xff");
2383
+                                fg="\x00\x00\x00\xff";
2384
+                        }
2385
+                        if(redata_line_getstartstr(re->funclisting,i,linebuf,sizeof(linebuf))!=0)
2386
+                                break;
2387
+                        reui_write(ui,x0+ui->fontwidth*3,ypos,fg,linebuf,strlen(linebuf));
2388
+                }
2389
+        }
2318 2390
         /* all done */
2319 2391
         if(printout==NULL || printout==&fakeprintout) {
2320 2392
                 re->contentsdirty=0;
... ...
@@ -2326,4 +2398,93 @@ re_drawcontents(re_t *re, printout_t *printout)
2326 2398
         return(0);
2327 2399
 }
2328 2400
 
2401
+redata_t *
2402
+re_getfunclisting(re_t *re)
2403
+{
2404
+        int lineno,total;
2405
+        char startbuf[3];
2406
+        char endbuf[3];
2407
+        char nextendbuf[3];
2408
+        int flag_havenextendbuf;
2409
+        int flag_isstart;
2410
+        int flag_semicolon;
2411
+        int flag_curlybrace;
2412
+        int flag_nextcurlybrace;
2413
+        int flag_previsstart;
2414
+        char linebuf[1024];
2415
+        char annotatedlinebuf[1024];
2416
+        redata_t *newdata;
2417
+        if(re==NULL)
2418
+                return(NULL); /* sanity check error */;
2419
+        if((newdata=redata_init(NULL))==NULL)
2420
+                return(NULL); /* couldn't init new buffer */
2421
+        for(lineno=0,total=redata_line_total(re->data);lineno<total;lineno++) {
2422
+                if(redata_line_getstartstr(re->data,lineno,startbuf,sizeof(startbuf))!=0)
2423
+                        break; /* internal error */
2424
+                if(flag_havenextendbuf==1) {
2425
+                        strncpy(endbuf,nextendbuf,sizeof(endbuf));
2426
+                        endbuf[sizeof(endbuf)-1]='\0';
2427
+                } else if(redata_line_getendstrtrimmed(re->data,lineno,endbuf,sizeof(endbuf)," \t")!=0) {
2428
+                        break; /* internal error */
2429
+                }
2430
+                flag_havenextendbuf=flag_nextcurlybrace=0;
2431
+                if(redata_line_getendstrtrimmed(re->data,lineno+1,nextendbuf,sizeof(nextendbuf)," \t")==0) {
2432
+                        flag_havenextendbuf=1;
2433
+                        flag_nextcurlybrace=(*nextendbuf!='\0' && nextendbuf[strlen(nextendbuf)-1]=='{')?1:0;
2434
+                }
2435
+                flag_isstart=(*startbuf!='\0' && strchr("# \t{/",*startbuf)==NULL)?1:0;
2436
+                flag_semicolon=(*endbuf!='\0' && endbuf[strlen(endbuf)-1]==';')?1:0;
2437
+                flag_curlybrace=(*endbuf!='\0' && endbuf[strlen(endbuf)-1]=='{')?1:0;
2438
+
2439
+                if(flag_isstart && !flag_semicolon && (flag_curlybrace || (flag_havenextendbuf && flag_nextcurlybrace))) {
2440
+                        if(flag_previsstart) {
2441
+                                snprintf(annotatedlinebuf,sizeof(annotatedlinebuf),"%6i: %s\n",lineno+1-1,linebuf);
2442
+                                annotatedlinebuf[sizeof(annotatedlinebuf)-1]='\0';
2443
+                                redata_op_add(newdata,redata_getused(newdata),annotatedlinebuf,strlen(annotatedlinebuf),NULL);
2444
+                                flag_previsstart=0;
2445
+                        }
2446
+                        redata_line_getstartstr(re->data,lineno,linebuf,sizeof(linebuf));
2447
+                        snprintf(annotatedlinebuf,sizeof(annotatedlinebuf),"%6i: %s\n\n",lineno+1,linebuf);
2448
+                        annotatedlinebuf[sizeof(annotatedlinebuf)-1]='\0';
2449
+                        redata_op_add(newdata,redata_getused(newdata),annotatedlinebuf,strlen(annotatedlinebuf),NULL);
2450
+                } else if(flag_isstart) {
2451
+                        redata_line_getstartstr(re->data,lineno,linebuf,sizeof(linebuf));
2452
+                        flag_previsstart=1;
2453
+                } else {
2454
+                        flag_previsstart=0;
2455
+                }
2456
+        }
2457
+        return(newdata);
2458
+}
2459
+
2460
+int
2461
+re_funclistingxy2line(re_t *re,int mx,int my)
2462
+{
2463
+        int total,i,ypos;
2464
+        char linebuf[2];
2465
+        int h;
2466
+        if(re==NULL || mx<0 || my<0)
2467
+                return(-1);
2468
+        for(total=redata_line_total(re->funclisting),i=re->originlinefunclisting,ypos=re->y;i<total && ypos<re->h;i++,ypos+=h) {
2469
+                if(redata_line_getstartstr(re->funclisting,i,linebuf,sizeof(linebuf))!=0)
2470
+                        break;
2471
+                h=(re->ui->fontheight/((linebuf[0]=='\0')?2:1));
2472
+                if(my>=ypos && my<(ypos+h)) {
2473
+                        if(linebuf[0]=='\0')
2474
+                                return(-1);
2475
+                        return(i);
2476
+                }
2477
+        }
2478
+        return(-1);
2479
+}
2480
+
2481
+
2482
+
2483
+
2484
+
2485
+
2486
+
2487
+
2488
+
2489
+
2329 2490