1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Gilles Roux
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 ****************************************************************************/
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
34 * -------------------------------
39 * windows 1 (when version <= 0x32, this value is view_mode)
42 * vertical_scrollbar 1
43 * (unused) 1 (for compatibility)
49 * horizontal_scrollbar 1
50 * horizontal_scroll_mode 1
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
71 * -----------------------------------
77 * next file pos 2 (prefences size + bookmark count * bookmark size + 1)
81 * windows 1 (when version <= 0x33, this value is view_mode)
84 * vertical_scrollbar 1
85 * (unused) 1 (for compatibility)
91 * horizontal_scrollbar 1
92 * horizontal_scroll_mode 1
110 #define VIEWER_SETTINGS_FILE VIEWERS_DIR "/viewer_file.dat"
111 #define TV_SETTINGS_FILE VIEWERS_DIR "/tv_file.dat"
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
;
136 else if (version
== 1)
139 if (rb
->read(pfd
, buf
, read_size
) < 0)
142 prefs
->word_mode
= *p
++;
143 prefs
->line_mode
= *p
++;
145 prefs
->windows
= *p
++;
150 prefs
->alignment
= *p
++;
152 prefs
->alignment
= AL_LEFT
;
154 prefs
->encoding
= *p
++;
155 prefs
->vertical_scrollbar
= *p
++;
156 /* skip need_scrollbar */
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
++;
165 prefs
->horizontal_scrollbar
= *p
;
167 prefs
->horizontal_scrollbar
= SB_OFF
;
170 prefs
->horizontal_scroll_mode
= *p
++;
172 prefs
->horizontal_scroll_mode
= HS_SCREEN
;
175 prefs
->narrow_mode
= *p
++;
177 prefs
->narrow_mode
= NM_PAGE
;
180 prefs
->indent_spaces
= *p
++;
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
);
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 */
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
);
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
;
233 unsigned char buf
[MAX_PATH
+ 2];
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)
251 if (!tv_read_preferences(sfd
, old_ver
, &new_prefs
))
254 if (!tv_write_preferences(dfd
, &new_prefs
))
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
);
274 static void tv_convert_settings_file(void)
276 unsigned char buf
[TV_SETTINGS_HEADER_SIZE
+ 2];
284 if ((sfd
= rb
->open(VIEWER_SETTINGS_FILE
, O_RDONLY
)) < 0)
287 if ((tfd
= rb
->open(TV_SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666)) < 0)
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)
302 for (i
= 0; i
< fcount
; i
++)
304 if (!tv_convert_settings(sfd
, tfd
, version
))
317 rb
->rename(TV_SETTINGS_TMP_FILE
, TV_SETTINGS_FILE
);
319 rb
->remove(TV_SETTINGS_TMP_FILE
);
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
];
337 * the viewer.rock's setting file read when the text_viewer.rock's setting file
340 if ((fd
= rb
->open(TV_GLOBAL_SETTINGS_FILE
, O_RDONLY
)) < 0)
341 fd
= rb
->open(VIEWER_GLOBAL_SETTINGS_FILE
, O_RDONLY
);
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
);
356 bool tv_save_global_settings(const struct tv_preferences
*prefs
)
358 unsigned char buf
[TV_GLOBAL_SETTINGS_HEADER_SIZE
];
362 if ((fd
= rb
->open(TV_SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666)) < 0)
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
));
374 rb
->remove(TV_GLOBAL_SETTINGS_FILE
);
375 rb
->rename(TV_SETTINGS_TMP_FILE
, TV_GLOBAL_SETTINGS_FILE
);
378 rb
->remove(TV_SETTINGS_TMP_FILE
);
383 /* ----------------------------------------------------------------------------
384 * load/save the settings
385 * ----------------------------------------------------------------------------
388 void tv_load_settings(const unsigned char *file_name
)
390 unsigned char buf
[MAX_PATH
+2];
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
);
422 rb
->lseek(fd
, size
, SEEK_CUR
);
429 /* when the settings file is illegal, removes it */
431 rb
->remove(TV_SETTINGS_FILE
);
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
;
453 if ((rb
->read(sfd
, buf
, MAX_PATH
) < 0) || (rb
->write(dfd
, buf
, MAX_PATH
) < 0))
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;
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)
483 if (rb
->write(tfd
, buf
, TV_SETTINGS_HEADER_SIZE
+ 2) < 0)
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));
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)
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
);
510 if ((rb
->write(tfd
, buf
, MAX_PATH
+ 2) < 0) ||
511 (!tv_copy_settings(ofd
, tfd
, size
)))
524 /* save to current read file's preferences and bookmarks */
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
);
535 size
+= TV_PREFERENCES_SIZE
;
536 rb
->lseek(tfd
, -size
- 2, SEEK_CUR
);
539 if (rb
->write(tfd
, buf
, 2) >= 0)
541 rb
->lseek(tfd
, TV_SETTINGS_HEADER_SIZE
, SEEK_SET
);
544 buf
[0] = fcount
>> 8;
546 res
= (rb
->write(tfd
, buf
, 2) >= 0);
556 rb
->remove(TV_SETTINGS_FILE
);
557 rb
->rename(TV_SETTINGS_TMP_FILE
, TV_SETTINGS_FILE
);
560 rb
->remove(TV_SETTINGS_TMP_FILE
);