... | ... |
@@ -52,7 +52,6 @@ redata_init(void) |
52 | 52 |
/* undo */ |
53 | 53 |
redata->sizeundo=0; |
54 | 54 |
redata->usedundo=0; |
55 |
- redata->curundo=0; |
|
56 | 55 |
redata->undo=NULL; |
57 | 56 |
redata->undobuf=NULL; |
58 | 57 |
/* unsaved */ |
... | ... |
@@ -178,6 +177,27 @@ redata_wipe(redata_t *redata) |
178 | 177 |
return(0); |
179 | 178 |
} |
180 | 179 |
|
180 |
+int |
|
181 |
+redata_chunk_insertnew(redata_t *redata, int afterthischunk) |
|
182 |
+{ |
|
183 |
+ rechunk_t *newchunk; |
|
184 |
+ int i; |
|
185 |
+ if(redata==NULL || afterthischunk<(-1) || afterthischunk>=redata->sizechunks) |
|
186 |
+ return(-1); |
|
187 |
+ if(redata->chunks[redata->sizechunks-1]->useddata!=0) { |
|
188 |
+ if(redata_preallocate(redata,redata_getsize(redata)+redata->chunkdatasize)==-1 |
|
189 |
+ || redata->chunks[redata->sizechunks-1]->useddata!=0) |
|
190 |
+ return(-1); |
|
191 |
+ } |
|
192 |
+ newchunk=redata->chunks[redata->sizechunks-1]; |
|
193 |
+ /* move the emtpy chunk to after chunkno */ |
|
194 |
+ for(i=redata->sizechunks-1;i>(afterthischunk+1);i--) |
|
195 |
+ redata->chunks[i]=redata->chunks[i-1]; |
|
196 |
+ redata->chunks[afterthischunk+1]=newchunk; |
|
197 |
+ return(0); |
|
198 |
+} |
|
199 |
+ |
|
200 |
+ |
|
181 | 201 |
int |
182 | 202 |
redata_preallocate(redata_t *redata, int newsize) |
183 | 203 |
{ |
... | ... |
@@ -243,6 +263,8 @@ redata_chunk_movedata(redata_t *redata, int chunkfrom, int posfrom, int chunkto, |
243 | 263 |
memmove(from->data+posfrom,from->data+posfrom+size,from->useddata-posfrom-size); |
244 | 264 |
from->useddata-=size; |
245 | 265 |
to->useddata+=size; |
266 |
+ from->whatin_fresh=0; |
|
267 |
+ to->whatin_fresh=0; |
|
246 | 268 |
} else { |
247 | 269 |
/* from==to */ |
248 | 270 |
rechunk_t *chunk=redata->chunks[chunkfrom]; |
... | ... |
@@ -256,12 +278,48 @@ redata_chunk_movedata(redata_t *redata, int chunkfrom, int posfrom, int chunkto, |
256 | 278 |
memmove(chunk->data+posfrom+size-inside,chunk->data+posto,inside); |
257 | 279 |
memcpy(chunk->data+posto,redata->tmpchunk->data,size); |
258 | 280 |
} |
281 |
+ chunk->whatin_fresh=0; |
|
259 | 282 |
} |
260 | 283 |
return(0); |
261 | 284 |
} |
262 | 285 |
|
263 | 286 |
int |
264 |
-redata_fill_whatin(redata_t *redata, int chunkno) |
|
287 |
+redata_chunk_insertdata(redata_t *redata, int chunkto, int posto, char *buf, int buflen) |
|
288 |
+{ |
|
289 |
+ rechunk_t *chunk; |
|
290 |
+ if(redata==NULL || buflen<0 || buf==NULL |
|
291 |
+ || chunkto<0 || chunkto>=redata->sizechunks |
|
292 |
+ || posto<0 || posto>redata->chunks[chunkto]->useddata |
|
293 |
+ || (redata->chunkdatasize-redata->chunks[chunkto]->useddata)<buflen) |
|
294 |
+ return(-1); /* sanity check failed */ |
|
295 |
+ chunk=redata->chunks[chunkto]; |
|
296 |
+ memmove(chunk->data+posto+buflen,chunk->data+posto,chunk->useddata-posto); |
|
297 |
+ memcpy(chunk->data+posto,buf,buflen); |
|
298 |
+ chunk->useddata+=buflen; |
|
299 |
+ chunk->whatin_fresh=0; |
|
300 |
+ return(0); |
|
301 |
+} |
|
302 |
+ |
|
303 |
+int |
|
304 |
+redata_chunk_deletedata(redata_t *redata, int chunkno, int pos, int n) |
|
305 |
+{ |
|
306 |
+ rechunk_t *chunk; |
|
307 |
+ if(redata==NULL || n<0 |
|
308 |
+ || chunk<0 || chunkno>=redata->sizechunks |
|
309 |
+ || pos<0 || pos>redata->chunks[chunkno]->useddata |
|
310 |
+ || (redata->chunks[chunkno]->useddata-pos)<n) |
|
311 |
+ return(-1); /* sanity check failed */ |
|
312 |
+ if(n==0) |
|
313 |
+ return(0); /* all done */ |
|
314 |
+ chunk=redata->chunks[chunkno]; |
|
315 |
+ memmove(chunk->data+pos,chunk->data+pos+n,chunk->useddata-pos-n); |
|
316 |
+ chunk->useddata-=n; |
|
317 |
+ chunk->whatin_fresh=0; |
|
318 |
+ return(0); |
|
319 |
+} |
|
320 |
+ |
|
321 |
+int |
|
322 |
+redata_whatin_refresh(redata_t *redata, int chunkno) |
|
265 | 323 |
{ |
266 | 324 |
rechunk_t *chunk; |
267 | 325 |
int nlcount; |
... | ... |
@@ -290,8 +348,7 @@ mymemrchr(const void *s, int c, size_t n) |
290 | 348 |
b=(*((unsigned int *)(&c)))&0xff; |
291 | 349 |
for(i=0;i<n;i++) { |
292 | 350 |
if(((unsigned char *)s)[i]==b) |
293 |
- res=s+i; |
|
294 |
- } |
|
351 |
+ res=(((unsigned char *)s)+i); } |
|
295 | 352 |
return(res); |
296 | 353 |
} |
297 | 354 |
|
... | ... |
@@ -321,28 +378,16 @@ redata_fix_nl(redata_t *redata, int chunkno) |
321 | 378 |
/* move incomplete line to next chunk */ |
322 | 379 |
redata_chunk_movedata(redata, chunkno, chunk->useddata-linesize, chunkno+1, 0, linesize); |
323 | 380 |
} else if(ptr!=NULL) { |
324 |
- /* only if we have more data un chunkno before this long line */ |
|
325 |
- int i,newavail; |
|
326 |
- rechunk_t *newchunk; |
|
381 |
+ /* only if we have more data in chunkno before this long line */ |
|
382 |
+ int newavail; |
|
327 | 383 |
/* create a new empty chunk in-between and put the line there */ |
328 |
- if(redata->chunks[redata->sizechunks-1]->useddata!=0) { |
|
329 |
- if(redata_preallocate(redata,redata->available+redata->chunkdatasize)==-1 |
|
330 |
- || redata->chunks[redata->sizechunks-1]->useddata!=0) |
|
331 |
- return(-1); |
|
332 |
- } |
|
333 |
- newchunk=redata->chunks[redata->sizechunks-1]; |
|
334 |
- /* move the emty chunk to after chunkno */ |
|
335 |
- for(i=redata->sizechunks-1;i>(chunkno+1);i--) |
|
336 |
- redata->chunks[i]=redata->chunks[i-1]; |
|
337 |
- redata->chunks[chunkno+1]=newchunk; |
|
384 |
+ if(redata_chunk_insertnew(redata,chunkno)==-1) |
|
385 |
+ return(-1); |
|
338 | 386 |
/* move the data; if it doesn't fit, move from the beginning until it is full */ |
339 | 387 |
redata_chunk_movedata(redata, chunkno, chunk->useddata-linesize, chunkno+1, 0, linesize); |
340 | 388 |
newavail=redata->sizechunks-linesize; |
341 | 389 |
redata_chunk_movedata(redata, chunkno+2, 0, chunkno+1, linesize, (newavail<nextlinesize)?newavail:nextlinesize); |
342 |
- redata->chunks[chunkno+2]->whatin_fresh=0; |
|
343 | 390 |
} |
344 |
- redata->chunks[chunkno]->whatin_fresh=0; |
|
345 |
- redata->chunks[chunkno+1]->whatin_fresh=0; |
|
346 | 391 |
return(0); |
347 | 392 |
} |
348 | 393 |
|
... | ... |
@@ -481,7 +526,7 @@ redata_load(redata_t *redata, char *filename, int use_unsaved) |
481 | 526 |
for(totalread=0,chunkno=0,nread=0;totalread<statbuf.st_size;totalread+=nread,nread=0) { |
482 | 527 |
if(chunkno>=redata->sizechunks || redata->chunks[chunkno]==NULL) { |
483 | 528 |
/* alloc another chunk */ |
484 |
- if(redata_preallocate(redata,(redata->sizechunks+1)*redata->chunkdatasize)==-1 || |
|
529 |
+ if(redata_preallocate(redata,redata_getsize(redata)+redata->chunkdatasize)==-1 || |
|
485 | 530 |
chunkno>=redata->sizechunks || redata->chunks[chunkno]==NULL) { |
486 | 531 |
close(fd),fd=-1; |
487 | 532 |
fprintf(stderr,"redata_load: INTERNAL ERROR\n"); |
... | ... |
@@ -508,7 +553,7 @@ redata_load(redata_t *redata, char *filename, int use_unsaved) |
508 | 553 |
for(chunkno=0;chunkno<redata->sizechunks;chunkno++) |
509 | 554 |
redata_fix_nl(redata,chunkno); |
510 | 555 |
for(chunkno=0;chunkno<redata->sizechunks;chunkno++) |
511 |
- redata_fill_whatin(redata,chunkno); |
|
556 |
+ redata_whatin_refresh(redata,chunkno); |
|
512 | 557 |
/* unsaved */ |
513 | 558 |
redata_hash(redata,redata->initialhash); |
514 | 559 |
if(use_unsaved) { |
... | ... |
@@ -642,7 +687,7 @@ redata_undo_newfromchunks(redata_t *redata,char *type, int pos1, int len) |
642 | 687 |
} |
643 | 688 |
|
644 | 689 |
undo_t * |
645 |
-redata_undobuf_newfrombuf(redata_t *redata, char *type, char *buf, int buflen) |
|
690 |
+redata_undo_newfrombuf(redata_t *redata, char *type, char *buf, int buflen) |
|
646 | 691 |
{ |
647 | 692 |
undo_t *undo; |
648 | 693 |
if(redata==NULL || type==NULL || buflen<=0) |
... | ... |
@@ -659,11 +704,73 @@ redata_undobuf_newfrombuf(redata_t *redata, char *type, char *buf, int buflen) |
659 | 704 |
} |
660 | 705 |
|
661 | 706 |
int |
662 |
-redata_op_add(redata_t *redata, char *buf, int sizebuf, int pos) |
|
707 |
+redata_op_add(redata_t *redata, char *buf, int buflen, int insertpos) |
|
663 | 708 |
{ |
709 |
+ int chunkno,pos; |
|
710 |
+ char hashpost[129]; |
|
711 |
+ undo_t *undo; |
|
712 |
+ rechunk_t *chunk,*nextchunk; |
|
713 |
+ int avail,nextavail; |
|
714 |
+ int i; |
|
715 |
+ int needed; |
|
716 |
+ char *ptr; |
|
717 |
+ if(redata==NULL || buf==NULL || buflen<0 || insertpos<0 || insertpos>redata_getused(redata)) |
|
718 |
+ return(-1); /* sanity check failed */ |
|
719 |
+ if(redata_getposptr(redata,insertpos,&chunkno,&pos)==-1) |
|
720 |
+ return(-1); /* invalid pos */ |
|
721 |
+ if((undo=redata_undo_newfrombuf(redata,"ADD",buf,buflen))==NULL) |
|
722 |
+ return(-1); /* couldn't create undo struct */ |
|
723 |
+ redata_hash(redata,undo->prehash); |
|
724 |
+ chunk=redata->chunks[chunkno]; |
|
725 |
+ avail=redata->chunkdatasize-chunk->useddata; |
|
726 |
+ nextchunk=((chunkno+1)<redata->sizechunks)?redata->chunks[chunkno+1]:NULL; |
|
727 |
+ nextavail=(nextchunk==NULL)?0:redata->chunkdatasize-nextchunk->useddata; |
|
728 |
+ if(avail>=buflen) { |
|
729 |
+ /* fits in current chunk */ |
|
730 |
+ redata_chunk_insertdata(redata,chunkno,pos,buf,buflen); |
|
731 |
+ redata_fix_nl(redata,chunkno); |
|
732 |
+ nextchunk=chunk; |
|
733 |
+ } else if((avail+nextavail)>=buflen) { |
|
734 |
+ /* part fits in current chunk, part in next chunk */ |
|
735 |
+ int bothering; |
|
736 |
+ bothering=chunk->useddata-pos; |
|
737 |
+ bothering=(bothering>nextavail)?nextavail:bothering; |
|
738 |
+ redata_chunk_movedata(redata,chunkno,chunk->useddata-bothering,chunkno+1,0,bothering); |
|
739 |
+ redata_chunk_insertdata(redata,chunkno,pos,buf,buflen); |
|
740 |
+ } else { |
|
741 |
+ /* will need to add more chunks */ |
|
742 |
+ needed=(buflen+redata->chunkdatasize-1)/redata->chunkdatasize; |
|
743 |
+ needed*=redata->chunkdatasize; |
|
744 |
+ needed+=(chunk->useddata-pos); |
|
745 |
+ if(redata_preallocate(redata,redata_getsize(redata)+needed)!=0) { |
|
746 |
+ redata->usedundobuf-=buflen; |
|
747 |
+ memset(undo,0,sizeof(undo_t)); |
|
748 |
+ return(-1); /* insuf. mem. */ |
|
749 |
+ } |
|
750 |
+ redata_chunk_insertnew(redata,chunkno); |
|
751 |
+ redata_chunk_movedata(redata,chunkno,pos,chunkno+1,0,chunk->useddata-pos); |
|
752 |
+ nextchunk=redata->chunks[chunkno+1]; |
|
753 |
+ avail=redata->chunkdatasize-chunk->useddata; |
|
754 |
+ avail=(avail>buflen)?buflen:avail; |
|
755 |
+ redata_chunk_insertdata(redata,chunkno,chunk->useddata,buf,avail); |
|
756 |
+ for(ptr=buf+avail,i=chunkno;(ptr-buf)<buflen;i++,ptr+=avail) { |
|
757 |
+ redata_chunk_insertnew(redata,i); |
|
758 |
+ avail=redata->chunkdatasize-redata->chunks[i+1]->useddata; |
|
759 |
+ avail=(avail>(buflen-(ptr-buf)))?(buflen-(ptr-buf)):avail; |
|
760 |
+ redata_chunk_insertdata(redata,i+1,0,ptr,avail); |
|
664 | 761 |
|
665 |
-#warning TODO |
|
666 |
- return(-1); |
|
762 |
+ } |
|
763 |
+ } |
|
764 |
+ /* fix nl until nextchunk (...fix_nl can insert chunks) */ |
|
765 |
+ for(i=chunkno;i<redata->sizechunks;i++) { |
|
766 |
+ redata_fix_nl(redata,i); |
|
767 |
+ if(redata->chunks[i]==nextchunk) |
|
768 |
+ break; |
|
769 |
+ } |
|
770 |
+ /* activate undo */ |
|
771 |
+ redata_hash(redata,undo->posthash); |
|
772 |
+ redata->usedundo++; |
|
773 |
+ return(0); |
|
667 | 774 |
} |
668 | 775 |
|
669 | 776 |
int |
... | ... |
@@ -25,9 +25,11 @@ typedef struct rechunk_t { |
25 | 25 |
} rechunk_t; |
26 | 26 |
|
27 | 27 |
typedef struct undo_t { |
28 |
- char type[5]; |
|
28 |
+ char type[4]; |
|
29 | 29 |
int off; |
30 | 30 |
int len; |
31 |
+ char prehash[129]; |
|
32 |
+ char posthash[129]; |
|
31 | 33 |
} undo_t; |
32 | 34 |
|
33 | 35 |
typedef struct redata_t { |
... | ... |
@@ -40,7 +42,6 @@ typedef struct redata_t { |
40 | 42 |
/* undo */ |
41 | 43 |
int sizeundo; |
42 | 44 |
int usedundo; |
43 |
- int curundo; |
|
44 | 45 |
undo_t *undo; |
45 | 46 |
int sizeundobuf; |
46 | 47 |
int usedundobuf; |
... | ... |
@@ -65,12 +66,20 @@ int redata_getavailable(redata_t *redata); |
65 | 66 |
int redata_getused(redata_t *redata); |
66 | 67 |
int redata_getposptr(redata_t *redata, int pos, int *numchunk, int *offset); |
67 | 68 |
|
69 |
+/* low level stuff */ |
|
68 | 70 |
int redata_wipe(redata_t *redata); |
69 | 71 |
int redata_preallocate(redata_t *redata, int size); |
72 |
+int redata_chunk_insertnew(redata_t *redata, int afterthischunk); |
|
70 | 73 |
int redata_chunk_movedata(redata_t *redata, int chunkfrom, int posfrom, int chunkto, int posto, int size); |
71 |
-int redata_fill_whatin(redata_t *redata, int chunkno); |
|
74 |
+int redata_chunk_insertdata(redata_t *redata, int chunkto, int posto, char *buf, int buflen); |
|
75 |
+int redata_chunk_deletedata(redata_t *redata, int chunk, int pos, int n); |
|
76 |
+int redata_whatin_refresh(redata_t *redata, int chunkno); |
|
72 | 77 |
int redata_fix_nl(redata_t *redata, int chunkno); |
78 |
+undo_t *redata_undo_new(redata_t *redata, char *type); |
|
79 |
+undo_t *redata_undo_newfromchunks(redata_t *redata,char *type, int pos1, int len); |
|
80 |
+undo_t *redata_undo_newfrombuf(redata_t *redata, char *type, char *buf, int buflen); |
|
73 | 81 |
|
82 |
+/* high level stuff */ |
|
74 | 83 |
int redata_unsaved_exists(redata_t *redata, char *filename); |
75 | 84 |
int redata_unsaved_check(redata_t *redata, char *filename); |
76 | 85 |
int redata_unsaved_loadappend(redata_t *redata); |
... | ... |
@@ -82,7 +91,7 @@ int redata_unsaved_unadd(redata_t *redata, undo_t *undo); |
82 | 91 |
int redata_load(redata_t *redata, char *filename, int use_unsaved); |
83 | 92 |
int redata_save(redata_t *redata, char *filename); |
84 | 93 |
|
85 |
-int redata_op_add(redata_t *redata, char *buf, int sizebuf, int pos); |
|
94 |
+int redata_op_add(redata_t *redata, char *buf, int buflen, int pos); |
|
86 | 95 |
int redata_op_del(redata_t *redata, int pos, int size); |
87 | 96 |
int redata_op_move(redata_t *redata, int posorig, int size, int posdest); |
88 | 97 |
int redata_op_undo(redata_t *redata); |
... | ... |
@@ -190,7 +190,7 @@ fprintf(stderr,"\ntest_edit(%s%s%s,%s%s%s,%i,%i);\nResult: ",(filename!=NULL)?"\ |
190 | 190 |
size=ptrend-ptr; |
191 | 191 |
if(k!=0) { |
192 | 192 |
/* editing */ |
193 |
- memmove(mem+l+size,mem+l,size); |
|
193 |
+ memmove(mem+l+size,mem+l,cursize-l); |
|
194 | 194 |
memcpy(mem+l,ptr,size); |
195 | 195 |
redata_op_add(redata,ptr,size,l); |
196 | 196 |
} |