... | ... |
@@ -24,7 +24,8 @@ |
24 | 24 |
#include "sha3/sha3.h" |
25 | 25 |
|
26 | 26 |
//#define CHUNKSIZE 32768 |
27 |
-#define CHUNKSIZE 160 |
|
27 |
+//#define CHUNKSIZE 160 |
|
28 |
+#define CHUNKSIZE 16 |
|
28 | 29 |
#define UNDOBLOCK 1024 |
29 | 30 |
#define ADDNBLOCK 1024 |
30 | 31 |
#define UNDOGROWSIZE (256*1024) |
... | ... |
@@ -35,6 +36,7 @@ static int redata_hash_gen(redata_t *redata, char *filename, char *buf, long buf |
35 | 36 |
static char *securesave_genname(char *filename, char *buf, int bufsize); |
36 | 37 |
static void *mymemrchr(const void *s, int c, size_t n); |
37 | 38 |
static void meminvert(void *start, void *end); |
39 |
+static size_t memrchroffset(char *ptr, int c, size_t n); |
|
38 | 40 |
|
39 | 41 |
#if 0 |
40 | 42 |
static void |
... | ... |
@@ -45,15 +47,22 @@ redata_debug_chunkdump(redata_t *redata, char *title) |
45 | 47 |
title=(title==NULL)?"":title; |
46 | 48 |
fprintf(stderr,"%s:CHUNKDUMP (sizechunks:%i)\n",title,redata->sizechunks); |
47 | 49 |
for(m=0;m<redata->sizechunks;m++) { |
48 |
- fprintf(stderr,"%s:chunk[%i]:\"",title,m); |
|
50 |
+ fprintf(stderr,"%s:chunk[%i] len:%-5i data:\"",title,m,redata->chunks[m]->useddata); |
|
49 | 51 |
for(k=0;k<redata->chunks[m]->useddata;k++) { |
50 | 52 |
c=redata->chunks[m]->data[k]; |
51 |
- c=(c>=' ' && c<='~')?c:'.'; |
|
52 |
- fprintf(stderr,"%c",c); |
|
53 |
+ if(c=='\n' || c=='\0') |
|
54 |
+ fprintf(stderr,"\\%c",(c=='\n')?'n':'0'); |
|
55 |
+ else if(c<' ' || c>'~' || c=='\\') |
|
56 |
+ fprintf(stderr,"\\x%02X",((unsigned char *)redata->chunks[m]->data)[k]); |
|
57 |
+ else |
|
58 |
+ fprintf(stderr,"%c",c); |
|
53 | 59 |
} |
54 | 60 |
fprintf(stderr,"\"\n"); |
55 | 61 |
} |
56 | 62 |
} |
63 |
+#define CHUNKDEBUG(a) redata_debug_chunkdump a |
|
64 |
+#else |
|
65 |
+#define CHUNKDEBUG(a) |
|
57 | 66 |
#endif |
58 | 67 |
|
59 | 68 |
redata_t * |
... | ... |
@@ -247,6 +256,7 @@ redata_chunk_deletechunk(redata_t *redata, int chunkno) |
247 | 256 |
redata->available+=chunk->useddata; |
248 | 257 |
chunk->useddata=0; |
249 | 258 |
chunk->whatin_fresh=0; |
259 |
+ redata_chunk_unfreshnext(redata, chunkno); |
|
250 | 260 |
} |
251 | 261 |
for(i=chunkno;(i+1)<redata->sizechunks;i++) |
252 | 262 |
redata->chunks[i]=redata->chunks[i+1]; |
... | ... |
@@ -320,8 +330,9 @@ redata_chunk_movedata(redata_t *redata, int chunkfrom, long posfrom, int chunkto |
320 | 330 |
memmove(from->data+posfrom,from->data+posfrom+size,from->useddata-posfrom-size); |
321 | 331 |
from->useddata-=size; |
322 | 332 |
to->useddata+=size; |
323 |
- from->whatin_fresh=0; |
|
324 |
- to->whatin_fresh=0; |
|
333 |
+ redata_chunk_unfreshrange(redata,chunkfrom,chunkto); |
|
334 |
+ redata_chunk_unfreshnext(redata,chunkfrom); |
|
335 |
+ redata_chunk_unfreshnext(redata,chunkto); |
|
325 | 336 |
} else { |
326 | 337 |
/* from==to */ |
327 | 338 |
rechunk_t *chunk=redata->chunks[chunkfrom]; |
... | ... |
@@ -334,6 +345,7 @@ redata_chunk_movedata(redata_t *redata, int chunkfrom, long posfrom, int chunkto |
334 | 345 |
memcpy(chunk->data+posto-size,redata->tmpchunk->data,size); |
335 | 346 |
} |
336 | 347 |
chunk->whatin_fresh=0; |
348 |
+ redata_chunk_unfreshnext(redata,chunkfrom); |
|
337 | 349 |
} |
338 | 350 |
return(0); |
339 | 351 |
} |
... | ... |
@@ -351,8 +363,9 @@ redata_chunk_insertdata(redata_t *redata, int chunkto, long posto, char *buf, lo |
351 | 363 |
memmove(chunk->data+posto+buflen,chunk->data+posto,chunk->useddata-posto); |
352 | 364 |
memcpy(chunk->data+posto,buf,buflen); |
353 | 365 |
chunk->useddata+=buflen; |
354 |
- chunk->whatin_fresh=0; |
|
355 | 366 |
redata->available-=buflen; |
367 |
+ chunk->whatin_fresh=0; |
|
368 |
+ redata_chunk_unfreshnext(redata,chunkto); |
|
356 | 369 |
return(0); |
357 | 370 |
} |
358 | 371 |
|
... | ... |
@@ -370,8 +383,9 @@ redata_chunk_deletedata(redata_t *redata, int chunkno, long pos, long n) |
370 | 383 |
chunk=redata->chunks[chunkno]; |
371 | 384 |
memmove(chunk->data+pos,chunk->data+pos+n,chunk->useddata-pos-n); |
372 | 385 |
chunk->useddata-=n; |
373 |
- chunk->whatin_fresh=0; |
|
374 | 386 |
redata->available+=n; |
387 |
+ chunk->whatin_fresh=0; |
|
388 |
+ redata_chunk_unfreshnext(redata,chunkno); |
|
375 | 389 |
return(0); |
376 | 390 |
} |
377 | 391 |
|
... | ... |
@@ -409,6 +423,38 @@ redata_chunk_fillfromnext(redata_t *redata, int chunkno, int n) |
409 | 423 |
return(redata_chunk_movedata(redata,chunkno+1,0,chunkno,redata->chunks[chunkno]->useddata,n)); |
410 | 424 |
} |
411 | 425 |
|
426 |
+int |
|
427 |
+redata_chunk_unfreshnext(redata_t *redata, int chunkno) |
|
428 |
+{ |
|
429 |
+ int next; |
|
430 |
+ if(redata==NULL || chunkno<0 || chunkno>=redata->sizechunks) |
|
431 |
+ return(-1); /* sanity check failed */ |
|
432 |
+ /* invalidate whatin for next chunks until one not empty */ |
|
433 |
+ for(next=chunkno+1;next<redata->sizechunks;next++) { |
|
434 |
+ redata->chunks[next]->whatin_fresh=0; |
|
435 |
+ if(redata->chunks[next]->useddata!=0) |
|
436 |
+ break; |
|
437 |
+ } |
|
438 |
+ return(0); |
|
439 |
+} |
|
440 |
+ |
|
441 |
+int |
|
442 |
+redata_chunk_unfreshrange(redata_t *redata, int fromchunkno, int tochunkno) |
|
443 |
+{ |
|
444 |
+ int chunkno; |
|
445 |
+ if(redata==NULL || fromchunkno<0 || fromchunkno>=redata->sizechunks || tochunkno<0 || tochunkno>=redata->sizechunks) |
|
446 |
+ return(-1); /* sanity check failed */ |
|
447 |
+ if(fromchunkno>tochunkno) { |
|
448 |
+ chunkno=fromchunkno; |
|
449 |
+ fromchunkno=tochunkno; |
|
450 |
+ tochunkno=chunkno; |
|
451 |
+ } |
|
452 |
+ /* invalidate whatin in range */ |
|
453 |
+ for(chunkno=fromchunkno;chunkno<=tochunkno;chunkno++) |
|
454 |
+ redata->chunks[chunkno]->whatin_fresh=0; |
|
455 |
+ return(0); |
|
456 |
+} |
|
457 |
+ |
|
412 | 458 |
|
413 | 459 |
int |
414 | 460 |
redata_whatin_refresh(redata_t *redata, int chunkno) |
... | ... |
@@ -423,10 +469,16 @@ redata_whatin_refresh(redata_t *redata, int chunkno) |
423 | 469 |
return(0); |
424 | 470 |
memset(&(chunk->whatin),0,sizeof(whatin_t)); |
425 | 471 |
nlcount=0; |
426 |
- for(i=0,lim=chunk->useddata;i<lim;i++) { |
|
472 |
+ for(i=0,lim=chunk->useddata;i<lim;i++) |
|
427 | 473 |
nlcount+=(chunk->data[i]=='\n')?1:0; |
428 |
- } |
|
429 | 474 |
chunk->whatin.nlcount=nlcount; |
475 |
+ if(chunkno>0) { |
|
476 |
+ int prev; |
|
477 |
+ for(prev=chunkno-1;prev>0 && redata->chunks[prev]->useddata==0;prev--) |
|
478 |
+ ; |
|
479 |
+ if(redata->chunks[prev]->useddata>0 && redata->chunks[prev]->data[redata->chunks[prev]->useddata-1]!='\n') |
|
480 |
+ chunk->whatin.iscontinuation=1; |
|
481 |
+ } |
|
430 | 482 |
chunk->whatin_fresh=1; |
431 | 483 |
return(0); |
432 | 484 |
} |
... | ... |
@@ -435,14 +487,14 @@ redata_whatin_refresh(redata_t *redata, int chunkno) |
435 | 487 |
int |
436 | 488 |
redata_fix_nl(redata_t *redata, int chunkno) |
437 | 489 |
{ |
490 |
+ rechunk_t *chunk,*nextchunk; |
|
491 |
+ int linesize, nextlinesize, avail, nextavail; |
|
492 |
+ unsigned char *ptr,*nextptr; |
|
438 | 493 |
/* make sure a line of len<chunksize is entirely inside one chunk (to simplify the syntax highlighting code) */ |
439 | 494 |
if(redata==NULL || chunkno<0 || chunkno>=redata->sizechunks || redata->chunks[chunkno]==NULL) |
440 | 495 |
return(-1); /* sanity check failed */ |
441 | 496 |
if(chunkno==(redata->sizechunks-1) || redata->chunks[chunkno]->useddata==0 || redata->chunks[chunkno]->data[redata->chunks[chunkno]->useddata-1]=='\n') |
442 | 497 |
return(0); /* Nothing to do (last chunk, chunk empty or already fixed) */ |
443 |
- rechunk_t *chunk,*nextchunk; |
|
444 |
- int linesize, nextlinesize, avail, nextavail; |
|
445 |
- unsigned char *ptr,*nextptr; |
|
446 | 498 |
chunk=redata->chunks[chunkno]; |
447 | 499 |
nextchunk=redata->chunks[chunkno+1]; |
448 | 500 |
ptr=mymemrchr(chunk->data,'\n',chunk->useddata); |
... | ... |
@@ -763,6 +815,20 @@ redata_undo_reactivatelast(redata_t *redata, undostack_t *stack) |
763 | 815 |
return(0); |
764 | 816 |
} |
765 | 817 |
|
818 |
+int |
|
819 |
+redata_undo_groupinit(redata_t *redata, undostack_t *stack) |
|
820 |
+{ |
|
821 |
+ /* stores the current position in (undostack).groupinit */ |
|
822 |
+#warning TODO |
|
823 |
+ return(-1); |
|
824 |
+} |
|
825 |
+ |
|
826 |
+int redata_undo_groupcommit(redata_t *redata, undostack_t *stack) |
|
827 |
+{ |
|
828 |
+ /* marks as hint_groupedwithnext from stored groupinit position in undostack to last-1 position (if groupinit pos is the last pos, do nothing)*/ |
|
829 |
+#warning TODO |
|
830 |
+ return(-1); |
|
831 |
+} |
|
766 | 832 |
|
767 | 833 |
int |
768 | 834 |
redata_op_add(redata_t *redata, long insertpos, char *buf, long buflen, undostack_t *fromhere) |
... | ... |
@@ -1333,6 +1399,14 @@ redata_generic_utf8charlen(char *ptr, int maxsize) |
1333 | 1399 |
return(i); |
1334 | 1400 |
} |
1335 | 1401 |
|
1402 |
+inline int |
|
1403 |
+redata_generic_utf8isstartbyte(int candidate) |
|
1404 |
+{ |
|
1405 |
+ if((candidate&0xc0)!=0x80) |
|
1406 |
+ return(1); |
|
1407 |
+ return(0); |
|
1408 |
+} |
|
1409 |
+ |
|
1336 | 1410 |
|
1337 | 1411 |
static int |
1338 | 1412 |
redata_hash_gen(redata_t *redata, char *filename, char *buf, long buflen, char *resbuf129bytes) |
... | ... |
@@ -1389,94 +1463,225 @@ redata_hash_gen(redata_t *redata, char *filename, char *buf, long buflen, char * |
1389 | 1463 |
return(0); |
1390 | 1464 |
} |
1391 | 1465 |
|
1392 |
-/*#define DEBUG_LINE_INFO*/ |
|
1393 |
- |
|
1394 |
-#ifdef DEBUG_LINE_INFO |
|
1395 |
-#define LINEINFODEBUG(a) fprintf a |
|
1396 |
-#else |
|
1397 |
-#define LINEINFODEBUG(a) |
|
1398 |
-#endif |
|
1399 |
- |
|
1400 | 1466 |
int |
1401 |
-redata_line_info(redata_t *redata, long pos, long *startpos, char **startptr, int *len) |
|
1467 |
+redata_line_rawinfo(redata_t *redata, long pos, long *startpos, char **startptr, int *len, int *is_continuation) |
|
1402 | 1468 |
{ |
1403 |
- int chunkno; |
|
1404 |
- long start; |
|
1405 |
- unsigned char *ptr,*end; |
|
1469 |
+ long chunkpos,newpos,endpos; |
|
1470 |
+ int nchunk; |
|
1406 | 1471 |
rechunk_t *chunk; |
1407 |
- if(redata==NULL || pos<0) |
|
1472 |
+ if(redata==NULL || pos<0 || pos>=redata_getused(redata)) |
|
1408 | 1473 |
return(-1); |
1409 |
- /* search chunk of pos */ |
|
1410 |
- for(chunkno=0,start=0;chunkno<redata->sizechunks;start+=(redata->chunks[chunkno]==NULL)?0:redata->chunks[chunkno]->useddata,chunkno++) { |
|
1411 |
- LINEINFODEBUG((stderr,"redata_line_info: searchchunk: pos:%li chunkno:%i start:%li\n",pos,chunkno,start)); |
|
1412 |
- if(redata->chunks[chunkno]==NULL) |
|
1474 |
+ for(nchunk=0,chunkpos=0 |
|
1475 |
+ ;nchunk<redata->sizechunks |
|
1476 |
+ ;chunkpos+=(chunk!=NULL)?chunk->useddata:0,nchunk++) { |
|
1477 |
+ if((chunk=redata->chunks[nchunk])==NULL) |
|
1413 | 1478 |
continue; |
1414 |
- if((start+redata->chunks[chunkno]->useddata)>pos) |
|
1479 |
+ if(pos>=chunkpos && pos<(chunkpos+chunk->useddata)) |
|
1415 | 1480 |
break; |
1416 | 1481 |
} |
1417 |
- if(chunkno>=redata->sizechunks) |
|
1418 |
- return(-1); |
|
1419 |
- chunk=redata->chunks[chunkno]; |
|
1420 |
- /* search line start */ |
|
1421 |
- LINEINFODEBUG((stderr,"redata_line_info: searchstart: pos:%li start:%li offset:%li\n",pos,start,(pos-start))); |
|
1422 |
- for(ptr=chunk->data+(pos-start);ptr>chunk->data && ptr[-1]!='\n';ptr--) |
|
1482 |
+ if(nchunk>=redata->sizechunks) |
|
1483 |
+ return(-1); /* pos not found */ |
|
1484 |
+ for(newpos=pos;newpos>chunkpos && chunk->data[newpos-chunkpos-1]!='\n';newpos--) |
|
1423 | 1485 |
; |
1424 |
- /* search line end */ |
|
1425 |
- LINEINFODEBUG((stderr,"redata_line_info: searchend: pos:%li start:%li offset:%li\n",pos,start,(pos-start))); |
|
1426 |
- for(end=chunk->data+(pos-start)+1;end<=(chunk->data+chunk->useddata) && end[-1]!='\n';end++) |
|
1486 |
+ for(endpos=pos;endpos<(chunkpos+chunk->useddata) && chunk->data[endpos-chunkpos]!='\n';endpos++) |
|
1427 | 1487 |
; |
1428 |
- /* fill results */ |
|
1429 |
- LINEINFODEBUG((stderr,"redata_line_info: filling results: len:%li\n",end-ptr)); |
|
1488 |
+ if(endpos==(chunkpos+chunk->useddata)) |
|
1489 |
+ endpos--; |
|
1430 | 1490 |
if(startpos!=NULL) |
1431 |
- *startpos=(pos-((chunk->data+(pos-start))-ptr)); |
|
1491 |
+ *startpos=newpos; |
|
1432 | 1492 |
if(startptr!=NULL) |
1433 |
- *startptr=(char *) ptr; |
|
1493 |
+ *startptr=(char *) (chunk->data+(newpos-chunkpos)); |
|
1434 | 1494 |
if(len!=NULL) |
1435 |
- *len=end-ptr; |
|
1495 |
+ *len=endpos-newpos+1; |
|
1496 |
+ if(is_continuation!=NULL) { |
|
1497 |
+ if(!(chunk->whatin_fresh)) |
|
1498 |
+ redata_whatin_refresh(redata,nchunk); |
|
1499 |
+ *is_continuation=(newpos==chunkpos && chunk->whatin.iscontinuation)?1:0; |
|
1500 |
+ } |
|
1436 | 1501 |
return(0); |
1437 | 1502 |
} |
1438 | 1503 |
|
1439 | 1504 |
int |
1440 |
-redata_pos2linecol(redata_t *redata, long pos, int *resline, int *rescol) |
|
1505 |
+redata_line_realstart(redata_t *redata, long pos, long *startpos) |
|
1441 | 1506 |
{ |
1442 |
- int line,col; |
|
1443 |
- int nchunk; |
|
1444 |
- int chunkpos; |
|
1445 |
- rechunk_t *chunk; |
|
1446 |
- int i,o; |
|
1447 |
- if(redata==NULL) |
|
1507 |
+ int is_continuation; |
|
1508 |
+ long nextpos,newpos; |
|
1509 |
+ if(redata==NULL || pos<0) |
|
1510 |
+ return(-1); /* sanity check failed */ |
|
1511 |
+ nextpos=pos; |
|
1512 |
+ do { |
|
1513 |
+ if(redata_line_rawinfo(redata,nextpos,&newpos,NULL,NULL,&is_continuation)==-1) |
|
1514 |
+ return(-1); |
|
1515 |
+ nextpos=newpos-1; |
|
1516 |
+ } while(is_continuation && newpos>0); |
|
1517 |
+ if(startpos!=NULL) |
|
1518 |
+ *startpos=newpos; |
|
1519 |
+ return(0); |
|
1520 |
+} |
|
1521 |
+ |
|
1522 |
+int |
|
1523 |
+redata_line_realend(redata_t *redata, long pos, long *endpos) |
|
1524 |
+{ |
|
1525 |
+ long nextpos,newpos; |
|
1526 |
+ long datasize; |
|
1527 |
+ char *ptr; |
|
1528 |
+ int len; |
|
1529 |
+ int has_nl; |
|
1530 |
+ if(redata==NULL || pos<0) |
|
1531 |
+ return(-1); /* sanity check failed */ |
|
1532 |
+ nextpos=pos; |
|
1533 |
+ if((datasize=redata_getused(redata))<=0) |
|
1534 |
+ return(-1); /* couldn't get last pos or there is no data */ |
|
1535 |
+ do { |
|
1536 |
+ if(redata_line_rawinfo(redata,nextpos,&newpos,&ptr,&len,NULL)==-1 || len==0) |
|
1537 |
+ return(-1); |
|
1538 |
+ nextpos=newpos+len; |
|
1539 |
+ has_nl=(len>0 && ptr[len-1]=='\n')?1:0; |
|
1540 |
+ } while(!has_nl && nextpos<datasize); |
|
1541 |
+ if(endpos!=NULL) |
|
1542 |
+ *endpos=newpos+len-1; |
|
1543 |
+ return(0); |
|
1544 |
+} |
|
1545 |
+ |
|
1546 |
+int |
|
1547 |
+redata_line_prevrealstart(redata_t *redata, long pos, long *startpos) |
|
1548 |
+{ |
|
1549 |
+ long newpos,prevpos; |
|
1550 |
+ if(redata==NULL || pos<0) |
|
1448 | 1551 |
return(-1); |
1449 |
- /* search chunk of pos while calculating first lineno of chunk */ |
|
1450 |
- for(nchunk=0,line=0,chunkpos=0 |
|
1451 |
- ;nchunk<redata->sizechunks |
|
1452 |
- ;line+=chunk->whatin.nlcount,chunkpos+=chunk->useddata,nchunk++) { |
|
1453 |
- chunk=redata->chunks[nchunk]; |
|
1454 |
- if(!(chunk->whatin_fresh)) |
|
1455 |
- redata_whatin_refresh(redata,nchunk); |
|
1456 |
- if(pos<(chunkpos+chunk->useddata)) |
|
1552 |
+ if(redata_line_realstart(redata,pos,&newpos)==-1) |
|
1553 |
+ return(-1); /* couldn't get start of line */ |
|
1554 |
+ if(redata_line_realstart(redata,newpos-1,&prevpos)==-1) |
|
1555 |
+ return(-1); /* couldn't get start of line */ |
|
1556 |
+ if(startpos!=NULL) |
|
1557 |
+ *startpos=prevpos; |
|
1558 |
+ return(0); |
|
1559 |
+} |
|
1560 |
+ |
|
1561 |
+int |
|
1562 |
+redata_line_nextrealstart(redata_t *redata, long pos, long *startpos) |
|
1563 |
+{ |
|
1564 |
+ long newpos,nextpos; |
|
1565 |
+ if(redata==NULL || pos<0) |
|
1566 |
+ return(-1); |
|
1567 |
+ if(redata_line_realend(redata,pos,&newpos)==-1) |
|
1568 |
+ return(-1); /* couldn't get end of line */ |
|
1569 |
+ if(redata_line_realstart(redata,newpos+1,&nextpos)==-1) |
|
1570 |
+ return(-1); /* couldn't get start of line */ |
|
1571 |
+ if(startpos!=NULL) |
|
1572 |
+ *startpos=nextpos; |
|
1573 |
+ return(0); |
|
1574 |
+} |
|
1575 |
+ |
|
1576 |
+int |
|
1577 |
+redata_line_inccol(redata_t *redata, long pos, int ncolrequest, long *newpos, int *ncoldone) |
|
1578 |
+{ |
|
1579 |
+ long curpos,startpos; |
|
1580 |
+ char *ptr; |
|
1581 |
+ int len; |
|
1582 |
+ int n,i; |
|
1583 |
+ int done; |
|
1584 |
+ if(redata==NULL || pos<0 || ncolrequest<0) |
|
1585 |
+ return(-1); /* sanity check failed */ |
|
1586 |
+ if(ncolrequest==0) { |
|
1587 |
+ if(newpos!=NULL) |
|
1588 |
+ *newpos=pos; |
|
1589 |
+ if(ncoldone!=NULL) |
|
1590 |
+ *ncoldone=0; |
|
1591 |
+ return(0); /* nothing to do */ |
|
1592 |
+ } |
|
1593 |
+ for(n=0,curpos=pos;n<=ncolrequest;) { |
|
1594 |
+ if(redata_line_rawinfo(redata,curpos,&startpos,&ptr,&len,NULL)==-1 || len==0) |
|
1595 |
+ return(-1); /* couldn't get current line data */ |
|
1596 |
+ done=0; |
|
1597 |
+ /* advance until we are positioned on the next char to the requested one */ |
|
1598 |
+ for(i=startpos-curpos;i<len;i++) { |
|
1599 |
+ if(redata_generic_utf8isstartbyte(ptr[i])) |
|
1600 |
+ n++; |
|
1601 |
+ if(ptr[i]=='\n' || n>ncolrequest) { |
|
1602 |
+ done=1; |
|
1603 |
+ break; |
|
1604 |
+ } |
|
1605 |
+ } |
|
1606 |
+ curpos=startpos+i; |
|
1607 |
+ if(done) |
|
1457 | 1608 |
break; |
1458 | 1609 |
} |
1459 |
- if(nchunk>=redata->sizechunks) |
|
1460 |
- return(-1); /* pos not found */ |
|
1461 |
- /* search chunk line/col */ |
|
1462 |
- for(i=0,o=chunkpos,col=0;o<pos && i<chunk->useddata;i++,o++) { |
|
1463 |
- if(chunk->data[i]=='\n') |
|
1464 |
- line++,col=0; |
|
1465 |
- else |
|
1466 |
- col++; |
|
1610 |
+ if(newpos!=NULL) |
|
1611 |
+ *newpos=curpos; |
|
1612 |
+ if(ncoldone!=NULL) |
|
1613 |
+ *ncoldone=n-1; |
|
1614 |
+ return(0); |
|
1615 |
+} |
|
1616 |
+ |
|
1617 |
+ |
|
1618 |
+int |
|
1619 |
+redata_pos2linecol(redata_t *redata, long pos, int *resline, int *rescol) |
|
1620 |
+{ |
|
1621 |
+ if(redata==NULL || pos<0 || pos>=redata_getused(redata)) |
|
1622 |
+ return(-1); |
|
1623 |
+ /* calculate line */ |
|
1624 |
+ if(resline!=NULL) { |
|
1625 |
+ long chunkpos,newpos; |
|
1626 |
+ int startline; |
|
1627 |
+ int nchunk; |
|
1628 |
+ rechunk_t *chunk; |
|
1629 |
+ int i; |
|
1630 |
+ for(nchunk=0,chunkpos=0,startline=0 |
|
1631 |
+ ;nchunk<redata->sizechunks |
|
1632 |
+ ;chunkpos+=(chunk!=NULL)?chunk->useddata:0 |
|
1633 |
+ ,startline+=(chunk!=NULL)?chunk->whatin.nlcount:0,nchunk++) { |
|
1634 |
+ if((chunk=redata->chunks[nchunk])==NULL) |
|
1635 |
+ continue; |
|
1636 |
+ if(!(chunk->whatin_fresh)) |
|
1637 |
+ redata_whatin_refresh(redata,nchunk); |
|
1638 |
+ if(pos>=chunkpos && pos<(chunkpos+chunk->useddata)) |
|
1639 |
+ break; |
|
1640 |
+ } |
|
1641 |
+ if(nchunk>=redata->sizechunks) |
|
1642 |
+ return(-1); /* pos not found */ |
|
1643 |
+ for(newpos=chunkpos,i=0;newpos<pos && i<chunk->useddata;newpos++,i++) { |
|
1644 |
+ if(chunk->data[i]=='\n') |
|
1645 |
+ startline++; |
|
1646 |
+ } |
|
1647 |
+ *resline=startline; |
|
1648 |
+ } |
|
1649 |
+ /* calculate col */ |
|
1650 |
+ if(rescol!=NULL) { |
|
1651 |
+ long realstart,curpos,startpos; |
|
1652 |
+ char *ptr; |
|
1653 |
+ int len; |
|
1654 |
+ int n,i; |
|
1655 |
+ int done; |
|
1656 |
+ if(redata_line_realstart(redata,pos,&realstart)==-1) |
|
1657 |
+ return(-1); /* startpos for pos not found */ |
|
1658 |
+ for(n=0,curpos=realstart;curpos<pos;) { |
|
1659 |
+ if(redata_line_rawinfo(redata,curpos,&startpos,&ptr,&len,NULL)==-1 || len==0) |
|
1660 |
+ return(-1); /* couldn't get current line data */ |
|
1661 |
+ done=0; |
|
1662 |
+ for(i=0;i<len && (startpos+i)<pos;i++) { |
|
1663 |
+ if(redata_generic_utf8isstartbyte(ptr[i])) |
|
1664 |
+ n++; |
|
1665 |
+ if(ptr[i]=='\n') { |
|
1666 |
+ done=1; |
|
1667 |
+ break; |
|
1668 |
+ } |
|
1669 |
+ } |
|
1670 |
+ curpos=startpos+i; |
|
1671 |
+ if(done) |
|
1672 |
+ break; |
|
1673 |
+ } |
|
1674 |
+ *rescol=n; |
|
1467 | 1675 |
} |
1468 |
- if(resline!=NULL) |
|
1469 |
- *resline=line; |
|
1470 |
- if(rescol!=NULL) |
|
1471 |
- *rescol=col; |
|
1472 | 1676 |
return(0); |
1473 |
-#warning DEBUG THIS |
|
1474 | 1677 |
} |
1475 | 1678 |
|
1476 | 1679 |
int |
1477 |
-redata_linecol2pos(redata_t *redata, int line, int col, long *pos) |
|
1680 |
+redata_linecol2pos(redata_t *redata, int line, int colrequest, long *pos, int *coldone) |
|
1478 | 1681 |
{ |
1479 |
-#warning TODO |
|
1682 |
+#warning TODO: XXX Implement this function |
|
1683 |
+#warning TODO: XXX: Add a parameter so this is like reata_line_inccol (colrequest, coldone) -- maybe also linetrequest linedone? (zed doesn''t let you go to the last line doing a Ctrl+q+l to an arbitrarily large number...) |
|
1684 |
+#warning TODO: XXX: The extra parameters are super-handy because the main user of this function is Control+Q+L "Go To Line" and we want to go to nearest pos |
|
1480 | 1685 |
return(-1); |
1481 | 1686 |
} |
1482 | 1687 |
|
... | ... |
@@ -1514,3 +1719,14 @@ meminvert(void *start, void *end) |
1514 | 1719 |
} |
1515 | 1720 |
} |
1516 | 1721 |
|
1722 |
+static size_t |
|
1723 |
+memrchroffset(char *ptr, int c, size_t n) |
|
1724 |
+{ |
|
1725 |
+ size_t i; |
|
1726 |
+ for(i=n-1;i>=0;i--) { |
|
1727 |
+ if(((unsigned char *)ptr)[i]==c) |
|
1728 |
+ return(i); |
|
1729 |
+ } |
|
1730 |
+ return(-1); |
|
1731 |
+} |
|
1732 |
+ |
... | ... |
@@ -17,6 +17,7 @@ |
17 | 17 |
|
18 | 18 |
typedef struct whatin_t { |
19 | 19 |
int nlcount; |
20 |
+ int iscontinuation; |
|
20 | 21 |
} whatin_t; |
21 | 22 |
|
22 | 23 |
typedef struct rechunk_t { |
... | ... |
@@ -34,12 +35,14 @@ typedef struct undo_t { |
34 | 35 |
long posdest; |
35 | 36 |
char prehash[129]; |
36 | 37 |
char posthash[129]; |
38 |
+ int hint_groupedwithnext; |
|
37 | 39 |
} undo_t; |
38 | 40 |
|
39 | 41 |
typedef struct undostack_t { |
40 | 42 |
int sizeundo; |
41 | 43 |
int usedundo; |
42 | 44 |
undo_t *undo; |
45 |
+ int groupinit; |
|
43 | 46 |
long sizebuf; |
44 | 47 |
long usedbuf; |
45 | 48 |
char *buf; |
... | ... |
@@ -98,6 +101,9 @@ int redata_chunk_insertdata(redata_t *redata, int chunkto, long posto, char *buf |
98 | 101 |
int redata_chunk_deletedata(redata_t *redata, int chunkno, long pos, long n); |
99 | 102 |
int redata_chunk_splithere(redata_t *redata, int chunkno, int pos); |
100 | 103 |
int redata_chunk_fillfromnext(redata_t *redata, int chunkno, int n); |
104 |
+int redata_chunk_unfreshnext(redata_t *redata, int chunkno); |
|
105 |
+int redata_chunk_unfreshrange(redata_t *redata, int fromchunkno, int tochunkno); |
|
106 |
+ |
|
101 | 107 |
int redata_whatin_refresh(redata_t *redata, int chunkno); |
102 | 108 |
int redata_fix_nl(redata_t *redata, int chunkno); |
103 | 109 |
int redata_undobuf_reserve(redata_t *redata, undostack_t *stack, int minavail); |
... | ... |
@@ -109,6 +115,8 @@ int redata_undo_removelast(redata_t *redata, undostack_t *stack); |
109 | 115 |
int redata_undo_wipe(redata_t *redata, undostack_t *stack); |
110 | 116 |
int redata_undo_inactivatelast(redata_t *redata, undostack_t *stack); |
111 | 117 |
int redata_undo_reactivatelast(redata_t *redata, undostack_t *stack); |
118 |
+int redata_undo_groupinit(redata_t *redata, undostack_t *stack); |
|
119 |
+int redata_undo_groupcommit(redata_t *redata, undostack_t *stack); |
|
112 | 120 |
|
113 | 121 |
/* high level stuff */ |
114 | 122 |
int redata_load(redata_t *redata, char *filename, int (*callback_question)(/*char *title, char *body, int nopts, char *opts[],void *userptr*/), void *userptr); |
... | ... |
@@ -140,10 +148,25 @@ int redata_generic_utf8len(char *ptr, int size); |
140 | 148 |
char *redata_generic_utf8col(char *ptr, int size, int col); |
141 | 149 |
/* returns the len in bytes of the character starting at ptr (zero on error)*/ |
142 | 150 |
int redata_generic_utf8charlen(char *ptr, int maxsize); |
151 |
+/* returns true if it's the forst byte of an UTF char */ |
|
152 |
+int redata_generic_utf8isstartbyte(int candidate); |
|
143 | 153 |
|
144 | 154 |
|
145 | 155 |
/* line convenience funtions */ |
146 |
-int redata_line_info(redata_t *redata, long pos, long *startpos, char **startptr, int *len); |
|
156 |
+/* get pointer to full line (if it doesn't fit in a chunk, is_continuation is 1 and/or doesn't have an ending nl */ |
|
157 |
+int redata_line_rawinfo(redata_t *redata, long pos, long *startpos, char **startptr, int *len, int *is_continuation); |
|
158 |
+/* get the startpos of line, even if it doesn't fit in one chunk */ |
|
159 |
+int redata_line_realstart(redata_t *redata, long pos, long *startpos); |
|
160 |
+/* get the endpos of line, even if it doesn't fit in one chunk */ |
|
161 |
+int redata_line_realend(redata_t *redata, long pos, long *endpos); |
|
162 |
+/* get pos of previous line real start */ |
|
163 |
+int redata_line_prevrealstart(redata_t *redata, long pos, long *startpos); |
|
164 |
+/* get pos of next line real start */ |
|
165 |
+int redata_line_nextrealstart(redata_t *redata, long pos, long *startpos); |
|
166 |
+/* advance "n" cols */ |
|
167 |
+int redata_line_inccol(redata_t *redata, long pos, int ncolrequest, long *newpos, int *ncoldone); |
|
168 |
+/* get the line/col of a pos (col is calculated using the utf8 convenience functions) */ |
|
147 | 169 |
int redata_pos2linecol(redata_t *redata, long pos, int *line, int *col); |
148 |
-int redata_linecol2pos(redata_t *redata, int line, int col, long *pos); |
|
170 |
+/* get the pos of that line/col (calculated using the utf8 convenience functions) */ |
|
171 |
+int redata_linecol2pos(redata_t *redata, int line, int colrequest, long *pos, int *coldone); |
|
149 | 172 |
|
... | ... |
@@ -21,6 +21,21 @@ |
21 | 21 |
#define LINEFORCESCROLL 1 |
22 | 22 |
#define COLFORCESCROLL 5 |
23 | 23 |
|
24 |
+#define COMMANDBUFSIZE 1024 |
|
25 |
+ |
|
26 |
+#define COMMAND_WARNING "(!)" |
|
27 |
+#define COMMAND_GOTOLINE "Go to line: " |
|
28 |
+ |
|
29 |
+#define COLOR_STATUSBG "\x00\x00\xff\xff" |
|
30 |
+#define COLOR_STATUSFG "\xff\xff\x00\xff" |
|
31 |
+ |
|
32 |
+#define COLOR_QUERYBG "\xc0\xff\x00\xff" |
|
33 |
+#define COLOR_QUERYFG "\x3f\x00\xff\xff" |
|
34 |
+ |
|
35 |
+#define COLOR_WARNINGBG "\xff\x00\x00\xff" |
|
36 |
+#define COLOR_WARNINGFG "\xff\xff\x00\xff" |
|
37 |
+ |
|
38 |
+ |
|
24 | 39 |
typedef struct re_t { |
25 | 40 |
redata_t *data; |
26 | 41 |
reui_t *ui; |
... | ... |
@@ -31,7 +46,11 @@ typedef struct re_t { |
31 | 46 |
int originline,origincol; |
32 | 47 |
int curline,curcol; |
33 | 48 |
int maxrow,maxcol; |
49 |
+ int headerdirty; |
|
34 | 50 |
int contentsdirty; |
51 |
+ char *command; |
|
52 |
+ char commandbuf[COMMANDBUFSIZE]; |
|
53 |
+ int ignorenkeys; |
|
35 | 54 |
} re_t; |
36 | 55 |
|
37 | 56 |
volatile int flag_sigint; |
... | ... |
@@ -47,10 +66,15 @@ re_t *re_init(void); |
47 | 66 |
void re_free(re_t *re); |
48 | 67 |
|
49 | 68 |
int re_setfilename(re_t *re, char *filename); |
50 |
-int re_processkey(re_t *re, SDL_Event *event); |
|
69 |
+int re_processkey_editing(re_t *re, SDL_Event *event); |
|
70 |
+int re_processkey_commandwait(re_t *re, SDL_Event *event); |
|
71 |
+int re_processkey_commanddata(re_t *re, SDL_Event *event); |
|
72 |
+int re_processcommand(re_t *re); |
|
51 | 73 |
int re_moveupdown(re_t *re, int totalinc); |
52 | 74 |
int re_moveleftright(re_t *re, int totalinc); |
53 |
-int re_drawheader(re_t *re); |
|
75 |
+int re_rtrim(re_t *re, long curpos, int *trimmed); |
|
76 |
+int re_drawheader_editing(re_t *re); |
|
77 |
+int re_drawheader_command(re_t *re); |
|
54 | 78 |
int re_drawcontents(re_t *re); |
55 | 79 |
|
56 | 80 |
|
... | ... |
@@ -106,10 +130,25 @@ main(int argc, char *argv[]) |
106 | 130 |
re->x=0,re->y=re->ui->fontheight,re->w=re->ui->w,re->h=re->ui->h-re->y; |
107 | 131 |
re->maxrow=re->h/re->ui->fontheight-1; |
108 | 132 |
re->maxcol=re->w/re->ui->fontwidth-1; |
109 |
- re_drawheader(re); |
|
110 |
- re_drawcontents(re); |
|
133 |
+ re->headerdirty=1; |
|
134 |
+ re->contentsdirty=1; |
|
111 | 135 |
flag_had_events=0; |
136 |
+ SDL_StartTextInput(); |
|
112 | 137 |
while(do_exit==0 && flag_sigint==0) { |
138 |
+ if(re->headerdirty) { |
|
139 |
+ if(re->command==NULL) { |
|
140 |
+fprintf(stderr,"REDRAW Header (editing)\n"); |
|
141 |
+ re_drawheader_editing(re); |
|
142 |
+ } else { |
|
143 |
+fprintf(stderr,"REDRAW Header (command)\n"); |
|
144 |
+ re_drawheader_command(re); |
|
145 |
+ if(strcmp(re->command,COMMAND_WARNING)==0) { |
|
146 |
+ /* the warnings only get shown once, remove it */ |
|
147 |
+ re->command=NULL; |
|
148 |
+ re->commandbuf[0]='\0'; |
|
149 |
+ } |
|
150 |
+ } |
|
151 |
+ } |
|
113 | 152 |
if(re->contentsdirty) |
114 | 153 |
re_drawcontents(re); |
115 | 154 |
if(re->ui->rendererdirty) |
... | ... |
@@ -124,7 +163,14 @@ main(int argc, char *argv[]) |
124 | 163 |
do_exit=1; |
125 | 164 |
break; |
126 | 165 |
case SDL_KEYDOWN: |
127 |
- re_processkey(re,&event); |
|
166 |
+ case SDL_TEXTINPUT: |
|
167 |
+ case SDL_TEXTEDITING: |
|
168 |
+ if(re->command==NULL || strcmp(re->command,COMMAND_WARNING)==0) |
|
169 |
+ re_processkey_editing(re,&event); |
|
170 |
+ else if(re->command[0]=='\0') |
|
171 |
+ re_processkey_commandwait(re,&event); |
|
172 |
+ else |
|
173 |
+ re_processkey_commanddata(re,&event); |
|
128 | 174 |
break; |
129 | 175 |
case SDL_WINDOWEVENT: |
130 | 176 |
if(event.window.event==SDL_WINDOWEVENT_SHOWN |
... | ... |
@@ -137,6 +183,7 @@ main(int argc, char *argv[]) |
137 | 183 |
} |
138 | 184 |
} |
139 | 185 |
} |
186 |
+ SDL_StopTextInput(); |
|
140 | 187 |
sselect_free(ssel),ssel=NULL; |
141 | 188 |
re_free(re),re=NULL; |
142 | 189 |
return(0); |
... | ... |
@@ -209,14 +256,79 @@ re_setfilename(re_t *re, char *filename) |
209 | 256 |
} |
210 | 257 |
|
211 | 258 |
int |
212 |
-re_processkey(re_t *re, SDL_Event *event) |
|
259 |
+re_processkey_editing(re_t *re, SDL_Event *event) |
|
213 | 260 |
{ |
214 |
- long newpos; |
|
215 |
- char *ptr; |
|
216 |
- int len; |
|
217 |
- int has_nl; |
|
218 |
- if(re==NULL || event==NULL || event->type!=SDL_KEYDOWN) |
|
261 |
+ SDL_Event returnevent; |
|
262 |
+ if(re==NULL || event==NULL) |
|
219 | 263 |
return(-1); /* sanity check failed */ |
264 |
+ /* convert RETURN KEYDOWN to TEXTINPUT */ |
|
265 |
+ if(event->type==SDL_KEYDOWN && event->key.keysym.sym==SDLK_RETURN) { |
|
266 |
+ memset(&returnevent,0,sizeof(SDL_Event)); |
|
267 |
+ event=&returnevent; |
|
268 |
+ event->type=SDL_TEXTINPUT; |
|
269 |
+ strncpy(event->text.text,"\n",sizeof(event->text.text)); |
|
270 |
+ event->text.text[sizeof(event->text.text)-1]='\0'; |
|
271 |
+ } |
|
272 |
+ /* special case: text editing event */ |
|
273 |
+ if(event->type==SDL_TEXTINPUT) { |
|
274 |
+ int len; |
|
275 |
+ long realend; |
|
276 |
+ int at_end; |
|
277 |
+ if(re->ignorenkeys>0) { |
|
278 |
+ re->ignorenkeys--; |
|
279 |
+ return(0); /* this is an already processed key, ignore it */ |
|
280 |
+ } |
|
281 |
+#if 1 |
|
282 |
+fprintf(stderr,"SDL_TEXTINPUT:\"%s\"\n",event->text.text); |
|
283 |
+#endif |
|
284 |
+ if(redata_line_realend(re->data,re->cursorpos,&realend)==-1) |
|
285 |
+ return(-1); /* couldn't get current line info */ |
|
286 |
+ at_end=(re->cursorpos==realend)?1:0; |
|
287 |
+ if(event->text.text[0]==' ' && event->text.text[1]=='\0' && at_end) { |
|
288 |
+ /* instead of adding a space at the end of the line, we move the cursor to the right */ |
|
289 |
+ re_moveleftright(re,1); |
|
290 |
+ return(0); /* no need to add spaces at the end of the line */ |
|
291 |
+ } |
|
292 |
+ redata_undo_groupinit(re->data,NULL); |
|
293 |
+ if(event!=&returnevent && at_end) { |
|
294 |
+ int col; |
|
295 |
+ if(redata_pos2linecol(re->data,re->cursorpos,NULL,&col)==-1) |
|
296 |
+ return(-1); /* couldn't get line info */ |
|
297 |
+ if(redata_op_addn(re->data,re->cursorpos,' ',re->curcol-col,NULL)!=0) |
|
298 |
+ return(-1); /* couldn't add spaces up to current displayed pos */ |
|
299 |
+ /* increment cursorpos; spaces are 1 byte, so the number of columns advanced is the number of bytes advanced */ |
|
300 |
+ re->cursorpos+=re->curcol-col; |
|
301 |
+ } |
|
302 |
+ len=strlen(event->text.text); |
|
303 |
+ if(redata_op_add(re->data,re->cursorpos,event->text.text,len,NULL)!=0) |
|
304 |
+ return(-1); /* couldn't add requested text */ |
|
305 |
+ re->cursorpos+=len; |
|
306 |
+ if(event==&returnevent) { |
|
307 |
+ int trimmed; |
|
308 |
+ if(re_rtrim(re,re->cursorpos-len,&trimmed)) |
|
309 |
+ re->cursorpos-=trimmed; |
|
310 |
+ re->curline++; |
|
311 |
+ re->curcol=0; |
|
312 |
+ } else { |
|
313 |
+ re->curcol+=redata_generic_utf8len(event->text.text,len); |
|
314 |
+ } |
|
315 |
+ redata_undo_groupcommit(re->data,NULL); |
|
316 |
+ re->headerdirty=1; |
|
317 |
+ re->contentsdirty=1; |
|
318 |
+ } |
|
319 |
+#if 0 |
|
320 |
+ else if(event->type==SDL_TEXTEDITING) { |
|
321 |
+ /* NOTE: on window enter events we cam also receive this event (!) */ |
|
322 |
+#warning TODO: CJK support |
|
323 |
+fprintf(stderr,"SDL_TEXTEDITING: composition:\"%s\" start:%i len:%i\n",event->edit.text,event->edit.start,event->edit.length); |
|
324 |
+ } |
|
325 |
+#endif |
|
326 |
+ /* default case: keydown event */ |
|
327 |
+ if(event->type!=SDL_KEYDOWN) |
|
328 |
+ return(0); /* Ignore other possible events */ |
|
329 |
+#if 1 |
|
330 |
+fprintf(stderr,"SDL_KEYDOWN: sym:%i\n",event->key.keysym.sym); |
|
331 |
+#endif |
|
220 | 332 |
if(event->key.keysym.sym==SDLK_DOWN || event->key.keysym.sym==SDLK_UP) { |
221 | 333 |
re_moveupdown(re,(event->key.keysym.sym==SDLK_UP)?-1:1); |
222 | 334 |
} else if(event->key.keysym.sym==SDLK_LEFT || event->key.keysym.sym==SDLK_RIGHT) { |
... | ... |
@@ -224,11 +336,14 @@ re_processkey(re_t *re, SDL_Event *event) |
224 | 336 |
} else if(event->key.keysym.sym==SDLK_PAGEDOWN || event->key.keysym.sym==SDLK_PAGEUP) { |
225 | 337 |
re_moveupdown(re,(event->key.keysym.sym==SDLK_PAGEUP)?-(re->maxrow):re->maxrow); |
226 | 338 |
} else if(event->key.keysym.sym==SDLK_HOME || event->key.keysym.sym==SDLK_END) { |
227 |
- if(redata_line_info(re->data,re->cursorpos,&newpos,&ptr,&len)==-1) |
|
228 |
- return(-1); /* couldn't get current line data */ |
|
229 |
- has_nl=((len>0 && ptr[len-1]=='\n')?1:0); |
|
230 |
- re->cursorpos=(event->key.keysym.sym==SDLK_HOME)?newpos:newpos+len-has_nl; |
|
231 |
- redata_pos2linecol(re->data,re->cursorpos,&(re->curline),&(re->curcol)); |
|
339 |
+ long newpos; |
|
340 |
+ if((event->key.keysym.sym==SDLK_HOME && redata_line_realstart(re->data,re->cursorpos,&newpos)==-1) |
|
341 |
+ || (event->key.keysym.sym==SDLK_END && redata_line_realend(re->data,re->cursorpos,&newpos)==-1)) { |
|
342 |
+ return(-1); /* couldn't get destination pos data */ |
|
343 |
+ } |
|
344 |
+ re->cursorpos=newpos; |
|
345 |
+ if(redata_pos2linecol(re->data,re->cursorpos,NULL,&(re->curcol))==-1) |
|
346 |
+ return(-1); /* couldn't get col of current pos */; |
|
232 | 347 |
if(re->curcol<re->origincol) { |
233 | 348 |
re->origincol=re->curcol; |
234 | 349 |
re->origincol=(re->origincol<0)?0:re->origincol; |
... | ... |
@@ -237,42 +352,184 @@ re_processkey(re_t *re, SDL_Event *event) |
237 | 352 |
re->origincol=re->curcol+COLFORCESCROLL-re->maxcol; |
238 | 353 |
re->origincol=(re->origincol<0)?0:re->origincol; |
239 | 354 |
} |
355 |
+ re->headerdirty=1; |
|
356 |
+ re->contentsdirty=1; |
|
357 |
+ } else if(event->key.keysym.sym==SDLK_BACKSPACE && re->cursorpos>0) { |
|
358 |
+ int line,col; |
|
359 |
+ long startpos,newpos,realstart,start; |
|
360 |
+ char *ptr; |
|
361 |
+ int len; |
|
362 |
+ int trimmed; |
|
363 |
+ int doneinc; |
|
364 |
+ if(redata_pos2linecol(re->data,re->cursorpos,&line,&col)==-1) |
|
365 |
+ return(-1); /* couldn't get current line data */ |
|
366 |
+ if(col<re->curcol) { |
|
367 |
+ re_moveleftright(re,-1); |
|
368 |
+ return(0); /* were hovering to the right of last char, only had to move left */ |
|
369 |
+ } |
|
370 |
+ redata_undo_groupinit(re->data,NULL); |
|
371 |
+ /* delete the last character */ |
|
372 |
+ if(col>0) { |
|
373 |
+ if(redata_line_realstart(re->data,re->cursorpos,&realstart)==-1) |
|
374 |
+ return(-1); /* couldn't get line info */ |
|
375 |
+ /* get the start of the part to delete */ |
|
376 |
+ doneinc=0; |
|
377 |
+ for(ptr=NULL,len=0,start=0,newpos=re->cursorpos;doneinc!=1;) { |
|
378 |
+ if((newpos-1)<realstart) |
|
379 |
+ break; |
|
380 |
+ newpos--; |
|
381 |
+ if(ptr==NULL || (start+len)<=newpos || newpos<start) { |
|
382 |
+ if(redata_line_rawinfo(re->data,newpos,&start,&ptr,&len,NULL)==-1) |
|
383 |
+ return(-1); /* couldn't get line data */ |
|
384 |
+ } |
|
385 |
+ if(redata_generic_utf8isstartbyte(ptr[newpos-start])) |
|
386 |
+ doneinc++; |
|
387 |
+ } |
|
388 |
+ /* delete */ |
|
389 |
+ redata_op_del(re->data,newpos,re->cursorpos-newpos,NULL); |
|
390 |
+ re->cursorpos=newpos; |
|
391 |
+ } else { |
|
392 |
+ long delpos; |
|
393 |
+ /* to make the code trivial, we're being lazy on '\n' deletion: we call ...rawinfo() for each byte in the multibyte utf-8 sequence */ |
|
394 |
+ for(delpos=re->cursorpos-1 |
|
395 |
+ ;delpos>0 |
|
396 |
+ && redata_line_rawinfo(re->data,delpos,&startpos,&ptr,&len,NULL)==0;) { |
|
397 |
+ if(redata_generic_utf8isstartbyte(ptr[delpos-startpos])) |
|
398 |
+ break; |
|
399 |
+ } |
|
400 |
+ redata_op_del(re->data,delpos,re->cursorpos-delpos,NULL); |
|
401 |
+ re->cursorpos=delpos; |
|
402 |
+ } |
|
403 |
+ redata_pos2linecol(re->data,re->cursorpos,&(re->curline),&(re->curcol)); |
|
404 |
+ /* if cursor at end of line and there are trailing spaces at the end, delete them too */ |
|
405 |
+ if(re_rtrim(re,re->cursorpos,&trimmed)) |
|
406 |
+ re->cursorpos-=trimmed; |
|
407 |
+ /* end of deletion */ |
|
408 |
+ redata_undo_groupcommit(re->data,NULL); |
|
409 |
+ re->headerdirty=1; |
|
240 | 410 |
re->contentsdirty=1; |
241 |
- re_drawheader(re); |
|
242 |
- } else if(event->key.keysym.sym==SDLK_a) { |
|
243 |
- ; |
|
411 |
+ } else if(event->key.keysym.sym==SDLK_q && (SDL_GetModState()&KMOD_CTRL)!=0) { |
|
412 |
+fprintf(stderr,"re_processkey(): received Control+q\n"); |
|
413 |
+ re->command=""; |
|
414 |
+ re->headerdirty=1; |
|
244 | 415 |
} |
245 |
- return(-1); |
|
416 |
+ return(0); |
|
417 |
+} |
|
418 |
+ |
|
419 |
+int |
|
420 |
+re_processkey_commandwait(re_t *re, SDL_Event *event) |
|
421 |
+{ |
|
422 |
+ if(re==NULL || event==NULL) |
|
423 |
+ return(-1); /* sanity check failed */ |
|
424 |
+ /* default case: keydown event */ |
|
425 |
+ if(event->type!=SDL_KEYDOWN) |
|
426 |
+ return(0); /* Ignore other possible events */ |
|
427 |
+ if(event->key.keysym.sym==SDLK_l) { |
|
428 |
+ re->command=COMMAND_GOTOLINE; |
|
429 |
+ re->commandbuf[0]='\0'; |
|
430 |
+ re->headerdirty=1; |
|
431 |
+ } else { |
|
432 |
+ re->command=NULL; |
|
433 |
+ re->headerdirty=1; |
|
434 |
+ } |
|
435 |
+ if(!(SDL_GetModState()&KMOD_CTRL)) |
|
436 |
+ re->ignorenkeys=1; /* control was not pressed, we will receive again this key as SDL_TEXTINPUT */ |
|
437 |
+ return(0); |
|
438 |
+} |
|
439 |
+ |
|
440 |
+int |
|
441 |
+re_processkey_commanddata(re_t *re, SDL_Event *event) |
|
442 |
+{ |
|
443 |
+ if(re==NULL || event==NULL) |
|
444 |
+ return(-1); /* sanity check failed */ |
|
445 |
+ /* special case: text editing event */ |
|
446 |
+ if(event->type==SDL_TEXTINPUT) { |
|
447 |
+ int len; |
|
448 |
+ if(re->ignorenkeys>0) { |
|
449 |
+ re->ignorenkeys--; |
|
450 |
+ return(0); /* this is an already processed key, ignore it */ |
|
451 |
+ } |
|
452 |
+ len=strlen(event->text.text); |
|
453 |
+ if((strlen(re->commandbuf)+len+1)>=sizeof(re->commandbuf)) |
|
454 |
+ return(-1); /* No space for text */ |
|
455 |
+ memcpy(re->commandbuf+strlen(re->commandbuf),event->text.text,len+1); |
|
456 |
+ re->commandbuf[sizeof(re->commandbuf)-1]='\0'; |
|
457 |
+ re->headerdirty=1; |
|
458 |
+ } |
|
459 |
+ /* default case: keydown event */ |
|
460 |
+ if(event->type!=SDL_KEYDOWN) |
|
461 |
+ return(0); /* Ignore other possible events */ |
|
462 |
+ if(event->key.keysym.sym==SDLK_ESCAPE) { |
|
463 |
+ re->command=NULL; |
|
464 |
+ re->commandbuf[0]='\0'; |
|
465 |
+ re->headerdirty=1; |
|
466 |
+ } else if(event->key.keysym.sym==SDLK_BACKSPACE && re->commandbuf[0]!='\0') { |
|
467 |
+ int nchar; |
|
468 |
+ char *ptr; |
|
469 |
+ if((nchar=redata_generic_utf8len(re->commandbuf,strlen(re->commandbuf)))<=0) |
|
470 |
+ return(-1); /* error parsing commandbuf */ |
|
471 |
+ if((ptr=redata_generic_utf8col(re->commandbuf,strlen(re->commandbuf),nchar-1))==NULL) |
|
472 |
+ return(-1); /* error positioning in commandbuf */ |
|
473 |
+ *ptr='\0'; |
|
474 |
+ re->headerdirty=1; |
|
475 |
+ } else if(event->key.keysym.sym==SDLK_RETURN) { |
|
476 |
+ re_processcommand(re); |
|
477 |
+ } |
|
478 |
+ return(0); |
|
479 |
+} |
|
480 |
+ |
|
481 |
+int |
|
482 |
+re_processcommand(re_t *re) |
|
483 |
+{ |
|
484 |
+ if(re==NULL || re->command==NULL) |
|
485 |
+ return(-1); |
|
486 |
+ re->commandbuf[sizeof(re->commandbuf)-1]='\0'; |
|
487 |
+ if(strcmp(re->command,COMMAND_GOTOLINE)==0) { |
|
488 |
+ int line; |
|
489 |
+ long pos; |
|
490 |
+ line=atoi(re->commandbuf); |
|
491 |
+ if(redata_linecol2pos(re->data,line,0,&pos,NULL)==-1) { |
|
492 |
+ re->command=COMMAND_WARNING; |
|
493 |
+ snprintf(re->commandbuf,sizeof(re->commandbuf),"Unknown line"); |
|
494 |
+ re->commandbuf[sizeof(re->commandbuf)-1]='\0'; |
|
495 |
+ re->headerdirty=1; |
|
496 |
+ return(-1); |
|
497 |
+ } |
|
498 |
+ re->cursorpos=pos; |
|
499 |
+ re->curcol=0; |
|
500 |
+ re->curline=line; |
|
501 |
+ re->origincol=0; |
|
502 |
+ if((re->originline+re->maxrow)<line) |
|
503 |
+ re->originline=line-re->maxrow; |
|
504 |
+ if(line<re->originline) |
|
505 |
+ re->originline=line; |
|
506 |
+ re->headerdirty=1; |
|
507 |
+ re->contentsdirty=1; |
|
508 |
+ } |
|
509 |
+ re->command=NULL; |
|
510 |
+ re->commandbuf[0]='\0'; |
|
511 |
+ return(0); |
|
246 | 512 |
} |
247 | 513 |
|
248 | 514 |
int |
249 | 515 |
re_moveupdown(re_t *re, int totalinc) |
250 | 516 |
{ |
251 | 517 |
long newpos,newpos2; |
252 |
- char *ptr; |
|
253 |
- int len; |
|
254 |
- int has_nl; |
|
255 |
- int maxcol; |
|
256 | 518 |
int inc,doneinc; |
257 |
- |
|
519 |
+ long realstart; |
|
258 | 520 |
if(re==NULL) |
259 | 521 |
return(-1); /* sanity check failed */ |
260 | 522 |
if(totalinc==0) |
261 | 523 |
return(0); /* nothing to do */ |
262 | 524 |
inc=(totalinc<0)?-1:1; |
525 |
+ newpos=re->cursorpos; /* get rid of compiler warning (will be overwitten in the loop as totalinc never is 0) */ |
|
263 | 526 |
for(doneinc=0;doneinc!=totalinc;doneinc+=inc) { |
264 |
- if(redata_line_info(re->data,re->cursorpos,&newpos,&ptr,&len)==-1) |
|
265 |
- return(-1); /* couldn't get current line data */ |
|
266 |
- if(inc==-1 && newpos==0) |
|
267 |
- return(0); /* going up but already at top; nothing to do */ |
|
268 |
- if(redata_line_info(re->data,(inc==1)?(newpos+len):(newpos-1),&newpos2,&ptr,&len)==-1) |
|
269 |
- return(-1); /* couldn't get next line data */ |
|
270 |
- has_nl=((len>0 && ptr[len-1]=='\n')?1:0); |
|
271 |
- maxcol=redata_generic_utf8len(ptr,len)-has_nl; |
|
272 |
- if(maxcol<re->curcol) |
|
273 |
- re->cursorpos=newpos2+len-has_nl; |
|
274 |
- else |
|
275 |
- re->cursorpos=newpos2+(redata_generic_utf8col(ptr,len,re->curcol)-ptr); |
|
527 |
+fprintf(stderr,"MOVING from cursorpos:%li line:%i col:%i\n",re->cursorpos,re->curline,re->curcol); |
|
528 |
+ if((inc==-1 && redata_line_prevrealstart(re->data,re->cursorpos,&realstart)==-1) |
|
529 |
+ || (inc==1 && redata_line_nextrealstart(re->data,re->cursorpos,&realstart)==-1)) { |
|
530 |
+ break; /* couldn't get current line data, we are at start/end */ |
|
531 |
+ } |
|
532 |
+ re->cursorpos=realstart; |
|
276 | 533 |
re->curline+=inc; |
277 | 534 |
if(re->curline<(re->originline+LINEFORCESCROLL)) { |
278 | 535 |
re->originline-=LINEFORCESCROLL; |
... | ... |
@@ -280,110 +537,230 @@ re_moveupdown(re_t *re, int totalinc) |
280 | 537 |
} |
281 | 538 |
if(re->curline>(re->originline+re->maxrow-LINEFORCESCROLL)) |
282 | 539 |
re->originline+=LINEFORCESCROLL; |
283 |
- re->contentsdirty=1; |
|
540 |
+fprintf(stderr,"MOVING to cursorpos:%li line:%i col:%i\n",re->cursorpos,re->curline,re->curcol); |
|
541 |
+ } |
|
542 |
+ if(redata_line_inccol(re->data,re->cursorpos,re->curcol,&newpos2,NULL)==-1) { |
|
543 |
+ /* error advancing cursor, "emergency" repositioning */ |
|
544 |
+fprintf(stderr,"COLUMN ERROR\n"); |
|
545 |
+ re->curcol=0; |
|
546 |
+ newpos2=newpos; |
|
284 | 547 |
} |
285 |
- re_drawheader(re); |
|
548 |
+fprintf(stderr,"COLUMN from cursorpos:%li line:%i col:%i\n",re->cursorpos,re->curline,re->curcol); |
|
549 |
+ re->cursorpos=newpos2; |
|
550 |
+fprintf(stderr,"COLUMN to cursorpos:%li line:%i col:%i\n",re->cursorpos,re->curline,re->curcol); |
|
551 |
+ re->contentsdirty=1; |
|
552 |
+ re->headerdirty=1; |
|
286 | 553 |
return(0); |
287 | 554 |
} |
288 | 555 |
|
289 | 556 |
int |
290 | 557 |
re_moveleftright(re_t *re, int totalinc) |
291 | 558 |
{ |
292 |
- long newpos; |
|
293 |
- char *ptr,*ptr2; |
|
294 |
- int len; |
|
295 |
- int has_nl; |
|
296 |
- int maxcol; |
|
559 |
+ long newpos,realstart; |
|
297 | 560 |
int inc,doneinc; |
298 |
- |
|
561 |
+ char *ptr; |
|
562 |
+ int len; |
|
563 |
+ long start; |
|
564 |
+ int tmpcol,oldcol; |
|
299 | 565 |
if(re==NULL) |
300 | 566 |
return(-1); /* sanity check failed */ |
301 | 567 |
if(totalinc==0) |
302 | 568 |
return(0); /* nothing to do */ |
303 |
- inc=(totalinc<0)?-1:1; |
|
304 |
- for(doneinc=0;doneinc!=totalinc;doneinc+=inc) { |
|
305 |
- if(redata_line_info(re->data,re->cursorpos,&newpos,&ptr,&len)==-1) |
|
306 |
- return(-1); /* couldn't get current line data */ |
|
307 |
- if(inc==-1 && re->cursorpos==0) |
|
308 |
- return(-1); /* going left but already at leftmost char */ |
|
309 |
- maxcol=redata_generic_utf8len(ptr,len); |
|
310 |
- has_nl=((len>0 && ptr[len-1]=='\n')?1:0); |
|
311 |
- if(re->curcol<=maxcol) |
|
312 |
- ptr2=redata_generic_utf8col(ptr,len,re->curcol+inc); |
|
313 |
- else |
|
314 |
- ptr2=NULL; |
|
315 |
- if(ptr2!=NULL) |
|
316 |
- re->cursorpos=newpos+(ptr2-ptr); |
|
317 |
- else |
|
318 |
- re->cursorpos=newpos+(len-has_nl); /* we're past the last col, set cursor to last pos in line */ |
|
319 |
- if((re->curcol+inc)>=0) |
|
320 |
- re->curcol+=inc; |
|
321 |
- if(re->curcol<(re->origincol+COLFORCESCROLL)) { |
|
322 |
- re->origincol-=COLFORCESCROLL; |
|
323 |
- re->origincol=(re->origincol<0)?0:re->origincol; |
|
569 |
+ oldcol=re->curcol; |
|
570 |
+ if(totalinc<0 && (re->curcol+totalinc)<=0) { |
|
571 |
+ /* we'll land on the start of the line -- do it trivially */ |
|
572 |
+ if(redata_line_realstart(re->data,re->cursorpos,&realstart)==-1) |
|
573 |
+ return(-1); /* couldn't get current pos */ |
|
574 |
+ re->curcol=0; |
|
575 |
+ re->cursorpos=realstart; |
|
576 |
+ } else { |
|
577 |
+ /* move a char at a time */ |
|
578 |
+ if(redata_line_realstart(re->data,re->cursorpos,&realstart)==-1) |
|
579 |
+ return(-1); /* couldn't get current pos */ |
|
580 |
+ inc=(totalinc<0)?-1:1; |
|
581 |
+ doneinc=0; |
|
582 |
+ if(redata_pos2linecol(re->data,re->cursorpos,NULL,&tmpcol)==-1) |
|
583 |
+ return(-1); /* couldn't get current pos */ |
|
584 |
+ /* special case: we're just over the '\n' going right, we have to move 1 to enable the generic case to work */ |
|
585 |
+ if(tmpcol==re->curcol && inc>0) { |
|
586 |
+ if(redata_line_rawinfo(re->data,re->cursorpos,&start,&ptr,&len,NULL)==-1) |
|
587 |
+ return(-1); /* couldn't get line data */ |
|
588 |
+ if(ptr[re->cursorpos-start]=='\n') { |
|
589 |
+ tmpcol++; |
|
590 |
+ totalinc--; |
|
591 |
+ re->curcol++; |
|
592 |
+ } |
|
324 | 593 |
} |
325 |
- if(re->curcol>(re->origincol+re->maxcol-COLFORCESCROLL)) |
|
326 |
- re->origincol+=COLFORCESCROLL; |
|
594 |
+ /* generic case: cursor after the \n ("floating") */ |
|
595 |
+ if(tmpcol<re->curcol) { |
|
596 |
+ int avail; |
|
597 |
+ if(inc>0) { |
|
598 |
+ doneinc=totalinc; |
|
599 |
+ } else { |
|
600 |
+ avail=re->curcol-tmpcol; |
|
601 |
+ doneinc=(avail>=totalinc)?totalinc:avail; |
|
602 |
+ } |
|
603 |
+ } |
|
604 |
+ /* generic case: move one char at a time */ |
|
605 |
+ for(ptr=NULL,len=0,start=0,newpos=re->cursorpos;doneinc!=totalinc;) { |
|
606 |
+ if((newpos+inc)<realstart) |
|
607 |
+ break; |
|
608 |
+ newpos+=inc; |
|
609 |
+ if(ptr==NULL || (start+len)<=newpos || newpos<start) { |
|
610 |
+ if(redata_line_rawinfo(re->data,newpos,&start,&ptr,&len,NULL)==-1) |
|
611 |
+ return(-1); /* couldn't get line data */ |
|
612 |
+ } |
|
613 |
+ if(redata_generic_utf8isstartbyte(ptr[newpos-start])) |
|
614 |
+ doneinc+=inc; |
|
615 |
+ if(ptr[newpos-start]=='\n') |
|
616 |
+ break; |
|
617 |
+ } |
|
618 |
+ re->cursorpos=newpos; |
|
619 |
+ re->curcol+=doneinc; |
|
620 |
+ if(inc>0 && doneinc<totalinc && ptr!=NULL && ptr[newpos-start]=='\n') |
|
621 |
+ re->curcol+=(totalinc-doneinc); |
|
622 |
+ } |
|
623 |
+ if(re->curcol!=oldcol) { |
|
327 | 624 |
re->contentsdirty=1; |
625 |
+ re->headerdirty=1; |
|
626 |
+ if(re->curcol<(re->origincol+COLFORCESCROLL) && re->origincol>0) { |
|
627 |
+ re->origincol=(re->curcol-COLFORCESCROLL)/COLFORCESCROLL; |
|
628 |
+ re->origincol=re->origincol*COLFORCESCROLL; |
|
629 |
+ re->origincol=(re->origincol<0)?0:re->origincol; |
|
630 |
+ } |
|
631 |
+ if(re->curcol>(re->origincol+re->maxrow-COLFORCESCROLL)) { |
|
632 |
+ re->origincol=re->curcol+COLFORCESCROLL-re->maxrow-(re->curcol%COLFORCESCROLL); |
|
633 |
+ re->origincol=(re->origincol<0)?0:re->origincol; |
|
634 |
+ } |
|
635 |
+ } |
|
636 |
+ return(0); |
|
637 |
+} |
|
638 |
+ |
|
639 |
+int |
|
640 |
+re_rtrim(re_t *re, long curpos, int *trimmed) |
|
641 |
+{ |
|
642 |
+ long startpos; |
|
643 |
+ char *start; |
|
644 |
+ int len; |
|
645 |
+ int n; |
|
646 |
+ if(re==NULL || curpos<0 || curpos>redata_getused(re->data)) |
|
647 |
+ return(-1); |
|
648 |
+ if(trimmed!=NULL) |
|
649 |
+ *trimmed=0; |
|
650 |
+ if(redata_line_rawinfo(re->data,curpos,&startpos,&start,&len,NULL)==0 && |
|
651 |
+ len>1 && start[len-1]=='\n' && start[len-2]==' ' && curpos==(startpos+len-1)) { |
|
652 |
+ for(n=1;(n+1)<(len-1) && start[len-1-n-1]==' ';n++) |
|
653 |
+ ; |
|
654 |
+fprintf(stderr,"Trying to DELETE SPACES del %i bytes\n",n); |
|
655 |
+ redata_op_del(re->data,curpos-n,n,NULL); |
|
656 |
+ re->cursorpos-=n; |
|
657 |
+ if(trimmed!=NULL) |
|
658 |
+ *trimmed=n; |
|
328 | 659 |
} |
329 |
- re_drawheader(re); |
|
330 | 660 |
return(0); |
331 | 661 |
} |
332 | 662 |
|
333 | 663 |
int |
334 |
-re_drawheader(re_t *re) |
|
664 |
+re_drawheader_editing(re_t *re) |
|
335 | 665 |
{ |
336 | 666 |
int line,col; |
337 | 667 |
if(re==NULL) |
338 | 668 |
return(-1); |
339 | 669 |
if(redata_pos2linecol(re->data,re->cursorpos,&line,&col)==-1) |
340 | 670 |
line=col=-1; |
341 |
- reui_fill(re->ui,0,0,re->ui->w,re->ui->fontheight,"\x00\x00\xff\xff"); |
|
342 |
- reui_printf(re->ui,0,0,"\xff\xff\x00\xff","File: %s Line:%i (%i) Col:%i (%i) Pos:%li",re->filename,re->curline,line,re->curcol,col,re->cursorpos); |
|
671 |
+ reui_fill(re->ui,0,0,re->ui->w,re->ui->fontheight,COLOR_STATUSBG); |
|
672 |
+ reui_printf(re->ui,0,0,COLOR_STATUSFG,"File: %s Line:%i (%i) Col:%i (%i) Pos:%li",re->filename,re->curline,line,re->curcol,col,re->cursorpos); |
|
673 |
+ re->headerdirty=0; |
|
674 |
+ re->ui->rendererdirty=1; |
|
675 |
+ return(0); |
|
676 |
+} |
|
677 |
+ |
|
678 |
+int |
|
679 |
+re_drawheader_command(re_t *re) |
|
680 |
+{ |
|
681 |
+ if(re==NULL) |
|
682 |
+ return(-1); |
|
683 |
+ if(re->command==NULL) |
|
684 |
+ return(-1); |
|
685 |
+ if(re->command[0]=='\0') { |
|
686 |
+ reui_fill(re->ui,0,0,re->ui->w,re->ui->fontheight,COLOR_QUERYBG); |
|
687 |
+ reui_printf(re->ui,0,0,COLOR_QUERYFG,"Command:"); |
|
688 |
+ } else if(strcmp(re->command,COMMAND_WARNING)==0) { |
|
689 |
+ reui_fill(re->ui,0,0,re->ui->w,re->ui->fontheight,COLOR_WARNINGBG); |
|
690 |
+ reui_printf(re->ui,0,0,COLOR_WARNINGFG,"%s %s",re->command,re->commandbuf); |
|
691 |
+ } else { |
|
692 |
+ reui_fill(re->ui,0,0,re->ui->w,re->ui->fontheight,COLOR_QUERYBG); |
|
693 |
+ re->commandbuf[sizeof(re->commandbuf)-1]='\0'; |
|
694 |
+ reui_printf(re->ui,0,0,COLOR_QUERYFG,"%s %s",re->command,re->commandbuf); |
|
695 |
+ } |
|
696 |
+ re->headerdirty=0; |
|
697 |
+ re->ui->rendererdirty=1; |
|
343 | 698 |
return(0); |
344 | 699 |
} |
345 | 700 |
|
701 |
+ |
|
346 | 702 |
int |
347 | 703 |
re_drawcontents(re_t *re) |
348 | 704 |
{ |
349 | 705 |
long pos,newpos; |
350 |
- char *ptr,*visibleptr; |
|
706 |
+ char *ptr; |
|
351 | 707 |
int len; |
352 | 708 |
int y,row; |
353 | 709 |
char *curptr; |
354 | 710 |
int curptrlen; |
355 | 711 |
int has_nl; |
712 |
+ int is_continuation; |
|
713 |
+ int tmpcol,availcol; |
|
714 |
+ int in_error; |
|
715 |
+ long realstart,realend; |
|
716 |
+ int drawn_cursor; |
|
356 | 717 |
if(re==NULL) |
357 | 718 |
return(-1); |
358 | 719 |
reui_fill(re->ui,re->x,re->y,re->w,re->h,"\xdf\xdf\xdf\xff"); |
359 | 720 |
row=re->curline-re->originline; |
360 | 721 |
pos=re->cursorpos; |
361 |
- while(row>0) { |
|
362 |
- if(redata_line_info(re->data,pos,&newpos,NULL,NULL)==-1) |
|
722 |
+ while(row>0 && pos>0) { |
|
723 |
+ if(redata_line_rawinfo(re->data,pos,&newpos,NULL,NULL,&is_continuation)==-1) |
|
363 | 724 |
return(-1); |
364 | 725 |
pos=(newpos>0)?newpos-1:0; |
365 |
- row--; |
|
726 |
+ if(!is_continuation) |
|
727 |
+ row--; |
|
366 | 728 |
} |
367 | 729 |
/* highlight current line */ |
368 | 730 |
reui_fill(re->ui,re->x,re->y+(re->curline-re->originline)*re->ui->fontheight,re->w,re->ui->fontheight+1,"\xef\xef\xef\xff"); |
369 | 731 |
/* draw the lines */ |
732 |
+ drawn_cursor=0; |
|
370 | 733 |
for(y=re->y;y<(re->y+re->h);y+=re->ui->fontheight,row++) { |
371 |
- if(redata_line_info(re->data,pos,&newpos,&ptr,&len)==-1) |
|
372 |
- break; /* couldn't get line start pos */ |
|
373 |
- has_nl=((len>0 && ptr[len-1]=='\n')?1:0); |
|
374 |
- visibleptr=redata_generic_utf8col((char *)ptr,len-has_nl,re->origincol); |
|
375 |
- if(visibleptr!=NULL) |
|
376 |
- reui_write(re->ui,re->x,y,"\x00\x00\x00\xff",visibleptr,len-has_nl-(visibleptr-ptr)); |
|
377 |
- if(row==(re->curline-re->originline)) { |
|
378 |
-#warning DEBUG write of current char |
|
379 |
- 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"); |
|
734 |
+ if(redata_line_realstart(re->data,pos,&realstart)==-1 || redata_line_realend(re->data,pos,&realend)==-1) { |
|
735 |
+ break; /* couldn't get real start/end */ |
|
736 |
+ } |
|
737 |
+ in_error=0; |
|
738 |
+ for(tmpcol=0,pos=realstart,availcol=0;tmpcol<(re->origincol+re->maxcol) && pos<=realend;pos=newpos+len,tmpcol+=availcol) { |
|
739 |
+ if(redata_line_rawinfo(re->data,pos,&newpos,&ptr,&len,&is_continuation)==-1) { |
|
740 |
+ in_error=1; |
|
741 |
+ break; /* couldn't get this line part info */ |
|
742 |
+ } |
|
743 |
+ has_nl=((len>0 && ptr[len-1]=='\n')?1:0); |
|
744 |
+ availcol=redata_generic_utf8len(ptr,len-has_nl); |
|
380 | 745 |
#warning TODO: consider tabs |
381 |
- curptr=redata_generic_utf8col(ptr,len-has_nl,re->curcol); |
|
382 |
- curptrlen=(curptr==NULL)?0:(len-has_nl)-(curptr-ptr); |
|
383 |
- reui_write(re->ui,re->x+re->ui->fontwidth*(re->curcol-re->origincol),y,"\xff\xff\xff\xff",curptr,redata_generic_utf8charlen(ptr,curptrlen)); |
|
746 |
+ reui_write(re->ui,re->x+(tmpcol-re->origincol)*re->ui->fontwidth,y,"\x00\x00\x00\xff",ptr,len-has_nl); |
|
747 |
+ if(row==(re->curline-re->originline)) { |
|
748 |
+ if(re->curcol>=tmpcol && re->curcol<(tmpcol+availcol)) { |
|
749 |
+ 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"); |
|
750 |
+ drawn_cursor=1; |
|
751 |
+ curptr=redata_generic_utf8col(ptr,len-has_nl,re->curcol-tmpcol); |
|
752 |
+ curptrlen=(curptr==NULL)?0:(len-has_nl)-(curptr-ptr); |
|
753 |
+ reui_write(re->ui,re->x+re->ui->fontwidth*(re->curcol-re->origincol),y,"\xff\xff\xff\xff",curptr,redata_generic_utf8charlen(ptr,curptrlen)); |
|
754 |
+ } |
|
384 | 755 |
#warning TODO: if it is one of '[','{','<','>','}',']', highlight the matching bracket/parens/anglebracket. |
756 |
+ } |
|
385 | 757 |
} |
386 |
- pos=newpos+len; |
|
758 |
+ if(row==(re->curline-re->originline) && !drawn_cursor) |
|
759 |
+ 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"); |
|
760 |
+ if(in_error) |
|
761 |
+ break; |
|
762 |
+ pos=realend+1; |
|
763 |
+/*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));*/ |
|
387 | 764 |
} |
388 | 765 |
re->contentsdirty=0; |
389 | 766 |
re->ui->rendererdirty=1; |