Browse code

Implement up/down movement

Dario Rodriguez authored on 26/08/2020 21:50:45
Showing 5 changed files
... ...
@@ -23,7 +23,8 @@
23 23
 #include "re_data.h"
24 24
 #include "sha3/sha3.h"
25 25
 
26
-#define CHUNKSIZE 32768
26
+//#define CHUNKSIZE 32768
27
+#define CHUNKSIZE 160
27 28
 #define UNDOBLOCK 1024
28 29
 #define UNDOGROWSIZE (256*1024)
29 30
 #define SECURESAVEPREFIX "."
... ...
@@ -1304,6 +1305,53 @@ redata_hash_gen(redata_t *redata, char *filename, char *buf, long buflen, char *
1304 1305
         return(0);
1305 1306
 }
1306 1307
 
1308
+/*#define DEBUG_LINE_INFO*/
1309
+
1310
+#ifdef DEBUG_LINE_INFO
1311
+#define LINEINFODEBUG(a) fprintf a
1312
+#else
1313
+#define LINEINFODEBUG(a)
1314
+#endif
1315
+
1316
+int
1317
+redata_line_info(redata_t *redata, long pos, long *startpos, char **startptr, int *len)
1318
+{
1319
+        int chunkno;
1320
+        long start;
1321
+        unsigned char *ptr,*end;
1322
+        rechunk_t *chunk;
1323
+        if(redata==NULL || pos<0)
1324
+                return(-1);
1325
+        /* search chunk of pos */
1326
+        for(chunkno=0,start=0;chunkno<redata->sizechunks;start+=(redata->chunks[chunkno]==NULL)?0:redata->chunks[chunkno]->useddata,chunkno++) {
1327
+        LINEINFODEBUG((stderr,"redata_line_info: searchchunk: pos:%li chunkno:%i start:%li\n",pos,chunkno,start));
1328
+                if(redata->chunks[chunkno]==NULL)
1329
+                        continue;
1330
+                if((start+redata->chunks[chunkno]->useddata)>pos)
1331
+                        break;
1332
+        }
1333
+        if(chunkno>=redata->sizechunks)
1334
+                return(-1);
1335
+        chunk=redata->chunks[chunkno];
1336
+        /* search line start */
1337
+        LINEINFODEBUG((stderr,"redata_line_info: searchstart: pos:%li start:%li offset:%li\n",pos,start,(pos-start)));
1338
+        for(ptr=chunk->data+(pos-start);ptr>chunk->data && ptr[-1]!='\n';ptr--)
1339
+                ;
1340
+        /* search line end */
1341
+        LINEINFODEBUG((stderr,"redata_line_info: searchend: pos:%li start:%li offset:%li\n",pos,start,(pos-start)));
1342
+        for(end=chunk->data+(pos-start)+1;end<=(chunk->data+chunk->useddata) && end[-1]!='\n';end++)
1343
+                ;
1344
+        /* fill results */
1345
+        LINEINFODEBUG((stderr,"redata_line_info: filling results: len:%li\n",end-ptr));
1346
+        if(startpos!=NULL)
1347
+                *startpos=(pos-((chunk->data+(pos-start))-ptr));
1348
+        if(startptr!=NULL)
1349
+                *startptr=(char *) ptr;
1350
+        if(len!=NULL)
1351
+                *len=end-ptr;
1352
+        return(0);
1353
+}
1354
+
1307 1355
 static char *
1308 1356
 securesave_genname(char *filename, char *buf, int bufsize)
1309 1357
 {
... ...
@@ -128,3 +128,5 @@ int redata_memhash(redata_t *redata, char *buf, long buflen, char *resbuf129byte
128 128
 undostack_t *redata_getstack(redata_t *redata, undo_t *undo);
129 129
 char *redata_generic_genname(char *filename,char *prefix, char *postfix, char *buf, int bufsize);
130 130
 
131
+/* line convenience funtions */
132
+int redata_line_info(redata_t *redata, long pos, long *startpos, char **startptr, int *len);
... ...
@@ -56,6 +56,17 @@ reui_init()
56 56
                 reui_free(ui),ui=NULL;
57 57
                 return(NULL);
58 58
         }
59
+        /* font width */
60
+        {
61
+                SDL_Surface *s;
62
+                SDL_Color c={0,0,0,0};
63
+                if((s=TTF_RenderUTF8_Blended(ui->font,"m",c))==NULL) {
64
+                        reui_free(ui),ui=NULL;
65
+                        return(NULL);
66
+                }
67
+                ui->fontwidth=s->w;
68
+                SDL_FreeSurface(s),s=NULL;
69
+        }
59 70
         /* finished */
60 71
         ui->scrdirty=1;
61 72
         ui->rendererdirty=1;
... ...
@@ -98,13 +109,17 @@ reui_title(reui_t *ui, char *titlefilename)
98 109
 
99 110
 
100 111
 int
101
-reui_fill(reui_t *ui, int x, int y, int w, int h, unsigned char *rgba)
112
+reui_fill(reui_t *ui, int x, int y, int w, int h, char *rgba)
102 113
 {
103 114
         SDL_Rect dstrect;
104 115
         if(ui==NULL || rgba==NULL)
105 116
                 return(-1);
106 117
         RECTFILL(dstrect,x,y,w,h);
107
-        SDL_SetRenderDrawColor(ui->renderer,rgba[0],rgba[1],rgba[2],rgba[3]);
118
+        SDL_SetRenderDrawColor(ui->renderer,
119
+                ((unsigned char *)rgba)[0],
120
+                ((unsigned char *)rgba)[1],
121
+                ((unsigned char *)rgba)[2],
122
+                ((unsigned char *)rgba)[3]);
108 123
         SDL_RenderFillRect(ui->renderer, &dstrect);
109 124
         ui->rendererdirty=1;
110 125
         return(0);
... ...
@@ -134,12 +149,15 @@ reui_present(reui_t *ui)
134 149
 }
135 150
 
136 151
 int
137
-reui_write(reui_t *ui, int x, int y, unsigned char *rgba, char *str, int nchar)
152
+reui_write(reui_t *ui, int x, int y, char *rgba, char *str, int nchar)
138 153
 {
139 154
         char buf[1024];
140 155
         SDL_Surface *fgsurface;
141 156
         SDL_Texture *fg;
142
-        SDL_Color c={rgba[0],rgba[1],rgba[2],rgba[3]};
157
+        SDL_Color c={((unsigned char *)rgba)[0],
158
+                     ((unsigned char *)rgba)[1],
159
+                     ((unsigned char *)rgba)[2],
160
+                     ((unsigned char *)rgba)[3]};
143 161
         SDL_Rect dstrect;
144 162
         if(nchar<sizeof(buf)) {
145 163
                 memcpy(buf,str,nchar);
... ...
@@ -164,7 +182,7 @@ reui_write(reui_t *ui, int x, int y, unsigned char *rgba, char *str, int nchar)
164 182
 
165 183
 
166 184
 int
167
-reui_printf(reui_t *ui, int x, int y, unsigned char *rgba, char *format, ...)
185
+reui_printf(reui_t *ui, int x, int y, char *rgba, char *format, ...)
168 186
 {
169 187
         char buf[1024];
170 188
         va_list l;
... ...
@@ -176,3 +194,25 @@ reui_printf(reui_t *ui, int x, int y, unsigned char *rgba, char *format, ...)
176 194
                 return(-1);
177 195
         return(0);
178 196
 }
197
+
198
+int
199
+reui_utf8len(reui_t *ui, char *ptr, int size)
200
+{
201
+        /* calculate the number of utf8-charaters in buffer */
202
+        if(ui==NULL || size<0 || (ptr==NULL && size!=0))
203
+                return(-1);
204
+#warning TODO
205
+        return(size);
206
+#warning Also consider tabs
207
+}
208
+
209
+char *
210
+reui_utf8col(reui_t *ui, char *ptr, int size, int col)
211
+{
212
+        /* return a pointer to the "n"th ("col"th) utf8-character in buffer */
213
+#warning TODO
214
+        if(col<size)
215
+                return(ptr+col);
216
+        return(NULL);
217
+#warning Also consider tabs
218
+}
... ...
@@ -25,6 +25,7 @@ typedef struct reui_t {
25 25
         SDL_RWops *fontdata;
26 26
         TTF_Font *font;
27 27
         int fontheight;
28
+        int fontwidth;
28 29
         int scrdirty;
29 30
         int rendererdirty;
30 31
 } reui_t;
... ...
@@ -33,13 +34,20 @@ reui_t *reui_init();
33 34
 void reui_free(reui_t *ui);
34 35
 
35 36
 int reui_title(reui_t *ui, char *titlefilename);
36
-int reui_fill(reui_t *ui, int x, int y, int w, int h, unsigned char *rgba);
37
+int reui_fill(reui_t *ui, int x, int y, int w, int h, char *rgba);
37 38
 int reui_scr2renderer(reui_t *ui, int x, int y, int w, int h);
38 39
 int reui_present(reui_t *ui);
39 40
 
40
-int reui_write(reui_t *ui, int x, int y, unsigned char *rgba, char *str, int nchar);
41
+int reui_write(reui_t *ui, int x, int y, char *rgba, char *str, int nchar);
41 42
 #ifdef __GNUC__
42
-int reui_printf(reui_t *ui, int x, int y, unsigned char *rgba, char *format, ...) __attribute__ ((format (printf, 5, 6)));
43
+int reui_printf(reui_t *ui, int x, int y, char *rgba, char *format, ...) __attribute__ ((format (printf, 5, 6)));
43 44
 #else
44
-int reui_printf(reui_t *ui, int x, int y, unsigned char *rgba, char *format, ...);
45
+int reui_printf(reui_t *ui, int x, int y, char *rgba, char *format, ...);
45 46
 #endif
47
+
48
+/* calculate the number of utf8-charaters in buffer */
49
+int reui_utf8len(reui_t *ui, char *ptr, int size);
50
+
51
+/* return a pointer to the "n"th ("col"th) utf8-character in buffer */
52
+char *reui_utf8col(reui_t *ui, char *ptr, int size, int col);
53
+
... ...
@@ -19,11 +19,14 @@
19 19
 #include "ext/socklib.h"
20 20
 
21 21
 typedef struct re_t {
22
-        redata_t *redata;
22
+        redata_t *data;
23 23
         reui_t *ui;
24 24
         int flag_newfile;
25 25
         char filename[PATH_MAX];
26 26
         int x, y, w, h; // contents rect
27
+        long cursorpos;
28
+        int lastcol,lastrow;
29
+        int maxrow,maxcol;
27 30
 } re_t;
28 31
 
29 32
 volatile int flag_sigint;
... ...
@@ -50,6 +53,7 @@ main(int argc, char *argv[])
50 53
         int do_exit;
51 54
         SDL_Event event;
52 55
         sselect *ssel;
56
+        int flag_had_events;
53 57
         if(argc!=2 || strcmp(argv[argc-1],"--help")==0) {
54 58
                 fprintf(stderr,"Syntax: %s filename\n",argv[0]);
55 59
                 return(1);
... ...
@@ -68,17 +72,18 @@ main(int argc, char *argv[])
68 72
                 re_free(re),re=NULL;
69 73
                 return(2);
70 74
         }
71
-        if((redata_load(re->redata,re->filename,NULL,NULL))!=0)
75
+        if((redata_load(re->data,re->filename,NULL,NULL))!=0)
72 76
                 re->flag_newfile=1;
73 77
         else
74 78
                 re->flag_newfile=0;
79
+#if 0
75 80
 #warning TESTS
76 81
         {
77 82
                 char buf[129];
78
-                redata_hash(re->redata,buf);
83
+                redata_hash(re->data,buf);
79 84
                 fprintf(stderr,"%s %s\n",buf,re->filename);
80 85
         }
81
-#warning TODO
86
+#endif
82 87
         reui_title(re->ui,re->filename);
83 88
         flag_sigint=flag_sigpipe=0;
84 89
         setsignal(SIGINT,sighandler_sigint);
... ...
@@ -91,15 +96,20 @@ main(int argc, char *argv[])
91 96
         }
92 97
         reui_scr2renderer(re->ui,0,0,re->ui->w,re->ui->h);
93 98
         re->x=0,re->y=re->ui->fontheight,re->w=re->ui->w,re->h=re->ui->h-re->y;
94
-        reui_fill(re->ui,0,0,re->ui->w,re->ui->fontheight,(unsigned char *) "\x00\x00\xff\xff");
95
-        reui_printf(re->ui,0,0,(unsigned char *) "\xff\xff\x00\xff","Fichero: %s",re->filename);
99
+        re->maxrow=re->h/re->ui->fontheight-1;
100
+        re->maxcol=re->w/re->ui->fontwidth-1;
101
+        reui_fill(re->ui,0,0,re->ui->w,re->ui->fontheight,"\x00\x00\xff\xff");
102
+        reui_printf(re->ui,0,0,"\xff\xff\x00\xff","Fichero: %s",re->filename);
96 103
         re_drawcontents(re);
104
+        flag_had_events=0;
97 105
         while(do_exit==0 && flag_sigint==0) {
98 106
                 if(re->ui->rendererdirty)
99 107
                         reui_present(re->ui);
100
-                sselect_wait(ssel,100);
108
+                sselect_wait(ssel,(flag_had_events)?10:100);
109
+                flag_had_events=(flag_had_events>0)?flag_had_events-1:0;
101 110
                 SDL_PumpEvents();
102 111
                 while(SDL_PeepEvents(&event,1,SDL_GETEVENT,SDL_FIRSTEVENT,SDL_LASTEVENT)>0) {
112
+                        flag_had_events=10;
103 113
                         switch(event.type) {
104 114
                                 case SDL_QUIT:
105 115
                                         do_exit=1;
... ...
@@ -153,7 +163,7 @@ re_init(void)
153 163
         if((re=malloc(sizeof(re_t)))==NULL)
154 164
                 return(NULL); /* insuf. mem. */
155 165
         memset(re,0,sizeof(re_t));
156
-        if((re->redata=redata_init(NULL))==NULL) {
166
+        if((re->data=redata_init(NULL))==NULL) {
157 167
                 re_free(re),re=NULL;
158 168
                 return(NULL); /* insuf. mem. */
159 169
         }
... ...
@@ -171,8 +181,8 @@ re_free(re_t *re)
171 181
                 return; /* all done */
172 182
         if(re->ui!=NULL)
173 183
                 reui_free(re->ui),re->ui=NULL;
174
-        if(re->redata!=NULL)
175
-                redata_free(re->redata),re->redata=NULL;
184
+        if(re->data!=NULL)
185
+                redata_free(re->data),re->data=NULL;
176 186
         free(re),re=NULL;
177 187
         return;
178 188
 }
... ...
@@ -192,7 +202,33 @@ re_setfilename(re_t *re, char *filename)
192 202
 int
193 203
 re_processkey(re_t *re, SDL_Event *event)
194 204
 {
195
-#warning TODO
205
+        long newpos,newpos2;
206
+        char *ptr,*ptr2;
207
+        int len;
208
+        int has_nl;
209
+        int oldcol;
210
+        if(re==NULL || event==NULL || event->type!=SDL_KEYDOWN)
211
+                return(-1);
212
+        if(event->key.keysym.sym==SDLK_DOWN || event->key.keysym.sym==SDLK_UP) {
213
+                if(redata_line_info(re->data,re->cursorpos,&newpos,&ptr,&len)==-1)
214
+                        return(-1); /* couldn't get current line data */
215
+                if(event->key.keysym.sym==SDLK_UP && newpos==0)
216
+                        return(-1); /* going up but already at top */
217
+                oldcol=reui_utf8len(re->ui,ptr,re->cursorpos-newpos);
218
+                if(redata_line_info(re->data,(event->key.keysym.sym==SDLK_DOWN)?(newpos+len):(newpos-1),&newpos2,&ptr,&len)==-1)
219
+                        return(-1); /* couldn't get next line data */
220
+                has_nl=((len>0 && ptr[len-1]=='\n')?1:0);
221
+                ptr2=reui_utf8col(re->ui,ptr,len-has_nl,oldcol);
222
+                if(ptr2!=NULL)
223
+                        re->cursorpos=newpos2+(ptr2-ptr);
224
+                else
225
+                        re->cursorpos=newpos2+len-has_nl;
226
+                if(event->key.keysym.sym==SDLK_DOWN && re->lastrow<re->maxrow)
227
+                        re->lastrow++;
228
+                else if(event->key.keysym.sym==SDLK_UP && re->lastrow>0)
229
+                        re->lastrow--;
230
+                re_drawcontents(re);
231
+        }
196 232
         return(-1);
197 233
 }
198 234
 
... ...
@@ -200,24 +236,40 @@ re_processkey(re_t *re, SDL_Event *event)
200 236
 int
201 237
 re_drawcontents(re_t *re)
202 238
 {
203
-        int numchunk;
204
-        long offset;
205
-        rechunk_t *chunk;
206
-        unsigned char *ptr,*end;
207
-        int y;
208
-        reui_fill(re->ui,re->x,re->y,re->w,re->h,(unsigned char *) "\xdf\xdf\xdf\xff");
209
-        if(redata_getposptr(re->redata,0,&numchunk,&offset)==-1)
210
-                return(-1);
211
-        chunk=re->redata->chunks[numchunk];
212
-        /* iterate on lines */
213
-        for(y=re->y,ptr=chunk->data+offset,end=memchr(ptr,'\n',chunk->useddata-(ptr-chunk->data)),
214
-          end=(end==NULL)?chunk->data+chunk->useddata:end;ptr!=NULL && y<(re->y+re->h);
215
-          y+=re->ui->fontheight,ptr=(end!=(chunk->data+chunk->useddata))?end+1:NULL,
216
-          end=(ptr==NULL)?NULL:memchr(ptr,'\n',chunk->useddata-(ptr-chunk->data)),
217
-          end=(end==NULL)?chunk->data+chunk->useddata:end) {
218
-                reui_write(re->ui,re->x,y,(unsigned char *) "\x00\x00\x00\xff",ptr,end-ptr);
239
+        long pos,newpos;
240
+        char *ptr;
241
+        int len;
242
+        int y,row;
243
+        char c;
244
+        int has_nl;
245
+        reui_fill(re->ui,re->x,re->y,re->w,re->h,"\xdf\xdf\xdf\xff");
246
+        row=re->lastrow;
247
+        pos=re->cursorpos;
248
+        while(row>0) {
249
+                if(redata_line_info(re->data,pos,&newpos,NULL,NULL)==-1)
250
+                        return(-1);
251
+                pos=(newpos>0)?newpos-1:0;
252
+                row--;
219 253
         }
220
-#warning TODO
221
-        return(-1);
254
+        /* highlight current line */
255
+        reui_fill(re->ui,re->x,re->y+(re->lastrow)*re->ui->fontheight,re->w,re->ui->fontheight+1,"\xef\xef\xef\xff");
256
+        /* draw the lines */
257
+        for(y=re->y;y<(re->y+re->h);y+=re->ui->fontheight,row++) {
258
+                if(redata_line_info(re->data,pos,&newpos,&ptr,&len)==-1)
259
+                        break; /* couldn't get line start pos */
260
+                has_nl=((len>0 && ptr[len-1]=='\n')?1:0);
261
+                reui_write(re->ui,re->x,y,"\x00\x00\x00\xff",(char *)ptr,len-has_nl);
262
+                if(row==re->lastrow) {
263
+                        reui_fill(re->ui,re->x+re->ui->fontwidth*re->lastcol,y,re->ui->fontwidth,re->ui->fontheight+1,"\x00\x00\x00\xff");
264
+#warning TODO: consider multibytes characters and tabs to position on the corect character and to pass the correct number of bytes to reui_write
265
+                        c=(re->lastcol>=(len-has_nl))?' ':ptr[re->lastcol];
266
+                        reui_write(re->ui,re->x+re->ui->fontwidth*re->lastcol,y,"\xff\xff\xff\xff",&c,1);
267
+#warning TODO: if it is one of  '[','{','<','>','}',']', highlight the matching bracket/parens/anglebracket.
268
+                }
269
+                pos=newpos+len;
270
+        }
271
+        re->ui->rendererdirty=1;
272
+        return(0);
222 273
 }
223 274
 
275
+