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
58 #define VIEWER_GLOBAL_SETTINGS_FILE VIEWERS_DIR "/viewer.dat"
59 #define TV_GLOBAL_SETTINGS_FILE VIEWERS_DIR "/tv_global.dat"
61 #define TV_GLOBAL_SETTINGS_HEADER "\x54\x56\x47\x53" /* "TVGS" */
62 #define TV_GLOBAL_SETTINGS_VERSION 0x38
63 #define TV_GLOBAL_SETTINGS_HEADER_SIZE 5
64 #define TV_GLOBAL_SETTINGS_FIRST_VERSION 0x31
66 /* preferences and bookmarks at each file
67 * binary file, so dont use .cfg
72 * -----------------------------------
78 * next file pos 2 (prefences size + bookmark count * bookmark size + 1)
82 * windows 1 (when version <= 0x33, this value is view_mode)
85 * vertical_scrollbar 1
86 * (unused) 1 (for compatibility)
92 * horizontal_scrollbar 1
93 * horizontal_scroll_mode 1
112 #define VIEWER_SETTINGS_FILE VIEWERS_DIR "/viewer_file.dat"
113 #define TV_SETTINGS_FILE VIEWERS_DIR "/tv_file.dat"
116 #define TV_SETTINGS_TMP_FILE VIEWERS_DIR "/tv_file.tmp"
118 #define TV_SETTINGS_HEADER "\x54\x56\x53" /* "TVS" */
119 #define TV_SETTINGS_VERSION 0x39
120 #define TV_SETTINGS_HEADER_SIZE 4
121 #define TV_SETTINGS_FIRST_VERSION 0x32
123 #define TV_PREFERENCES_SIZE (28 + MAX_PATH)
125 /* ----------------------------------------------------------------------------
126 * read/write the preferences
127 * ----------------------------------------------------------------------------
130 static bool tv_read_preferences(int pfd
, int version
, struct tv_preferences
*prefs
)
132 unsigned char buf
[TV_PREFERENCES_SIZE
];
133 const unsigned char *p
= buf
;
134 int read_size
= TV_PREFERENCES_SIZE
;
138 else if (version
== 1)
141 if (rb
->read(pfd
, buf
, read_size
) < 0)
144 prefs
->word_mode
= *p
++;
145 prefs
->line_mode
= *p
++;
147 prefs
->windows
= *p
++;
152 prefs
->alignment
= *p
++;
154 prefs
->alignment
= AL_LEFT
;
156 prefs
->encoding
= *p
++;
157 prefs
->vertical_scrollbar
= *p
++;
158 /* skip need_scrollbar */
160 prefs
->page_mode
= *p
++;
164 prefs
->statusbar
= false;
167 prefs
->header_mode
= (*p
& 1);
168 prefs
->statusbar
= true;
171 prefs
->header_mode
= *p
;
175 prefs
->footer_mode
= (*p
& 1);
176 prefs
->statusbar
= true;
179 prefs
->footer_mode
= *p
;
185 prefs
->header_mode
= *p
++;
186 prefs
->footer_mode
= *p
++;
189 prefs
->vertical_scroll_mode
= *p
++;
190 prefs
->autoscroll_speed
= *p
++;
193 prefs
->horizontal_scrollbar
= *p
;
195 prefs
->horizontal_scrollbar
= SB_OFF
;
198 prefs
->horizontal_scroll_mode
= *p
++;
200 prefs
->horizontal_scroll_mode
= HS_SCREEN
;
203 prefs
->narrow_mode
= *p
++;
205 prefs
->narrow_mode
= NM_PAGE
;
208 prefs
->indent_spaces
= *p
++;
210 prefs
->indent_spaces
= 2;
213 prefs
->statusbar
= (*p
++ != 0);
215 #ifdef HAVE_LCD_BITMAP
216 rb
->memcpy(prefs
->font_name
, buf
+ read_size
- MAX_PATH
, MAX_PATH
);
218 prefs
->font
= rb
->font_get(FONT_UI
);
224 static bool tv_write_preferences(int pfd
, const struct tv_preferences
*prefs
)
226 unsigned char buf
[TV_PREFERENCES_SIZE
];
227 unsigned char *p
= buf
;
229 *p
++ = prefs
->word_mode
;
230 *p
++ = prefs
->line_mode
;
231 *p
++ = prefs
->windows
;
232 *p
++ = prefs
->alignment
;
233 *p
++ = prefs
->encoding
;
234 *p
++ = prefs
->vertical_scrollbar
;
235 /* skip need_scrollbar */
237 *p
++ = prefs
->page_mode
;
238 *p
++ = prefs
->header_mode
;
239 *p
++ = prefs
->footer_mode
;
240 *p
++ = prefs
->vertical_scroll_mode
;
241 *p
++ = prefs
->autoscroll_speed
;
242 *p
++ = prefs
->horizontal_scrollbar
;
243 *p
++ = prefs
->horizontal_scroll_mode
;
244 *p
++ = prefs
->narrow_mode
;
245 *p
++ = prefs
->indent_spaces
;
246 *p
++ = prefs
->statusbar
;
248 #ifdef HAVE_LCD_BITMAP
249 rb
->memcpy(buf
+ 28, prefs
->font_name
, MAX_PATH
);
252 return (rb
->write(pfd
, buf
, TV_PREFERENCES_SIZE
) >= 0);
255 /* ----------------------------------------------------------------------------
256 * convert vewer.rock's settings file to text_viewer.rock's settings file
257 * ----------------------------------------------------------------------------
260 static bool tv_convert_settings(int sfd
, int dfd
, int old_ver
)
262 struct tv_preferences new_prefs
;
265 unsigned char buf
[MAX_PATH
+ 2];
268 rb
->read(sfd
, buf
, MAX_PATH
+ 2);
269 rb
->write(dfd
, buf
, MAX_PATH
+ 2);
271 settings_size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+ 1];
273 old_pos
= rb
->lseek(sfd
, 0, SEEK_CUR
);
274 new_pos
= rb
->lseek(dfd
, 0, SEEK_CUR
);
277 * when the settings size != preferences size + bookmarks size,
278 * settings data are considered to be old version.
280 if (old_ver
> 0 && ((settings_size
- TV_PREFERENCES_SIZE
) % 8) == 0)
283 if (!tv_read_preferences(sfd
, old_ver
, &new_prefs
))
286 if (!tv_write_preferences(dfd
, &new_prefs
))
289 settings_size
-= (rb
->lseek(sfd
, 0, SEEK_CUR
) - old_pos
);
291 if (settings_size
> 0)
293 rb
->read(sfd
, buf
, settings_size
);
294 rb
->write(dfd
, buf
, settings_size
);
297 settings_size
= rb
->lseek(dfd
, 0, SEEK_CUR
) - new_pos
;
298 buf
[0] = settings_size
>> 8;
299 buf
[1] = settings_size
;
300 rb
->lseek(dfd
, new_pos
- 2, SEEK_SET
);
301 rb
->write(dfd
, buf
, 2);
302 rb
->lseek(dfd
, settings_size
, SEEK_CUR
);
306 static void tv_convert_settings_file(void)
308 unsigned char buf
[TV_SETTINGS_HEADER_SIZE
+ 2];
316 if ((sfd
= rb
->open(VIEWER_SETTINGS_FILE
, O_RDONLY
)) < 0)
319 if ((tfd
= rb
->open(TV_SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666)) < 0)
325 if (rb
->read(sfd
, buf
, TV_SETTINGS_HEADER_SIZE
+ 2) >= 0)
327 version
= buf
[TV_SETTINGS_HEADER_SIZE
- 1] - TV_SETTINGS_FIRST_VERSION
;
328 fcount
= (buf
[TV_SETTINGS_HEADER_SIZE
] << 8) | buf
[TV_SETTINGS_HEADER_SIZE
+ 1];
329 buf
[TV_SETTINGS_HEADER_SIZE
- 1] = TV_SETTINGS_VERSION
;
331 if (rb
->write(tfd
, buf
, TV_SETTINGS_HEADER_SIZE
+ 2) >= 0)
334 for (i
= 0; i
< fcount
; i
++)
336 if (!tv_convert_settings(sfd
, tfd
, version
))
349 rb
->rename(TV_SETTINGS_TMP_FILE
, TV_SETTINGS_FILE
);
351 rb
->remove(TV_SETTINGS_TMP_FILE
);
356 /* ----------------------------------------------------------------------------
357 * load/save the global settings
358 * ----------------------------------------------------------------------------
361 bool tv_load_global_settings(struct tv_preferences
*prefs
)
363 unsigned char buf
[TV_GLOBAL_SETTINGS_HEADER_SIZE
];
369 * the viewer.rock's setting file read when the text_viewer.rock's setting file
372 if ((fd
= rb
->open(TV_GLOBAL_SETTINGS_FILE
, O_RDONLY
)) < 0)
373 fd
= rb
->open(VIEWER_GLOBAL_SETTINGS_FILE
, O_RDONLY
);
377 if ((rb
->read(fd
, buf
, TV_GLOBAL_SETTINGS_HEADER_SIZE
) > 0) &&
378 (rb
->memcmp(buf
, TV_GLOBAL_SETTINGS_HEADER
, TV_GLOBAL_SETTINGS_HEADER_SIZE
- 1) == 0))
380 version
= buf
[TV_GLOBAL_SETTINGS_HEADER_SIZE
- 1] - TV_GLOBAL_SETTINGS_FIRST_VERSION
;
381 res
= tv_read_preferences(fd
, version
, prefs
);
388 bool tv_save_global_settings(const struct tv_preferences
*prefs
)
390 unsigned char buf
[TV_GLOBAL_SETTINGS_HEADER_SIZE
];
394 if ((fd
= rb
->open(TV_SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666)) < 0)
397 rb
->memcpy(buf
, TV_GLOBAL_SETTINGS_HEADER
, TV_GLOBAL_SETTINGS_HEADER_SIZE
- 1);
398 buf
[TV_GLOBAL_SETTINGS_HEADER_SIZE
- 1] = TV_GLOBAL_SETTINGS_VERSION
;
400 res
= (rb
->write(fd
, buf
, TV_GLOBAL_SETTINGS_HEADER_SIZE
) >= 0) &&
401 (tv_write_preferences(fd
, prefs
));
406 rb
->remove(TV_GLOBAL_SETTINGS_FILE
);
407 rb
->rename(TV_SETTINGS_TMP_FILE
, TV_GLOBAL_SETTINGS_FILE
);
410 rb
->remove(TV_SETTINGS_TMP_FILE
);
415 /* ----------------------------------------------------------------------------
416 * load/save the settings
417 * ----------------------------------------------------------------------------
420 void tv_load_settings(const unsigned char *file_name
)
422 unsigned char buf
[MAX_PATH
+2];
429 struct tv_preferences prefs
;
431 if (!rb
->file_exists(TV_SETTINGS_FILE
))
432 tv_convert_settings_file();
434 if ((fd
= rb
->open(TV_SETTINGS_FILE
, O_RDONLY
)) >= 0)
436 if ((rb
->read(fd
, buf
, TV_SETTINGS_HEADER_SIZE
+ 2) >= 0) &&
437 (rb
->memcmp(buf
, TV_SETTINGS_HEADER
, TV_SETTINGS_HEADER_SIZE
- 1) == 0))
439 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];
442 for (i
= 0; i
< fcount
; i
++)
444 if (rb
->read(fd
, buf
, MAX_PATH
+2) >= 0)
446 size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+1];
447 if (rb
->strcmp(buf
, file_name
) == 0)
449 if (tv_read_preferences(fd
, version
, &prefs
))
450 res
= tv_deserialize_bookmarks(fd
);
454 rb
->lseek(fd
, size
, SEEK_CUR
);
461 /* when the settings file is illegal, removes it */
463 rb
->remove(TV_SETTINGS_FILE
);
468 /* specifications are acquired from the global settings */
469 if (!tv_load_global_settings(&prefs
))
470 tv_set_default_preferences(&prefs
);
472 rb
->strlcpy(prefs
.file_name
, file_name
, MAX_PATH
);
473 tv_set_preferences(&prefs
);
476 static bool tv_copy_settings(int sfd
, int dfd
, int size
)
478 unsigned char buf
[MAX_PATH
];
479 int i
= size
/ MAX_PATH
;
485 if ((rb
->read(sfd
, buf
, MAX_PATH
) < 0) || (rb
->write(dfd
, buf
, MAX_PATH
) < 0))
489 return ((rb
->read(sfd
, buf
, size
) >= 0) && (rb
->write(dfd
, buf
, size
) >= 0));
492 bool tv_save_settings(void)
494 unsigned char buf
[MAX_PATH
+2];
495 unsigned int fcount
= 0;
502 /* add reading page to bookmarks */
503 tv_create_system_bookmark();
505 if (!rb
->file_exists(TV_SETTINGS_FILE
))
506 tv_convert_settings_file();
508 /* create header for the temporary file */
509 rb
->memcpy(buf
, TV_SETTINGS_HEADER
, TV_SETTINGS_HEADER_SIZE
- 1);
510 buf
[TV_SETTINGS_HEADER_SIZE
- 1] = TV_SETTINGS_VERSION
;
512 if ((tfd
= rb
->open(TV_SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666)) < 0)
515 if (rb
->write(tfd
, buf
, TV_SETTINGS_HEADER_SIZE
+ 2) < 0)
521 if ((ofd
= rb
->open(TV_SETTINGS_FILE
, O_RDONLY
)) >= 0)
523 res
= ((rb
->read(ofd
, buf
, TV_SETTINGS_HEADER_SIZE
+ 2) >= 0) &&
524 (rb
->memcmp(buf
, TV_SETTINGS_HEADER
, TV_SETTINGS_HEADER_SIZE
- 1) == 0));
528 fcount
= (buf
[TV_SETTINGS_HEADER_SIZE
] << 8) | buf
[TV_SETTINGS_HEADER_SIZE
+ 1];
529 for (i
= 0; i
< fcount
; i
++)
531 if (rb
->read(ofd
, buf
, MAX_PATH
+ 2) < 0)
537 size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+ 1];
538 if (rb
->strcmp(buf
, preferences
->file_name
) == 0)
539 rb
->lseek(ofd
, size
, SEEK_CUR
);
542 if ((rb
->write(tfd
, buf
, MAX_PATH
+ 2) < 0) ||
543 (!tv_copy_settings(ofd
, tfd
, size
)))
556 /* save to current read file's preferences and bookmarks */
558 rb
->strlcpy(buf
, preferences
->file_name
, MAX_PATH
);
560 if (rb
->write(tfd
, buf
, MAX_PATH
+ 2) >= 0)
562 if (tv_write_preferences(tfd
, preferences
))
564 size
= tv_serialize_bookmarks(tfd
);
567 size
+= TV_PREFERENCES_SIZE
;
568 rb
->lseek(tfd
, -size
- 2, SEEK_CUR
);
571 if (rb
->write(tfd
, buf
, 2) >= 0)
573 rb
->lseek(tfd
, TV_SETTINGS_HEADER_SIZE
, SEEK_SET
);
576 buf
[0] = fcount
>> 8;
578 res
= (rb
->write(tfd
, buf
, 2) >= 0);
588 rb
->remove(TV_SETTINGS_FILE
);
589 rb
->rename(TV_SETTINGS_TMP_FILE
, TV_SETTINGS_FILE
);
592 rb
->remove(TV_SETTINGS_TMP_FILE
);