Browse code

Refactor unsaved into a plugin of redata

Dario Rodriguez authored on 04/04/2019 21:53:07
Showing 7 changed files
... ...
@@ -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
         }