... | ... |
@@ -8,16 +8,18 @@ recenteditor.o: recenteditor.c re_data.h |
8 | 8 |
|
9 | 9 |
re_data.o: re_data.c re_data.h |
10 | 10 |
|
11 |
+re_plugin_unsaved.o: re_plugin_unsaved.c re_plugin_unsaved.h re_data.h |
|
12 |
+ |
|
11 | 13 |
re_tests.o: re_tests.c re_data.h |
12 | 14 |
|
13 | 15 |
sha3.o: sha3/sha3.c sha3/sha3.h |
14 | 16 |
$(CC) $(CFLAGS) -Isha3 -c -o sha3.o sha3/sha3.c |
15 | 17 |
|
16 |
-re: recenteditor.o re_data.o sha3.o |
|
17 |
- $(CC) $(LDFLAGS) -o re recenteditor.o re_data.o sha3.o |
|
18 |
+re: recenteditor.o re_data.o re_plugin_unsaved.o sha3.o |
|
19 |
+ $(CC) $(LDFLAGS) -o re recenteditor.o re_data.o re_plugin_unsaved.o sha3.o |
|
18 | 20 |
|
19 | 21 |
tests: re_tests.o re_data.o sha3.o |
20 | 22 |
$(CC) $(LDFLAGS) -o tests re_tests.o re_data.o sha3.o |
21 | 23 |
|
22 | 24 |
clean: |
23 |
- rm -f recenteditor.o re_data.o re_tests.o sha3.o re tests |
|
25 |
+ rm -f recenteditor.o re_data.o re_tests.o re_plugin_unsaved.o sha3.o re tests |
... | ... |
@@ -18,6 +18,7 @@ |
18 | 18 |
#include <fcntl.h> |
19 | 19 |
#include <limits.h> |
20 | 20 |
#include <inttypes.h> |
21 |
+#include <stdarg.h> |
|
21 | 22 |
|
22 | 23 |
#include "re_data.h" |
23 | 24 |
#include "sha3/sha3.h" |
... | ... |
@@ -25,21 +26,11 @@ |
25 | 26 |
#define CHUNKSIZE 32768 |
26 | 27 |
#define UNDOBLOCK 1024 |
27 | 28 |
#define UNDOGROWSIZE (256*1024) |
28 |
-#define UNSAVEDPREFIX "." |
|
29 |
-#define UNSAVEDPOSTFIX ".reu" |
|
30 | 29 |
#define SECURESAVEPREFIX "." |
31 | 30 |
#define SECURESAVEPOSTFIX ".saving" |
32 |
-#define UNSAVEDHEADER "reunsaved00," |
|
33 | 31 |
|
34 | 32 |
static int redata_hash_gen(redata_t *redata, char *filename, char *buf, long buflen, char *resbuf129bytes); |
35 |
-static int redata_unsaved_check_gen(redata_t *redata, char *filename); |
|
36 |
-static char *unsaved_genname(char *filename, char *buf, int bufsize); |
|
37 | 33 |
static char *securesave_genname(char *filename, char *buf, int bufsize); |
38 |
-static char *genname(char *filename,char *prefix, char *postfix, char *buf, int bufsize); |
|
39 |
-static char *ptr_getlong(char *ptr,char *endptr,long *data); |
|
40 |
-static char *ptr_getchar(char *ptr,char *endptr,char *data); |
|
41 |
-static char *ptr_searchendchar(char *ptr, char *endptr, char endchar, char **endcharpos); |
|
42 |
-static char sep_select(char *buf, int bufsize, char **pos); |
|
43 | 34 |
static void *mymemrchr(const void *s, int c, size_t n); |
44 | 35 |
static void meminvert(void *start, void *end); |
45 | 36 |
|
... | ... |
@@ -64,12 +55,23 @@ redata_debug_chunkdump(redata_t *redata, char *title) |
64 | 55 |
#endif |
65 | 56 |
|
66 | 57 |
redata_t * |
67 |
-redata_init(void) |
|
58 |
+redata_init(int (*pluginregisterfn)(redata_t *redata, redata_plugin_t *slot), ...) |
|
68 | 59 |
{ |
69 | 60 |
redata_t *redata; |
70 |
- if((redata=malloc(sizeof(redata_t)))==NULL) |
|
61 |
+ va_list args; |
|
62 |
+ int nargs; |
|
63 |
+ int res; |
|
64 |
+ int (*fn)(redata_t *redata, redata_plugin_t *slot); |
|
65 |
+ /* count number of plugins */ |
|
66 |
+ va_start(args,pluginregisterfn); |
|
67 |
+ for(nargs=0,fn=pluginregisterfn;fn!=NULL;fn=va_arg(args,int (*)(redata_t *redata, redata_plugin_t *slot))) |
|
68 |
+ nargs++; |
|
69 |
+ va_end(args); |
|
70 |
+ /* get memory */ |
|
71 |
+ if((redata=malloc(sizeof(redata_t)+sizeof(redata_plugin_t)*(nargs-1)))==NULL) |
|
71 | 72 |
return(NULL); /* sanity check failed */ |
72 |
- memset(redata,0,sizeof(redata_t)); |
|
73 |
+ memset(redata,0,sizeof(redata_t)+sizeof(redata_plugin_t)*(nargs-1)); |
|
74 |
+ redata->sizeplugins=nargs; |
|
73 | 75 |
/* data */ |
74 | 76 |
redata->sizechunks=0; |
75 | 77 |
redata->chunks=NULL; |
... | ... |
@@ -80,10 +82,15 @@ redata_init(void) |
80 | 82 |
redata->undostack.usedundo=0; |
81 | 83 |
redata->undostack.undo=NULL; |
82 | 84 |
redata->undostack.buf=NULL; |
83 |
- /* unsaved */ |
|
85 |
+ /* plugins */ |
|
86 |
+ for(nargs=0,fn=pluginregisterfn;fn!=NULL;fn=va_arg(args,int (*)(redata_t *redata,redata_plugin_t *slot))) { |
|
87 |
+ res=fn(redata,redata->plugins+nargs); |
|
88 |
+ redata->plugins[nargs].active=(res==0)?1:0; |
|
89 |
+ nargs++; |
|
90 |
+ } |
|
91 |
+ va_end(args); |
|
92 |
+ /* filename */ |
|
84 | 93 |
redata->filename[0]='\0'; |
85 |
- redata->unsavedfd=-1; |
|
86 |
- redata->unsaved.sizebuf=redata->unsaved.usedbuf=0; |
|
87 | 94 |
/* all done */ |
88 | 95 |
return(redata); |
89 | 96 |
} |
... | ... |
@@ -92,9 +99,14 @@ void |
92 | 99 |
redata_free(redata_t *redata) |
93 | 100 |
{ |
94 | 101 |
int i; |
95 |
- char unsname[PATH_MAX]; |
|
96 | 102 |
if(redata==NULL) |
97 | 103 |
return; /* nothing to do */ |
104 |
+ /* plugins */ |
|
105 |
+ for(i=0;i<redata->sizeplugins;i++) { |
|
106 |
+ if(redata->plugins[i].unregister!=NULL) |
|
107 |
+ redata->plugins[i].unregister(redata,redata->plugins+i,redata->filename); |
|
108 |
+ memset(redata->plugins+i,0,sizeof(redata_plugin_t)); |
|
109 |
+ } |
|
98 | 110 |
/* data */ |
99 | 111 |
for(i=0;i<redata->sizechunks;i++) { |
100 | 112 |
if(redata->chunks[i]!=NULL) |
... | ... |
@@ -115,16 +127,6 @@ redata_free(redata_t *redata) |
115 | 127 |
free(redata->redostack.undo),redata->redostack.undo=NULL; |
116 | 128 |
if(redata->redostack.buf!=NULL) |
117 | 129 |
free(redata->redostack.buf),redata->redostack.buf=NULL; |
118 |
- /* unsaved */ |
|
119 |
- if(redata->unsavedfd!=-1) { |
|
120 |
- close(redata->unsavedfd),redata->unsavedfd=-1; |
|
121 |
- if(unsaved_genname(redata->filename,unsname,sizeof(unsname))!=NULL) |
|
122 |
- unlink(unsname); |
|
123 |
- } |
|
124 |
- if(redata->unsaved.buf!=NULL) { |
|
125 |
- free(redata->unsaved.buf),redata->unsaved.buf=NULL; |
|
126 |
- redata->unsaved.sizebuf=redata->unsaved.usedbuf=0; |
|
127 |
- } |
|
128 | 130 |
/* free main struct */ |
129 | 131 |
free(redata),redata=NULL; |
130 | 132 |
return; |
... | ... |
@@ -190,7 +192,6 @@ int |
190 | 192 |
redata_wipe(redata_t *redata) |
191 | 193 |
{ |
192 | 194 |
int i; |
193 |
- char unsname[PATH_MAX]; |
|
194 | 195 |
if(redata==NULL) |
195 | 196 |
return(-1); /* sanity check failed */ |
196 | 197 |
/* data */ |
... | ... |
@@ -199,14 +200,12 @@ redata_wipe(redata_t *redata) |
199 | 200 |
memset(&(redata->chunks[i]->whatin),0,sizeof(whatin_t)); |
200 | 201 |
} |
201 | 202 |
redata->available=redata_getsize(redata); |
202 |
- /* unsaved */ |
|
203 |
- if(redata->unsavedfd!=-1) { |
|
204 |
- close(redata->unsavedfd),redata->unsavedfd=-1; |
|
205 |
- if(unsaved_genname(redata->filename,unsname,sizeof(unsname))!=NULL) |
|
206 |
- unlink(unsname); |
|
203 |
+ /* plugins */ |
|
204 |
+ for(i=0;i<redata->sizeplugins;i++) { |
|
205 |
+ if(redata->plugins[i].wipe!=NULL) |
|
206 |
+ redata->plugins[i].wipe(redata,redata->plugins+i,redata->filename); |
|
207 | 207 |
} |
208 | 208 |
redata->filename[0]='\0'; |
209 |
- redata->unsaved.usedbuf=0; |
|
210 | 209 |
/* all done */ |
211 | 210 |
return(0); |
212 | 211 |
} |
... | ... |
@@ -467,385 +466,6 @@ redata_fix_nl(redata_t *redata, int chunkno) |
467 | 466 |
return(0); |
468 | 467 |
} |
469 | 468 |
|
470 |
-int |
|
471 |
-redata_unsaved_exists(redata_t *redata, char *filename) |
|
472 |
-{ |
|
473 |
- char unsname[PATH_MAX+1]; |
|
474 |
- int fd; |
|
475 |
- if(redata==NULL || filename==NULL) |
|
476 |
- return(-1); /* sanity check failed */ |
|
477 |
- if((unsaved_genname(filename,unsname,sizeof(unsname)))==NULL) |
|
478 |
- return(-1); /* malformed filename */ |
|
479 |
- if((fd=open(unsname,O_RDONLY))==-1) |
|
480 |
- return(-1); |
|
481 |
- close(fd),fd=-1; |
|
482 |
- return(0); |
|
483 |
-} |
|
484 |
- |
|
485 |
-static int |
|
486 |
-redata_unsaved_check_gen(redata_t *redata, char *filename) |
|
487 |
-{ |
|
488 |
- char unsname[PATH_MAX+1]; |
|
489 |
- int fd,nread; |
|
490 |
- static char header[]={UNSAVEDHEADER}; |
|
491 |
- char filehash[129],undohash[129],buf[16]; |
|
492 |
- char fileheader[]={UNSAVEDHEADER}; |
|
493 |
- if(redata==NULL || filename==NULL) |
|
494 |
- return(-1); /* sanity check failed */ |
|
495 |
- if((unsaved_genname(filename,unsname,sizeof(unsname)))==NULL) |
|
496 |
- return(-1); /* malformed filename */ |
|
497 |
- if(redata_filehash(redata,filename,filehash)!=0) |
|
498 |
- return(-1); |
|
499 |
- if((fd=open(unsname,O_RDONLY))==-1) |
|
500 |
- return(-1); |
|
501 |
- memset(fileheader,0,sizeof(fileheader)); |
|
502 |
- if((nread=read(fd,fileheader,sizeof(fileheader)-1))==-1 |
|
503 |
- || nread!=(sizeof(fileheader)-1) || memcmp(fileheader,header,sizeof(fileheader))!=0) { |
|
504 |
- close(fd),fd=-1; |
|
505 |
- return(-1); /* corrupted header */ |
|
506 |
- } |
|
507 |
- if((nread=read(fd,undohash,128))==-1 || nread!=128 || memcmp(undohash,filehash,128)!=0) { |
|
508 |
- close(fd),fd=-1; |
|
509 |
- return(-1); /* wrong hash */ |
|
510 |
- } |
|
511 |
- if((nread=read(fd,buf,1))==-1 || nread!=1 || *buf!=',') { |
|
512 |
- close(fd),fd=-1; |
|
513 |
- return(-1); /* wrong hash separator */ |
|
514 |
- } |
|
515 |
- return(fd); |
|
516 |
-} |
|
517 |
- |
|
518 |
-int |
|
519 |
-redata_unsaved_check(redata_t *redata, char *filename) |
|
520 |
-{ |
|
521 |
- int fd; |
|
522 |
- if((fd=redata_unsaved_check_gen(redata,filename))==-1) |
|
523 |
- return(-1); /* check failed */ |
|
524 |
- close(fd),fd=-1; |
|
525 |
- return(0); |
|
526 |
-} |
|
527 |
- |
|
528 |
- |
|
529 |
-int |
|
530 |
-redata_unsaved_unlink(redata_t *redata) |
|
531 |
-{ |
|
532 |
- char unsname[PATH_MAX+1]; |
|
533 |
- if(redata==NULL || redata->filename[0]=='\0') |
|
534 |
- return(-1); /* sanity check failed */ |
|
535 |
- if(redata_unsaved_exists(redata,redata->filename)==-1) |
|
536 |
- return(0); /* file not found, nothing to unlink */ |
|
537 |
- if((unsaved_genname(redata->filename,unsname,sizeof(unsname)))==NULL) |
|
538 |
- return(-1); /* malformed filename */ |
|
539 |
- unlink(unsname); |
|
540 |
- return(0); |
|
541 |
-} |
|
542 |
- |
|
543 |
-int |
|
544 |
-redata_unsaved_trunc(redata_t *redata) |
|
545 |
-{ |
|
546 |
- char unsname[PATH_MAX+1]; |
|
547 |
- static char header[]={UNSAVEDHEADER}; |
|
548 |
- int n; |
|
549 |
- if(redata==NULL || redata->filename[0]=='\0') |
|
550 |
- return(-1); /* sanity check failed */ |
|
551 |
- redata_unsaved_unlink(redata); |
|
552 |
- if((unsaved_genname(redata->filename,unsname,sizeof(unsname)))==NULL) |
|
553 |
- return(-1); /* malformed filename */ |
|
554 |
- if(redata->unsavedfd!=-1) |
|
555 |
- close(redata->unsavedfd),redata->unsavedfd=-1; |
|
556 |
- redata_hash(redata,redata->initialhash); |
|
557 |
- redata->unsaved.usedbuf=0; |
|
558 |
- if((redata->unsavedfd=open(unsname,O_WRONLY|O_TRUNC|O_CREAT,0644))==-1) |
|
559 |
- return(-1); /* couldn't open file for writing */ |
|
560 |
- if((n=write(redata->unsavedfd,header,sizeof(header)-1))==-1 |
|
561 |
- || n!=(sizeof(header)-1) |
|
562 |
- || (n=write(redata->unsavedfd,redata->initialhash,128))==-1 || n!=128 |
|
563 |
- || (n=write(redata->unsavedfd,",",1))==-1 || n!=1) { |
|
564 |
- close(redata->unsavedfd),redata->unsavedfd=-1; |
|
565 |
- unlink(unsname); |
|
566 |
- return(-1); /* couldn't write header/hash */ |
|
567 |
- } |
|
568 |
- return(0); |
|
569 |
-} |
|
570 |
- |
|
571 |
- |
|
572 |
-int |
|
573 |
-redata_unsaved_loadappend(redata_t *redata) |
|
574 |
-{ |
|
575 |
- int fd; |
|
576 |
- struct stat statbuf; |
|
577 |
- static char header[]={UNSAVEDHEADER}; |
|
578 |
- long headerhashsize; |
|
579 |
- char *newptr; |
|
580 |
- long nread,lim; |
|
581 |
- char *ptr,*endptr,*aux,*bufptr; |
|
582 |
- char actioncode; |
|
583 |
- long pos,pos2; |
|
584 |
- char endcode; |
|
585 |
- int flag_multipart; |
|
586 |
- if((fd=redata_unsaved_check_gen(redata,redata->filename))==-1) |
|
587 |
- return(-1); /* check failed */ |
|
588 |
- if(fstat(fd,&statbuf)!=0 || !S_ISREG(statbuf.st_mode)) { |
|
589 |
- close(fd),fd=-1; |
|
590 |
- return(-1); /* couldn't query size or not regular file */ |
|
591 |
- } |
|
592 |
- headerhashsize=(sizeof(header)-1)+1+128+1; |
|
593 |
- /* load unsaved to memory */ |
|
594 |
- if(redata->unsaved.sizebuf<(statbuf.st_size-headerhashsize)) { |
|
595 |
- if((newptr=realloc(redata->unsaved.buf,(statbuf.st_size-headerhashsize)))==NULL) { |
|
596 |
- close(fd),fd=-1; |
|
597 |
- return(-1); /* insuf. mem. */ |
|
598 |
- } |
|
599 |
- redata->unsaved.buf=newptr; |
|
600 |
- redata->unsaved.sizebuf=(statbuf.st_size-headerhashsize); |
|
601 |
- } |
|
602 |
- redata->unsaved.usedbuf=0; |
|
603 |
- lim=(statbuf.st_size-headerhashsize); |
|
604 |
- for(nread=0;redata->unsaved.usedbuf<lim;redata->unsaved.usedbuf+=nread,nread=0) { |
|
605 |
- if((nread=read(fd,redata->unsaved.buf+redata->unsaved.usedbuf,lim-redata->unsaved.usedbuf))<=0) { |
|
606 |
- redata->unsaved.usedbuf=0; |
|
607 |
- close(fd),fd=-1; |
|
608 |
- return(-1); /* short read */ |
|
609 |
- } |
|
610 |
- } |
|
611 |
- close(fd),fd=-1; |
|
612 |
- /* process unsaved data */ |
|
613 |
- endptr=redata->unsaved.buf+redata->unsaved.usedbuf; |
|
614 |
- for(ptr=redata->unsaved.buf;ptr<endptr;) { |
|
615 |
- if((ptr=ptr_getchar(ptr,endptr,&actioncode))==NULL) |
|
616 |
- return(-1); /* no space for action char */ |
|
617 |
- /* multipart example: A10+$aj$%$% >> insert "aj$" into pos 10 */ |
|
618 |
- if(actioncode=='A') { |
|
619 |
- ptr=ptr_getlong(ptr,endptr,&pos); |
|
620 |
- do { |
|
621 |
- flag_multipart=0; |
|
622 |
- ptr=ptr_getchar(ptr,endptr,&endcode); |
|
623 |
- if(ptr!=NULL && endcode=='+') { |
|
624 |
- flag_multipart=1; |
|
625 |
- ptr=ptr_getchar(ptr,endptr,&endcode); |
|
626 |
- } |
|
627 |
- bufptr=ptr; |
|
628 |
- ptr=ptr_searchendchar(ptr,endptr,endcode,&aux); |
|
629 |
- if(ptr==NULL || pos<0 || pos>redata_getused(redata)) |
|
630 |
- return(-1); /* malformed register */ |
|
631 |
- redata_op_add(redata,pos,bufptr,aux-bufptr,NULL); |
|
632 |
- pos+=aux-bufptr; |
|
633 |
- } while(flag_multipart); |
|
634 |
- } else if(actioncode=='D') { |
|
635 |
- ptr=ptr_getlong(ptr,endptr,&pos); |
|
636 |
- do { |
|
637 |
- flag_multipart=0; |
|
638 |
- ptr=ptr_getchar(ptr,endptr,&endcode); |
|
639 |
- if(ptr!=NULL && endcode=='+') { |
|
640 |
- flag_multipart=1; |
|
641 |
- ptr=ptr_getchar(ptr,endptr,&endcode); |
|
642 |
- } |
|
643 |
- bufptr=ptr; |
|
644 |
- ptr=ptr_searchendchar(ptr,endptr,endcode,&aux); |
|
645 |
- if(ptr==NULL || pos<0 || (pos+(aux-bufptr))>redata_getused(redata)) |
|
646 |
- return(-1); /* malformed register */ |
|
647 |
- if(redata_data_compare(redata,pos,bufptr,aux-bufptr)!=0) |
|
648 |
- return(-1); /* corrupted data */ |
|
649 |
- redata_op_del(redata,pos,aux-bufptr,NULL); |
|
650 |
- } while(flag_multipart); |
|
651 |
- } else if(actioncode=='M') { |
|
652 |
- ptr=ptr_getlong(ptr,endptr,&pos); |
|
653 |
- ptr+=(ptr!=NULL && ptr<endptr)?1:0; |
|
654 |
- ptr=ptr_getlong(ptr,endptr,&pos2); |
|
655 |
- do { |
|
656 |
- flag_multipart=0; |
|
657 |
- ptr=ptr_getchar(ptr,endptr,&endcode); |
|
658 |
- if(ptr!=NULL && endcode=='+') { |
|
659 |
- flag_multipart=1; |
|
660 |
- ptr=ptr_getchar(ptr,endptr,&endcode); |
|
661 |
- } |
|
662 |
- bufptr=ptr; |
|
663 |
- ptr=ptr_searchendchar(ptr,endptr,endcode,&aux); |
|
664 |
- if(ptr==NULL |
|
665 |
- || pos<0 || (pos+(aux-bufptr))>redata_getused(redata) |
|
666 |
- || pos2<0 || pos2>redata_getused(redata) |
|
667 |
- || ((aux-bufptr)>0 && pos2>=pos && pos2<(pos+(aux-bufptr))) |
|
668 |
- ) { |
|
669 |
- return(-1); /* malformed register */ |
|
670 |
- } |
|
671 |
- if(redata_data_compare(redata,pos,bufptr,aux-bufptr)!=0) |
|
672 |
- return(-1); /* corrupted data */ |
|
673 |
- redata_op_move(redata,pos,(aux-bufptr),pos2,NULL); |
|
674 |
- pos=(pos<pos2)?pos:(pos+(aux-bufptr)); |
|
675 |
- pos2=pos2+(aux-bufptr); |
|
676 |
- } while(flag_multipart); |
|
677 |
- } else { |
|
678 |
- return(-1); /* corrupted undobuf */ |
|
679 |
- } |
|
680 |
- } |
|
681 |
- return(-1); |
|
682 |
-} |
|
683 |
- |
|
684 |
- |
|
685 |
-int |
|
686 |
-redata_unsaved_add(redata_t *redata, undostack_t *stack, int undono) |
|
687 |
-{ |
|
688 |
- char sep; |
|
689 |
- undo_t *undo; |
|
690 |
- char *sepend,*ptr,*endptr; |
|
691 |
- char *buf; |
|
692 |
- int k; |
|
693 |
- int maxsize,newsize; |
|
694 |
- char posbuf[128]; |
|
695 |
- if(redata==NULL |
|
696 |
- || (stack!=&(redata->undostack) && stack!=&(redata->redostack)) |
|
697 |
- || undono<0 || undono>=stack->usedundo) |
|
698 |
- return(-1); /* sanity check failed */ |
|
699 |
- /* syntax (see loadappend): A<pos><+?><sep><text><sep>[<+?><sep><text><sep>[...]] */ |
|
700 |
- undo=stack->undo+undono; |
|
701 |
- if(undo->type!='A' && undo->type!='D' && undo->type!='M') |
|
702 |
- return(-1); /* unrecognized undo type */ |
|
703 |
- for(k=0,maxsize=0,buf=NULL;k<2;k++,maxsize=0) { |
|
704 |
- ptr=stack->buf+undo->off; |
|
705 |
- endptr=ptr+undo->len; |
|
706 |
- if(k!=0) |
|
707 |
- buf[maxsize]=undo->type; |
|
708 |
- maxsize++; |
|
709 |
- snprintf(posbuf,sizeof(posbuf),"%li",undo->posorig); |
|
710 |
- posbuf[sizeof(posbuf)-1]='\0'; |
|
711 |
- if(k!=0) |
|
712 |
- strcpy(buf+maxsize,posbuf); |
|
713 |
- maxsize+=strlen(posbuf); |
|
714 |
- if(undo->type=='M') { |
|
715 |
- snprintf(posbuf,sizeof(posbuf),",%li",undo->posdest); |
|
716 |
- posbuf[sizeof(posbuf)-1]='\0'; |
|
717 |
- if(k!=0) |
|
718 |
- strcpy(buf+maxsize,posbuf); |
|
719 |
- maxsize+=strlen(posbuf); |
|
720 |
- } |
|
721 |
- while(ptr<endptr) { |
|
722 |
- sep=sep_select(ptr,endptr-ptr,&sepend); |
|
723 |
- if(sepend!=endptr) { |
|
724 |
- if(k!=0) |
|
725 |
- buf[maxsize]='+'; |
|
726 |
- maxsize++; |
|
727 |
- } |
|
728 |
- if(k!=0) |
|
729 |
- buf[maxsize]=sep; |
|
730 |
- maxsize++; |
|
731 |
- if(k!=0) |
|
732 |
- memcpy(buf+maxsize,ptr,sepend-ptr); |
|
733 |
- maxsize+=sepend-ptr; |
|
734 |
- if(k!=0) |
|
735 |
- buf[maxsize]=sep; |
|
736 |
- maxsize++; |
|
737 |
- ptr=sepend; |
|
738 |
- } |
|
739 |
- if(k==0) { |
|
740 |
- /* get mem */ |
|
741 |
- if((redata->unsaved.sizebuf-redata->unsaved.sizebuf)<maxsize) { |
|
742 |
- newsize=(redata->unsaved.sizebuf+maxsize+UNDOGROWSIZE-1)/UNDOGROWSIZE; |
|
743 |
- newsize*=UNDOGROWSIZE; |
|
744 |
- if((buf=realloc(redata->unsaved.buf,newsize))==NULL) |
|
745 |
- return(-1); /* insuf. mem. */ |
|
746 |
- redata->unsaved.buf=buf; |
|
747 |
- redata->unsaved.sizebuf=newsize; |
|
748 |
- } |
|
749 |
- buf=redata->unsaved.buf+redata->unsaved.usedbuf; |
|
750 |
- } |
|
751 |
- } |
|
752 |
- return(0); |
|
753 |
-} |
|
754 |
- |
|
755 |
-int |
|
756 |
-redata_unsaved_unadd(redata_t *redata, undostack_t *stack, int undono) |
|
757 |
-{ |
|
758 |
- /* adds to unsaved the inverse operation to the one specified in the undo */ |
|
759 |
- char sep; |
|
760 |
- undo_t *undo; |
|
761 |
- char *sepend,*ptr,*endptr; |
|
762 |
- char *buf; |
|
763 |
- int k; |
|
764 |
- int maxsize,newsize; |
|
765 |
- char posbuf[128]; |
|
766 |
- if(redata==NULL |
|
767 |
- || (stack!=&(redata->undostack) && stack!=&(redata->redostack)) |
|
768 |
- || undono<0 || undono>=stack->usedundo) |
|
769 |
- return(-1); /* sanity check failed */ |
|
770 |
- /* syntax (see loadappend): A<pos><+?><sep><text><sep>[<+?><sep><text><sep>[...]] */ |
|
771 |
- undo=stack->undo+undono; |
|
772 |
- if(undo->type!='A' && undo->type!='D' && undo->type!='M') |
|
773 |
- return(-1); /* unrecognized undo type */ |
|
774 |
- for(k=0,maxsize=0,buf=NULL;k<2;k++,maxsize=0) { |
|
775 |
- ptr=stack->buf+undo->off; |
|
776 |
- endptr=ptr+undo->len; |
|
777 |
- if(k!=0) |
|
778 |
- buf[maxsize]=(undo->type=='A')?'D':(undo->type=='D')?'A':undo->type; |
|
779 |
- maxsize++; |
|
780 |
- if(undo->type=='A' || undo->type=='D') |
|
781 |
- snprintf(posbuf,sizeof(posbuf),"%li",undo->posorig); |
|
782 |
- else |
|
783 |
- snprintf(posbuf,sizeof(posbuf),"%li",(undo->posorig<undo->posdest)?undo->posdest-undo->len:undo->posdest); |
|
784 |
- posbuf[sizeof(posbuf)-1]='\0'; |
|
785 |
- if(k!=0) |
|
786 |
- strcpy(buf+maxsize,posbuf); |
|
787 |
- maxsize+=strlen(posbuf); |
|
788 |
- if(undo->type=='M') { |
|
789 |
- snprintf(posbuf,sizeof(posbuf),",%li",(undo->posorig<undo->posdest)?undo->posorig:undo->posorig+undo->len); |
|
790 |
- posbuf[sizeof(posbuf)-1]='\0'; |
|
791 |
- if(k!=0) |
|
792 |
- strcpy(buf+maxsize,posbuf); |
|
793 |
- maxsize+=strlen(posbuf); |
|
794 |
- } |
|
795 |
- while(ptr<endptr) { |
|
796 |
- sep=sep_select(ptr,endptr-ptr,&sepend); |
|
797 |
- if(sepend!=endptr) { |
|
798 |
- if(k!=0) |
|
799 |
- buf[maxsize]='+'; |
|
800 |
- maxsize++; |
|
801 |
- } |
|
802 |
- if(k!=0) |
|
803 |
- buf[maxsize]=sep; |
|
804 |
- maxsize++; |
|
805 |
- if(k!=0) |
|
806 |
- memcpy(buf+maxsize,ptr,sepend-ptr); |
|
807 |
- maxsize+=sepend-ptr; |
|
808 |
- if(k!=0) |
|
809 |
- buf[maxsize]=sep; |
|
810 |
- maxsize++; |
|
811 |
- ptr=sepend; |
|
812 |
- } |
|
813 |
- if(k==0) { |
|
814 |
- /* get mem */ |
|
815 |
- if((redata->unsaved.sizebuf-redata->unsaved.sizebuf)<maxsize) { |
|
816 |
- newsize=(redata->unsaved.sizebuf+maxsize+UNDOGROWSIZE-1)/UNDOGROWSIZE; |
|
817 |
- newsize*=UNDOGROWSIZE; |
|
818 |
- if((buf=realloc(redata->unsaved.buf,newsize))==NULL) |
|
819 |
- return(-1); /* insuf. mem. */ |
|
820 |
- redata->unsaved.buf=buf; |
|
821 |
- redata->unsaved.sizebuf=newsize; |
|
822 |
- } |
|
823 |
- buf=redata->unsaved.buf+redata->unsaved.usedbuf; |
|
824 |
- } |
|
825 |
- } |
|
826 |
- return(0); |
|
827 |
-} |
|
828 |
- |
|
829 |
-int |
|
830 |
-redata_unsaved_commit(redata_t *redata) |
|
831 |
-{ |
|
832 |
- int n,nwritten; |
|
833 |
- char unsname[PATH_MAX+1]; |
|
834 |
- if(redata==NULL || redata->unsavedfd==-1) |
|
835 |
- return(-1); |
|
836 |
- for(nwritten=0;nwritten<redata->unsaved.usedbuf;nwritten+=n) { |
|
837 |
- if((n=write(redata->unsavedfd,redata->unsaved.buf+nwritten,redata->unsaved.usedbuf-nwritten))<0) { |
|
838 |
- close(redata->unsavedfd),redata->unsavedfd=-1; |
|
839 |
- if((unsaved_genname(redata->filename,unsname,sizeof(unsname)))!=NULL) |
|
840 |
- unlink(unsname); /* a corrupted unsaved is of no use, delete it */ |
|
841 |
- return(-1); /* error writing */ |
|
842 |
- } |
|
843 |
- } |
|
844 |
- redata->unsaved.usedbuf=0; |
|
845 |
- return(0); |
|
846 |
-} |
|
847 |
- |
|
848 |
- |
|
849 | 469 |
int |
850 | 470 |
redata_load(redata_t *redata, char *filename, int use_unsaved) |
851 | 471 |
{ |
... | ... |
@@ -853,6 +473,7 @@ redata_load(redata_t *redata, char *filename, int use_unsaved) |
853 | 473 |
int chunkno, avail; |
854 | 474 |
struct stat statbuf; |
855 | 475 |
rechunk_t *chunk; |
476 |
+ int i; |
|
856 | 477 |
if(redata==NULL || filename==NULL) |
857 | 478 |
return(-1); /* sanity check failed */ |
858 | 479 |
redata_wipe(redata); |
... | ... |
@@ -900,14 +521,17 @@ redata_load(redata_t *redata, char *filename, int use_unsaved) |
900 | 521 |
for(chunkno=0;chunkno<redata->sizechunks;chunkno++) |
901 | 522 |
redata_whatin_refresh(redata,chunkno); |
902 | 523 |
/* unsaved */ |
903 |
- if(use_unsaved) { |
|
904 |
- /* apply missing changes and append new changes to unsaved */ |
|
905 |
- redata_hash(redata,redata->initialhash); |
|
906 |
- redata_unsaved_loadappend(redata); |
|
907 |
- } else { |
|
908 |
- /* nuke existing unsaved (if exists) and prepare new unsaved */ |
|
909 |
- /* _trunc() fills itself redata->initialhash */ |
|
910 |
- redata_unsaved_trunc(redata); |
|
524 |
+ for(i=0;i<redata->sizeplugins;i++) { |
|
525 |
+ if(use_unsaved) { |
|
526 |
+ /* apply missing changes and append new changes to unsaved */ |
|
527 |
+ if(redata->plugins[i].postload!=NULL) |
|
528 |
+ redata->plugins[i].postload(redata,redata->plugins+i,filename); |
|
529 |
+ } else { |
|
530 |
+ /* nuke existing unsaved (if exists) and prepare new unsaved */ |
|
531 |
+ /* _trunc() fills itself redata->initialhash */ |
|
532 |
+ if(redata->plugins[i].truncload!=NULL) |
|
533 |
+ redata->plugins[i].truncload(redata,redata->plugins+i,filename); |
|
534 |
+ } |
|
911 | 535 |
} |
912 | 536 |
/* all done */ |
913 | 537 |
return(0); |
... | ... |
@@ -939,10 +563,12 @@ redata_save(redata_t *redata, char *filename) |
939 | 563 |
unlink(tmpfile); |
940 | 564 |
return(-1); /* couldn't overwrite old file */ |
941 | 565 |
} |
942 |
- redata_unsaved_unlink(redata); |
|
566 |
+ for(i=0;i<redata->sizeplugins;i++) { |
|
567 |
+ if(redata->plugins[i].postsave!=NULL) |
|
568 |
+ redata->plugins[i].postsave(redata,redata->plugins+i,redata->filename,filename); |
|
569 |
+ } |
|
943 | 570 |
strncpy(redata->filename,filename,sizeof(redata->filename)); |
944 | 571 |
redata->filename[sizeof(redata->filename)-1]='\0'; |
945 |
- redata_unsaved_trunc(redata); |
|
946 | 572 |
return(0); |
947 | 573 |
} |
948 | 574 |
|
... | ... |
@@ -1219,8 +845,11 @@ redata_op_add(redata_t *redata, long insertpos, char *buf, long buflen, undostac |
1219 | 845 |
/* from undo stack */ |
1220 | 846 |
redata_undo_movelast(redata,&(redata->undostack),&(redata->redostack)); |
1221 | 847 |
} |
1222 |
- /* add to unsaved */ |
|
1223 |
- redata_unsaved_add(redata,&(redata->undostack),redata->undostack.usedundo-1); |
|
848 |
+ /* add to plugins (unsaved,...) */ |
|
849 |
+ for(i=0;i<redata->sizeplugins;i++) { |
|
850 |
+ if(redata->plugins[i].add!=NULL) |
|
851 |
+ redata->plugins[i].add(redata,redata->plugins+i,redata->undostack.undo+redata->undostack.usedundo-1); |
|
852 |
+ } |
|
1224 | 853 |
/* compact if needed */ |
1225 | 854 |
if(redata_getsize(redata)>(redata->chunkdatasize) && redata_getavailable(redata)>(redata_getsize(redata)/2)) |
1226 | 855 |
redata_compact(redata); |
... | ... |
@@ -1236,6 +865,7 @@ redata_op_del(redata_t *redata, long delpos, long size, undostack_t *fromhere) |
1236 | 865 |
rechunk_t *chunk; |
1237 | 866 |
long ndel; |
1238 | 867 |
long curpos,curdel; |
868 |
+ int i; |
|
1239 | 869 |
if(redata==NULL || size<0 |
1240 | 870 |
|| delpos<0 |
1241 | 871 |
|| (delpos+size)>redata_getused(redata) |
... | ... |
@@ -1279,8 +909,11 @@ redata_op_del(redata_t *redata, long delpos, long size, undostack_t *fromhere) |
1279 | 909 |
/* from undo stack */ |
1280 | 910 |
redata_undo_movelast(redata,&(redata->undostack),&(redata->redostack)); |
1281 | 911 |
} |
1282 |
- /* add to unsaved */ |
|
1283 |
- redata_unsaved_add(redata,&(redata->undostack),redata->undostack.usedundo-1); |
|
912 |
+ /* add to plugins (unsaved,...) */ |
|
913 |
+ for(i=0;i<redata->sizeplugins;i++) { |
|
914 |
+ if(redata->plugins[i].add!=NULL) |
|
915 |
+ redata->plugins[i].add(redata,redata->plugins+i,redata->undostack.undo+redata->undostack.usedundo-1); |
|
916 |
+ } |
|
1284 | 917 |
/* compact if needed */ |
1285 | 918 |
if(redata_getsize(redata)>(redata->chunkdatasize) && redata_getavailable(redata)>(redata_getsize(redata)/2)) |
1286 | 919 |
redata_compact(redata); |
... | ... |
@@ -1294,6 +927,7 @@ redata_op_move(redata_t *redata, long posorig, long size, long posdest, undostac |
1294 | 927 |
long pos,dpos; |
1295 | 928 |
undo_t *undo; |
1296 | 929 |
rechunk_t *chunk; |
930 |
+ int i; |
|
1297 | 931 |
if(redata==NULL || size<0 |
1298 | 932 |
|| posorig<0 |
1299 | 933 |
|| (posorig+size)>redata_getused(redata) |
... | ... |
@@ -1410,8 +1044,11 @@ redata_op_move(redata_t *redata, long posorig, long size, long posdest, undostac |
1410 | 1044 |
/* from undo stack */ |
1411 | 1045 |
redata_undo_movelast(redata,&(redata->undostack),&(redata->redostack)); |
1412 | 1046 |
} |
1413 |
- /* add to unsaved */ |
|
1414 |
- redata_unsaved_add(redata,&(redata->undostack),redata->undostack.usedundo-1); |
|
1047 |
+ /* add to plugins (unsaved,...) */ |
|
1048 |
+ for(i=0;i<redata->sizeplugins;i++) { |
|
1049 |
+ if(redata->plugins[i].add!=NULL) |
|
1050 |
+ redata->plugins[i].add(redata,redata->plugins+i,redata->undostack.undo+redata->undostack.usedundo-1); |
|
1051 |
+ } |
|
1415 | 1052 |
/* compact if needed */ |
1416 | 1053 |
if(redata_getsize(redata)>(redata->chunkdatasize) && redata_getavailable(redata)>(redata_getsize(redata)/2)) |
1417 | 1054 |
redata_compact(redata); |
... | ... |
@@ -1437,6 +1074,7 @@ redata_op_undo(redata_t *redata) |
1437 | 1074 |
redata_op_move(redata,undo->posdest, undo->len, undo->posorig+undo->len,&(redata->undostack)); |
1438 | 1075 |
} else |
1439 | 1076 |
return(-1); /* unknown operation */ |
1077 |
+#warning TODO: Is it neccessary to do an unadd to the plugins? |
|
1440 | 1078 |
return(-1); |
1441 | 1079 |
} |
1442 | 1080 |
|
... | ... |
@@ -1456,6 +1094,7 @@ redata_op_redo(redata_t *redata) |
1456 | 1094 |
redata_op_move(redata,undo->posorig, undo->len, undo->posdest,&(redata->redostack)); |
1457 | 1095 |
} else |
1458 | 1096 |
return(-1); /* unknown operation */ |
1097 |
+#warning TODO: Is it neccessary to do an unadd to the plugins? |
|
1459 | 1098 |
return(-1); |
1460 | 1099 |
} |
1461 | 1100 |
|
... | ... |
@@ -1559,6 +1198,54 @@ redata_memhash(redata_t *redata, char *buf, long buflen, char *resbuf129bytes) |
1559 | 1198 |
return(redata_hash_gen(NULL,NULL,buf,buflen,resbuf129bytes)); |
1560 | 1199 |
} |
1561 | 1200 |
|
1201 |
+undostack_t * |
|
1202 |
+redata_getstack(redata_t *redata, undo_t *undo) |
|
1203 |
+{ |
|
1204 |
+ if(redata==NULL || undo==NULL) |
|
1205 |
+ return(NULL); /* sanity check failed */ |
|
1206 |
+ if(undo>=redata->undostack.undo && undo<(redata->undostack.undo+redata->undostack.sizeundo)) |
|
1207 |
+ return(&(redata->undostack)); |
|
1208 |
+ if(undo>=redata->redostack.undo && undo<(redata->redostack.undo+redata->redostack.sizeundo)) |
|
1209 |
+ return(&(redata->redostack)); |
|
1210 |
+ return(NULL); /* unknown stack */ |
|
1211 |
+} |
|
1212 |
+ |
|
1213 |
+char * |
|
1214 |
+redata_generic_genname(char *filename,char *prefix, char *postfix, char *buf, int bufsize) |
|
1215 |
+{ |
|
1216 |
+ char *name,*ptr; |
|
1217 |
+ int filenamelen; |
|
1218 |
+ int prelen,postlen,finallen,off; |
|
1219 |
+ if(filename==NULL || prefix==NULL || postfix==NULL) |
|
1220 |
+ return(NULL); |
|
1221 |
+ filenamelen=strlen(filename); |
|
1222 |
+ prelen=strlen(prefix); |
|
1223 |
+ postlen=strlen(postfix); |
|
1224 |
+ finallen=filenamelen+prelen+postlen+1; |
|
1225 |
+ if(buf==NULL) { |
|
1226 |
+ if((name=malloc(finallen))==NULL) |
|
1227 |
+ return(NULL); |
|
1228 |
+ } else { |
|
1229 |
+ if(bufsize<filenamelen) |
|
1230 |
+ return(NULL); |
|
1231 |
+ name=buf; |
|
1232 |
+ } |
|
1233 |
+ for(ptr=filename+strlen(filename);ptr>filename && ptr[-1]!='/';ptr--) |
|
1234 |
+ ; |
|
1235 |
+ off=0; |
|
1236 |
+ memcpy(name+off,filename,ptr-filename); |
|
1237 |
+ off+=ptr-filename; |
|
1238 |
+ memcpy(name+off,prefix,prelen); |
|
1239 |
+ off+=prelen; |
|
1240 |
+ memcpy(name+off,ptr,filenamelen-(ptr-filename)); |
|
1241 |
+ off+=filenamelen-(ptr-filename); |
|
1242 |
+ memcpy(name+off,postfix,postlen); |
|
1243 |
+ off+=postlen; |
|
1244 |
+ name[off]='\0'; |
|
1245 |
+ return(name); |
|
1246 |
+} |
|
1247 |
+ |
|
1248 |
+ |
|
1562 | 1249 |
static int |
1563 | 1250 |
redata_hash_gen(redata_t *redata, char *filename, char *buf, long buflen, char *resbuf129bytes) |
1564 | 1251 |
{ |
... | ... |
@@ -1614,128 +1301,12 @@ redata_hash_gen(redata_t *redata, char *filename, char *buf, long buflen, char * |
1614 | 1301 |
return(0); |
1615 | 1302 |
} |
1616 | 1303 |
|
1617 |
- |
|
1618 |
-static char * |
|
1619 |
-unsaved_genname(char *filename, char *buf, int bufsize) |
|
1620 |
-{ |
|
1621 |
- static char pre[]={UNSAVEDPREFIX}; |
|
1622 |
- static char post[]={UNSAVEDPOSTFIX}; |
|
1623 |
- return(genname(filename,pre,post,buf,bufsize)); |
|
1624 |
-} |
|
1625 |
- |
|
1626 | 1304 |
static char * |
1627 | 1305 |
securesave_genname(char *filename, char *buf, int bufsize) |
1628 | 1306 |
{ |
1629 | 1307 |
static char pre[]={SECURESAVEPREFIX}; |
1630 | 1308 |
static char post[]={SECURESAVEPOSTFIX}; |
1631 |
- return(genname(filename,pre,post,buf,bufsize)); |
|
1632 |
-} |
|
1633 |
- |
|
1634 |
- |
|
1635 |
-static char * |
|
1636 |
-genname(char *filename,char *prefix, char *postfix, char *buf, int bufsize) |
|
1637 |
-{ |
|
1638 |
- char *name,*ptr; |
|
1639 |
- int filenamelen; |
|
1640 |
- int prelen,postlen,finallen,off; |
|
1641 |
- if(filename==NULL || prefix==NULL || postfix==NULL) |
|
1642 |
- return(NULL); |
|
1643 |
- filenamelen=strlen(filename); |
|
1644 |
- prelen=strlen(prefix); |
|
1645 |
- postlen=strlen(postfix); |
|
1646 |
- finallen=filenamelen+prelen+postlen+1; |
|
1647 |
- if(buf==NULL) { |
|
1648 |
- if((name=malloc(finallen))==NULL) |
|
1649 |
- return(NULL); |
|
1650 |
- } else { |
|
1651 |
- if(bufsize<filenamelen) |
|
1652 |
- return(NULL); |
|
1653 |
- name=buf; |
|
1654 |
- } |
|
1655 |
- for(ptr=filename+strlen(filename);ptr>filename && ptr[-1]!='/';ptr--) |
|
1656 |
- ; |
|
1657 |
- off=0; |
|
1658 |
- memcpy(name+off,filename,ptr-filename); |
|
1659 |
- off+=ptr-filename; |
|
1660 |
- memcpy(name+off,prefix,prelen); |
|
1661 |
- off+=prelen; |
|
1662 |
- memcpy(name+off,ptr,filenamelen-(ptr-filename)); |
|
1663 |
- off+=filenamelen-(ptr-filename); |
|
1664 |
- memcpy(name+off,postfix,postlen); |
|
1665 |
- off+=postlen; |
|
1666 |
- name[off]='\0'; |
|
1667 |
- return(name); |
|
1668 |
-} |
|
1669 |
- |
|
1670 |
-static char * |
|
1671 |
-ptr_getlong(char *ptr,char *endptr,long *data) |
|
1672 |
-{ |
|
1673 |
- long l,s; |
|
1674 |
- if(ptr==NULL || endptr==NULL || ptr>endptr) |
|
1675 |
- return(NULL); |
|
1676 |
- s=1; |
|
1677 |
- if(ptr<endptr && *ptr=='-') { |
|
1678 |
- s=-1; |
|
1679 |
- ptr++; |
|
1680 |
- } |
|
1681 |
- for(l=0;ptr<endptr && *ptr>='0' && *ptr<='9';ptr++) { |
|
1682 |
- l*=10; |
|
1683 |
- l+=(*ptr-'0'); |
|
1684 |
- } |
|
1685 |
- l*=s; |
|
1686 |
- if(data!=NULL) |
|
1687 |
- *data=l; |
|
1688 |
- return(ptr); |
|
1689 |
-} |
|
1690 |
- |
|
1691 |
- |
|
1692 |
-static char * |
|
1693 |
-ptr_getchar(char *ptr,char *endptr,char *data) |
|
1694 |
-{ |
|
1695 |
- if(ptr==NULL || endptr==NULL || ptr>endptr) |
|
1696 |
- return(NULL); |
|
1697 |
- if(data!=NULL) |
|
1698 |
- *data=*ptr; |
|
1699 |
- ptr++; |
|
1700 |
- return(ptr); |
|
1701 |
-} |
|
1702 |
- |
|
1703 |
-static char * |
|
1704 |
-ptr_searchendchar(char *ptr, char *endptr, char endchar, char **endcharpos) |
|
1705 |
-{ |
|
1706 |
- char *aux; |
|
1707 |
- if(ptr==NULL || endptr==NULL || ptr>endptr) |
|
1708 |
- return(NULL); |
|
1709 |
- if((aux=memchr(ptr,endchar,endptr-ptr))==NULL) |
|
1710 |
- return(NULL); |
|
1711 |
- if(endcharpos!=NULL) |
|
1712 |
- *endcharpos=aux; |
|
1713 |
- return(aux+1); |
|
1714 |
-} |
|
1715 |
- |
|
1716 |
-static char |
|
1717 |
-sep_select(char *buf, int bufsize, char **pos) |
|
1718 |
-{ |
|
1719 |
- static char seps[]={"$%@!|&/='\"^*;:,-_"}; |
|
1720 |
- char *ptr,*bestptr; |
|
1721 |
- int i,besti; |
|
1722 |
- bestptr=buf; |
|
1723 |
- if(pos!=NULL) |
|
1724 |
- *pos=NULL; |
|
1725 |
- for(i=0,besti=0;i<sizeof(seps);i++) { |
|
1726 |
- if((ptr=memchr(buf,seps[i],bufsize))==NULL) { |
|
1727 |
- if(pos!=NULL) |
|
1728 |
- *pos=buf+bufsize; |
|
1729 |
- return(seps[i]); |
|
1730 |
- } |
|
1731 |
- if(ptr>bestptr) { |
|
1732 |
- besti=0; |
|
1733 |
- bestptr=ptr; |
|
1734 |
- } |
|
1735 |
- } |
|
1736 |
- if(pos!=NULL) |
|
1737 |
- *pos=bestptr; |
|
1738 |
- return(seps[besti]); |
|
1309 |
+ return(redata_generic_genname(filename,pre,post,buf,bufsize)); |
|
1739 | 1310 |
} |
1740 | 1311 |
|
1741 | 1312 |
static void * |
... | ... |
@@ -1,5 +1,5 @@ |
1 | 1 |
/* |
2 |
- * re_data.c |
|
2 |
+ * re_data.h |
|
3 | 3 |
* |
4 | 4 |
* A programmers editor |
5 | 5 |
* |
... | ... |
@@ -43,13 +43,26 @@ typedef struct undostack_t { |
43 | 43 |
char *buf; |
44 | 44 |
} undostack_t; |
45 | 45 |
|
46 |
-typedef struct unsaved_t { |
|
47 |
- long sizebuf; |
|
48 |
- long usedbuf; |
|
49 |
- char *buf; |
|
50 |
-} unsaved_t; |
|
46 |
+#define PLUGIN_CHECKUSERCONFIRM 1 /* if check is Ok, confirm with user whether to postload or go inactive */ |
|
47 |
+ |
|
48 |
+typedef struct redata_plugin_t { |
|
49 |
+ int active; |
|
50 |
+ int (*unregister)(/*redata_t *redata, redata_plugin_t *plugin,char *filename*/); |
|
51 |
+ /* checkload returns 0:Ok, 1:Not needed, -1: error, go inactive */ |
|
52 |
+ int (*wipe)(/*redata_t *redata, redata_plugin_t *plugin,char *filename*/); |
|
53 |
+ int (*checkload)(/*redata_t *redata, redata_plugin_t *plugin,char *filename*/); |
|
54 |
+ int (*postload)(/*redata_t *redata, redata_plugin_t *plugin,char *filename*/); |
|
55 |
+ int (*truncload)(/*redata_t *redata, redata_plugin_t *plugin,char *filename*/); |
|
56 |
+ int (*postsave)(/*redata_t *redata, redata_plugin_t *plugin,char *oldfilename,char *newfilename*/); |
|
57 |
+ int (*add)(/*redata_t *redata, redata_plugin_t *plugin,undo_t *undo*/); |
|
58 |
+ int (*unadd)(/*redata_t *redata, redata_plugin_t *plugin,undo_t *undo*/); |
|
59 |
+ int (*commit)(/*redata_t *redata, redata_plugin_t *plugin,char *filename*/); |
|
60 |
+ void *userptr; |
|
61 |
+ int flags; |
|
62 |
+} redata_plugin_t; |
|
51 | 63 |
|
52 | 64 |
typedef struct redata_t { |
65 |
+ char filename[PATH_MAX]; |
|
53 | 66 |
/* data */ |
54 | 67 |
long chunkdatasize; |
55 | 68 |
int sizechunks; |
... | ... |
@@ -59,14 +72,13 @@ typedef struct redata_t { |
59 | 72 |
/* undo */ |
60 | 73 |
undostack_t undostack; |
61 | 74 |
undostack_t redostack; |
62 |
- /* unsaved (for recovery when the program closes unexpectedly) */ |
|
63 |
- char filename[PATH_MAX]; |
|
64 |
- char initialhash[129]; |
|
65 |
- int unsavedfd; |
|
66 |
- unsaved_t unsaved; |
|
75 |
+ /* plugins */ |
|
76 |
+ int sizeplugins; |
|
77 |
+ redata_plugin_t plugins[1]; |
|
67 | 78 |
} redata_t; |
68 | 79 |
|
69 |
-redata_t *redata_init(void); |
|
80 |
+#warning TODO: Make redata_xxx call the plugins |
|
81 |
+redata_t *redata_init( int (*pluginregisterfn)(redata_t *redata, redata_plugin_t *slot), ...); |
|
70 | 82 |
void redata_free(redata_t *redata); |
71 | 83 |
|
72 | 84 |
int redata_config_chunkdatasize(redata_t *redata, int chunkdatasize); |
... | ... |
@@ -98,17 +110,7 @@ int redata_undo_wipe(redata_t *redata, undostack_t *stack); |
98 | 110 |
int redata_undo_inactivatelast(redata_t *redata, undostack_t *stack); |
99 | 111 |
int redata_undo_reactivatelast(redata_t *redata, undostack_t *stack); |
100 | 112 |
|
101 |
- |
|
102 | 113 |
/* high level stuff */ |
103 |
-int redata_unsaved_exists(redata_t *redata, char *filename); |
|
104 |
-int redata_unsaved_check(redata_t *redata, char *filename); |
|
105 |
-int redata_unsaved_loadappend(redata_t *redata); |
|
106 |
-int redata_unsaved_unlink(redata_t *redata); |
|
107 |
-int redata_unsaved_trunc(redata_t *redata); |
|
108 |
-int redata_unsaved_add(redata_t *redata, undostack_t *stack, int undono); |
|
109 |
-int redata_unsaved_unadd(redata_t *redata, undostack_t *stack, int undono); |
|
110 |
-int redata_unsaved_commit(redata_t *redata); |
|
111 |
- |
|
112 | 114 |
int redata_load(redata_t *redata, char *filename, int use_unsaved); |
113 | 115 |
int redata_save(redata_t *redata, char *filename); |
114 | 116 |
|
... | ... |
@@ -125,4 +127,6 @@ int redata_compact(redata_t *redata); |
125 | 127 |
int redata_hash(redata_t *redata, char *resbuf129bytes); |
126 | 128 |
int redata_filehash(redata_t *redata, char *filename, char *resbuf129bytes); |
127 | 129 |
int redata_memhash(redata_t *redata, char *buf, long buflen, char *resbuf129bytes); |
130 |
+undostack_t *redata_getstack(redata_t *redata, undo_t *undo); |
|
131 |
+char *redata_generic_genname(char *filename,char *prefix, char *postfix, char *buf, int bufsize); |
|
128 | 132 |
|
129 | 133 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,565 @@ |
1 |
+/* |
|
2 |
+ * re_plugin_unsaved->c |
|
3 |
+ * |
|
4 |
+ * A programmers editor |
|
5 |
+ * |
|
6 |
+ * re_data plugin to support the unsaved changes file. |
|
7 |
+ * (for recovery when the program closes unexpectedly) |
|
8 |
+ * |
|
9 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
10 |
+ * This program is licensed under the terms of GNU GPL v2.1+ |
|
11 |
+ */ |
|
12 |
+ |
|
13 |
+#include <stdio.h> |
|
14 |
+#include <stdlib.h> |
|
15 |
+#include <unistd.h> |
|
16 |
+#include <string.h> |
|
17 |
+#include <fcntl.h> |
|
18 |
+#include <sys/types.h> |
|
19 |
+#include <sys/stat.h> |
|
20 |
+ |
|
21 |
+ |
|
22 |
+#include "re_plugin_unsaved.h" |
|
23 |
+ |
|
24 |
+#define UNSAVEDPREFIX "." |
|
25 |
+#define UNSAVEDPOSTFIX ".reu" |
|
26 |
+#define UNSAVEDHEADER "reunsaved00," |
|
27 |
+#define UNSAVEDGROWSIZE (256*1024) |
|
28 |
+ |
|
29 |
+ |
|
30 |
+ |
|
31 |
+static int redata_unsaved_check_gen(redata_t *redata, redata_plugin_t *slot, char *filename); |
|
32 |
+static char *unsaved_genname(char *filename, char *buf, int bufsize); |
|
33 |
+static char *ptr_getlong(char *ptr,char *endptr,long *data); |
|
34 |
+static char *ptr_getchar(char *ptr,char *endptr,char *data); |
|
35 |
+static char *ptr_searchendchar(char *ptr, char *endptr, char endchar, char **endcharpos); |
|
36 |
+static char sep_select(char *buf, int bufsize, char **pos); |
|
37 |
+ |
|
38 |
+int |
|
39 |
+redata_unsaved_register(redata_t *redata, redata_plugin_t *slot) |
|
40 |
+{ |
|
41 |
+ unsaved_t *unsaved; |
|
42 |
+ if(redata==NULL || slot==NULL) |
|
43 |
+ return(-1); |
|
44 |
+ if((unsaved=malloc(sizeof(unsaved_t)))==NULL) |
|
45 |
+ return(-1); |
|
46 |
+ memset(unsaved,0,sizeof(unsaved_t)); |
|
47 |
+ unsaved->unsavedfd=-1; |
|
48 |
+ unsaved->sizebuf=unsaved->usedbuf=0; |
|
49 |
+ slot->unregister=redata_unsaved_unregister; |
|
50 |
+ slot->checkload=redata_unsaved_check; |
|
51 |
+ slot->wipe=redata_unsaved_wipe; |
|
52 |
+ slot->postload=redata_unsaved_loadappend; |
|
53 |
+ slot->truncload=redata_unsaved_truncload; |
|
54 |
+ slot->postsave=redata_unsaved_trunc; |
|
55 |
+ slot->add=redata_unsaved_add; |
|
56 |
+ slot->unadd=redata_unsaved_unadd; |
|
57 |
+ slot->flags=PLUGIN_CHECKUSERCONFIRM; |
|
58 |
+ return(0); |
|
59 |
+} |
|
60 |
+ |
|
61 |
+int |
|
62 |
+redata_unsaved_unregister(redata_t *redata, redata_plugin_t *slot, char *filename) |
|
63 |
+{ |
|
64 |
+ char unsname[PATH_MAX]; |
|
65 |
+ unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
66 |
+ if(redata==NULL || slot==NULL || unsaved==NULL) |
|
67 |
+ return(-1); |
|
68 |
+ if(unsaved->buf!=NULL) |
|
69 |
+ free(unsaved->buf),unsaved->buf=NULL; |
|
70 |
+ unsaved->sizebuf=unsaved->usedbuf=0; |
|
71 |
+ if(unsaved->unsavedfd!=-1) { |
|
72 |
+ close(unsaved->unsavedfd),unsaved->unsavedfd=-1; |
|
73 |
+ if(filename!=NULL && unsaved_genname(filename,unsname,sizeof(unsname))!=NULL) |
|
74 |
+ unlink(unsname); |
|
75 |
+ } |
|
76 |
+ return(0); |
|
77 |
+} |
|
78 |
+ |
|
79 |
+ |
|
80 |
+int |
|
81 |
+redata_unsaved_exists(redata_t *redata, redata_plugin_t *slot, char *filename) |
|
82 |
+{ |
|
83 |
+ char unsname[PATH_MAX+1]; |
|
84 |
+ int fd; |
|
85 |
+ unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
86 |
+ if(redata==NULL || slot==NULL || unsaved==NULL || filename==NULL || filename[0]=='\0') |
|
87 |
+ return(-1); /* sanity check failed */ |
|
88 |
+ if((unsaved_genname(filename,unsname,sizeof(unsname)))==NULL) |
|
89 |
+ return(-1); /* malformed filename */ |
|
90 |
+ if((fd=open(unsname,O_RDONLY))==-1) |
|
91 |
+ return(-1); |
|
92 |
+ close(fd),fd=-1; |
|
93 |
+ return(0); |
|
94 |
+} |
|
95 |
+ |
|
96 |
+int |
|
97 |
+redata_unsaved_wipe(redata_t *redata, redata_plugin_t *slot, char *filename) |
|
98 |
+{ |
|
99 |
+ char unsname[PATH_MAX]; |
|
100 |
+ unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
101 |
+ if(redata==NULL || slot==NULL || unsaved==NULL || filename==NULL || filename[0]=='\0') |
|
102 |
+ return(-1); |
|
103 |
+ if(unsaved->unsavedfd!=-1) { |
|
104 |
+ close(unsaved->unsavedfd),unsaved->unsavedfd=-1; |
|
105 |
+ if(unsaved_genname(filename,unsname,sizeof(unsname))!=NULL) |
|
106 |
+ unlink(unsname); |
|
107 |
+ } |
|
108 |
+ unsaved->usedbuf=0; |
|
109 |
+ return(0); |
|
110 |
+} |
|
111 |
+ |
|
112 |
+static int |
|
113 |
+redata_unsaved_check_gen(redata_t *redata, redata_plugin_t *slot, char *filename) |
|
114 |
+{ |
|
115 |
+ char unsname[PATH_MAX+1]; |
|
116 |
+ int fd,nread; |
|
117 |
+ static char header[]={UNSAVEDHEADER}; |
|
118 |
+ char filehash[129],undohash[129],buf[16]; |
|
119 |
+ char fileheader[]={UNSAVEDHEADER}; |
|
120 |
+ unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
121 |
+ if(redata==NULL || slot==NULL || unsaved==NULL || filename==NULL || filename[0]=='\0') |
|
122 |
+ return(-1); /* sanity check failed */ |
|
123 |
+ if((unsaved_genname(filename,unsname,sizeof(unsname)))==NULL) |
|
124 |
+ return(-1); /* malformed filename */ |
|
125 |
+ if(redata_filehash(redata,filename,filehash)!=0) |
|
126 |
+ return(-1); |
|
127 |
+ if((fd=open(unsname,O_RDONLY))==-1) |
|
128 |
+ return(-1); |
|
129 |
+ memset(fileheader,0,sizeof(fileheader)); |
|
130 |
+ if((nread=read(fd,fileheader,sizeof(fileheader)-1))==-1 |
|
131 |
+ || nread!=(sizeof(fileheader)-1) || memcmp(fileheader,header,sizeof(fileheader))!=0) { |
|
132 |
+ close(fd),fd=-1; |
|
133 |
+ return(-1); /* corrupted header */ |
|
134 |
+ } |
|
135 |
+ if((nread=read(fd,undohash,128))==-1 || nread!=128 || memcmp(undohash,filehash,128)!=0) { |
|
136 |
+ close(fd),fd=-1; |
|
137 |
+ return(-1); /* wrong hash */ |
|
138 |
+ } |
|
139 |
+ if((nread=read(fd,buf,1))==-1 || nread!=1 || *buf!=',') { |
|
140 |
+ close(fd),fd=-1; |
|
141 |
+ return(-1); /* wrong hash separator */ |
|
142 |
+ } |
|
143 |
+ return(fd); |
|
144 |
+} |
|
145 |
+ |
|
146 |
+int |
|
147 |
+redata_unsaved_check(redata_t *redata, redata_plugin_t *slot, char *filename) |
|
148 |
+{ |
|
149 |
+ int fd; |
|
150 |
+ if((fd=redata_unsaved_check_gen(redata,slot,filename))==-1) |
|
151 |
+ return(-1); /* check failed */ |
|
152 |
+ close(fd),fd=-1; |
|
153 |
+ return(0); |
|
154 |
+} |
|
155 |
+ |
|
156 |
+ |
|
157 |
+int |
|
158 |
+redata_unsaved_unlink(redata_t *redata, redata_plugin_t *slot, char *filename) |
|
159 |
+{ |
|
160 |
+ char unsname[PATH_MAX+1]; |
|
161 |
+ unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
162 |
+ if(redata==NULL || slot==NULL || unsaved==NULL || filename==NULL || filename[0]=='\0') |
|
163 |
+ return(-1); /* sanity check failed */ |
|
164 |
+ if(redata_unsaved_exists(redata,slot,filename)==-1) |
|
165 |
+ return(0); /* file not found, nothing to unlink */ |
|
166 |
+ if((unsaved_genname(filename,unsname,sizeof(unsname)))==NULL) |
|
167 |
+ return(-1); /* malformed filename */ |
|
168 |
+ unlink(unsname); |
|
169 |
+ return(0); |
|
170 |
+} |
|
171 |
+ |
|
172 |
+int |
|
173 |
+redata_unsaved_trunc(redata_t *redata, redata_plugin_t *slot, char *oldfilename, char *newfilename) |
|
174 |
+{ |
|
175 |
+ char unsname[PATH_MAX+1]; |
|
176 |
+ static char header[]={UNSAVEDHEADER}; |
|
177 |
+ int n; |
|
178 |
+ unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
179 |
+ if(redata==NULL || slot==NULL || unsaved==NULL || newfilename==NULL || newfilename[0]=='\0') |
|
180 |
+ return(-1); /* sanity check failed */ |
|
181 |
+ if(oldfilename!=NULL) |
|
182 |
+ redata_unsaved_unlink(redata,slot,oldfilename); |
|
183 |
+ if((unsaved_genname(newfilename,unsname,sizeof(unsname)))==NULL) |
|
184 |
+ return(-1); /* malformed filename */ |
|
185 |
+ if(unsaved->unsavedfd!=-1) |
|
186 |
+ close(unsaved->unsavedfd),unsaved->unsavedfd=-1; |
|
187 |
+ redata_hash(redata,unsaved->initialhash); |
|
188 |
+ unsaved->usedbuf=0; |
|
189 |
+ if((unsaved->unsavedfd=open(unsname,O_WRONLY|O_TRUNC|O_CREAT,0644))==-1) |
|
190 |
+ return(-1); /* couldn't open file for writing */ |
|
191 |
+ if((n=write(unsaved->unsavedfd,header,sizeof(header)-1))==-1 |
|
192 |
+ || n!=(sizeof(header)-1) |
|
193 |
+ || (n=write(unsaved->unsavedfd,unsaved->initialhash,128))==-1 || n!=128 |
|
194 |
+ || (n=write(unsaved->unsavedfd,",",1))==-1 || n!=1) { |
|
195 |
+ close(unsaved->unsavedfd),unsaved->unsavedfd=-1; |
|
196 |
+ unlink(unsname); |
|
197 |
+ return(-1); /* couldn't write header/hash */ |
|
198 |
+ } |
|
199 |
+ return(0); |
|
200 |
+} |
|
201 |
+ |
|
202 |
+int |
|
203 |
+redata_unsaved_truncload(redata_t *redata, redata_plugin_t *slot, char *filename) |
|
204 |
+{ |
|
205 |
+ return(redata_unsaved_trunc(redata, slot, NULL, filename)); |
|
206 |
+} |
|
207 |
+ |
|
208 |
+ |
|
209 |
+int |
|
210 |
+redata_unsaved_loadappend(redata_t *redata, redata_plugin_t *slot, char *filename) |
|
211 |
+{ |
|
212 |
+ int fd; |
|
213 |
+ struct stat statbuf; |
|
214 |
+ static char header[]={UNSAVEDHEADER}; |
|
215 |
+ long headerhashsize; |
|
216 |
+ char *newptr; |
|
217 |
+ long nread,lim; |
|
218 |
+ char *ptr,*endptr,*aux,*bufptr; |
|
219 |
+ char actioncode; |
|
220 |
+ long pos,pos2; |
|
221 |
+ char endcode; |
|
222 |
+ int flag_multipart; |
|
223 |
+ unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
224 |
+ if(redata==NULL || slot==NULL || unsaved==NULL || filename==NULL) |
|
225 |
+ return(-1); |
|
226 |
+ if((fd=redata_unsaved_check_gen(redata,slot,filename))==-1) |
|
227 |
+ return(-1); /* check failed */ |
|
228 |
+ if(fstat(fd,&statbuf)!=0 || !S_ISREG(statbuf.st_mode)) { |
|
229 |
+ close(fd),fd=-1; |
|
230 |
+ return(-1); /* couldn't query size or not regular file */ |
|
231 |
+ } |
|
232 |
+ redata_hash(redata,unsaved->initialhash); |
|
233 |
+ headerhashsize=(sizeof(header)-1)+1+128+1; |
|
234 |
+ /* load unsaved to memory */ |
|
235 |
+ if(unsaved->sizebuf<(statbuf.st_size-headerhashsize)) { |
|
236 |
+ if((newptr=realloc(unsaved->buf,(statbuf.st_size-headerhashsize)))==NULL) { |
|
237 |
+ close(fd),fd=-1; |
|
238 |
+ return(-1); /* insuf. mem. */ |
|
239 |
+ } |
|
240 |
+ unsaved->buf=newptr; |
|
241 |
+ unsaved->sizebuf=(statbuf.st_size-headerhashsize); |
|
242 |
+ } |
|
243 |
+ unsaved->usedbuf=0; |
|
244 |
+ lim=(statbuf.st_size-headerhashsize); |
|
245 |
+ for(nread=0;unsaved->usedbuf<lim;unsaved->usedbuf+=nread,nread=0) { |
|
246 |
+ if((nread=read(fd,unsaved->buf+unsaved->usedbuf,lim-unsaved->usedbuf))<=0) { |
|
247 |
+ unsaved->usedbuf=0; |
|
248 |
+ close(fd),fd=-1; |
|
249 |
+ return(-1); /* short read */ |
|
250 |
+ } |
|
251 |
+ } |
|
252 |
+ close(fd),fd=-1; |
|
253 |
+ /* process unsaved data */ |
|
254 |
+ endptr=unsaved->buf+unsaved->usedbuf; |
|
255 |
+ for(ptr=unsaved->buf;ptr<endptr;) { |
|
256 |
+ if((ptr=ptr_getchar(ptr,endptr,&actioncode))==NULL) |
|
257 |
+ return(-1); /* no space for action char */ |
|
258 |
+ /* multipart example: A10+$aj$%$% >> insert "aj$" into pos 10 */ |
|
259 |
+ if(actioncode=='A') { |
|
260 |
+ ptr=ptr_getlong(ptr,endptr,&pos); |
|
261 |
+ do { |
|
262 |
+ flag_multipart=0; |
|
263 |
+ ptr=ptr_getchar(ptr,endptr,&endcode); |
|
264 |
+ if(ptr!=NULL && endcode=='+') { |
|
265 |
+ flag_multipart=1; |
|
266 |
+ ptr=ptr_getchar(ptr,endptr,&endcode); |
|
267 |
+ } |
|
268 |
+ bufptr=ptr; |
|
269 |
+ ptr=ptr_searchendchar(ptr,endptr,endcode,&aux); |
|
270 |
+ if(ptr==NULL || pos<0 || pos>redata_getused(redata)) |
|
271 |
+ return(-1); /* malformed register */ |
|
272 |
+ redata_op_add(redata,pos,bufptr,aux-bufptr,NULL); |
|
273 |
+ pos+=aux-bufptr; |
|
274 |
+ } while(flag_multipart); |
|
275 |
+ } else if(actioncode=='D') { |
|
276 |
+ ptr=ptr_getlong(ptr,endptr,&pos); |
|
277 |
+ do { |
|
278 |
+ flag_multipart=0; |
|
279 |
+ ptr=ptr_getchar(ptr,endptr,&endcode); |
|
280 |
+ if(ptr!=NULL && endcode=='+') { |
|
281 |
+ flag_multipart=1; |
|
282 |
+ ptr=ptr_getchar(ptr,endptr,&endcode); |
|
283 |
+ } |
|
284 |
+ bufptr=ptr; |
|
285 |
+ ptr=ptr_searchendchar(ptr,endptr,endcode,&aux); |
|
286 |
+ if(ptr==NULL || pos<0 || (pos+(aux-bufptr))>redata_getused(redata)) |
|
287 |
+ return(-1); /* malformed register */ |
|
288 |
+ if(redata_data_compare(redata,pos,bufptr,aux-bufptr)!=0) |
|
289 |
+ return(-1); /* corrupted data */ |
|
290 |
+ redata_op_del(redata,pos,aux-bufptr,NULL); |
|
291 |
+ } while(flag_multipart); |
|
292 |
+ } else if(actioncode=='M') { |
|
293 |
+ ptr=ptr_getlong(ptr,endptr,&pos); |
|
294 |
+ ptr+=(ptr!=NULL && ptr<endptr)?1:0; |
|
295 |
+ ptr=ptr_getlong(ptr,endptr,&pos2); |
|
296 |
+ do { |
|
297 |
+ flag_multipart=0; |
|
298 |
+ ptr=ptr_getchar(ptr,endptr,&endcode); |
|
299 |
+ if(ptr!=NULL && endcode=='+') { |
|
300 |
+ flag_multipart=1; |
|
301 |
+ ptr=ptr_getchar(ptr,endptr,&endcode); |
|
302 |
+ } |
|
303 |
+ bufptr=ptr; |
|
304 |
+ ptr=ptr_searchendchar(ptr,endptr,endcode,&aux); |
|
305 |
+ if(ptr==NULL |
|
306 |
+ || pos<0 || (pos+(aux-bufptr))>redata_getused(redata) |
|
307 |
+ || pos2<0 || pos2>redata_getused(redata) |
|
308 |
+ || ((aux-bufptr)>0 && pos2>=pos && pos2<(pos+(aux-bufptr))) |
|
309 |
+ ) { |
|
310 |
+ return(-1); /* malformed register */ |
|
311 |
+ } |
|
312 |
+ if(redata_data_compare(redata,pos,bufptr,aux-bufptr)!=0) |
|
313 |
+ return(-1); /* corrupted data */ |
|
314 |
+ redata_op_move(redata,pos,(aux-bufptr),pos2,NULL); |
|
315 |
+ pos=(pos<pos2)?pos:(pos+(aux-bufptr)); |
|
316 |
+ pos2=pos2+(aux-bufptr); |
|
317 |
+ } while(flag_multipart); |
|
318 |
+ } else { |
|
319 |
+ return(-1); /* corrupted undobuf */ |
|
320 |
+ } |
|
321 |
+ } |
|
322 |
+ return(-1); |
|
323 |
+} |
|
324 |
+ |
|
325 |
+int |
|
326 |
+redata_unsaved_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
|
327 |
+{ |
|
328 |
+ char sep; |
|
329 |
+ char *sepend,*ptr,*endptr; |
|
330 |
+ char *buf; |
|
331 |
+ int k; |
|
332 |
+ int maxsize,newsize; |
|
333 |
+ char posbuf[128]; |
|
334 |
+ undostack_t *stack; |
|
335 |
+ unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
336 |
+ stack=redata_getstack(redata,undo); |
|
337 |
+ if(redata==NULL || slot==NULL || unsaved==NULL || undo==NULL || stack==NULL) |
|
338 |
+ return(-1); /* sanity check failed */ |
|
339 |
+ /* syntax (see loadappend): A<pos><+?><sep><text><sep>[<+?><sep><text><sep>[...]] */ |
|
340 |
+ if(undo->type!='A' && undo->type!='D' && undo->type!='M') |
|
341 |
+ return(-1); /* unrecognized undo type */ |
|
342 |
+ for(k=0,maxsize=0,buf=NULL;k<2;k++,maxsize=0) { |
|
343 |
+ ptr=stack->buf+undo->off; |
|
344 |
+ endptr=ptr+undo->len; |
|
345 |
+ if(k!=0) |
|
346 |
+ buf[maxsize]=undo->type; |
|
347 |
+ maxsize++; |
|
348 |
+ snprintf(posbuf,sizeof(posbuf),"%li",undo->posorig); |
|
349 |
+ posbuf[sizeof(posbuf)-1]='\0'; |
|
350 |
+ if(k!=0) |
|
351 |
+ strcpy(buf+maxsize,posbuf); |
|
352 |
+ maxsize+=strlen(posbuf); |
|
353 |
+ if(undo->type=='M') { |
|
354 |
+ snprintf(posbuf,sizeof(posbuf),",%li",undo->posdest); |
|
355 |
+ posbuf[sizeof(posbuf)-1]='\0'; |
|
356 |
+ if(k!=0) |
|
357 |
+ strcpy(buf+maxsize,posbuf); |
|
358 |
+ maxsize+=strlen(posbuf); |
|
359 |
+ } |
|
360 |
+ while(ptr<endptr) { |
|
361 |
+ sep=sep_select(ptr,endptr-ptr,&sepend); |
|
362 |
+ if(sepend!=endptr) { |
|
363 |
+ if(k!=0) |
|
364 |
+ buf[maxsize]='+'; |
|
365 |
+ maxsize++; |
|
366 |
+ } |
|
367 |
+ if(k!=0) |
|
368 |
+ buf[maxsize]=sep; |
|
369 |
+ maxsize++; |
|
370 |
+ if(k!=0) |
|
371 |
+ memcpy(buf+maxsize,ptr,sepend-ptr); |
|
372 |
+ maxsize+=sepend-ptr; |
|
373 |
+ if(k!=0) |
|
374 |
+ buf[maxsize]=sep; |
|
375 |
+ maxsize++; |
|
376 |
+ ptr=sepend; |
|
377 |
+ } |
|
378 |
+ if(k==0) { |
|
379 |
+ /* get mem */ |
|
380 |
+ if((unsaved->sizebuf-unsaved->sizebuf)<maxsize) { |
|
381 |
+ newsize=(unsaved->sizebuf+maxsize+UNSAVEDGROWSIZE-1)/UNSAVEDGROWSIZE; |
|
382 |
+ newsize*=UNSAVEDGROWSIZE; |
|
383 |
+ if((buf=realloc(unsaved->buf,newsize))==NULL) |
|
384 |
+ return(-1); /* insuf. mem. */ |
|
385 |
+ unsaved->buf=buf; |
|
386 |
+ unsaved->sizebuf=newsize; |
|
387 |
+ } |
|
388 |
+ buf=unsaved->buf+unsaved->usedbuf; |
|
389 |
+ } |
|
390 |
+ } |
|
391 |
+ return(0); |
|
392 |
+} |
|
393 |
+ |
|
394 |
+int |
|
395 |
+redata_unsaved_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
|
396 |
+{ |
|
397 |
+ /* adds to unsaved the inverse operation to the one specified in the undo */ |
|
398 |
+ char sep; |
|
399 |
+ char *sepend,*ptr,*endptr; |
|
400 |
+ char *buf; |
|
401 |
+ int k; |
|
402 |
+ int maxsize,newsize; |
|
403 |
+ char posbuf[128]; |
|
404 |
+ undostack_t *stack; |
|
405 |
+ unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
406 |
+ stack=redata_getstack(redata,undo); |
|
407 |
+ if(redata==NULL || slot==NULL || unsaved==NULL || undo==NULL || stack==NULL) |
|
408 |
+ return(-1); /* sanity check failed */ |
|
409 |
+ /* syntax (see loadappend): A<pos><+?><sep><text><sep>[<+?><sep><text><sep>[...]] */ |
|
410 |
+ if(undo->type!='A' && undo->type!='D' && undo->type!='M') |
|
411 |
+ return(-1); /* unrecognized undo type */ |
|
412 |
+ for(k=0,maxsize=0,buf=NULL;k<2;k++,maxsize=0) { |
|
413 |
+ ptr=stack->buf+undo->off; |
|
414 |
+ endptr=ptr+undo->len; |
|
415 |
+ if(k!=0) |
|
416 |
+ buf[maxsize]=(undo->type=='A')?'D':(undo->type=='D')?'A':undo->type; |
|
417 |
+ maxsize++; |
|
418 |
+ if(undo->type=='A' || undo->type=='D') |
|
419 |
+ snprintf(posbuf,sizeof(posbuf),"%li",undo->posorig); |
|
420 |
+ else |
|
421 |
+ snprintf(posbuf,sizeof(posbuf),"%li",(undo->posorig<undo->posdest)?undo->posdest-undo->len:undo->posdest); |
|
422 |
+ posbuf[sizeof(posbuf)-1]='\0'; |
|
423 |
+ if(k!=0) |
|
424 |
+ strcpy(buf+maxsize,posbuf); |
|
425 |
+ maxsize+=strlen(posbuf); |
|
426 |
+ if(undo->type=='M') { |
|
427 |
+ snprintf(posbuf,sizeof(posbuf),",%li",(undo->posorig<undo->posdest)?undo->posorig:undo->posorig+undo->len); |
|
428 |
+ posbuf[sizeof(posbuf)-1]='\0'; |
|
429 |
+ if(k!=0) |
|
430 |
+ strcpy(buf+maxsize,posbuf); |
|
431 |
+ maxsize+=strlen(posbuf); |
|
432 |
+ } |
|
433 |
+ while(ptr<endptr) { |
|
434 |
+ sep=sep_select(ptr,endptr-ptr,&sepend); |
|
435 |
+ if(sepend!=endptr) { |
|
436 |
+ if(k!=0) |
|
437 |
+ buf[maxsize]='+'; |
|
438 |
+ maxsize++; |
|
439 |
+ } |
|
440 |
+ if(k!=0) |
|
441 |
+ buf[maxsize]=sep; |
|
442 |
+ maxsize++; |
|
443 |
+ if(k!=0) |
|
444 |
+ memcpy(buf+maxsize,ptr,sepend-ptr); |
|
445 |
+ maxsize+=sepend-ptr; |
|
446 |
+ if(k!=0) |
|
447 |
+ buf[maxsize]=sep; |
|
448 |
+ maxsize++; |
|
449 |
+ ptr=sepend; |
|
450 |
+ } |
|
451 |
+ if(k==0) { |
|
452 |
+ /* get mem */ |
|
453 |
+ if((unsaved->sizebuf-unsaved->sizebuf)<maxsize) { |
|
454 |
+ newsize=(unsaved->sizebuf+maxsize+UNSAVEDGROWSIZE-1)/UNSAVEDGROWSIZE; |
|
455 |
+ newsize*=UNSAVEDGROWSIZE; |
|
456 |
+ if((buf=realloc(unsaved->buf,newsize))==NULL) |
|
457 |
+ return(-1); /* insuf. mem. */ |
|
458 |
+ unsaved->buf=buf; |
|
459 |
+ unsaved->sizebuf=newsize; |
|
460 |
+ } |
|
461 |
+ buf=unsaved->buf+unsaved->usedbuf; |
|
462 |
+ } |
|
463 |
+ } |
|
464 |
+ return(0); |
|
465 |
+} |
|
466 |
+ |
|
467 |
+int |
|
468 |
+redata_unsaved_commit(redata_t *redata, redata_plugin_t *slot,char *filename) |
|
469 |
+{ |
|
470 |
+ int n,nwritten; |
|
471 |
+ char unsname[PATH_MAX+1]; |
|
472 |
+ unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
|
473 |
+ if(redata==NULL || slot==NULL || unsaved==NULL || unsaved->unsavedfd==-1) |
|
474 |
+ return(-1); |
|
475 |
+ for(nwritten=0;nwritten<unsaved->usedbuf;nwritten+=n) { |
|
476 |
+ if((n=write(unsaved->unsavedfd,unsaved->buf+nwritten,unsaved->usedbuf-nwritten))<0) { |
|
477 |
+ close(unsaved->unsavedfd),unsaved->unsavedfd=-1; |
|
478 |
+ if((unsaved_genname(filename,unsname,sizeof(unsname)))!=NULL) |
|
479 |
+ unlink(unsname); /* a corrupted unsaved is of no use, delete it */ |
|
480 |
+ return(-1); /* error writing */ |
|
481 |
+ } |
|
482 |
+ } |
|
483 |
+ unsaved->usedbuf=0; |
|
484 |
+ return(0); |
|
485 |
+} |
|
486 |
+ |
|
487 |
+static char * |
|
488 |
+unsaved_genname(char *filename, char *buf, int bufsize) |
|
489 |
+{ |
|
490 |
+ static char pre[]={UNSAVEDPREFIX}; |
|
491 |
+ static char post[]={UNSAVEDPOSTFIX}; |
|
492 |
+ return(redata_generic_genname(filename,pre,post,buf,bufsize)); |
|
493 |
+} |
|
494 |
+ |
|
495 |
+static char * |
|
496 |
+ptr_getlong(char *ptr,char *endptr,long *data) |
|
497 |
+{ |
|
498 |
+ long l,s; |
|
499 |
+ if(ptr==NULL || endptr==NULL || ptr>endptr) |
|
500 |
+ return(NULL); |
|
501 |
+ s=1; |
|
502 |
+ if(ptr<endptr && *ptr=='-') { |
|
503 |
+ s=-1; |
|
504 |
+ ptr++; |
|
505 |
+ } |
|
506 |
+ for(l=0;ptr<endptr && *ptr>='0' && *ptr<='9';ptr++) { |
|
507 |
+ l*=10; |
|
508 |
+ l+=(*ptr-'0'); |
|
509 |
+ } |
|
510 |
+ l*=s; |
|
511 |
+ if(data!=NULL) |
|
512 |
+ *data=l; |
|
513 |
+ return(ptr); |
|
514 |
+} |
|
515 |
+ |
|
516 |
+ |
|
517 |
+static char * |
|
518 |
+ptr_getchar(char *ptr,char *endptr,char *data) |
|
519 |
+{ |
|
520 |
+ if(ptr==NULL || endptr==NULL || ptr>endptr) |
|
521 |
+ return(NULL); |
|
522 |
+ if(data!=NULL) |
|
523 |
+ *data=*ptr; |
|
524 |
+ ptr++; |
|
525 |
+ return(ptr); |
|
526 |
+} |
|
527 |
+ |
|
528 |
+static char * |
|
529 |
+ptr_searchendchar(char *ptr, char *endptr, char endchar, char **endcharpos) |
|
530 |
+{ |
|
531 |
+ char *aux; |
|
532 |
+ if(ptr==NULL || endptr==NULL || ptr>endptr) |
|
533 |
+ return(NULL); |
|
534 |
+ if((aux=memchr(ptr,endchar,endptr-ptr))==NULL) |
|
535 |
+ return(NULL); |
|
536 |
+ if(endcharpos!=NULL) |
|
537 |
+ *endcharpos=aux; |
|
538 |
+ return(aux+1); |
|
539 |
+} |
|
540 |
+ |
|
541 |
+static char |
|
542 |
+sep_select(char *buf, int bufsize, char **pos) |
|
543 |
+{ |
|
544 |
+ static char seps[]={"$%@!|&/='\"^*;:,-_"}; |
|
545 |
+ char *ptr,*bestptr; |
|
546 |
+ int i,besti; |
|
547 |
+ bestptr=buf; |
|
548 |
+ if(pos!=NULL) |
|
549 |
+ *pos=NULL; |
|
550 |
+ for(i=0,besti=0;i<sizeof(seps);i++) { |
|
551 |
+ if((ptr=memchr(buf,seps[i],bufsize))==NULL) { |
|
552 |
+ if(pos!=NULL) |
|
553 |
+ *pos=buf+bufsize; |
|
554 |
+ return(seps[i]); |
|
555 |
+ } |
|
556 |
+ if(ptr>bestptr) { |
|
557 |
+ besti=0; |
|
558 |
+ bestptr=ptr; |
|
559 |
+ } |
|
560 |
+ } |
|
561 |
+ if(pos!=NULL) |
|
562 |
+ *pos=bestptr; |
|
563 |
+ return(seps[besti]); |
|
564 |
+} |
|
565 |
+ |
0 | 566 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,39 @@ |
1 |
+/* |
|
2 |
+ * re_plugin_unsaved.h |
|
3 |
+ * |
|
4 |
+ * A programmers editor |
|
5 |
+ * |
|
6 |
+ * re_data plugin to support the unsaved changes file. |
|
7 |
+ * (for recovery when the program closes unexpectedly) |
|
8 |
+ * |
|
9 |
+ * HEADER FILE |
|
10 |
+ * |
|
11 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
12 |
+ * This program is licensed under the terms of GNU GPL v2.1+ |
|
13 |
+ */ |
|
14 |
+ |
|
15 |
+#include "re_data.h" |
|
16 |
+ |
|
17 |
+typedef struct unsaved_t { |
|
18 |
+ char initialhash[129]; |
|
19 |
+ int unsavedfd; |
|
20 |
+ long sizebuf; |
|
21 |
+ long usedbuf; |
|
22 |
+ char *buf; |
|
23 |
+} unsaved_t; |
|
24 |
+ |
|
25 |
+int redata_unsaved_register(redata_t *redata, redata_plugin_t *slot); |
|
26 |
+int redata_unsaved_unregister(redata_t *redata, redata_plugin_t *slot,char *filename); |
|
27 |
+ |
|
28 |
+int redata_unsaved_exists(redata_t *redata, redata_plugin_t *slot, char *filename); |
|
29 |
+int redata_unsaved_check(redata_t *redata, redata_plugin_t *slot, char *filename); |
|
30 |
+int redata_unsaved_wipe(redata_t *redata, redata_plugin_t *slot, char *filename); |
|
31 |
+int redata_unsaved_truncload(redata_t *redata, redata_plugin_t *slot, char *filename); |
|
32 |
+int redata_unsaved_loadappend(redata_t *redata, redata_plugin_t *slot, char *filename); |
|
33 |
+int redata_unsaved_unlink(redata_t *redata, redata_plugin_t *slot, char *filename); |
|
34 |
+int redata_unsaved_trunc(redata_t *redata, redata_plugin_t *slot, char *oldfilename, char *newfilename); |
|
35 |
+int redata_unsaved_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo); |
|
36 |
+int redata_unsaved_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo); |
|
37 |
+int redata_unsaved_commit(redata_t *redata, redata_plugin_t *slot, char *filename); |
|
38 |
+ |
|
39 |
+ |
... | ... |
@@ -75,7 +75,7 @@ main(int argc, char *argv[]) |
75 | 75 |
for(i=0;i<(sizeof(tests)/sizeof(tests[0]));i++,total++) { |
76 | 76 |
if(!flag_all && tests[i].int1>=1024) |
77 | 77 |
continue; /* too slow: skip unless testing --all */ |
78 |
- if((redata=redata_init())==NULL) { |
|
78 |
+ if((redata=redata_init(NULL))==NULL) { |
|
79 | 79 |
fprintf(stderr,"ERROR: problem initializing redata module\n"); |
80 | 80 |
return(1); |
81 | 81 |
} |
... | ... |
@@ -65,7 +65,7 @@ re_init(void) |
65 | 65 |
if((re=malloc(sizeof(re_t)))==NULL) |
66 | 66 |
return(NULL); /* insuf. mem. */ |
67 | 67 |
memset(re,0,sizeof(re_t)); |
68 |
- if((re->redata=redata_init())==NULL) { |
|
68 |
+ if((re->redata=redata_init(NULL))==NULL) { |
|
69 | 69 |
re_free(re),re=NULL; |
70 | 70 |
return(NULL); /* insuf. mem. */ |
71 | 71 |
} |