Commit FS#11799 by Alexander Meshcheryakov. Improves the text viewer plugin to write to the disk less often, and correct several minor bugs.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28833 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Giacomelli 2010-12-14 21:33:45 +00:00
parent ee4ea4266b
commit 990cbf302e
9 changed files with 131 additions and 64 deletions

View file

@ -28,6 +28,9 @@
#include "tv_settings.h"
#include "tv_window.h"
bool bookmarks_changed = false;
bool scrolled = false;
bool tv_init_action(unsigned char **buf, size_t *size)
{
/* initialize bookmarks and window modules */
@ -36,10 +39,6 @@ bool tv_init_action(unsigned char **buf, size_t *size)
static void tv_finalize_action(void)
{
/* save preference and bookmarks */
if (!tv_save_settings())
rb->splash(HZ, "Can't save preferences and bookmarks");
/* finalize bookmark modules */
tv_finalize_bookmark();
@ -50,8 +49,19 @@ static void tv_finalize_action(void)
void tv_exit(void)
{
/* save preference and bookmarks */
if (!tv_save_settings())
rb->splash(HZ, "Can't save preferences and bookmarks");
DEBUGF("preferences_changed=%d\tbookmarks_changed=%d\tscrolled=%d\n",preferences_changed,bookmarks_changed,scrolled);
if ( preferences_changed || bookmarks_changed
#ifndef HAVE_DISK_STORAGE
|| scrolled
#endif
)
{
DEBUGF("Saving settings\n");
if (!tv_save_settings())
rb->splash(HZ, "Can't save preferences and bookmarks");
}
else
DEBUGF("Skip saving settings\n");
/* finalize modules */
tv_finalize_action();
@ -95,6 +105,7 @@ void tv_scroll_up(unsigned mode)
#endif
}
tv_move_screen(offset_page, offset_line, SEEK_CUR);
scrolled = true;
}
void tv_scroll_down(unsigned mode)
@ -111,6 +122,7 @@ void tv_scroll_down(unsigned mode)
#endif
}
tv_move_screen(offset_page, offset_line, SEEK_CUR);
scrolled = true;
}
void tv_scroll_left(unsigned mode)
@ -130,6 +142,7 @@ void tv_scroll_left(unsigned mode)
offset_window--;
}
tv_move_window(offset_window, offset_column);
scrolled = true;
}
void tv_scroll_right(unsigned mode)
@ -149,6 +162,7 @@ void tv_scroll_right(unsigned mode)
offset_window++;
}
tv_move_window(offset_window, offset_column);
scrolled = true;
}
void tv_top(void)
@ -186,4 +200,5 @@ unsigned tv_menu(void)
void tv_add_or_remove_bookmark(void)
{
tv_toggle_bookmark();
bookmarks_changed = true;
}

View file

@ -32,7 +32,6 @@ enum {
TV_BOOKMARK_USER = 2,
};
#define SERIALIZE_BOOKMARK_SIZE 8
struct tv_bookmark_info {
struct tv_screen_pos pos;
@ -287,11 +286,8 @@ bool tv_deserialize_bookmarks(int fd)
return res;
}
static bool tv_write_bookmark_info(int fd, const struct tv_bookmark_info *b)
static void tv_write_bookmark_info(unsigned char *p, const struct tv_bookmark_info *b)
{
unsigned char buf[SERIALIZE_BOOKMARK_SIZE];
unsigned char *p = buf;
*p++ = b->pos.file_pos >> 24;
*p++ = b->pos.file_pos >> 16;
*p++ = b->pos.file_pos >> 8;
@ -302,21 +298,17 @@ static bool tv_write_bookmark_info(int fd, const struct tv_bookmark_info *b)
*p++ = b->pos.line;
*p = b->flag;
return (rb->write(fd, buf, SERIALIZE_BOOKMARK_SIZE) >= 0);
}
int tv_serialize_bookmarks(int fd)
int tv_serialize_bookmarks(unsigned char *buf)
{
int i;
if (rb->write(fd, &bookmark_count, 1) < 0)
return 0;
buf[0] = bookmark_count;
for (i = 0; i < bookmark_count; i++)
{
if (!tv_write_bookmark_info(fd, &bookmarks[i]))
break;
tv_write_bookmark_info(buf + i * SERIALIZE_BOOKMARK_SIZE + 1, &bookmarks[i]);
}
return i * SERIALIZE_BOOKMARK_SIZE + 1;
}

View file

@ -29,6 +29,7 @@
/* Maximum amount of register possible bookmarks */
#define TV_MAX_BOOKMARKS 16
#define SERIALIZE_BOOKMARK_SIZE 8
/*
* initialize the bookmark module
@ -83,7 +84,7 @@ void tv_create_system_bookmark(void);
* Return
* the size of the result
*/
int tv_serialize_bookmarks(int fd);
int tv_serialize_bookmarks(unsigned char *buf);
/*
* deserialize the bookmark array

View file

@ -329,6 +329,8 @@ unsigned tv_display_menu(void)
case 1: /* change settings */
tv_copy_preferences(&new_prefs);
result = tv_options_menu();
if (tv_compare_preferences(&new_prefs))
preferences_changed = true;
if (!tv_set_preferences(&new_prefs))
result = TV_MENU_RESULT_ERROR;
break;

View file

@ -28,6 +28,8 @@ static struct tv_preferences prefs;
/* read-only preferences pointer, for access by other files */
const struct tv_preferences * const preferences = &prefs;
bool preferences_changed = false;
static int listner_count = 0;
#define TV_MAX_LISTNERS 5
@ -91,6 +93,11 @@ void tv_copy_preferences(struct tv_preferences *copy_prefs)
rb->memcpy(copy_prefs, preferences, sizeof(struct tv_preferences));
}
bool tv_compare_preferences(struct tv_preferences *copy_prefs)
{
return rb->memcmp(copy_prefs, preferences, sizeof(struct tv_preferences)) != 0;
}
void tv_set_default_preferences(struct tv_preferences *p)
{
p->word_mode = WM_WRAP;

View file

@ -104,6 +104,7 @@ struct tv_preferences {
* global pointer to the preferences (read-only)
*/
extern const struct tv_preferences * const preferences;
extern bool preferences_changed;
/*
* change the preferences
@ -125,6 +126,15 @@ bool tv_set_preferences(const struct tv_preferences *new_prefs);
*/
void tv_copy_preferences(struct tv_preferences *copy_prefs);
/*
* compare the preferences structs (binary)
*
* return
* true differs
* false identical
*/
bool tv_compare_preferences(struct tv_preferences *copy_prefs);
/*
* set the default settings
*

View file

@ -120,6 +120,10 @@
#define TV_SETTINGS_FIRST_VERSION 0x32
#define TV_PREFERENCES_SIZE (28 + MAX_PATH)
#define TV_MAX_FILE_RECORD_SIZE (MAX_PATH+2 + TV_PREFERENCES_SIZE + TV_MAX_BOOKMARKS*SERIALIZE_BOOKMARK_SIZE+1)
static off_t stored_preferences_offset = 0;
static int stored_preferences_size = 0;
/* ----------------------------------------------------------------------------
* read/write the preferences
@ -220,9 +224,8 @@ static bool tv_read_preferences(int pfd, int version, struct tv_preferences *pre
return true;
}
static bool tv_write_preferences(int pfd, const struct tv_preferences *prefs)
static void tv_serialize_preferences(unsigned char *buf, const struct tv_preferences *prefs)
{
unsigned char buf[TV_PREFERENCES_SIZE];
unsigned char *p = buf;
rb->memset(buf, 0, TV_PREFERENCES_SIZE);
@ -248,6 +251,13 @@ static bool tv_write_preferences(int pfd, const struct tv_preferences *prefs)
#ifdef HAVE_LCD_BITMAP
rb->strlcpy(buf + 28, prefs->font_name, MAX_PATH);
#endif
}
static bool tv_write_preferences(int pfd, const struct tv_preferences *prefs)
{
unsigned char buf[TV_PREFERENCES_SIZE];
tv_serialize_preferences(buf, prefs);
return (rb->write(pfd, buf, TV_PREFERENCES_SIZE) >= 0);
}
@ -427,6 +437,7 @@ bool tv_load_settings(const unsigned char *file_name)
int version;
unsigned int size;
struct tv_preferences prefs;
off_t current_pref_offset;
if (!rb->file_exists(TV_SETTINGS_FILE))
tv_convert_settings_file();
@ -438,6 +449,8 @@ bool tv_load_settings(const unsigned char *file_name)
{
version = buf[TV_SETTINGS_HEADER_SIZE - 1] - TV_SETTINGS_FIRST_VERSION;
fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE+1];
current_pref_offset = rb->lseek(fd, 0, SEEK_CUR);
for (i = 0; i < fcount; i++)
{
@ -448,10 +461,15 @@ bool tv_load_settings(const unsigned char *file_name)
{
if (tv_read_preferences(fd, version, &prefs))
res = tv_deserialize_bookmarks(fd);
if (res) {
stored_preferences_offset = current_pref_offset;
stored_preferences_size = size;
}
break;
}
rb->lseek(fd, size, SEEK_CUR);
current_pref_offset = rb->lseek(fd, size, SEEK_CUR);
}
}
rb->close(fd);
@ -473,38 +491,74 @@ bool tv_load_settings(const unsigned char *file_name)
return tv_set_preferences(&prefs);
}
static bool tv_copy_settings(int sfd, int dfd, int size)
{
unsigned char buf[MAX_PATH];
int i = size / MAX_PATH;
size %= MAX_PATH;
while (i--)
{
if ((rb->read(sfd, buf, MAX_PATH) < 0) || (rb->write(dfd, buf, MAX_PATH) < 0))
return false;
}
return ((rb->read(sfd, buf, size) >= 0) && (rb->write(dfd, buf, size) >= 0));
}
bool tv_save_settings(void)
{
unsigned char buf[MAX_PATH+2];
unsigned char buf[TV_MAX_FILE_RECORD_SIZE];
unsigned char preferences_buf[TV_MAX_FILE_RECORD_SIZE];
unsigned int fcount = 0;
unsigned int new_fcount = 0;
unsigned int i;
int ofd = -1;
int tfd;
off_t size;
off_t preferences_buf_size;
bool res = true;
/* add reading page to bookmarks */
tv_create_system_bookmark();
/* storing preferences record in memory */
rb->memset(preferences_buf, 0, MAX_PATH);
rb->strlcpy(preferences_buf, preferences->file_name, MAX_PATH);
preferences_buf_size = MAX_PATH + 2;
tv_serialize_preferences(preferences_buf + preferences_buf_size, preferences);
preferences_buf_size += TV_PREFERENCES_SIZE;
preferences_buf_size += tv_serialize_bookmarks(preferences_buf + preferences_buf_size);
size = preferences_buf_size - (MAX_PATH + 2);
preferences_buf[MAX_PATH + 0] = size >> 8;
preferences_buf[MAX_PATH + 1] = size;
/* Just overwrite preferences if possible*/
if ( (stored_preferences_offset > 0) && (stored_preferences_size == size) )
{
DEBUGF("Saving preferences: overwriting\n");
if ((tfd = rb->open(TV_SETTINGS_FILE, O_WRONLY)) < 0)
return false;
rb->lseek(tfd, stored_preferences_offset, SEEK_SET);
res = (rb->write(tfd, preferences_buf, preferences_buf_size) >= 0);
rb->close(tfd);
return res;
}
if (!rb->file_exists(TV_SETTINGS_FILE))
tv_convert_settings_file();
/* Try appending preferences */
if ( (stored_preferences_offset == 0) &&
( (tfd = rb->open(TV_SETTINGS_FILE, O_RDWR)) >= 0) )
{
DEBUGF("Saving preferences: appending\n");
rb->lseek(tfd, 0, SEEK_END);
if (rb->write(tfd, preferences_buf, preferences_buf_size) < 0)
return false;
rb->lseek(tfd, TV_SETTINGS_HEADER_SIZE, SEEK_SET);
rb->read(tfd, buf, 2);
fcount = (buf[0] << 8) | buf[1];
fcount ++;
buf[0] = fcount >> 8;
buf[1] = fcount;
rb->lseek(tfd, TV_SETTINGS_HEADER_SIZE, SEEK_SET);
res = rb->write(tfd, buf, 2) >= 0;
rb->close(tfd);
return res;
}
/* create header for the temporary file */
rb->memcpy(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1);
buf[TV_SETTINGS_HEADER_SIZE - 1] = TV_SETTINGS_VERSION;
@ -539,12 +593,13 @@ bool tv_save_settings(void)
rb->lseek(ofd, size, SEEK_CUR);
else
{
if ((rb->write(tfd, buf, MAX_PATH + 2) < 0) ||
(!tv_copy_settings(ofd, tfd, size)))
if ((rb->read(ofd, buf + (MAX_PATH + 2), size) < 0) ||
(rb->write(tfd, buf, size + MAX_PATH + 2) < 0))
{
res = false;
break;
}
new_fcount++;
}
}
}
@ -555,31 +610,15 @@ bool tv_save_settings(void)
{
/* save to current read file's preferences and bookmarks */
res = false;
rb->memset(buf, 0, MAX_PATH);
rb->strlcpy(buf, preferences->file_name, MAX_PATH);
if (rb->write(tfd, buf, MAX_PATH + 2) >= 0)
if (rb->write(tfd, preferences_buf, preferences_buf_size) >= 0)
{
if (tv_write_preferences(tfd, preferences))
{
size = tv_serialize_bookmarks(tfd);
if (size > 0)
{
size += TV_PREFERENCES_SIZE;
rb->lseek(tfd, -size - 2, SEEK_CUR);
buf[0] = size >> 8;
buf[1] = size;
if (rb->write(tfd, buf, 2) >= 0)
{
rb->lseek(tfd, TV_SETTINGS_HEADER_SIZE, SEEK_SET);
rb->lseek(tfd, TV_SETTINGS_HEADER_SIZE, SEEK_SET);
fcount++;
buf[0] = fcount >> 8;
buf[1] = fcount;
res = (rb->write(tfd, buf, 2) >= 0);
}
}
}
new_fcount++;
buf[0] = new_fcount >> 8;
buf[1] = new_fcount;
res = (rb->write(tfd, buf, 2) >= 0);
}
}
rb->close(tfd);

View file

@ -63,6 +63,7 @@ bool tv_load_settings(const unsigned char *file_name);
/*
* save the settings at each file
* supposed to be called only once at plugin exit
*
* return
* true success

View file

@ -573,7 +573,7 @@ William Peters
Li Jie
Cristina Talpiga
Ştefan Moisei
Alexander Meshcheryakov
The libmad team
The wavpack team