diff options
Diffstat (limited to 'apps/plugins/text_viewer/tv_settings.c')
-rw-r--r-- | apps/plugins/text_viewer/tv_settings.c | 127 |
1 files changed, 83 insertions, 44 deletions
diff --git a/apps/plugins/text_viewer/tv_settings.c b/apps/plugins/text_viewer/tv_settings.c index 3004ac3d60..20e8212147 100644 --- a/apps/plugins/text_viewer/tv_settings.c +++ b/apps/plugins/text_viewer/tv_settings.c | |||
@@ -120,6 +120,10 @@ | |||
120 | #define TV_SETTINGS_FIRST_VERSION 0x32 | 120 | #define TV_SETTINGS_FIRST_VERSION 0x32 |
121 | 121 | ||
122 | #define TV_PREFERENCES_SIZE (28 + MAX_PATH) | 122 | #define TV_PREFERENCES_SIZE (28 + MAX_PATH) |
123 | #define TV_MAX_FILE_RECORD_SIZE (MAX_PATH+2 + TV_PREFERENCES_SIZE + TV_MAX_BOOKMARKS*SERIALIZE_BOOKMARK_SIZE+1) | ||
124 | |||
125 | static off_t stored_preferences_offset = 0; | ||
126 | static int stored_preferences_size = 0; | ||
123 | 127 | ||
124 | /* ---------------------------------------------------------------------------- | 128 | /* ---------------------------------------------------------------------------- |
125 | * read/write the preferences | 129 | * read/write the preferences |
@@ -220,9 +224,8 @@ static bool tv_read_preferences(int pfd, int version, struct tv_preferences *pre | |||
220 | return true; | 224 | return true; |
221 | } | 225 | } |
222 | 226 | ||
223 | static bool tv_write_preferences(int pfd, const struct tv_preferences *prefs) | 227 | static void tv_serialize_preferences(unsigned char *buf, const struct tv_preferences *prefs) |
224 | { | 228 | { |
225 | unsigned char buf[TV_PREFERENCES_SIZE]; | ||
226 | unsigned char *p = buf; | 229 | unsigned char *p = buf; |
227 | 230 | ||
228 | rb->memset(buf, 0, TV_PREFERENCES_SIZE); | 231 | rb->memset(buf, 0, TV_PREFERENCES_SIZE); |
@@ -248,6 +251,13 @@ static bool tv_write_preferences(int pfd, const struct tv_preferences *prefs) | |||
248 | #ifdef HAVE_LCD_BITMAP | 251 | #ifdef HAVE_LCD_BITMAP |
249 | rb->strlcpy(buf + 28, prefs->font_name, MAX_PATH); | 252 | rb->strlcpy(buf + 28, prefs->font_name, MAX_PATH); |
250 | #endif | 253 | #endif |
254 | } | ||
255 | |||
256 | static bool tv_write_preferences(int pfd, const struct tv_preferences *prefs) | ||
257 | { | ||
258 | unsigned char buf[TV_PREFERENCES_SIZE]; | ||
259 | |||
260 | tv_serialize_preferences(buf, prefs); | ||
251 | 261 | ||
252 | return (rb->write(pfd, buf, TV_PREFERENCES_SIZE) >= 0); | 262 | return (rb->write(pfd, buf, TV_PREFERENCES_SIZE) >= 0); |
253 | } | 263 | } |
@@ -427,6 +437,7 @@ bool tv_load_settings(const unsigned char *file_name) | |||
427 | int version; | 437 | int version; |
428 | unsigned int size; | 438 | unsigned int size; |
429 | struct tv_preferences prefs; | 439 | struct tv_preferences prefs; |
440 | off_t current_pref_offset; | ||
430 | 441 | ||
431 | if (!rb->file_exists(TV_SETTINGS_FILE)) | 442 | if (!rb->file_exists(TV_SETTINGS_FILE)) |
432 | tv_convert_settings_file(); | 443 | tv_convert_settings_file(); |
@@ -438,6 +449,8 @@ bool tv_load_settings(const unsigned char *file_name) | |||
438 | { | 449 | { |
439 | version = buf[TV_SETTINGS_HEADER_SIZE - 1] - TV_SETTINGS_FIRST_VERSION; | 450 | version = buf[TV_SETTINGS_HEADER_SIZE - 1] - TV_SETTINGS_FIRST_VERSION; |
440 | fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE+1]; | 451 | fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE+1]; |
452 | |||
453 | current_pref_offset = rb->lseek(fd, 0, SEEK_CUR); | ||
441 | 454 | ||
442 | for (i = 0; i < fcount; i++) | 455 | for (i = 0; i < fcount; i++) |
443 | { | 456 | { |
@@ -448,10 +461,15 @@ bool tv_load_settings(const unsigned char *file_name) | |||
448 | { | 461 | { |
449 | if (tv_read_preferences(fd, version, &prefs)) | 462 | if (tv_read_preferences(fd, version, &prefs)) |
450 | res = tv_deserialize_bookmarks(fd); | 463 | res = tv_deserialize_bookmarks(fd); |
464 | |||
465 | if (res) { | ||
466 | stored_preferences_offset = current_pref_offset; | ||
467 | stored_preferences_size = size; | ||
468 | } | ||
451 | 469 | ||
452 | break; | 470 | break; |
453 | } | 471 | } |
454 | rb->lseek(fd, size, SEEK_CUR); | 472 | current_pref_offset = rb->lseek(fd, size, SEEK_CUR); |
455 | } | 473 | } |
456 | } | 474 | } |
457 | rb->close(fd); | 475 | rb->close(fd); |
@@ -473,38 +491,74 @@ bool tv_load_settings(const unsigned char *file_name) | |||
473 | return tv_set_preferences(&prefs); | 491 | return tv_set_preferences(&prefs); |
474 | } | 492 | } |
475 | 493 | ||
476 | static bool tv_copy_settings(int sfd, int dfd, int size) | ||
477 | { | ||
478 | unsigned char buf[MAX_PATH]; | ||
479 | int i = size / MAX_PATH; | ||
480 | |||
481 | size %= MAX_PATH; | ||
482 | |||
483 | while (i--) | ||
484 | { | ||
485 | if ((rb->read(sfd, buf, MAX_PATH) < 0) || (rb->write(dfd, buf, MAX_PATH) < 0)) | ||
486 | return false; | ||
487 | } | ||
488 | |||
489 | return ((rb->read(sfd, buf, size) >= 0) && (rb->write(dfd, buf, size) >= 0)); | ||
490 | } | ||
491 | |||
492 | bool tv_save_settings(void) | 494 | bool tv_save_settings(void) |
493 | { | 495 | { |
494 | unsigned char buf[MAX_PATH+2]; | 496 | unsigned char buf[TV_MAX_FILE_RECORD_SIZE]; |
497 | unsigned char preferences_buf[TV_MAX_FILE_RECORD_SIZE]; | ||
495 | unsigned int fcount = 0; | 498 | unsigned int fcount = 0; |
499 | unsigned int new_fcount = 0; | ||
496 | unsigned int i; | 500 | unsigned int i; |
497 | int ofd = -1; | 501 | int ofd = -1; |
498 | int tfd; | 502 | int tfd; |
499 | off_t size; | 503 | off_t size; |
504 | off_t preferences_buf_size; | ||
500 | bool res = true; | 505 | bool res = true; |
501 | 506 | ||
502 | /* add reading page to bookmarks */ | 507 | /* add reading page to bookmarks */ |
503 | tv_create_system_bookmark(); | 508 | tv_create_system_bookmark(); |
504 | 509 | ||
510 | /* storing preferences record in memory */ | ||
511 | rb->memset(preferences_buf, 0, MAX_PATH); | ||
512 | rb->strlcpy(preferences_buf, preferences->file_name, MAX_PATH); | ||
513 | preferences_buf_size = MAX_PATH + 2; | ||
514 | |||
515 | tv_serialize_preferences(preferences_buf + preferences_buf_size, preferences); | ||
516 | preferences_buf_size += TV_PREFERENCES_SIZE; | ||
517 | preferences_buf_size += tv_serialize_bookmarks(preferences_buf + preferences_buf_size); | ||
518 | size = preferences_buf_size - (MAX_PATH + 2); | ||
519 | preferences_buf[MAX_PATH + 0] = size >> 8; | ||
520 | preferences_buf[MAX_PATH + 1] = size; | ||
521 | |||
522 | |||
523 | /* Just overwrite preferences if possible*/ | ||
524 | if ( (stored_preferences_offset > 0) && (stored_preferences_size == size) ) | ||
525 | { | ||
526 | DEBUGF("Saving preferences: overwriting\n"); | ||
527 | if ((tfd = rb->open(TV_SETTINGS_FILE, O_WRONLY)) < 0) | ||
528 | return false; | ||
529 | rb->lseek(tfd, stored_preferences_offset, SEEK_SET); | ||
530 | res = (rb->write(tfd, preferences_buf, preferences_buf_size) >= 0); | ||
531 | rb->close(tfd); | ||
532 | return res; | ||
533 | } | ||
534 | |||
535 | |||
505 | if (!rb->file_exists(TV_SETTINGS_FILE)) | 536 | if (!rb->file_exists(TV_SETTINGS_FILE)) |
506 | tv_convert_settings_file(); | 537 | tv_convert_settings_file(); |
507 | 538 | ||
539 | |||
540 | /* Try appending preferences */ | ||
541 | if ( (stored_preferences_offset == 0) && | ||
542 | ( (tfd = rb->open(TV_SETTINGS_FILE, O_RDWR)) >= 0) ) | ||
543 | { | ||
544 | DEBUGF("Saving preferences: appending\n"); | ||
545 | rb->lseek(tfd, 0, SEEK_END); | ||
546 | if (rb->write(tfd, preferences_buf, preferences_buf_size) < 0) | ||
547 | return false; | ||
548 | |||
549 | rb->lseek(tfd, TV_SETTINGS_HEADER_SIZE, SEEK_SET); | ||
550 | rb->read(tfd, buf, 2); | ||
551 | fcount = (buf[0] << 8) | buf[1]; | ||
552 | fcount ++; | ||
553 | buf[0] = fcount >> 8; | ||
554 | buf[1] = fcount; | ||
555 | rb->lseek(tfd, TV_SETTINGS_HEADER_SIZE, SEEK_SET); | ||
556 | res = rb->write(tfd, buf, 2) >= 0; | ||
557 | |||
558 | rb->close(tfd); | ||
559 | return res; | ||
560 | } | ||
561 | |||
508 | /* create header for the temporary file */ | 562 | /* create header for the temporary file */ |
509 | rb->memcpy(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1); | 563 | rb->memcpy(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1); |
510 | buf[TV_SETTINGS_HEADER_SIZE - 1] = TV_SETTINGS_VERSION; | 564 | buf[TV_SETTINGS_HEADER_SIZE - 1] = TV_SETTINGS_VERSION; |
@@ -539,12 +593,13 @@ bool tv_save_settings(void) | |||
539 | rb->lseek(ofd, size, SEEK_CUR); | 593 | rb->lseek(ofd, size, SEEK_CUR); |
540 | else | 594 | else |
541 | { | 595 | { |
542 | if ((rb->write(tfd, buf, MAX_PATH + 2) < 0) || | 596 | if ((rb->read(ofd, buf + (MAX_PATH + 2), size) < 0) || |
543 | (!tv_copy_settings(ofd, tfd, size))) | 597 | (rb->write(tfd, buf, size + MAX_PATH + 2) < 0)) |
544 | { | 598 | { |
545 | res = false; | 599 | res = false; |
546 | break; | 600 | break; |
547 | } | 601 | } |
602 | new_fcount++; | ||
548 | } | 603 | } |
549 | } | 604 | } |
550 | } | 605 | } |
@@ -555,31 +610,15 @@ bool tv_save_settings(void) | |||
555 | { | 610 | { |
556 | /* save to current read file's preferences and bookmarks */ | 611 | /* save to current read file's preferences and bookmarks */ |
557 | res = false; | 612 | res = false; |
558 | rb->memset(buf, 0, MAX_PATH); | ||
559 | rb->strlcpy(buf, preferences->file_name, MAX_PATH); | ||
560 | 613 | ||
561 | if (rb->write(tfd, buf, MAX_PATH + 2) >= 0) | 614 | if (rb->write(tfd, preferences_buf, preferences_buf_size) >= 0) |
562 | { | 615 | { |
563 | if (tv_write_preferences(tfd, preferences)) | 616 | rb->lseek(tfd, TV_SETTINGS_HEADER_SIZE, SEEK_SET); |
564 | { | ||
565 | size = tv_serialize_bookmarks(tfd); | ||
566 | if (size > 0) | ||
567 | { | ||
568 | size += TV_PREFERENCES_SIZE; | ||
569 | rb->lseek(tfd, -size - 2, SEEK_CUR); | ||
570 | buf[0] = size >> 8; | ||
571 | buf[1] = size; | ||
572 | if (rb->write(tfd, buf, 2) >= 0) | ||
573 | { | ||
574 | rb->lseek(tfd, TV_SETTINGS_HEADER_SIZE, SEEK_SET); | ||
575 | 617 | ||
576 | fcount++; | 618 | new_fcount++; |
577 | buf[0] = fcount >> 8; | 619 | buf[0] = new_fcount >> 8; |
578 | buf[1] = fcount; | 620 | buf[1] = new_fcount; |
579 | res = (rb->write(tfd, buf, 2) >= 0); | 621 | res = (rb->write(tfd, buf, 2) >= 0); |
580 | } | ||
581 | } | ||
582 | } | ||
583 | } | 622 | } |
584 | } | 623 | } |
585 | rb->close(tfd); | 624 | rb->close(tfd); |