... | ... |
@@ -547,8 +547,8 @@ redata_unsaved_loadquestion(redata_t *redata, redata_plugin_t *slot,char *filena |
547 | 547 |
static char mybody[]={"The file you're trying to load has some unsaved data from a previous session. I can recover the data. What do you want to do?"}; |
548 | 548 |
static char *myopts[]={"Recover unsaved data (safest option)","Don't use old unsaved data, delete old unsaved data (if you're sure what you're doing)"}; |
549 | 549 |
static char mytitleshort[]={"Unsaved data found"}; |
550 |
- static char mybodyshort[]={"Should try to recover the data?"}; |
|
551 |
- static char *myoptsshort[]={"Recover","Ignore it"}; |
|
550 |
+ static char mybodyshort[]={"Try to recover the data?"}; |
|
551 |
+ static char *myoptsshort[]={"Recover data","Ignore data","Quit"}; |
|
552 | 552 |
question_t *q; |
553 | 553 |
if(redata==NULL || slot==NULL || filename==NULL) |
554 | 554 |
return(-1); /* sanity check failed */ |
... | ... |
@@ -563,7 +563,7 @@ redata_unsaved_loadquestion(redata_t *redata, redata_plugin_t *slot,char *filena |
563 | 563 |
q->bodyshort=mybodyshort; |
564 | 564 |
q->opts=myopts; |
565 | 565 |
q->optsshort=myoptsshort; |
566 |
- q->nopts=2; |
|
566 |
+ q->nopts=3; |
|
567 | 567 |
q->defaultoption=1; |
568 | 568 |
q->selectedoption=-1; |
569 | 569 |
return(0); |
... | ... |
@@ -582,6 +582,11 @@ redata_unsaved_postload(redata_t *redata, redata_plugin_t *slot,char *filename) |
582 | 582 |
return(redata_unsaved_truncload(redata, slot, filename)); |
583 | 583 |
else if(selectedoption==0) /* recover */ |
584 | 584 |
return(redata_unsaved_loadappend(redata, slot, filename)); |
585 |
+#if 0 |
|
586 |
+#error TODO: implement be able to force-quit from plugin */ |
|
587 |
+ else if(selectedoption==2) /* quit */ |
|
588 |
+ return(-1); |
|
589 |
+#endif |
|
585 | 590 |
return(-1); |
586 | 591 |
} |
587 | 592 |
|
... | ... |
@@ -6,7 +6,7 @@ |
6 | 6 |
* re_data plugin to support the unsaved changes file. |
7 | 7 |
* (for recovery when the program closes unexpectedly) |
8 | 8 |
* |
9 |
- * Author: Dario Rodriguez dario@softhome.net |
|
9 |
+ * Author: Dario Rodriguez antartica@whereismybit.com |
|
10 | 10 |
* This program is licensed under the terms of GNU GPL v2.1+ |
11 | 11 |
*/ |
12 | 12 |
|
... | ... |
@@ -27,7 +27,8 @@ |
27 | 27 |
#define UNSAVEDGROWSIZE (256*1024) |
28 | 28 |
|
29 | 29 |
|
30 |
- |
|
30 |
+int redata_unsaved_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo); |
|
31 |
+int redata_unsaved_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo); |
|
31 | 32 |
static int redata_unsaved_loadquestion(redata_t *redata, redata_plugin_t *slot,char *filename); |
32 | 33 |
static int redata_unsaved_postload(redata_t *redata, redata_plugin_t *slot,char *filename); |
33 | 34 |
static int redata_unsaved_check_gen(redata_t *redata, redata_plugin_t *slot, char *filename); |
... | ... |
@@ -55,8 +56,7 @@ redata_unsaved_register(redata_t *redata, redata_plugin_t *slot) |
55 | 56 |
slot->wipe=redata_unsaved_wipe; |
56 | 57 |
slot->postload=redata_unsaved_postload; |
57 | 58 |
slot->postsave=redata_unsaved_trunc; |
58 |
- slot->add=redata_unsaved_add; |
|
59 |
- slot->unadd=redata_unsaved_unadd; |
|
59 |
+ slot->add_or_unadd=redata_unsaved_add_or_unadd; |
|
60 | 60 |
slot->commit=redata_unsaved_commit; |
61 | 61 |
slot->userptr=unsaved; |
62 | 62 |
return(0); |
... | ... |
@@ -357,6 +357,15 @@ fprintf(stderr,"\n"); |
357 | 357 |
return(0); |
358 | 358 |
} |
359 | 359 |
|
360 |
+int |
|
361 |
+redata_unsaved_add_or_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo, int is_unadd) |
|
362 |
+{ |
|
363 |
+ return((is_unadd==0)? |
|
364 |
+ redata_unsaved_add(redata, slot, undo): |
|
365 |
+ redata_unsaved_unadd(redata, slot, undo)); |
|
366 |
+} |
|
367 |
+ |
|
368 |
+ |
|
360 | 369 |
int |
361 | 370 |
redata_unsaved_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
362 | 371 |
{ |
... | ... |
@@ -208,7 +208,7 @@ redata_unsaved_trunc(redata_t *redata, redata_plugin_t *slot, char *oldfilename, |
208 | 208 |
int |
209 | 209 |
redata_unsaved_truncload(redata_t *redata, redata_plugin_t *slot, char *filename) |
210 | 210 |
{ |
211 |
-#if 1 |
|
211 |
+#if 0 |
|
212 | 212 |
fprintf(stderr,"UNSAVED: TRUNCLOAD (ignore)\n"); |
213 | 213 |
#endif |
214 | 214 |
return(redata_unsaved_trunc(redata, slot, NULL, filename)); |
... | ... |
@@ -230,17 +230,17 @@ redata_unsaved_loadappend(redata_t *redata, redata_plugin_t *slot, char *filenam |
230 | 230 |
char endcode; |
231 | 231 |
int flag_multipart; |
232 | 232 |
unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
233 |
-#if 1 |
|
233 |
+#if 0 |
|
234 | 234 |
fprintf(stderr,"UNSAVED: LOADAPPEND (recover)\n"); |
235 | 235 |
#endif |
236 | 236 |
if(redata==NULL || slot==NULL || unsaved==NULL || filename==NULL) |
237 | 237 |
return(-1); |
238 |
-#if 1 |
|
238 |
+#if 0 |
|
239 | 239 |
fprintf(stderr,"UNSAVED: LOADAPPEND pre-check\n"); |
240 | 240 |
#endif |
241 | 241 |
if((fd=redata_unsaved_check_gen(redata,slot,filename))==-1) |
242 | 242 |
return(-1); /* check failed */ |
243 |
-#if 1 |
|
243 |
+#if 0 |
|
244 | 244 |
fprintf(stderr,"UNSAVED: LOADAPPEND post-check\n"); |
245 | 245 |
#endif |
246 | 246 |
if(fstat(fd,&statbuf)!=0 || !S_ISREG(statbuf.st_mode)) { |
... | ... |
@@ -249,7 +249,7 @@ fprintf(stderr,"UNSAVED: LOADAPPEND post-check\n"); |
249 | 249 |
} |
250 | 250 |
redata_hash(redata,unsaved->initialhash); |
251 | 251 |
headerhashsize=(sizeof(header)-1)+128+1; |
252 |
-#if 1 |
|
252 |
+#if 0 |
|
253 | 253 |
fprintf(stderr,"UNSAVED: LOADAPPEND headerhashsize: %li\n",headerhashsize); |
254 | 254 |
#endif |
255 | 255 |
/* load unsaved to memory */ |
... | ... |
@@ -419,7 +419,7 @@ redata_unsaved_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
419 | 419 |
return(-1); /* insuf. mem. */ |
420 | 420 |
unsaved->buf=buf; |
421 | 421 |
unsaved->sizebuf=newsize; |
422 |
-#if 1 |
|
422 |
+#if 0 |
|
423 | 423 |
fprintf(stderr,"UNSAVED: ADD realloc: %li\n",(long)newsize); |
424 | 424 |
#endif |
425 | 425 |
} |
... | ... |
@@ -496,7 +496,7 @@ redata_unsaved_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
496 | 496 |
return(-1); /* insuf. mem. */ |
497 | 497 |
unsaved->buf=buf; |
498 | 498 |
unsaved->sizebuf=newsize; |
499 |
-#if 1 |
|
499 |
+#if 0 |
|
500 | 500 |
fprintf(stderr,"UNSAVED: UNADD realloc: %li\n",(long)newsize); |
501 | 501 |
#endif |
502 | 502 |
} |
... | ... |
@@ -514,7 +514,7 @@ redata_unsaved_commit(redata_t *redata, redata_plugin_t *slot,char *filename) |
514 | 514 |
unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
515 | 515 |
if(redata==NULL || slot==NULL || unsaved==NULL || unsaved->unsavedfd==-1) |
516 | 516 |
return(-1); |
517 |
-#if 1 |
|
517 |
+#if 0 |
|
518 | 518 |
if(unsaved->usedbuf>0) |
519 | 519 |
fprintf(stderr,"UNSAVED_COMMITTED\n"); |
520 | 520 |
#endif |
... | ... |
@@ -412,13 +412,16 @@ redata_unsaved_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
412 | 412 |
} |
413 | 413 |
if(k==0) { |
414 | 414 |
/* get mem */ |
415 |
- if((unsaved->sizebuf-unsaved->sizebuf)<maxsize) { |
|
415 |
+ if((unsaved->sizebuf-unsaved->usedbuf)<maxsize) { |
|
416 | 416 |
newsize=(unsaved->sizebuf+maxsize+UNSAVEDGROWSIZE-1)/UNSAVEDGROWSIZE; |
417 | 417 |
newsize*=UNSAVEDGROWSIZE; |
418 | 418 |
if((buf=realloc(unsaved->buf,newsize))==NULL) |
419 | 419 |
return(-1); /* insuf. mem. */ |
420 | 420 |
unsaved->buf=buf; |
421 | 421 |
unsaved->sizebuf=newsize; |
422 |
+#if 1 |
|
423 |
+fprintf(stderr,"UNSAVED: ADD realloc: %li\n",(long)newsize); |
|
424 |
+#endif |
|
422 | 425 |
} |
423 | 426 |
buf=unsaved->buf+unsaved->usedbuf; |
424 | 427 |
} else |
... | ... |
@@ -486,13 +489,16 @@ redata_unsaved_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
486 | 489 |
} |
487 | 490 |
if(k==0) { |
488 | 491 |
/* get mem */ |
489 |
- if((unsaved->sizebuf-unsaved->sizebuf)<maxsize) { |
|
492 |
+ if((unsaved->sizebuf-unsaved->usedbuf)<maxsize) { |
|
490 | 493 |
newsize=(unsaved->sizebuf+maxsize+UNSAVEDGROWSIZE-1)/UNSAVEDGROWSIZE; |
491 | 494 |
newsize*=UNSAVEDGROWSIZE; |
492 | 495 |
if((buf=realloc(unsaved->buf,newsize))==NULL) |
493 | 496 |
return(-1); /* insuf. mem. */ |
494 | 497 |
unsaved->buf=buf; |
495 | 498 |
unsaved->sizebuf=newsize; |
499 |
+#if 1 |
|
500 |
+fprintf(stderr,"UNSAVED: UNADD realloc: %li\n",(long)newsize); |
|
501 |
+#endif |
|
496 | 502 |
} |
497 | 503 |
buf=unsaved->buf+unsaved->usedbuf; |
498 | 504 |
} |
... | ... |
@@ -517,6 +517,7 @@ if(unsaved->usedbuf>0) |
517 | 517 |
close(unsaved->unsavedfd),unsaved->unsavedfd=-1; |
518 | 518 |
if((unsaved_genname(filename,unsname,sizeof(unsname)))!=NULL) |
519 | 519 |
unlink(unsname); /* a corrupted unsaved is of no use, delete it */ |
520 |
+ slot->active=0; |
|
520 | 521 |
return(-1); /* error writing */ |
521 | 522 |
} |
522 | 523 |
} |
... | ... |
@@ -77,6 +77,8 @@ redata_unsaved_unregister(redata_t *redata, redata_plugin_t *slot, char *filenam |
77 | 77 |
if(filename!=NULL && unsaved_genname(filename,unsname,sizeof(unsname))!=NULL) |
78 | 78 |
unlink(unsname); |
79 | 79 |
} |
80 |
+ if(slot->userptr!=NULL) |
|
81 |
+ free(slot->userptr),slot->userptr=NULL; |
|
80 | 82 |
return(0); |
81 | 83 |
} |
82 | 84 |
|
... | ... |
@@ -507,7 +507,8 @@ redata_unsaved_commit(redata_t *redata, redata_plugin_t *slot,char *filename) |
507 | 507 |
if(redata==NULL || slot==NULL || unsaved==NULL || unsaved->unsavedfd==-1) |
508 | 508 |
return(-1); |
509 | 509 |
#if 1 |
510 |
-fprintf(stderr,"UNSAVED_COMMITTED\n"); |
|
510 |
+if(unsaved->usedbuf>0) |
|
511 |
+ fprintf(stderr,"UNSAVED_COMMITTED\n"); |
|
511 | 512 |
#endif |
512 | 513 |
for(nwritten=0;nwritten<unsaved->usedbuf;nwritten+=n) { |
513 | 514 |
if((n=write(unsaved->unsavedfd,unsaved->buf+nwritten,unsaved->usedbuf-nwritten))<0) { |
... | ... |
@@ -28,8 +28,8 @@ |
28 | 28 |
|
29 | 29 |
|
30 | 30 |
|
31 |
-static int redata_unsaved_loadquestion(redata_t *redata, redata_plugin_t *slot,char *filename, char **title, char **body, int *nopts, char **opts[]); |
|
32 |
-static int redata_unsaved_postload(redata_t *redata, redata_plugin_t *slot,char *filename,int questionreply); |
|
31 |
+static int redata_unsaved_loadquestion(redata_t *redata, redata_plugin_t *slot,char *filename); |
|
32 |
+static int redata_unsaved_postload(redata_t *redata, redata_plugin_t *slot,char *filename); |
|
33 | 33 |
static int redata_unsaved_check_gen(redata_t *redata, redata_plugin_t *slot, char *filename); |
34 | 34 |
static char *unsaved_genname(char *filename, char *buf, int bufsize); |
35 | 35 |
static char *ptr_getlong(char *ptr,char *endptr,long *data); |
... | ... |
@@ -58,6 +58,7 @@ redata_unsaved_register(redata_t *redata, redata_plugin_t *slot) |
58 | 58 |
slot->add=redata_unsaved_add; |
59 | 59 |
slot->unadd=redata_unsaved_unadd; |
60 | 60 |
slot->commit=redata_unsaved_commit; |
61 |
+ slot->userptr=unsaved; |
|
61 | 62 |
return(0); |
62 | 63 |
} |
63 | 64 |
|
... | ... |
@@ -205,6 +206,9 @@ redata_unsaved_trunc(redata_t *redata, redata_plugin_t *slot, char *oldfilename, |
205 | 206 |
int |
206 | 207 |
redata_unsaved_truncload(redata_t *redata, redata_plugin_t *slot, char *filename) |
207 | 208 |
{ |
209 |
+#if 1 |
|
210 |
+fprintf(stderr,"UNSAVED: TRUNCLOAD (ignore)\n"); |
|
211 |
+#endif |
|
208 | 212 |
return(redata_unsaved_trunc(redata, slot, NULL, filename)); |
209 | 213 |
} |
210 | 214 |
|
... | ... |
@@ -224,16 +228,28 @@ redata_unsaved_loadappend(redata_t *redata, redata_plugin_t *slot, char *filenam |
224 | 228 |
char endcode; |
225 | 229 |
int flag_multipart; |
226 | 230 |
unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
231 |
+#if 1 |
|
232 |
+fprintf(stderr,"UNSAVED: LOADAPPEND (recover)\n"); |
|
233 |
+#endif |
|
227 | 234 |
if(redata==NULL || slot==NULL || unsaved==NULL || filename==NULL) |
228 | 235 |
return(-1); |
236 |
+#if 1 |
|
237 |
+fprintf(stderr,"UNSAVED: LOADAPPEND pre-check\n"); |
|
238 |
+#endif |
|
229 | 239 |
if((fd=redata_unsaved_check_gen(redata,slot,filename))==-1) |
230 | 240 |
return(-1); /* check failed */ |
241 |
+#if 1 |
|
242 |
+fprintf(stderr,"UNSAVED: LOADAPPEND post-check\n"); |
|
243 |
+#endif |
|
231 | 244 |
if(fstat(fd,&statbuf)!=0 || !S_ISREG(statbuf.st_mode)) { |
232 | 245 |
close(fd),fd=-1; |
233 | 246 |
return(-1); /* couldn't query size or not regular file */ |
234 | 247 |
} |
235 | 248 |
redata_hash(redata,unsaved->initialhash); |
236 |
- headerhashsize=(sizeof(header)-1)+1+128+1; |
|
249 |
+ headerhashsize=(sizeof(header)-1)+128+1; |
|
250 |
+#if 1 |
|
251 |
+fprintf(stderr,"UNSAVED: LOADAPPEND headerhashsize: %li\n",headerhashsize); |
|
252 |
+#endif |
|
237 | 253 |
/* load unsaved to memory */ |
238 | 254 |
if(unsaved->sizebuf<(statbuf.st_size-headerhashsize)) { |
239 | 255 |
if((newptr=realloc(unsaved->buf,(statbuf.st_size-headerhashsize)))==NULL) { |
... | ... |
@@ -254,8 +270,21 @@ redata_unsaved_loadappend(redata_t *redata, redata_plugin_t *slot, char *filenam |
254 | 270 |
} |
255 | 271 |
close(fd),fd=-1; |
256 | 272 |
/* process unsaved data */ |
273 |
+ slot->active=0; |
|
257 | 274 |
endptr=unsaved->buf+unsaved->usedbuf; |
258 | 275 |
for(ptr=unsaved->buf;ptr<endptr;) { |
276 |
+#ifdef DEBUG_PLUGIN_UNSAVED |
|
277 |
+{ |
|
278 |
+int m; |
|
279 |
+fprintf(stderr,"%05X: ",ptr-unsaved->buf); |
|
280 |
+for(m=0;m<16 && (ptr+m)<endptr;m++) |
|
281 |
+ fprintf(stderr,"%02X%s ",((unsigned char *)ptr)[m],(m==7)?" ":""); |
|
282 |
+fprintf(stderr," | "); |
|
283 |
+for(m=0;m<16 && (ptr+m)<endptr;m++) |
|
284 |
+ fprintf(stderr,"%c%s",((((unsigned char *)ptr)[m])<20)?'.':((((unsigned char *)ptr)[m])>126)?'.':((unsigned char *)ptr)[m],(m==7)?" ":""); |
|
285 |
+fprintf(stderr,"\n"); |
|
286 |
+} |
|
287 |
+#endif |
|
259 | 288 |
if((ptr=ptr_getchar(ptr,endptr,&actioncode))==NULL) |
260 | 289 |
return(-1); /* no space for action char */ |
261 | 290 |
/* multipart example: A10+$aj$%$% >> insert "aj$" into pos 10 */ |
... | ... |
@@ -322,7 +351,8 @@ redata_unsaved_loadappend(redata_t *redata, redata_plugin_t *slot, char *filenam |
322 | 351 |
return(-1); /* corrupted undobuf */ |
323 | 352 |
} |
324 | 353 |
} |
325 |
- return(-1); |
|
354 |
+ slot->active=1; |
|
355 |
+ return(0); |
|
326 | 356 |
} |
327 | 357 |
|
328 | 358 |
int |
... | ... |
@@ -337,7 +367,7 @@ redata_unsaved_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
337 | 367 |
undostack_t *stack; |
338 | 368 |
unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
339 | 369 |
stack=redata_getstack(redata,undo); |
340 |
- if(redata==NULL || slot==NULL || unsaved==NULL || undo==NULL || stack==NULL) |
|
370 |
+ if(redata==NULL || slot==NULL || unsaved==NULL || undo==NULL || stack==NULL || slot->active==0) |
|
341 | 371 |
return(-1); /* sanity check failed */ |
342 | 372 |
/* syntax (see loadappend): A<pos><+?><sep><text><sep>[<+?><sep><text><sep>[...]] */ |
343 | 373 |
if(undo->type!='A' && undo->type!='D' && undo->type!='M') |
... | ... |
@@ -389,7 +419,8 @@ redata_unsaved_add(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
389 | 419 |
unsaved->sizebuf=newsize; |
390 | 420 |
} |
391 | 421 |
buf=unsaved->buf+unsaved->usedbuf; |
392 |
- } |
|
422 |
+ } else |
|
423 |
+ unsaved->usedbuf+=maxsize; |
|
393 | 424 |
} |
394 | 425 |
return(0); |
395 | 426 |
} |
... | ... |
@@ -407,7 +438,7 @@ redata_unsaved_unadd(redata_t *redata, redata_plugin_t *slot, undo_t *undo) |
407 | 438 |
undostack_t *stack; |
408 | 439 |
unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
409 | 440 |
stack=redata_getstack(redata,undo); |
410 |
- if(redata==NULL || slot==NULL || unsaved==NULL || undo==NULL || stack==NULL) |
|
441 |
+ if(redata==NULL || slot==NULL || unsaved==NULL || undo==NULL || stack==NULL || slot->active==0) |
|
411 | 442 |
return(-1); /* sanity check failed */ |
412 | 443 |
/* syntax (see loadappend): A<pos><+?><sep><text><sep>[<+?><sep><text><sep>[...]] */ |
413 | 444 |
if(undo->type!='A' && undo->type!='D' && undo->type!='M') |
... | ... |
@@ -475,6 +506,9 @@ redata_unsaved_commit(redata_t *redata, redata_plugin_t *slot,char *filename) |
475 | 506 |
unsaved_t *unsaved=(unsaved_t *) ((slot!=NULL)?(slot->userptr):NULL); |
476 | 507 |
if(redata==NULL || slot==NULL || unsaved==NULL || unsaved->unsavedfd==-1) |
477 | 508 |
return(-1); |
509 |
+#if 1 |
|
510 |
+fprintf(stderr,"UNSAVED_COMMITTED\n"); |
|
511 |
+#endif |
|
478 | 512 |
for(nwritten=0;nwritten<unsaved->usedbuf;nwritten+=n) { |
479 | 513 |
if((n=write(unsaved->unsavedfd,unsaved->buf+nwritten,unsaved->usedbuf-nwritten))<0) { |
480 | 514 |
close(unsaved->unsavedfd),unsaved->unsavedfd=-1; |
... | ... |
@@ -488,30 +522,47 @@ redata_unsaved_commit(redata_t *redata, redata_plugin_t *slot,char *filename) |
488 | 522 |
} |
489 | 523 |
|
490 | 524 |
static int |
491 |
-redata_unsaved_loadquestion(redata_t *redata, redata_plugin_t *slot,char *filename, char **title, char **body, int *nopts, char **opts[]) |
|
525 |
+redata_unsaved_loadquestion(redata_t *redata, redata_plugin_t *slot,char *filename) |
|
492 | 526 |
{ |
493 | 527 |
static char mytitle[]={"Unsaved data from a previous session detected"}; |
494 | 528 |
static char mybody[]={"The file you're trying to load has some unsaved data from a previous session. I can recover the data. What do you want to do?"}; |
495 | 529 |
static char *myopts[]={"Recover unsaved data (safest option)","Don't use old unsaved data, delete old unsaved data (if you're sure what you're doing)"}; |
496 |
- if(redata==NULL || slot==NULL || filename==NULL || title==NULL || body==NULL || nopts==NULL || opts==NULL) |
|
530 |
+ static char mytitleshort[]={"Unsaved data found"}; |
|
531 |
+ static char mybodyshort[]={"Should try to recover the data?"}; |
|
532 |
+ static char *myoptsshort[]={"Recover","Ignore it"}; |
|
533 |
+ question_t *q; |
|
534 |
+ if(redata==NULL || slot==NULL || filename==NULL) |
|
497 | 535 |
return(-1); /* sanity check failed */ |
536 |
+ q=&(slot->question); |
|
537 |
+ q->active=0; |
|
498 | 538 |
if(redata_unsaved_check(redata,slot,filename)==-1) |
499 |
- return(-1); /* no unsaved data on disk */ |
|
500 |
- *title=mytitle; |
|
501 |
- *body=mybody; |
|
502 |
- *opts=myopts; |
|
503 |
- *nopts=2; |
|
539 |
+ return(0); /* no unsaved data on disk */ |
|
540 |
+ q->active=1; |
|
541 |
+ q->title=mytitle; |
|
542 |
+ q->titleshort=mytitleshort; |
|
543 |
+ q->body=mybody; |
|
544 |
+ q->bodyshort=mybodyshort; |
|
545 |
+ q->opts=myopts; |
|
546 |
+ q->optsshort=myoptsshort; |
|
547 |
+ q->nopts=2; |
|
548 |
+ q->defaultoption=1; |
|
549 |
+ q->selectedoption=-1; |
|
504 | 550 |
return(0); |
505 | 551 |
} |
506 | 552 |
|
507 | 553 |
static int |
508 |
-redata_unsaved_postload(redata_t *redata, redata_plugin_t *slot,char *filename,int questionreply) |
|
554 |
+redata_unsaved_postload(redata_t *redata, redata_plugin_t *slot,char *filename) |
|
509 | 555 |
{ |
556 |
+#warning XXX TODO: add errordesc parameter, so that the user can see what happened. |
|
557 |
+ int selectedoption; |
|
558 |
+ if(redata==NULL || slot==NULL || filename==NULL) |
|
559 |
+ return(-1); /* sanity check failed */ |
|
510 | 560 |
/* questionreply is from loadquestion, specifically the selected element in the array "opts" */ |
511 |
- if(questionreply==0) /* recover */ |
|
512 |
- return(redata_unsaved_loadappend(redata, slot, filename)); |
|
513 |
- else if(questionreply==1 || questionreply==-1) /* delete unsaved data */ |
|
561 |
+ selectedoption=slot->question.selectedoption; |
|
562 |
+ if(slot->question.active==0 || selectedoption==1 || selectedoption==-1) /* delete unsaved data */ |
|
514 | 563 |
return(redata_unsaved_truncload(redata, slot, filename)); |
564 |
+ else if(selectedoption==0) /* recover */ |
|
565 |
+ return(redata_unsaved_loadappend(redata, slot, filename)); |
|
515 | 566 |
return(-1); |
516 | 567 |
} |
517 | 568 |
|
... | ... |
@@ -28,6 +28,8 @@ |
28 | 28 |
|
29 | 29 |
|
30 | 30 |
|
31 |
+static int redata_unsaved_loadquestion(redata_t *redata, redata_plugin_t *slot,char *filename, char **title, char **body, int *nopts, char **opts[]); |
|
32 |
+static int redata_unsaved_postload(redata_t *redata, redata_plugin_t *slot,char *filename,int questionreply); |
|
31 | 33 |
static int redata_unsaved_check_gen(redata_t *redata, redata_plugin_t *slot, char *filename); |
32 | 34 |
static char *unsaved_genname(char *filename, char *buf, int bufsize); |
33 | 35 |
static char *ptr_getlong(char *ptr,char *endptr,long *data); |
... | ... |
@@ -46,15 +48,16 @@ redata_unsaved_register(redata_t *redata, redata_plugin_t *slot) |
46 | 48 |
memset(unsaved,0,sizeof(unsaved_t)); |
47 | 49 |
unsaved->unsavedfd=-1; |
48 | 50 |
unsaved->sizebuf=unsaved->usedbuf=0; |
51 |
+ strncpy(slot->name,"unsaved",sizeof(slot->name)); |
|
52 |
+ slot->name[sizeof(slot->name)-1]='\0'; |
|
49 | 53 |
slot->unregister=redata_unsaved_unregister; |
50 |
- slot->checkload=redata_unsaved_check; |
|
54 |
+ slot->loadquestion=redata_unsaved_loadquestion; |
|
51 | 55 |
slot->wipe=redata_unsaved_wipe; |
52 |
- slot->postload=redata_unsaved_loadappend; |
|
53 |
- slot->truncload=redata_unsaved_truncload; |
|
56 |
+ slot->postload=redata_unsaved_postload; |
|
54 | 57 |
slot->postsave=redata_unsaved_trunc; |
55 | 58 |
slot->add=redata_unsaved_add; |
56 | 59 |
slot->unadd=redata_unsaved_unadd; |
57 |
- slot->flags=PLUGIN_CHECKUSERCONFIRM; |
|
60 |
+ slot->commit=redata_unsaved_commit; |
|
58 | 61 |
return(0); |
59 | 62 |
} |
60 | 63 |
|
... | ... |
@@ -484,6 +487,35 @@ redata_unsaved_commit(redata_t *redata, redata_plugin_t *slot,char *filename) |
484 | 487 |
return(0); |
485 | 488 |
} |
486 | 489 |
|
490 |
+static int |
|
491 |
+redata_unsaved_loadquestion(redata_t *redata, redata_plugin_t *slot,char *filename, char **title, char **body, int *nopts, char **opts[]) |
|
492 |
+{ |
|
493 |
+ static char mytitle[]={"Unsaved data from a previous session detected"}; |
|
494 |
+ static char mybody[]={"The file you're trying to load has some unsaved data from a previous session. I can recover the data. What do you want to do?"}; |
|
495 |
+ static char *myopts[]={"Recover unsaved data (safest option)","Don't use old unsaved data, delete old unsaved data (if you're sure what you're doing)"}; |
|
496 |
+ if(redata==NULL || slot==NULL || filename==NULL || title==NULL || body==NULL || nopts==NULL || opts==NULL) |
|
497 |
+ return(-1); /* sanity check failed */ |
|
498 |
+ if(redata_unsaved_check(redata,slot,filename)==-1) |
|
499 |
+ return(-1); /* no unsaved data on disk */ |
|
500 |
+ *title=mytitle; |
|
501 |
+ *body=mybody; |
|
502 |
+ *opts=myopts; |
|
503 |
+ *nopts=2; |
|
504 |
+ return(0); |
|
505 |
+} |
|
506 |
+ |
|
507 |
+static int |
|
508 |
+redata_unsaved_postload(redata_t *redata, redata_plugin_t *slot,char *filename,int questionreply) |
|
509 |
+{ |
|
510 |
+ /* questionreply is from loadquestion, specifically the selected element in the array "opts" */ |
|
511 |
+ if(questionreply==0) /* recover */ |
|
512 |
+ return(redata_unsaved_loadappend(redata, slot, filename)); |
|
513 |
+ else if(questionreply==1 || questionreply==-1) /* delete unsaved data */ |
|
514 |
+ return(redata_unsaved_truncload(redata, slot, filename)); |
|
515 |
+ return(-1); |
|
516 |
+} |
|
517 |
+ |
|
518 |
+ |
|
487 | 519 |
static char * |
488 | 520 |
unsaved_genname(char *filename, char *buf, int bufsize) |
489 | 521 |
{ |
1 | 1 |
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 |
+ |