text_viewer: rename preference values.
[kugel-rb.git] / apps / plugins / text_viewer / tv_settings.c
blob93f16b5a6658c48b5c7fc9251970162e214e8792
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
23 #include "plugin.h"
24 #include "tv_bookmark.h"
25 #include "tv_reader.h"
26 #include "tv_settings.h"
28 /* global settings file
29 * binary file, so dont use .cfg
31 * setting file format
33 * part byte count
34 * -------------------------------
35 * 'TVGS' 4
36 * version 1
37 * word_mode 1
38 * line_mode 1
39 * windows 1 (when version <= 0x32, this value is view_mode)
40 * alignment 1
41 * encoding 1
42 * vertical_scrollbar 1
43 * (unused) 1 (for compatibility)
44 * page_mode 1
45 * page_number_mode 1
46 * title_mode 1
47 * scroll_mode 1
48 * autoscroll_speed 1
49 * horizontal_scrollbar 1
50 * horizontal_scroll_mode 1
51 * narrow_mode 1
52 * indent_spaces 1
53 * (reserved) 12
54 * font name MAX_PATH
57 #define VIEWER_GLOBAL_SETTINGS_FILE VIEWERS_DIR "/viewer.dat"
58 #define TV_GLOBAL_SETTINGS_FILE VIEWERS_DIR "/tv_global.dat"
60 #define TV_GLOBAL_SETTINGS_HEADER "\x54\x56\x47\x53" /* "TVGS" */
61 #define TV_GLOBAL_SETTINGS_VERSION 0x37
62 #define TV_GLOBAL_SETTINGS_HEADER_SIZE 5
63 #define TV_GLOBAL_SETTINGS_FIRST_VERSION 0x31
65 /* preferences and bookmarks at each file
66 * binary file, so dont use .cfg
68 * setting file format
70 * part byte count
71 * -----------------------------------
72 * 'TVS' 3
73 * version 1
74 * file count 2
75 * [1st file]
76 * file path MAX_PATH
77 * next file pos 2 (prefences size + bookmark count * bookmark size + 1)
78 * [preferences]
79 * word_mode 1
80 * line_mode 1
81 * windows 1 (when version <= 0x33, this value is view_mode)
82 * alignment 1
83 * encoding 1
84 * vertical_scrollbar 1
85 * (unused) 1 (for compatibility)
86 * page_mode 1
87 * header_mode 1
88 * footer_mode 1
89 * scroll_mode 1
90 * autoscroll_speed 1
91 * horizontal_scrollbar 1
92 * horizontal_scroll_mode 1
93 * narrow_mode 1
94 * indent_spaces 1
95 * (reserved) 12
96 * font name MAX_PATH
97 * bookmark count 1
98 * [1st bookmark]
99 * file_position 4
100 * page 2
101 * line 1
102 * flag 1
103 * [2nd bookmark]
104 * ...
105 * [last bookmark]
106 * [2nd file]
107 * ...
108 * [last file]
110 #define VIEWER_SETTINGS_FILE VIEWERS_DIR "/viewer_file.dat"
111 #define TV_SETTINGS_FILE VIEWERS_DIR "/tv_file.dat"
113 /* temporary file */
114 #define TV_SETTINGS_TMP_FILE VIEWERS_DIR "/tv_file.tmp"
116 #define TV_SETTINGS_HEADER "\x54\x56\x53" /* "TVS" */
117 #define TV_SETTINGS_VERSION 0x38
118 #define TV_SETTINGS_HEADER_SIZE 4
119 #define TV_SETTINGS_FIRST_VERSION 0x32
121 #define TV_PREFERENCES_SIZE (28 + MAX_PATH)
123 /* ----------------------------------------------------------------------------
124 * read/write the preferences
125 * ----------------------------------------------------------------------------
128 static bool tv_read_preferences(int pfd, int version, struct tv_preferences *prefs)
130 unsigned char buf[TV_PREFERENCES_SIZE];
131 const unsigned char *p = buf;
132 int read_size = TV_PREFERENCES_SIZE;
134 if (version == 0)
135 read_size -= 17;
136 else if (version == 1)
137 read_size -= 16;
139 if (rb->read(pfd, buf, read_size) < 0)
140 return false;
142 prefs->word_mode = *p++;
143 prefs->line_mode = *p++;
145 prefs->windows = *p++;
146 if (version <= 1)
147 prefs->windows++;
149 if (version > 0)
150 prefs->alignment = *p++;
151 else
152 prefs->alignment = AL_LEFT;
154 prefs->encoding = *p++;
155 prefs->vertical_scrollbar = *p++;
156 /* skip need_scrollbar */
157 p++;
158 prefs->page_mode = *p++;
159 prefs->header_mode = *p++;
160 prefs->footer_mode = *p++;
161 prefs->vertical_scroll_mode = *p++;
162 prefs->autoscroll_speed = *p++;
164 if (version > 2)
165 prefs->horizontal_scrollbar = *p;
166 else
167 prefs->horizontal_scrollbar = SB_OFF;
169 if (version > 3)
170 prefs->horizontal_scroll_mode = *p++;
171 else
172 prefs->horizontal_scroll_mode = HS_SCREEN;
174 if (version > 4)
175 prefs->narrow_mode = *p++;
176 else
177 prefs->narrow_mode = NM_PAGE;
179 if (version > 5)
180 prefs->indent_spaces = *p++;
181 else
182 prefs->indent_spaces = 2;
184 #ifdef HAVE_LCD_BITMAP
185 rb->memcpy(prefs->font_name, buf + read_size - MAX_PATH, MAX_PATH);
187 prefs->font = rb->font_get(FONT_UI);
188 #endif
190 return true;
193 static bool tv_write_preferences(int pfd, const struct tv_preferences *prefs)
195 unsigned char buf[TV_PREFERENCES_SIZE];
196 unsigned char *p = buf;
198 *p++ = prefs->word_mode;
199 *p++ = prefs->line_mode;
200 *p++ = prefs->windows;
201 *p++ = prefs->alignment;
202 *p++ = prefs->encoding;
203 *p++ = prefs->vertical_scrollbar;
204 /* skip need_scrollbar */
205 p++;
206 *p++ = prefs->page_mode;
207 *p++ = prefs->header_mode;
208 *p++ = prefs->footer_mode;
209 *p++ = prefs->vertical_scroll_mode;
210 *p++ = prefs->autoscroll_speed;
211 *p++ = prefs->horizontal_scrollbar;
212 *p++ = prefs->horizontal_scroll_mode;
213 *p++ = prefs->narrow_mode;
214 *p++ = prefs->indent_spaces;
216 #ifdef HAVE_LCD_BITMAP
217 rb->memcpy(buf + 28, prefs->font_name, MAX_PATH);
218 #endif
220 return (rb->write(pfd, buf, TV_PREFERENCES_SIZE) >= 0);
223 /* ----------------------------------------------------------------------------
224 * convert vewer.rock's settings file to text_viewer.rock's settings file
225 * ----------------------------------------------------------------------------
228 static bool tv_convert_settings(int sfd, int dfd, int old_ver)
230 struct tv_preferences new_prefs;
231 off_t old_pos;
232 off_t new_pos;
233 unsigned char buf[MAX_PATH + 2];
234 int settings_size;
236 rb->read(sfd, buf, MAX_PATH + 2);
237 rb->write(dfd, buf, MAX_PATH + 2);
239 settings_size = (buf[MAX_PATH] << 8) | buf[MAX_PATH + 1];
241 old_pos = rb->lseek(sfd, 0, SEEK_CUR);
242 new_pos = rb->lseek(dfd, 0, SEEK_CUR);
245 * when the settings size != preferences size + bookmarks size,
246 * settings data are considered to be old version.
248 if (old_ver > 0 && ((settings_size - TV_PREFERENCES_SIZE) % 8) == 0)
249 old_ver = 0;
251 if (!tv_read_preferences(sfd, old_ver, &new_prefs))
252 return false;
254 if (!tv_write_preferences(dfd, &new_prefs))
255 return false;
257 settings_size -= (rb->lseek(sfd, 0, SEEK_CUR) - old_pos);
259 if (settings_size > 0)
261 rb->read(sfd, buf, settings_size);
262 rb->write(dfd, buf, settings_size);
265 settings_size = rb->lseek(dfd, 0, SEEK_CUR) - new_pos;
266 buf[0] = settings_size >> 8;
267 buf[1] = settings_size;
268 rb->lseek(dfd, new_pos - 2, SEEK_SET);
269 rb->write(dfd, buf, 2);
270 rb->lseek(dfd, settings_size, SEEK_CUR);
271 return true;
274 static void tv_convert_settings_file(void)
276 unsigned char buf[TV_SETTINGS_HEADER_SIZE + 2];
277 int sfd;
278 int tfd;
279 int i;
280 int fcount;
281 int version;
282 bool res = false;
284 if ((sfd = rb->open(VIEWER_SETTINGS_FILE, O_RDONLY)) < 0)
285 return;
287 if ((tfd = rb->open(TV_SETTINGS_TMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
289 rb->close(sfd);
290 return;
293 if (rb->read(sfd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0)
295 version = buf[TV_SETTINGS_HEADER_SIZE - 1] - TV_SETTINGS_FIRST_VERSION;
296 fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE + 1];
297 buf[TV_SETTINGS_HEADER_SIZE - 1] = TV_SETTINGS_VERSION;
299 if (rb->write(tfd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0)
301 res = true;
302 for (i = 0; i < fcount; i++)
304 if (!tv_convert_settings(sfd, tfd, version))
306 res = false;
307 break;
313 rb->close(sfd);
314 rb->close(tfd);
316 if (res)
317 rb->rename(TV_SETTINGS_TMP_FILE, TV_SETTINGS_FILE);
318 else
319 rb->remove(TV_SETTINGS_TMP_FILE);
321 return;
324 /* ----------------------------------------------------------------------------
325 * load/save the global settings
326 * ----------------------------------------------------------------------------
329 bool tv_load_global_settings(struct tv_preferences *prefs)
331 unsigned char buf[TV_GLOBAL_SETTINGS_HEADER_SIZE];
332 int fd;
333 int version;
334 bool res = false;
337 * the viewer.rock's setting file read when the text_viewer.rock's setting file
338 * does not read.
340 if ((fd = rb->open(TV_GLOBAL_SETTINGS_FILE, O_RDONLY)) < 0)
341 fd = rb->open(VIEWER_GLOBAL_SETTINGS_FILE, O_RDONLY);
343 if (fd >= 0)
345 if ((rb->read(fd, buf, TV_GLOBAL_SETTINGS_HEADER_SIZE) > 0) &&
346 (rb->memcmp(buf, TV_GLOBAL_SETTINGS_HEADER, TV_GLOBAL_SETTINGS_HEADER_SIZE - 1) == 0))
348 version = buf[TV_GLOBAL_SETTINGS_HEADER_SIZE - 1] - TV_GLOBAL_SETTINGS_FIRST_VERSION;
349 res = tv_read_preferences(fd, version, prefs);
351 rb->close(fd);
353 return res;
356 bool tv_save_global_settings(const struct tv_preferences *prefs)
358 unsigned char buf[TV_GLOBAL_SETTINGS_HEADER_SIZE];
359 int fd;
360 bool res;
362 if ((fd = rb->open(TV_SETTINGS_TMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
363 return false;
365 rb->memcpy(buf, TV_GLOBAL_SETTINGS_HEADER, TV_GLOBAL_SETTINGS_HEADER_SIZE - 1);
366 buf[TV_GLOBAL_SETTINGS_HEADER_SIZE - 1] = TV_GLOBAL_SETTINGS_VERSION;
368 res = (rb->write(fd, buf, TV_GLOBAL_SETTINGS_HEADER_SIZE) >= 0) &&
369 (tv_write_preferences(fd, prefs));
370 rb->close(fd);
372 if (res)
374 rb->remove(TV_GLOBAL_SETTINGS_FILE);
375 rb->rename(TV_SETTINGS_TMP_FILE, TV_GLOBAL_SETTINGS_FILE);
377 else
378 rb->remove(TV_SETTINGS_TMP_FILE);
380 return res;
383 /* ----------------------------------------------------------------------------
384 * load/save the settings
385 * ----------------------------------------------------------------------------
388 void tv_load_settings(const unsigned char *file_name)
390 unsigned char buf[MAX_PATH+2];
391 unsigned int fcount;
392 unsigned int i;
393 bool res = false;
394 int fd;
395 int version;
396 unsigned int size;
397 struct tv_preferences prefs;
399 if (!rb->file_exists(TV_SETTINGS_FILE))
400 tv_convert_settings_file();
402 if ((fd = rb->open(TV_SETTINGS_FILE, O_RDONLY)) >= 0)
404 if ((rb->read(fd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0) &&
405 (rb->memcmp(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1) == 0))
407 version = buf[TV_SETTINGS_HEADER_SIZE - 1] - TV_SETTINGS_FIRST_VERSION;
408 fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE+1];
410 for (i = 0; i < fcount; i++)
412 if (rb->read(fd, buf, MAX_PATH+2) >= 0)
414 size = (buf[MAX_PATH] << 8) | buf[MAX_PATH+1];
415 if (rb->strcmp(buf, file_name) == 0)
417 if (tv_read_preferences(fd, version, &prefs))
418 res = tv_deserialize_bookmarks(fd);
420 break;
422 rb->lseek(fd, size, SEEK_CUR);
425 rb->close(fd);
427 else
429 /* when the settings file is illegal, removes it */
430 rb->close(fd);
431 rb->remove(TV_SETTINGS_FILE);
434 if (!res)
436 /* specifications are acquired from the global settings */
437 if (!tv_load_global_settings(&prefs))
438 tv_set_default_preferences(&prefs);
440 rb->strlcpy(prefs.file_name, file_name, MAX_PATH);
441 tv_set_preferences(&prefs);
444 static bool tv_copy_settings(int sfd, int dfd, int size)
446 unsigned char buf[MAX_PATH];
447 int i = size / MAX_PATH;
449 size %= MAX_PATH;
451 while (i--)
453 if ((rb->read(sfd, buf, MAX_PATH) < 0) || (rb->write(dfd, buf, MAX_PATH) < 0))
454 return false;
457 return ((rb->read(sfd, buf, size) >= 0) && (rb->write(dfd, buf, size) >= 0));
460 bool tv_save_settings(void)
462 unsigned char buf[MAX_PATH+2];
463 unsigned int fcount = 0;
464 unsigned int i;
465 int ofd = -1;
466 int tfd;
467 off_t size;
468 bool res = true;
470 /* add reading page to bookmarks */
471 tv_create_system_bookmark();
473 if (!rb->file_exists(TV_SETTINGS_FILE))
474 tv_convert_settings_file();
476 /* create header for the temporary file */
477 rb->memcpy(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1);
478 buf[TV_SETTINGS_HEADER_SIZE - 1] = TV_SETTINGS_VERSION;
480 if ((tfd = rb->open(TV_SETTINGS_TMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
481 return false;
483 if (rb->write(tfd, buf, TV_SETTINGS_HEADER_SIZE + 2) < 0)
485 rb->close(tfd);
486 return false;
489 if ((ofd = rb->open(TV_SETTINGS_FILE, O_RDONLY)) >= 0)
491 res = ((rb->read(ofd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0) &&
492 (rb->memcmp(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1) == 0));
494 if (res)
496 fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE + 1];
497 for (i = 0; i < fcount; i++)
499 if (rb->read(ofd, buf, MAX_PATH + 2) < 0)
501 res = false;
502 break;
505 size = (buf[MAX_PATH] << 8) | buf[MAX_PATH + 1];
506 if (rb->strcmp(buf, preferences->file_name) == 0)
507 rb->lseek(ofd, size, SEEK_CUR);
508 else
510 if ((rb->write(tfd, buf, MAX_PATH + 2) < 0) ||
511 (!tv_copy_settings(ofd, tfd, size)))
513 res = false;
514 break;
519 rb->close(ofd);
522 if (res)
524 /* save to current read file's preferences and bookmarks */
525 res = false;
526 rb->strlcpy(buf, preferences->file_name, MAX_PATH);
528 if (rb->write(tfd, buf, MAX_PATH + 2) >= 0)
530 if (tv_write_preferences(tfd, preferences))
532 size = tv_serialize_bookmarks(tfd);
533 if (size > 0)
535 size += TV_PREFERENCES_SIZE;
536 rb->lseek(tfd, -size - 2, SEEK_CUR);
537 buf[0] = size >> 8;
538 buf[1] = size;
539 if (rb->write(tfd, buf, 2) >= 0)
541 rb->lseek(tfd, TV_SETTINGS_HEADER_SIZE, SEEK_SET);
543 fcount++;
544 buf[0] = fcount >> 8;
545 buf[1] = fcount;
546 res = (rb->write(tfd, buf, 2) >= 0);
552 rb->close(tfd);
554 if (res)
556 rb->remove(TV_SETTINGS_FILE);
557 rb->rename(TV_SETTINGS_TMP_FILE, TV_SETTINGS_FILE);
559 else
560 rb->remove(TV_SETTINGS_TMP_FILE);
562 return res;