summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/viewer.c1601
1 files changed, 1398 insertions, 203 deletions
diff --git a/apps/plugins/viewer.c b/apps/plugins/viewer.c
index 8dae52780e..0901be427b 100644
--- a/apps/plugins/viewer.c
+++ b/apps/plugins/viewer.c
@@ -24,22 +24,108 @@
24 24
25PLUGIN_HEADER 25PLUGIN_HEADER
26 26
27#define SETTINGS_FILE VIEWERS_DIR "/viewer.dat" /* binary file, so dont use .cfg */ 27/* global settings file
28#define BOOKMARKS_FILE VIEWERS_DIR "/viewer_bookmarks.dat" 28 * binary file, so dont use .cfg
29 *
30 * setting file format
31 *
32 * part byte count
33 * --------------------------------
34 * 'TVGS' 4
35 * version 1
36 * word_mode 1
37 * line_mode 1
38 * view_mode 1
39 * encoding 1
40 * scrollbar_mode 1
41 * need_scrollbar 1
42 * page_mode 1
43 * page_number_mode 1
44 * title_mode 1
45 * scroll_mode 1
46 * autoscroll_speed 1
47 * font name MAX_PATH
48 */
49#define GLOBAL_SETTINGS_FILE VIEWERS_DIR "/viewer.dat"
50
51/* temporary file */
52#define GLOBAL_SETTINGS_TMP_FILE VIEWERS_DIR "/viewer_file.tmp"
53
54#define GLOBAL_SETTINGS_HEADER "\x54\x56\x47\x53\x31" /* header="TVGS" version=1 */
55#define GLOBAL_SETTINGS_H_SIZE 5
56
57/* preferences and bookmarks at each file
58 * binary file, so dont use .cfg
59 *
60 * setting file format
61 *
62 * part byte count
63 * --------------------------------
64 * 'TVS' 3
65 * version 1
66 * file count 2
67 * [1st file]
68 * file path MAX_PATH
69 * next file pos 2
70 * [preferences]
71 * word_mode 1
72 * line_mode 1
73 * view_mode 1
74 * encoding 1
75 * scrollbar_mode 1
76 * need_scrollbar 1
77 * page_mode 1
78 * header_mode 1
79 * footer_mode 1
80 * scroll_mode 1
81 * autoscroll_speed 1
82 * font name MAX_PATH
83 * bookmark count 1
84 * [1st bookmark]
85 * file_position 4
86 * page 2
87 * line 1
88 * flag 1
89 * [2nd bookmark]
90 * ...
91 * [last bookmark]
92 * [2nd file]
93 * ...
94 * [last file]
95 */
96#define SETTINGS_FILE VIEWERS_DIR "/viewer_file.dat"
97
98/* temporary file */
99#define SETTINGS_TMP_FILE VIEWERS_DIR "/viewer_file.tmp"
100
101#define SETTINGS_HEADER "\x54\x56\x53\x32" /* header="TVS" version=2 */
102#define SETTINGS_H_SIZE 4
29 103
30#define WRAP_TRIM 44 /* Max number of spaces to trim (arbitrary) */ 104#define WRAP_TRIM 44 /* Max number of spaces to trim (arbitrary) */
31#define MAX_COLUMNS 64 /* Max displayable string len (over-estimate) */ 105#define NARROW_MAX_COLUMNS 64 /* Max displayable string len [narrow] (over-estimate) */
106#define WIDE_MAX_COLUMNS 128 /* Max displayable string len [wide] (over-estimate) */
32#define MAX_WIDTH 910 /* Max line length in WIDE mode */ 107#define MAX_WIDTH 910 /* Max line length in WIDE mode */
33#define READ_PREV_ZONE 910 /* Arbitrary number less than SMALL_BLOCK_SIZE */ 108#define READ_PREV_ZONE (block_size*9/10) /* Arbitrary number less than SMALL_BLOCK_SIZE */
34#define SMALL_BLOCK_SIZE 0x1000 /* 4k: Smallest file chunk we will read */ 109#define SMALL_BLOCK_SIZE block_size /* Smallest file chunk we will read */
35#define LARGE_BLOCK_SIZE 0x2000 /* 8k: Preferable size of file chunk to read */ 110#define LARGE_BLOCK_SIZE (block_size << 1) /* Preferable size of file chunk to read */
36#define TOP_SECTOR buffer 111#define TOP_SECTOR buffer
37#define MID_SECTOR (buffer + SMALL_BLOCK_SIZE) 112#define MID_SECTOR (buffer + SMALL_BLOCK_SIZE)
38#define BOTTOM_SECTOR (buffer + 2*(SMALL_BLOCK_SIZE)) 113#define BOTTOM_SECTOR (buffer + (SMALL_BLOCK_SIZE << 1))
39#undef SCROLLBAR_WIDTH 114#undef SCROLLBAR_WIDTH
40#define SCROLLBAR_WIDTH rb->global_settings->scrollbar_width 115#define SCROLLBAR_WIDTH rb->global_settings->scrollbar_width
116#define MAX_PAGE 9999
117
118#define BOOKMARK_SIZE 8
119#define MAX_BOOKMARKS 10 /* user setting bookmarks + last read page */
41 120
42#define MAX_BOOKMARKED_FILES ((buffer_size/(signed)sizeof(struct bookmarked_file_info))-1) 121#define BOOKMARK_LAST 1
122#define BOOKMARK_USER 2
123
124#ifndef HAVE_LCD_BITMAP
125#define BOOKMARK_ICON "\xee\x84\x81\x00"
126#endif
127
128#define PREFERENCES_SIZE (11 + MAX_PATH)
43 129
44/* Out-Of-Bounds test for any pointer to data in the buffer */ 130/* Out-Of-Bounds test for any pointer to data in the buffer */
45#define BUFFER_OOB(p) ((p) < buffer || (p) >= buffer_end) 131#define BUFFER_OOB(p) ((p) < buffer || (p) >= buffer_end)
@@ -77,6 +163,7 @@ PLUGIN_HEADER
77#define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN) 163#define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN)
78#define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT) 164#define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT)
79#define VIEWER_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT) 165#define VIEWER_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT)
166#define VIEWER_BOOKMARK BUTTON_F2
80 167
81#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD 168#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
82#define VIEWER_QUIT BUTTON_OFF 169#define VIEWER_QUIT BUTTON_OFF
@@ -90,6 +177,7 @@ PLUGIN_HEADER
90#define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN) 177#define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN)
91#define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT) 178#define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT)
92#define VIEWER_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT) 179#define VIEWER_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT)
180#define VIEWER_BOOKMARK BUTTON_F2
93 181
94/* Ondio keys */ 182/* Ondio keys */
95#elif CONFIG_KEYPAD == ONDIO_PAD 183#elif CONFIG_KEYPAD == ONDIO_PAD
@@ -101,6 +189,7 @@ PLUGIN_HEADER
101#define VIEWER_MENU (BUTTON_MENU|BUTTON_REPEAT) 189#define VIEWER_MENU (BUTTON_MENU|BUTTON_REPEAT)
102#define VIEWER_AUTOSCROLL_PRE BUTTON_MENU 190#define VIEWER_AUTOSCROLL_PRE BUTTON_MENU
103#define VIEWER_AUTOSCROLL (BUTTON_MENU|BUTTON_REL) 191#define VIEWER_AUTOSCROLL (BUTTON_MENU|BUTTON_REL)
192#define VIEWER_BOOKMARK (BUTTON_MENU|BUTTON_OFF)
104 193
105/* Player keys */ 194/* Player keys */
106#elif CONFIG_KEYPAD == PLAYER_PAD 195#elif CONFIG_KEYPAD == PLAYER_PAD
@@ -111,6 +200,7 @@ PLUGIN_HEADER
111#define VIEWER_SCREEN_RIGHT (BUTTON_ON|BUTTON_RIGHT) 200#define VIEWER_SCREEN_RIGHT (BUTTON_ON|BUTTON_RIGHT)
112#define VIEWER_MENU BUTTON_MENU 201#define VIEWER_MENU BUTTON_MENU
113#define VIEWER_AUTOSCROLL BUTTON_PLAY 202#define VIEWER_AUTOSCROLL BUTTON_PLAY
203#define VIEWER_BOOKMARK BUTTON_ON
114 204
115/* iRiver H1x0 && H3x0 keys */ 205/* iRiver H1x0 && H3x0 keys */
116#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 206#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
@@ -126,6 +216,7 @@ PLUGIN_HEADER
126#define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN) 216#define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN)
127#define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT) 217#define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT)
128#define VIEWER_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT) 218#define VIEWER_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT)
219#define VIEWER_BOOKMARK (BUTTON_ON | BUTTON_SELECT)
129 220
130#define VIEWER_RC_QUIT BUTTON_RC_STOP 221#define VIEWER_RC_QUIT BUTTON_RC_STOP
131 222
@@ -141,6 +232,7 @@ PLUGIN_HEADER
141#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 232#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
142#define VIEWER_MENU BUTTON_MENU 233#define VIEWER_MENU BUTTON_MENU
143#define VIEWER_AUTOSCROLL BUTTON_PLAY 234#define VIEWER_AUTOSCROLL BUTTON_PLAY
235#define VIEWER_BOOKMARK BUTTON_SELECT
144 236
145/* iFP7xx keys */ 237/* iFP7xx keys */
146#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD 238#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
@@ -151,6 +243,7 @@ PLUGIN_HEADER
151#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 243#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
152#define VIEWER_MENU BUTTON_MODE 244#define VIEWER_MENU BUTTON_MODE
153#define VIEWER_AUTOSCROLL BUTTON_SELECT 245#define VIEWER_AUTOSCROLL BUTTON_SELECT
246#define VIEWER_BOOKMARK (BUTTON_LEFT|BUTTON_SELECT)
154 247
155/* iAudio X5 keys */ 248/* iAudio X5 keys */
156#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD 249#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
@@ -161,6 +254,7 @@ PLUGIN_HEADER
161#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 254#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
162#define VIEWER_MENU BUTTON_SELECT 255#define VIEWER_MENU BUTTON_SELECT
163#define VIEWER_AUTOSCROLL BUTTON_PLAY 256#define VIEWER_AUTOSCROLL BUTTON_PLAY
257#define VIEWER_BOOKMARK BUTTON_REC
164 258
165/* GIGABEAT keys */ 259/* GIGABEAT keys */
166#elif CONFIG_KEYPAD == GIGABEAT_PAD 260#elif CONFIG_KEYPAD == GIGABEAT_PAD
@@ -171,6 +265,7 @@ PLUGIN_HEADER
171#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 265#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
172#define VIEWER_MENU BUTTON_MENU 266#define VIEWER_MENU BUTTON_MENU
173#define VIEWER_AUTOSCROLL BUTTON_A 267#define VIEWER_AUTOSCROLL BUTTON_A
268#define VIEWER_BOOKMARK BUTTON_SELECT
174 269
175/* Sansa E200 keys */ 270/* Sansa E200 keys */
176#elif CONFIG_KEYPAD == SANSA_E200_PAD 271#elif CONFIG_KEYPAD == SANSA_E200_PAD
@@ -183,6 +278,7 @@ PLUGIN_HEADER
183#define VIEWER_AUTOSCROLL BUTTON_REC 278#define VIEWER_AUTOSCROLL BUTTON_REC
184#define VIEWER_LINE_UP BUTTON_SCROLL_BACK 279#define VIEWER_LINE_UP BUTTON_SCROLL_BACK
185#define VIEWER_LINE_DOWN BUTTON_SCROLL_FWD 280#define VIEWER_LINE_DOWN BUTTON_SCROLL_FWD
281#define VIEWER_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT)
186 282
187/* Sansa Fuze keys */ 283/* Sansa Fuze keys */
188#elif CONFIG_KEYPAD == SANSA_FUZE_PAD 284#elif CONFIG_KEYPAD == SANSA_FUZE_PAD
@@ -195,6 +291,7 @@ PLUGIN_HEADER
195#define VIEWER_AUTOSCROLL BUTTON_SELECT|BUTTON_DOWN 291#define VIEWER_AUTOSCROLL BUTTON_SELECT|BUTTON_DOWN
196#define VIEWER_LINE_UP BUTTON_SCROLL_BACK 292#define VIEWER_LINE_UP BUTTON_SCROLL_BACK
197#define VIEWER_LINE_DOWN BUTTON_SCROLL_FWD 293#define VIEWER_LINE_DOWN BUTTON_SCROLL_FWD
294#define VIEWER_BOOKMARK BUTTON_SELECT
198 295
199/* Sansa C200 keys */ 296/* Sansa C200 keys */
200#elif CONFIG_KEYPAD == SANSA_C200_PAD 297#elif CONFIG_KEYPAD == SANSA_C200_PAD
@@ -207,6 +304,7 @@ PLUGIN_HEADER
207#define VIEWER_AUTOSCROLL BUTTON_REC 304#define VIEWER_AUTOSCROLL BUTTON_REC
208#define VIEWER_LINE_UP BUTTON_UP 305#define VIEWER_LINE_UP BUTTON_UP
209#define VIEWER_LINE_DOWN BUTTON_DOWN 306#define VIEWER_LINE_DOWN BUTTON_DOWN
307#define VIEWER_BOOKMARK (BUTTON_DOWN | BUTTON_SELECT)
210 308
211/* Sansa Clip keys */ 309/* Sansa Clip keys */
212#elif CONFIG_KEYPAD == SANSA_CLIP_PAD 310#elif CONFIG_KEYPAD == SANSA_CLIP_PAD
@@ -219,6 +317,7 @@ PLUGIN_HEADER
219#define VIEWER_AUTOSCROLL BUTTON_HOME 317#define VIEWER_AUTOSCROLL BUTTON_HOME
220#define VIEWER_LINE_UP BUTTON_UP 318#define VIEWER_LINE_UP BUTTON_UP
221#define VIEWER_LINE_DOWN BUTTON_DOWN 319#define VIEWER_LINE_DOWN BUTTON_DOWN
320#define VIEWER_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT)
222 321
223/* Sansa M200 keys */ 322/* Sansa M200 keys */
224#elif CONFIG_KEYPAD == SANSA_M200_PAD 323#elif CONFIG_KEYPAD == SANSA_M200_PAD
@@ -231,6 +330,7 @@ PLUGIN_HEADER
231#define VIEWER_AUTOSCROLL (BUTTON_SELECT | BUTTON_REL) 330#define VIEWER_AUTOSCROLL (BUTTON_SELECT | BUTTON_REL)
232#define VIEWER_LINE_UP BUTTON_UP 331#define VIEWER_LINE_UP BUTTON_UP
233#define VIEWER_LINE_DOWN BUTTON_DOWN 332#define VIEWER_LINE_DOWN BUTTON_DOWN
333#define VIEWER_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT)
234 334
235/* iriver H10 keys */ 335/* iriver H10 keys */
236#elif CONFIG_KEYPAD == IRIVER_H10_PAD 336#elif CONFIG_KEYPAD == IRIVER_H10_PAD
@@ -241,6 +341,7 @@ PLUGIN_HEADER
241#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 341#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
242#define VIEWER_MENU BUTTON_REW 342#define VIEWER_MENU BUTTON_REW
243#define VIEWER_AUTOSCROLL BUTTON_PLAY 343#define VIEWER_AUTOSCROLL BUTTON_PLAY
344#define VIEWER_BOOKMARK BUTTON_FF
244 345
245/*M-Robe 500 keys */ 346/*M-Robe 500 keys */
246#elif CONFIG_KEYPAD == MROBE500_PAD 347#elif CONFIG_KEYPAD == MROBE500_PAD
@@ -251,6 +352,7 @@ PLUGIN_HEADER
251#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 352#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
252#define VIEWER_MENU BUTTON_RC_HEART 353#define VIEWER_MENU BUTTON_RC_HEART
253#define VIEWER_AUTOSCROLL BUTTON_RC_MODE 354#define VIEWER_AUTOSCROLL BUTTON_RC_MODE
355#define VIEWER_BOOKMARK BUTTON_CENTER
254 356
255/*Gigabeat S keys */ 357/*Gigabeat S keys */
256#elif CONFIG_KEYPAD == GIGABEAT_S_PAD 358#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
@@ -266,6 +368,7 @@ PLUGIN_HEADER
266#define VIEWER_LINE_DOWN BUTTON_DOWN 368#define VIEWER_LINE_DOWN BUTTON_DOWN
267#define VIEWER_COLUMN_LEFT BUTTON_LEFT 369#define VIEWER_COLUMN_LEFT BUTTON_LEFT
268#define VIEWER_COLUMN_RIGHT BUTTON_RIGHT 370#define VIEWER_COLUMN_RIGHT BUTTON_RIGHT
371#define VIEWER_BOOKMARK BUTTON_SELECT
269 372
270/*M-Robe 100 keys */ 373/*M-Robe 100 keys */
271#elif CONFIG_KEYPAD == MROBE100_PAD 374#elif CONFIG_KEYPAD == MROBE100_PAD
@@ -276,17 +379,19 @@ PLUGIN_HEADER
276#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 379#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
277#define VIEWER_MENU BUTTON_MENU 380#define VIEWER_MENU BUTTON_MENU
278#define VIEWER_AUTOSCROLL BUTTON_DISPLAY 381#define VIEWER_AUTOSCROLL BUTTON_DISPLAY
382#define VIEWER_BOOKMARK BUTTON_SELECT
279 383
280/* iAUdio M3 keys */ 384/* iAUdio M3 keys */
281#elif CONFIG_KEYPAD == IAUDIO_M3_PAD 385#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
282#define VIEWER_QUIT BUTTON_RC_REC 386#define VIEWER_QUIT BUTTON_REC
283#define VIEWER_PAGE_UP BUTTON_RC_VOL_UP 387#define VIEWER_PAGE_UP BUTTON_RC_VOL_UP
284#define VIEWER_PAGE_DOWN BUTTON_RC_VOL_DOWN 388#define VIEWER_PAGE_DOWN BUTTON_RC_VOL_DOWN
285#define VIEWER_SCREEN_LEFT BUTTON_RC_REW 389#define VIEWER_SCREEN_LEFT BUTTON_RC_REW
286#define VIEWER_SCREEN_RIGHT BUTTON_RC_FF 390#define VIEWER_SCREEN_RIGHT BUTTON_RC_FF
287#define VIEWER_MENU BUTTON_RC_MENU 391#define VIEWER_MENU BUTTON_RC_MENU
288#define VIEWER_AUTOSCROLL BUTTON_RC_MODE 392#define VIEWER_AUTOSCROLL BUTTON_RC_MODE
289#define VIEWER_RC_QUIT BUTTON_REC 393#define VIEWER_RC_QUIT BUTTON_RC_REC
394#define VIEWER_BOOKMARK BUTTON_RC_PLAY
290 395
291/* Cowon D2 keys */ 396/* Cowon D2 keys */
292#elif CONFIG_KEYPAD == COWON_D2_PAD 397#elif CONFIG_KEYPAD == COWON_D2_PAD
@@ -294,6 +399,7 @@ PLUGIN_HEADER
294#define VIEWER_MENU BUTTON_MENU 399#define VIEWER_MENU BUTTON_MENU
295#define VIEWER_PAGE_UP BUTTON_MINUS 400#define VIEWER_PAGE_UP BUTTON_MINUS
296#define VIEWER_PAGE_DOWN BUTTON_PLUS 401#define VIEWER_PAGE_DOWN BUTTON_PLUS
402#define VIEWER_BOOKMARK (BUTTON_MENU|BUTTON_PLUS)
297 403
298#elif CONFIG_KEYPAD == IAUDIO67_PAD 404#elif CONFIG_KEYPAD == IAUDIO67_PAD
299#define VIEWER_QUIT BUTTON_POWER 405#define VIEWER_QUIT BUTTON_POWER
@@ -304,6 +410,7 @@ PLUGIN_HEADER
304#define VIEWER_MENU BUTTON_MENU 410#define VIEWER_MENU BUTTON_MENU
305#define VIEWER_AUTOSCROLL BUTTON_PLAY 411#define VIEWER_AUTOSCROLL BUTTON_PLAY
306#define VIEWER_RC_QUIT BUTTON_STOP 412#define VIEWER_RC_QUIT BUTTON_STOP
413#define VIEWER_BOOKMARK (BUTTON_LEFT|BUTTON_PLAY)
307 414
308/* Creative Zen Vision:M keys */ 415/* Creative Zen Vision:M keys */
309#elif CONFIG_KEYPAD == CREATIVEZVM_PAD 416#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
@@ -314,6 +421,7 @@ PLUGIN_HEADER
314#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 421#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
315#define VIEWER_MENU BUTTON_MENU 422#define VIEWER_MENU BUTTON_MENU
316#define VIEWER_AUTOSCROLL BUTTON_SELECT 423#define VIEWER_AUTOSCROLL BUTTON_SELECT
424#define VIEWER_BOOKMARK BUTTON_PLAY
317 425
318/* Philips HDD1630 keys */ 426/* Philips HDD1630 keys */
319#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD 427#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
@@ -324,6 +432,7 @@ PLUGIN_HEADER
324#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 432#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
325#define VIEWER_MENU BUTTON_MENU 433#define VIEWER_MENU BUTTON_MENU
326#define VIEWER_AUTOSCROLL BUTTON_VIEW 434#define VIEWER_AUTOSCROLL BUTTON_VIEW
435#define VIEWER_BOOKMARK BUTTON_SELECT
327 436
328/* Philips SA9200 keys */ 437/* Philips SA9200 keys */
329#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD 438#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
@@ -334,15 +443,18 @@ PLUGIN_HEADER
334#define VIEWER_SCREEN_RIGHT BUTTON_NEXT 443#define VIEWER_SCREEN_RIGHT BUTTON_NEXT
335#define VIEWER_MENU BUTTON_MENU 444#define VIEWER_MENU BUTTON_MENU
336#define VIEWER_AUTOSCROLL BUTTON_PLAY 445#define VIEWER_AUTOSCROLL BUTTON_PLAY
446#define VIEWER_BOOKMARK BUTTON_RIGHT
337 447
338/* Onda VX747 keys */ 448/* Onda VX747 keys */
339#elif CONFIG_KEYPAD == ONDAVX747_PAD 449#elif CONFIG_KEYPAD == ONDAVX747_PAD
340#define VIEWER_QUIT BUTTON_POWER 450#define VIEWER_QUIT BUTTON_POWER
341#define VIEWER_MENU BUTTON_MENU 451#define VIEWER_MENU BUTTON_MENU
452#define VIEWER_BOOKMARK BUTTON_RIGHT
342 453
343/* Onda VX777 keys */ 454/* Onda VX777 keys */
344#elif CONFIG_KEYPAD == ONDAVX777_PAD 455#elif CONFIG_KEYPAD == ONDAVX777_PAD
345#define VIEWER_QUIT BUTTON_POWER 456#define VIEWER_QUIT BUTTON_POWER
457#define VIEWER_BOOKMARK BUTTON_RIGHT
346 458
347/* SAMSUNG YH-820 / YH-920 / YH-925 keys */ 459/* SAMSUNG YH-820 / YH-920 / YH-925 keys */
348#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD 460#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
@@ -353,6 +465,7 @@ PLUGIN_HEADER
353#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 465#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
354#define VIEWER_MENU BUTTON_PLAY 466#define VIEWER_MENU BUTTON_PLAY
355#define VIEWER_AUTOSCROLL BUTTON_REW 467#define VIEWER_AUTOSCROLL BUTTON_REW
468#define VIEWER_BOOKMARK BUTTON_FFWD
356 469
357/* Packard Bell Vibe 500 keys */ 470/* Packard Bell Vibe 500 keys */
358#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD 471#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
@@ -365,6 +478,7 @@ PLUGIN_HEADER
365#define VIEWER_SCREEN_RIGHT BUTTON_NEXT 478#define VIEWER_SCREEN_RIGHT BUTTON_NEXT
366#define VIEWER_MENU BUTTON_MENU 479#define VIEWER_MENU BUTTON_MENU
367#define VIEWER_AUTOSCROLL BUTTON_PLAY 480#define VIEWER_AUTOSCROLL BUTTON_PLAY
481#define VIEWER_BOOKMARK BUTTON_POWER
368 482
369#else 483#else
370#error No keymap defined! 484#error No keymap defined!
@@ -403,15 +517,11 @@ PLUGIN_HEADER
403#endif 517#endif
404 518
405/* stuff for the bookmarking */ 519/* stuff for the bookmarking */
406struct bookmarked_file_info { 520struct bookmark_info {
407 long file_position; 521 long file_position;
408 int top_ptr_pos; 522 int page;
409 char filename[MAX_PATH]; 523 int line;
410}; 524 unsigned char flag;
411
412struct bookmark_file_data {
413 signed int bookmarked_files_count;
414 struct bookmarked_file_info bookmarks[];
415}; 525};
416 526
417struct preferences { 527struct preferences {
@@ -434,7 +544,6 @@ struct preferences {
434 544
435 enum codepages encoding; 545 enum codepages encoding;
436 546
437#ifdef HAVE_LCD_BITMAP
438 enum { 547 enum {
439 SB_OFF=0, 548 SB_OFF=0,
440 SB_ON, 549 SB_ON,
@@ -445,7 +554,20 @@ struct preferences {
445 NO_OVERLAP=0, 554 NO_OVERLAP=0,
446 OVERLAP, 555 OVERLAP,
447 } page_mode; 556 } page_mode;
448#endif /* HAVE_LCD_BITMAP */ 557
558 enum {
559 HD_NONE = 0,
560 HD_PATH,
561 HD_SBAR,
562 HD_BOTH,
563 } header_mode;
564
565 enum {
566 FT_NONE = 0,
567 FT_PAGE,
568 FT_SBAR,
569 FT_BOTH,
570 } footer_mode;
449 571
450 enum { 572 enum {
451 PAGE=0, 573 PAGE=0,
@@ -453,6 +575,13 @@ struct preferences {
453 } scroll_mode; 575 } scroll_mode;
454 576
455 int autoscroll_speed; 577 int autoscroll_speed;
578
579 unsigned char font[MAX_PATH];
580};
581
582enum {
583 VIEWER_FONT_MENU = 0,
584 VIEWER_FONT_TEXT,
456}; 585};
457 586
458struct preferences prefs; 587struct preferences prefs;
@@ -460,6 +589,7 @@ struct preferences old_prefs;
460 589
461static unsigned char *buffer; 590static unsigned char *buffer;
462static long buffer_size; 591static long buffer_size;
592static long block_size = 0x1000;
463static unsigned char line_break[] = {0,0x20,9,0xB,0xC,'-'}; 593static unsigned char line_break[] = {0,0x20,9,0xB,0xC,'-'};
464static int display_columns; /* number of (pixel) columns on the display */ 594static int display_columns; /* number of (pixel) columns on the display */
465static int display_lines; /* number of lines on the display */ 595static int display_lines; /* number of lines on the display */
@@ -471,18 +601,34 @@ static long file_size;
471static long start_position; /* position in the file after the viewer is started */ 601static long start_position; /* position in the file after the viewer is started */
472static bool mac_text; 602static bool mac_text;
473static long file_pos; /* Position of the top of the buffer in the file */ 603static long file_pos; /* Position of the top of the buffer in the file */
604static long last_file_pos;
474static unsigned char *buffer_end; /*Set to BUFFER_END() when file_pos changes*/ 605static unsigned char *buffer_end; /*Set to BUFFER_END() when file_pos changes*/
475static int max_line_len; 606static int max_line_len;
607static int max_width;
608static int max_columns;
609static int cline = 1;
610static int cpage = 1;
611static int lpage = 0;
476static unsigned char *screen_top_ptr; 612static unsigned char *screen_top_ptr;
477static unsigned char *next_screen_ptr; 613static unsigned char *next_screen_ptr;
478static unsigned char *next_screen_to_draw_ptr; 614static unsigned char *next_screen_to_draw_ptr;
479static unsigned char *next_line_ptr; 615static unsigned char *next_line_ptr;
616static unsigned char *last_screen_top_ptr = NULL;
480#ifdef HAVE_LCD_BITMAP 617#ifdef HAVE_LCD_BITMAP
481static struct font *pf; 618static struct font *pf;
619static int header_height = 0;
620static int footer_height = 0;
482#endif 621#endif
622struct bookmark_info bookmarks[MAX_BOOKMARKS];
623static int bookmark_count;
624
625/* UTF-8 BOM */
626#define BOM "\xef\xbb\xbf"
627#define BOM_SIZE 3
483 628
629static bool is_bom = false;
484 630
485int glyph_width(int ch) 631static int glyph_width(int ch)
486{ 632{
487 if (ch == 0) 633 if (ch == 0)
488 ch = ' '; 634 ch = ' ';
@@ -494,7 +640,7 @@ int glyph_width(int ch)
494#endif 640#endif
495} 641}
496 642
497unsigned char* get_ucs(const unsigned char* str, unsigned short* ch) 643static unsigned char* get_ucs(const unsigned char* str, unsigned short* ch)
498{ 644{
499 unsigned char utf8_tmp[6]; 645 unsigned char utf8_tmp[6];
500 int count; 646 int count;
@@ -515,12 +661,60 @@ unsigned char* get_ucs(const unsigned char* str, unsigned short* ch)
515 return (unsigned char*)str+1; 661 return (unsigned char*)str+1;
516} 662}
517 663
664static unsigned char *decode2utf8(const unsigned char *src, unsigned char *dst,
665 int skip_width, int disp_width)
666{
667 unsigned short ch;
668 const unsigned char *oldstr;
669 const unsigned char *str = src;
670 unsigned char *utf8 = dst;
671 int width = 0;
672
673 while (*str != '\0')
674 {
675 oldstr = str;
676 str = get_ucs(oldstr, &ch);
677 width += glyph_width(ch);
678 if (width > skip_width)
679 {
680 str = oldstr;
681 break;
682 }
683 }
684 width = 0;
685 while(*str != '\0')
686 {
687 str = get_ucs(str, &ch);
688 width += glyph_width(ch);
689 if (width > disp_width)
690 break;
691
692 utf8 = rb->utf8encode(ch, utf8);
693 }
694
695 return utf8;
696}
697
698static void calc_max_width(void)
699{
700 if (prefs.view_mode == NARROW)
701 {
702 max_columns = NARROW_MAX_COLUMNS;
703 max_width = draw_columns;
704 }
705 else
706 {
707 max_columns = WIDE_MAX_COLUMNS;
708 max_width = 2 * draw_columns;
709 }
710}
711
518bool done = false; 712bool done = false;
519int col = 0; 713int col = 0;
520 714
521#define ADVANCE_COUNTERS(c) { width += glyph_width(c); k++; } 715#define ADVANCE_COUNTERS(c) { width += glyph_width(c); k++; }
522#define LINE_IS_FULL ((k>=MAX_COLUMNS-1) ||( width >= draw_columns)) 716#define LINE_IS_FULL ((k>=max_columns-1) ||( width >= max_width))
523#define LINE_IS_NOT_FULL ((k<MAX_COLUMNS-1) &&( width < draw_columns)) 717#define LINE_IS_NOT_FULL ((k<max_columns-1) &&( width < max_width))
524static unsigned char* crop_at_width(const unsigned char* p) 718static unsigned char* crop_at_width(const unsigned char* p)
525{ 719{
526 int k,width; 720 int k,width;
@@ -531,6 +725,8 @@ static unsigned char* crop_at_width(const unsigned char* p)
531 725
532 while (LINE_IS_NOT_FULL) { 726 while (LINE_IS_NOT_FULL) {
533 oldp = p; 727 oldp = p;
728 if (BUFFER_OOB(p))
729 break;
534 p = get_ucs(p, &ch); 730 p = get_ucs(p, &ch);
535 ADVANCE_COUNTERS(ch); 731 ADVANCE_COUNTERS(ch);
536 } 732 }
@@ -716,7 +912,11 @@ static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_sho
716 next_line++; 912 next_line++;
717 913
718 if (BUFFER_OOB(next_line)) 914 if (BUFFER_OOB(next_line))
915 {
916 if (BUFFER_EOF() && next_line != cur_line)
917 return (unsigned char*) next_line;
719 return NULL; 918 return NULL;
919 }
720 920
721 if (is_short) 921 if (is_short)
722 *is_short = false; 922 *is_short = false;
@@ -758,7 +958,7 @@ static unsigned char* find_prev_line(const unsigned char* cur_line)
758 /* (else return NULL and read previous block) */ 958 /* (else return NULL and read previous block) */
759 959
760 /* Wrap downwards until too far, then use the one before. */ 960 /* Wrap downwards until too far, then use the one before. */
761 while (p < cur_line && p != NULL) { 961 while (p != NULL && p < cur_line) {
762 prev_line = p; 962 prev_line = p;
763 p = find_next_line(prev_line, NULL); 963 p = find_next_line(prev_line, NULL);
764 } 964 }
@@ -769,15 +969,34 @@ static unsigned char* find_prev_line(const unsigned char* cur_line)
769 return (unsigned char*) prev_line; 969 return (unsigned char*) prev_line;
770} 970}
771 971
972static void check_bom(void)
973{
974 unsigned char bom[BOM_SIZE];
975 off_t orig = rb->lseek(fd, 0, SEEK_CUR);
976
977 is_bom = false;
978
979 rb->lseek(fd, 0, SEEK_SET);
980
981 if (rb->read(fd, bom, BOM_SIZE) == BOM_SIZE)
982 is_bom = !memcmp(bom, BOM, BOM_SIZE);
983
984 rb->lseek(fd, orig, SEEK_SET);
985}
986
772static void fill_buffer(long pos, unsigned char* buf, unsigned size) 987static void fill_buffer(long pos, unsigned char* buf, unsigned size)
773{ 988{
774 /* Read from file and preprocess the data */ 989 /* Read from file and preprocess the data */
775 /* To minimize disk access, always read on sector boundaries */ 990 /* To minimize disk access, always read on sector boundaries */
776 unsigned numread, i; 991 unsigned numread, i;
777 bool found_CR = false; 992 bool found_CR = false;
993 off_t offset = rb->lseek(fd, pos, SEEK_SET);
994
995 if (offset == 0 && prefs.encoding == UTF_8 && is_bom)
996 rb->lseek(fd, BOM_SIZE, SEEK_SET);
778 997
779 rb->lseek(fd, pos, SEEK_SET);
780 numread = rb->read(fd, buf, size); 998 numread = rb->read(fd, buf, size);
999 buf[numread] = 0;
781 rb->button_clear_queue(); /* clear button queue */ 1000 rb->button_clear_queue(); /* clear button queue */
782 1001
783 for(i = 0; i < numread; i++) { 1002 for(i = 0; i < numread; i++) {
@@ -810,6 +1029,18 @@ static void fill_buffer(long pos, unsigned char* buf, unsigned size)
810 } 1029 }
811} 1030}
812 1031
1032static int viewer_find_bookmark(int page, int line)
1033{
1034 int i;
1035
1036 for (i = 0; i < bookmark_count; i++)
1037 {
1038 if (bookmarks[i].page == page && bookmarks[i].line == line)
1039 return i;
1040 }
1041 return -1;
1042}
1043
813static int read_and_synch(int direction) 1044static int read_and_synch(int direction)
814{ 1045{
815/* Read next (or prev) block, and reposition global pointers. */ 1046/* Read next (or prev) block, and reposition global pointers. */
@@ -848,6 +1079,48 @@ static int read_and_synch(int direction)
848 return move_vector; 1079 return move_vector;
849} 1080}
850 1081
1082static void get_next_line_position(unsigned char **line_begin,
1083 unsigned char **line_end,
1084 bool *is_short)
1085{
1086 int resynch_move;
1087
1088 *line_begin = *line_end;
1089 *line_end = find_next_line(*line_begin, is_short);
1090
1091 if (*line_end == NULL && !BUFFER_EOF())
1092 {
1093 resynch_move = read_and_synch(1); /* Read block & move ptrs */
1094 *line_begin -= resynch_move;
1095 if (next_line_ptr > buffer)
1096 next_line_ptr -= resynch_move;
1097
1098 *line_end = find_next_line(*line_begin, is_short);
1099 }
1100}
1101
1102static void increment_current_line(void)
1103{
1104 if (cline < display_lines)
1105 cline++;
1106 else if (cpage < MAX_PAGE)
1107 {
1108 cpage++;
1109 cline = 1;
1110 }
1111}
1112
1113static void decrement_current_line(void)
1114{
1115 if (cline > 1)
1116 cline--;
1117 else if (cpage > 1)
1118 {
1119 cpage--;
1120 cline = display_lines;
1121 }
1122}
1123
851static void viewer_scroll_up(void) 1124static void viewer_scroll_up(void)
852{ 1125{
853 unsigned char *p; 1126 unsigned char *p;
@@ -859,17 +1132,33 @@ static void viewer_scroll_up(void)
859 } 1132 }
860 if (p != NULL) 1133 if (p != NULL)
861 screen_top_ptr = p; 1134 screen_top_ptr = p;
1135
1136 decrement_current_line();
862} 1137}
863 1138
864static void viewer_scroll_down(void) 1139static void viewer_scroll_down(bool autoscroll)
865{ 1140{
866 if (next_screen_ptr != NULL) 1141 if (cpage == lpage)
1142 return;
1143
1144 if (next_line_ptr != NULL)
867 screen_top_ptr = next_line_ptr; 1145 screen_top_ptr = next_line_ptr;
1146
1147 if (prefs.scroll_mode == LINE || autoscroll)
1148 increment_current_line();
1149}
1150
1151static void viewer_scroll_to_top_line(void)
1152{
1153 int line;
1154
1155 for (line = cline; line > 1; line--)
1156 viewer_scroll_up();
868} 1157}
869 1158
870#ifdef HAVE_LCD_BITMAP 1159#ifdef HAVE_LCD_BITMAP
871static void viewer_scrollbar(void) { 1160static void viewer_scrollbar(void) {
872 int items, min_shown, max_shown; 1161 int items, min_shown, max_shown, sb_begin_y, sb_height;
873 1162
874 items = (int) file_size; /* (SH1 int is same as long) */ 1163 items = (int) file_size; /* (SH1 int is same as long) */
875 min_shown = (int) file_pos + (screen_top_ptr - buffer); 1164 min_shown = (int) file_pos + (screen_top_ptr - buffer);
@@ -879,14 +1168,47 @@ static void viewer_scrollbar(void) {
879 else 1168 else
880 max_shown = min_shown + (next_screen_ptr - screen_top_ptr); 1169 max_shown = min_shown + (next_screen_ptr - screen_top_ptr);
881 1170
882 rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, 0, SCROLLBAR_WIDTH-1, 1171 sb_begin_y = header_height;
883 LCD_HEIGHT, items, min_shown, max_shown, VERTICAL); 1172 sb_height = LCD_HEIGHT - header_height - footer_height;
1173
1174 rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, sb_begin_y,
1175 SCROLLBAR_WIDTH-1, sb_height,
1176 items, min_shown, max_shown, VERTICAL);
1177}
1178#endif
1179
1180#ifdef HAVE_LCD_BITMAP
1181static void viewer_show_header(void)
1182{
1183 if (prefs.header_mode == HD_SBAR || prefs.header_mode == HD_BOTH)
1184 rb->gui_syncstatusbar_draw(rb->statusbars, true);
1185
1186 if (prefs.header_mode == HD_PATH || prefs.header_mode == HD_BOTH)
1187 rb->lcd_putsxy(0, header_height - pf->height, file_name);
1188}
1189
1190static void viewer_show_footer(void)
1191{
1192 if (prefs.footer_mode == FT_SBAR || prefs.footer_mode == FT_BOTH)
1193 rb->gui_syncstatusbar_draw(rb->statusbars, true);
1194
1195 if (prefs.footer_mode == FT_PAGE || prefs.footer_mode == FT_BOTH)
1196 {
1197 unsigned char buf[12];
1198
1199 if (cline == 1)
1200 rb->snprintf(buf, sizeof(buf), "%d", cpage);
1201 else
1202 rb->snprintf(buf, sizeof(buf), "%d - %d", cpage, cpage+1);
1203
1204 rb->lcd_putsxy(0, LCD_HEIGHT - footer_height, buf);
1205 }
884} 1206}
885#endif 1207#endif
886 1208
887static void viewer_draw(int col) 1209static void viewer_draw(int col)
888{ 1210{
889 int i, j, k, line_len, line_width, resynch_move, spaces, left_col=0; 1211 int i, j, k, line_len, line_width, spaces, left_col=0;
890 int width, extra_spaces, indent_spaces, spaces_per_word; 1212 int width, extra_spaces, indent_spaces, spaces_per_word;
891 bool multiple_spacing, line_is_short; 1213 bool multiple_spacing, line_is_short;
892 unsigned short ch; 1214 unsigned short ch;
@@ -894,8 +1216,8 @@ static void viewer_draw(int col)
894 unsigned char *line_begin; 1216 unsigned char *line_begin;
895 unsigned char *line_end; 1217 unsigned char *line_end;
896 unsigned char c; 1218 unsigned char c;
897 unsigned char scratch_buffer[MAX_COLUMNS + 1]; 1219 unsigned char scratch_buffer[max_columns + 1];
898 unsigned char utf8_buffer[MAX_COLUMNS*4 + 1]; 1220 unsigned char utf8_buffer[max_columns*4 + 1];
899 unsigned char *endptr; 1221 unsigned char *endptr;
900 1222
901 /* If col==-1 do all calculations but don't display */ 1223 /* If col==-1 do all calculations but don't display */
@@ -912,39 +1234,26 @@ static void viewer_draw(int col)
912 1234
913 for (i = 0; i < display_lines; i++) { 1235 for (i = 0; i < display_lines; i++) {
914 if (BUFFER_OOB(line_end)) 1236 if (BUFFER_OOB(line_end))
915 break; /* Happens after display last line at BUFFER_EOF() */ 1237 {
916 1238 if (lpage == cpage)
917 line_begin = line_end; 1239 break; /* Happens after display last line at BUFFER_EOF() */
918 line_end = find_next_line(line_begin, &line_is_short);
919
920 if (line_end == NULL) {
921 if (BUFFER_EOF()) {
922 if (i < display_lines - 1 && !BUFFER_BOF()) {
923 if (col != -1)
924 rb->lcd_clear_display();
925
926 for (; i < display_lines - 1; i++)
927 viewer_scroll_up();
928 1240
929 line_begin = line_end = screen_top_ptr; 1241 if (lpage == 0 && cline == 1)
930 i = -1; 1242 {
931 continue; 1243 lpage = cpage;
932 } 1244 last_screen_top_ptr = screen_top_ptr;
933 else { 1245 last_file_pos = file_pos;
934 line_end = buffer_end;
935 }
936 }
937 else {
938 resynch_move = read_and_synch(1); /* Read block & move ptrs */
939 line_begin -= resynch_move;
940 if (i > 0)
941 next_line_ptr -= resynch_move;
942
943 line_end = find_next_line(line_begin, NULL);
944 if (line_end == NULL) /* Should not really happen */
945 break;
946 } 1246 }
947 } 1247 }
1248
1249 get_next_line_position(&line_begin, &line_end, &line_is_short);
1250 if (line_end == NULL)
1251 {
1252 if (BUFFER_OOB(line_begin))
1253 break;
1254 line_end = buffer_end + 1;
1255 }
1256
948 line_len = line_end - line_begin; 1257 line_len = line_end - line_begin;
949 1258
950 /* calculate line_len */ 1259 /* calculate line_len */
@@ -970,7 +1279,7 @@ static void viewer_draw(int col)
970 line_len--; 1279 line_len--;
971 } 1280 }
972 for (j=k=spaces=0; j < line_len; j++) { 1281 for (j=k=spaces=0; j < line_len; j++) {
973 if (k == MAX_COLUMNS) 1282 if (k == max_columns)
974 break; 1283 break;
975 1284
976 c = line_begin[j]; 1285 c = line_begin[j];
@@ -986,7 +1295,7 @@ static void viewer_draw(int col)
986 while (spaces) { 1295 while (spaces) {
987 spaces--; 1296 spaces--;
988 scratch_buffer[k++] = ' '; 1297 scratch_buffer[k++] = ' ';
989 if (k == MAX_COLUMNS - 1) 1298 if (k == max_columns - 1)
990 break; 1299 break;
991 } 1300 }
992 scratch_buffer[k++] = c; 1301 scratch_buffer[k++] = c;
@@ -995,8 +1304,7 @@ static void viewer_draw(int col)
995 } 1304 }
996 if (col != -1) { 1305 if (col != -1) {
997 scratch_buffer[k] = 0; 1306 scratch_buffer[k] = 0;
998 endptr = rb->iso_decode(scratch_buffer + col, utf8_buffer, 1307 endptr = decode2utf8(scratch_buffer, utf8_buffer, col, draw_columns);
999 prefs.encoding, draw_columns/glyph_width('i'));
1000 *endptr = 0; 1308 *endptr = 0;
1001 } 1309 }
1002 } 1310 }
@@ -1036,7 +1344,7 @@ static void viewer_draw(int col)
1036 1344
1037 if (spaces) { 1345 if (spaces) {
1038 /* total number of spaces to insert between words */ 1346 /* total number of spaces to insert between words */
1039 extra_spaces = (draw_columns-width)/glyph_width(' ') 1347 extra_spaces = (max_width-width)/glyph_width(' ')
1040 - indent_spaces; 1348 - indent_spaces;
1041 /* number of spaces between each word*/ 1349 /* number of spaces between each word*/
1042 spaces_per_word = extra_spaces / spaces; 1350 spaces_per_word = extra_spaces / spaces;
@@ -1056,7 +1364,7 @@ static void viewer_draw(int col)
1056 1364
1057 multiple_spacing = false; 1365 multiple_spacing = false;
1058 for (j=k=spaces=0; j < line_len; j++) { 1366 for (j=k=spaces=0; j < line_len; j++) {
1059 if (k == MAX_COLUMNS) 1367 if (k == max_columns)
1060 break; 1368 break;
1061 1369
1062 c = line_begin[j]; 1370 c = line_begin[j];
@@ -1081,11 +1389,9 @@ static void viewer_draw(int col)
1081 break; 1389 break;
1082 } 1390 }
1083 } 1391 }
1084
1085 if (col != -1) { 1392 if (col != -1) {
1086 scratch_buffer[k] = 0; 1393 scratch_buffer[k] = 0;
1087 endptr = rb->iso_decode(scratch_buffer + col, utf8_buffer, 1394 endptr = decode2utf8(scratch_buffer, utf8_buffer, col, draw_columns);
1088 prefs.encoding, k-col);
1089 *endptr = 0; 1395 *endptr = 0;
1090 } 1396 }
1091 } 1397 }
@@ -1116,11 +1422,29 @@ static void viewer_draw(int col)
1116 } 1422 }
1117 } 1423 }
1118 if (col != -1 && line_width > col) 1424 if (col != -1 && line_width > col)
1425 {
1426 int dpage = (cline+i <= display_lines)?cpage:cpage+1;
1427 int dline = cline+i - ((cline+i <= display_lines)?0:display_lines);
1428 bool bflag = (viewer_find_bookmark(dpage, dline) >= 0);
1429#ifdef HAVE_LCD_BITMAP
1430 int dy = i * pf->height + header_height;
1431#endif
1432 if (bflag)
1119#ifdef HAVE_LCD_BITMAP 1433#ifdef HAVE_LCD_BITMAP
1120 rb->lcd_putsxy(left_col, i*pf->height, utf8_buffer); 1434 {
1435 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_FG);
1436 rb->lcd_fillrect(left_col, dy, LCD_WIDTH, pf->height);
1437 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1438 }
1439 rb->lcd_putsxy(left_col, dy, utf8_buffer);
1440 rb->lcd_set_drawmode(DRMODE_SOLID);
1121#else 1441#else
1122 rb->lcd_puts(left_col, i, utf8_buffer); 1442 {
1443 rb->lcd_puts(left_col, i, BOOKMARK_ICON);
1444 }
1445 rb->lcd_puts(left_col+1, i, utf8_buffer);
1123#endif 1446#endif
1447 }
1124 if (line_width > max_line_len) 1448 if (line_width > max_line_len)
1125 max_line_len = line_width; 1449 max_line_len = line_width;
1126 1450
@@ -1140,6 +1464,14 @@ static void viewer_draw(int col)
1140 next_screen_to_draw_ptr = next_screen_ptr; 1464 next_screen_to_draw_ptr = next_screen_ptr;
1141#endif 1465#endif
1142 1466
1467#ifdef HAVE_LCD_BITMAP
1468 /* show header */
1469 viewer_show_header();
1470
1471 /* show footer */
1472 viewer_show_footer();
1473#endif
1474
1143 if (col != -1) 1475 if (col != -1)
1144 rb->lcd_update(); 1476 rb->lcd_update();
1145} 1477}
@@ -1150,38 +1482,53 @@ static void viewer_top(void)
1150 and point screen pointer to top */ 1482 and point screen pointer to top */
1151 if (file_pos != 0) 1483 if (file_pos != 0)
1152 { 1484 {
1485 rb->splash(0, "Loading...");
1486
1153 file_pos = 0; 1487 file_pos = 0;
1154 buffer_end = BUFFER_END(); /* Update whenever file_pos changes */ 1488 buffer_end = BUFFER_END(); /* Update whenever file_pos changes */
1155 fill_buffer(0, buffer, buffer_size); 1489 fill_buffer(0, buffer, buffer_size);
1156 } 1490 }
1157 1491
1158 screen_top_ptr = buffer; 1492 screen_top_ptr = buffer;
1493 cpage = 1;
1494 cline = 1;
1159} 1495}
1160 1496
1161static void viewer_bottom(void) 1497static void viewer_bottom(void)
1162{ 1498{
1163 /* Read bottom of file into buffer 1499 unsigned char *line_begin;
1164 and point screen pointer to bottom */ 1500 unsigned char *line_end;
1165 long last_sectors;
1166 1501
1167 if (file_size > buffer_size) { 1502 rb->splash(0, "Loading...");
1168 /* Find last buffer in file, round up to next sector boundary */
1169 last_sectors = file_size - buffer_size + SMALL_BLOCK_SIZE;
1170 last_sectors /= SMALL_BLOCK_SIZE;
1171 last_sectors *= SMALL_BLOCK_SIZE;
1172 }
1173 else {
1174 last_sectors = 0;
1175 }
1176 1503
1177 if (file_pos != last_sectors) 1504 if (last_screen_top_ptr)
1178 { 1505 {
1179 file_pos = last_sectors; 1506 cpage = lpage;
1180 buffer_end = BUFFER_END(); /* Update whenever file_pos changes */ 1507 cline = 1;
1181 fill_buffer(last_sectors, buffer, buffer_size); 1508 screen_top_ptr = last_screen_top_ptr;
1509 file_pos = last_file_pos;
1510 fill_buffer(file_pos, buffer, buffer_size);
1511 buffer_end = BUFFER_END();
1512 return;
1182 } 1513 }
1183 1514
1184 screen_top_ptr = buffer_end-1; 1515 line_end = screen_top_ptr;
1516
1517 while (!BUFFER_EOF() || !BUFFER_OOB(line_end))
1518 {
1519 get_next_line_position(&line_begin, &line_end, NULL);
1520 if (line_end == NULL)
1521 break;
1522
1523 increment_current_line();
1524 if (cline == 1)
1525 screen_top_ptr = line_end;
1526 }
1527 lpage = cpage;
1528 cline = 1;
1529 last_screen_top_ptr = screen_top_ptr;
1530 last_file_pos = file_pos;
1531 buffer_end = BUFFER_END();
1185} 1532}
1186 1533
1187#ifdef HAVE_LCD_BITMAP 1534#ifdef HAVE_LCD_BITMAP
@@ -1192,18 +1539,80 @@ static void init_need_scrollbar(void) {
1192 prefs.need_scrollbar = NEED_SCROLLBAR(); 1539 prefs.need_scrollbar = NEED_SCROLLBAR();
1193 draw_columns = prefs.need_scrollbar? display_columns-SCROLLBAR_WIDTH : display_columns; 1540 draw_columns = prefs.need_scrollbar? display_columns-SCROLLBAR_WIDTH : display_columns;
1194 par_indent_spaces = draw_columns/(5*glyph_width(' ')); 1541 par_indent_spaces = draw_columns/(5*glyph_width(' '));
1542 calc_max_width();
1543}
1544
1545static void init_header_and_footer(void)
1546{
1547 header_height = 0;
1548 footer_height = 0;
1549 if (rb->global_settings->statusbar == STATUSBAR_TOP)
1550 {
1551 if (prefs.header_mode == HD_SBAR || prefs.header_mode == HD_BOTH)
1552 header_height = STATUSBAR_HEIGHT;
1553
1554 if (prefs.footer_mode == FT_SBAR)
1555 prefs.footer_mode = FT_NONE;
1556 else if (prefs.footer_mode == FT_BOTH)
1557 prefs.footer_mode = FT_PAGE;
1558 }
1559 else if (rb->global_settings->statusbar == STATUSBAR_BOTTOM)
1560 {
1561 if (prefs.footer_mode == FT_SBAR || prefs.footer_mode == FT_BOTH)
1562 footer_height = STATUSBAR_HEIGHT;
1563
1564 if (prefs.header_mode == HD_SBAR)
1565 prefs.header_mode = HD_NONE;
1566 else if (prefs.header_mode == HD_BOTH)
1567 prefs.header_mode = HD_PATH;
1568 }
1569 else /* STATUSBAR_OFF || STATUSBAR_CUSTOM */
1570 {
1571 if (prefs.header_mode == HD_SBAR)
1572 prefs.header_mode = HD_NONE;
1573 else if (prefs.header_mode == HD_BOTH)
1574 prefs.header_mode = HD_PATH;
1575
1576 if (prefs.footer_mode == FT_SBAR)
1577 prefs.footer_mode = FT_NONE;
1578 else if (prefs.footer_mode == FT_BOTH)
1579 prefs.footer_mode = FT_PAGE;
1580 }
1581
1582 if (prefs.header_mode == HD_NONE || prefs.header_mode == HD_PATH ||
1583 prefs.footer_mode == FT_NONE || prefs.footer_mode == FT_PAGE)
1584 rb->gui_syncstatusbar_draw(rb->statusbars, false);
1585
1586 if (prefs.header_mode == HD_PATH || prefs.header_mode == HD_BOTH)
1587 header_height += pf->height;
1588 if (prefs.footer_mode == FT_PAGE || prefs.footer_mode == FT_BOTH)
1589 footer_height += pf->height;
1590
1591 display_lines = (LCD_HEIGHT - header_height - footer_height) / pf->height;
1592
1593 lpage = 0;
1594 last_file_pos = 0;
1595 last_screen_top_ptr = NULL;
1596}
1597
1598static void change_font(unsigned char *font)
1599{
1600 unsigned char buf[MAX_PATH];
1601
1602 if (font == NULL || *font == '\0')
1603 return;
1604
1605 rb->snprintf(buf, MAX_PATH, "%s/%s.fnt", FONT_DIR, font);
1606 if (rb->font_load(NULL, buf) < 0)
1607 rb->splash(HZ/2, "font load failed.");
1195} 1608}
1196#else
1197#define init_need_scrollbar()
1198#endif 1609#endif
1199 1610
1200static bool viewer_init(void) 1611static bool viewer_init(void)
1201{ 1612{
1202#ifdef HAVE_LCD_BITMAP 1613#ifdef HAVE_LCD_BITMAP
1203 1614 /* initialize fonts */
1204 pf = rb->font_get(FONT_UI); 1615 pf = rb->font_get(FONT_UI);
1205
1206 display_lines = LCD_HEIGHT / pf->height;
1207 draw_columns = display_columns = LCD_WIDTH; 1616 draw_columns = display_columns = LCD_WIDTH;
1208#else 1617#else
1209 /* REAL fixed pitch :) all chars use up 1 cell */ 1618 /* REAL fixed pitch :) all chars use up 1 cell */
@@ -1216,172 +1625,727 @@ static bool viewer_init(void)
1216 if (fd < 0) 1625 if (fd < 0)
1217 return false; 1626 return false;
1218 1627
1219 file_size = rb->filesize(fd);
1220 if (file_size==-1)
1221 return false;
1222
1223 /* Init mac_text value used in processing buffer */ 1628 /* Init mac_text value used in processing buffer */
1224 mac_text = false; 1629 mac_text = false;
1225 1630
1226 return true; 1631 return true;
1227} 1632}
1228 1633
1229static void viewer_default_settings(void) 1634/* When a file is UTF-8 file with BOM, if prefs.encoding is UTF-8,
1635 * then file size decreases only BOM_SIZE.
1636 */
1637static void get_filesize(void)
1638{
1639 file_size = rb->filesize(fd);
1640 if (file_size == -1)
1641 return;
1642
1643 if (prefs.encoding == UTF_8 && is_bom)
1644 file_size -= BOM_SIZE;
1645}
1646
1647static int bm_comp(const void *a, const void *b)
1648{
1649 struct bookmark_info *pa;
1650 struct bookmark_info *pb;
1651
1652 pa = (struct bookmark_info*)a;
1653 pb = (struct bookmark_info*)b;
1654
1655 if (pa->page != pb->page)
1656 return pa->page - pb->page;
1657
1658 return pa->line - pb->line;
1659}
1660
1661static void viewer_add_bookmark(void)
1662{
1663 if (bookmark_count >= MAX_BOOKMARKS-1)
1664 return;
1665
1666 bookmarks[bookmark_count].file_position
1667 = file_pos + screen_top_ptr - buffer;
1668 bookmarks[bookmark_count].page = cpage;
1669 bookmarks[bookmark_count].line = cline;
1670 bookmarks[bookmark_count].flag = BOOKMARK_USER;
1671 bookmark_count++;
1672}
1673
1674static int viewer_add_last_read_bookmark(void)
1675{
1676 int i;
1677
1678 i = viewer_find_bookmark(cpage, cline);
1679 if (i >= 0)
1680 bookmarks[i].flag |= BOOKMARK_LAST;
1681 else
1682 {
1683 viewer_add_bookmark();
1684 i = bookmark_count-1;
1685 bookmarks[i].flag = BOOKMARK_LAST;
1686 }
1687 return i;
1688}
1689
1690static void viewer_remove_bookmark(int i)
1691{
1692 int j;
1693
1694 if (i < 0 || i >= bookmark_count)
1695 return;
1696
1697 for (j = i+1; j < bookmark_count; j++)
1698 rb->memcpy(&bookmarks[j-1], &bookmarks[j],
1699 sizeof(struct bookmark_info));
1700
1701 bookmark_count--;
1702}
1703
1704static void viewer_remove_last_read_bookmark(void)
1705{
1706 int i, j;
1707
1708 for (i = 0; i < bookmark_count; i++)
1709 {
1710 if (bookmarks[i].flag & BOOKMARK_LAST)
1711 {
1712 if (bookmarks[i].flag == BOOKMARK_LAST)
1713 {
1714 for (j = i+1; j < bookmark_count; j++)
1715 rb->memcpy(&bookmarks[j-1], &bookmarks[j],
1716 sizeof(struct bookmark_info));
1717
1718 bookmark_count--;
1719 }
1720 else
1721 bookmarks[i].flag = BOOKMARK_USER;
1722 break;
1723 }
1724 }
1725}
1726
1727static int viewer_get_last_read_bookmark(void)
1728{
1729 int i;
1730
1731 for (i = 0; i < bookmark_count; i++)
1732 {
1733 if (bookmarks[i].flag & BOOKMARK_LAST)
1734 return i;
1735 }
1736 return -1;
1737}
1738
1739static void viewer_select_bookmark(int initval)
1740{
1741 int i;
1742 int ipage = 0;
1743 int iline = 0;
1744 int screen_pos;
1745 int screen_top;
1746 int selected = -1;
1747
1748 struct opt_items items[bookmark_count];
1749 unsigned char names[bookmark_count][38];
1750
1751 if (initval >= 0 && initval < bookmark_count)
1752 {
1753 ipage = bookmarks[initval].page;
1754 iline = bookmarks[initval].line;
1755 }
1756
1757 rb->qsort(bookmarks, bookmark_count, sizeof(struct bookmark_info),
1758 bm_comp);
1759
1760 for (i = 0; i < bookmark_count; i++)
1761 {
1762 rb->snprintf(names[i], sizeof(names[0]),
1763#if CONFIG_KEYPAD != PLAYER_PAD
1764 "%sPage: %d Line: %d",
1765#else
1766 "%sP:%d L:%d",
1767#endif
1768 (bookmarks[i].flag&BOOKMARK_LAST)? "*":" ",
1769 bookmarks[i].page,
1770 bookmarks[i].line);
1771 items[i].string = names[i];
1772 items[i].voice_id = -1;
1773 if (selected < 0 && bookmarks[i].page == ipage && bookmarks[i].line == iline)
1774 selected = i;
1775 }
1776
1777 rb->set_option("Select bookmark", &selected, INT, items,
1778 sizeof(items) / sizeof(items[0]), NULL);
1779
1780 if (selected < 0 || selected >= bookmark_count)
1781 {
1782 if (initval < 0 || (selected = viewer_get_last_read_bookmark()) < 0)
1783 {
1784 if (initval < 0)
1785 rb->splash(HZ, "Start the first page.");
1786 file_pos = 0;
1787 screen_top_ptr = buffer;
1788 cpage = 1;
1789 cline = 1;
1790 buffer_end = BUFFER_END();
1791 return;
1792 }
1793 }
1794
1795 screen_pos = bookmarks[selected].file_position;
1796 screen_top = screen_pos % buffer_size;
1797 file_pos = screen_pos - screen_top;
1798 screen_top_ptr = buffer + screen_top;
1799 cpage = bookmarks[selected].page;
1800 cline = bookmarks[selected].line;
1801 buffer_end = BUFFER_END();
1802}
1803
1804static void viewer_default_preferences(void)
1230{ 1805{
1231 prefs.word_mode = WRAP; 1806 prefs.word_mode = WRAP;
1232 prefs.line_mode = NORMAL; 1807 prefs.line_mode = NORMAL;
1233 prefs.view_mode = NARROW; 1808 prefs.view_mode = NARROW;
1234 prefs.scroll_mode = PAGE; 1809 prefs.scroll_mode = PAGE;
1235#ifdef HAVE_LCD_BITMAP
1236 prefs.page_mode = NO_OVERLAP; 1810 prefs.page_mode = NO_OVERLAP;
1237 prefs.scrollbar_mode = SB_OFF; 1811 prefs.scrollbar_mode = SB_OFF;
1812 rb->memset(prefs.font, 0, MAX_PATH);
1813#ifdef HAVE_LCD_BITMAP
1814 prefs.header_mode = HD_BOTH;
1815 prefs.footer_mode = FT_BOTH;
1816 rb->snprintf(prefs.font, MAX_PATH, "%s", rb->global_settings->font_file);
1817#else
1818 prefs.header_mode = HD_NONE;
1819 prefs.footer_mode = FT_NONE;
1238#endif 1820#endif
1239 prefs.autoscroll_speed = 1; 1821 prefs.autoscroll_speed = 1;
1240 /* Set codepage to system default */ 1822 /* Set codepage to system default */
1241 prefs.encoding = rb->global_settings->default_codepage; 1823 prefs.encoding = rb->global_settings->default_codepage;
1242} 1824}
1243 1825
1244static void viewer_load_settings(void) /* same name as global, but not the same file.. */ 1826static bool viewer_read_preferences(int pfd)
1827{
1828 unsigned char buf[PREFERENCES_SIZE];
1829 unsigned char *p = buf;
1830
1831 if (rb->read(pfd, buf, sizeof(buf)) != sizeof(buf))
1832 return false;
1833
1834 prefs.word_mode = *p++;
1835 prefs.line_mode = *p++;
1836 prefs.view_mode = *p++;
1837 prefs.encoding = *p++;
1838 prefs.scrollbar_mode = *p++;
1839 prefs.need_scrollbar = *p++;
1840 prefs.page_mode = *p++;
1841 prefs.header_mode = *p++;
1842 prefs.footer_mode = *p++;
1843 prefs.scroll_mode = *p++;
1844 prefs.autoscroll_speed = *p++;
1845 rb->memcpy(prefs.font, p, MAX_PATH);
1846
1847 return true;
1848}
1849
1850static bool viewer_write_preferences(int pfd)
1851{
1852 unsigned char buf[PREFERENCES_SIZE];
1853 unsigned char *p = buf;
1854
1855 *p++ = prefs.word_mode;
1856 *p++ = prefs.line_mode;
1857 *p++ = prefs.view_mode;
1858 *p++ = prefs.encoding;
1859 *p++ = prefs.scrollbar_mode;
1860 *p++ = prefs.need_scrollbar;
1861 *p++ = prefs.page_mode;
1862 *p++ = prefs.header_mode;
1863 *p++ = prefs.footer_mode;
1864 *p++ = prefs.scroll_mode;
1865 *p++ = prefs.autoscroll_speed;
1866 rb->memcpy(p, prefs.font, MAX_PATH);
1867
1868 return (rb->write(pfd, buf, sizeof(buf)) == sizeof(buf));
1869}
1870
1871static bool viewer_read_bookmark_info(int bfd, struct bookmark_info *b)
1872{
1873 unsigned char buf[BOOKMARK_SIZE];
1874
1875 if (rb->read(bfd, buf, sizeof(buf)) != sizeof(buf))
1876 return false;
1877
1878 b->file_position = (buf[0] << 24)|(buf[1] << 16)|(buf[2] << 8)|buf[3];
1879 b->page = (buf[4] << 8)|buf[5];
1880 b->line = buf[6];
1881 b->flag = buf[7];
1882
1883 return true;
1884}
1885
1886static bool viewer_read_bookmark_infos(int bfd)
1245{ 1887{
1246 int settings_fd, i; 1888 unsigned char c;
1247 struct bookmark_file_data *data; 1889 int i;
1248 struct bookmarked_file_info this_bookmark;
1249 1890
1250 /* read settings file */ 1891 if (rb->read(bfd, &c, 1) != 1)
1251 settings_fd=rb->open(SETTINGS_FILE, O_RDONLY);
1252 if ((settings_fd >= 0) && (rb->filesize(settings_fd) == sizeof(struct preferences)))
1253 { 1892 {
1254 rb->read(settings_fd, &prefs, sizeof(struct preferences)); 1893 bookmark_count = 0;
1255 rb->close(settings_fd); 1894 return false;
1256 } 1895 }
1257 else 1896
1897 bookmark_count = c;
1898 if (bookmark_count > MAX_BOOKMARKS)
1899 bookmark_count = MAX_BOOKMARKS;
1900
1901 for (i = 0; i < bookmark_count; i++)
1258 { 1902 {
1259 /* load default settings if there is no settings file */ 1903 if (!viewer_read_bookmark_info(bfd, &bookmarks[i]))
1260 viewer_default_settings(); 1904 {
1905 bookmark_count = i;
1906 return false;
1907 }
1261 } 1908 }
1909 return true;
1910}
1262 1911
1263 rb->memcpy(&old_prefs, &prefs, sizeof(struct preferences)); 1912static bool viewer_write_bookmark_info(int bfd, struct bookmark_info *b)
1913{
1914 unsigned char buf[BOOKMARK_SIZE];
1915 unsigned char *p = buf;
1916 unsigned long ul;
1917
1918 ul = b->file_position;
1919 *p++ = ul >> 24;
1920 *p++ = ul >> 16;
1921 *p++ = ul >> 8;
1922 *p++ = ul;
1264 1923
1265 data = (struct bookmark_file_data*)buffer; /* grab the text buffer */ 1924 ul = b->page;
1266 data->bookmarked_files_count = 0; 1925 *p++ = ul >> 8;
1926 *p++ = ul;
1267 1927
1268 /* read bookmarks if file exists */ 1928 *p++ = b->line;
1269 settings_fd = rb->open(BOOKMARKS_FILE, O_RDONLY); 1929 *p = b->flag;
1270 if (settings_fd >= 0) 1930
1931 return (rb->write(bfd, buf, sizeof(buf)) == sizeof(buf));
1932}
1933
1934static bool viewer_write_bookmark_infos(int bfd)
1935{
1936 unsigned char c = bookmark_count;
1937 int i;
1938
1939 if (rb->write(bfd, &c, 1) != 1)
1940 return false;
1941
1942 for (i = 0; i < bookmark_count; i++)
1271 { 1943 {
1272 /* figure out how many items to read */ 1944 if (!viewer_write_bookmark_info(bfd, &bookmarks[i]))
1273 rb->read(settings_fd, &data->bookmarked_files_count, sizeof(signed int)); 1945 return false;
1274 if (data->bookmarked_files_count > MAX_BOOKMARKED_FILES)
1275 data->bookmarked_files_count = MAX_BOOKMARKED_FILES;
1276 rb->read(settings_fd, data->bookmarks,
1277 sizeof(struct bookmarked_file_info) * data->bookmarked_files_count);
1278 rb->close(settings_fd);
1279 } 1946 }
1280 1947
1281 file_pos = 0; 1948 return true;
1282 screen_top_ptr = buffer; 1949}
1283 1950
1284 /* check if current file is in list */ 1951static bool viewer_load_global_settings(void)
1285 for (i=0; i < data->bookmarked_files_count; i++) 1952{
1286 { 1953 unsigned buf[GLOBAL_SETTINGS_H_SIZE];
1287 if (!rb->strcmp(file_name, data->bookmarks[i].filename)) 1954 int sfd = rb->open(GLOBAL_SETTINGS_FILE, O_RDONLY);
1288 { 1955
1289 int screen_pos = data->bookmarks[i].file_position + data->bookmarks[i].top_ptr_pos; 1956 if (sfd < 0)
1290 int screen_top = screen_pos % buffer_size; 1957 return false;
1291 file_pos = screen_pos - screen_top; 1958
1292 screen_top_ptr = buffer + screen_top; 1959 if ((rb->read(sfd, buf, GLOBAL_SETTINGS_H_SIZE) != GLOBAL_SETTINGS_H_SIZE) ||
1293 break; 1960 rb->memcmp(buf, GLOBAL_SETTINGS_HEADER, GLOBAL_SETTINGS_H_SIZE) ||
1294 } 1961 !viewer_read_preferences(sfd))
1962 {
1963 rb->close(sfd);
1964 return false;
1295 } 1965 }
1966 rb->close(sfd);
1967 return true;
1968}
1296 1969
1297 this_bookmark.file_position = file_pos; 1970static bool viewer_save_global_settings(void)
1298 this_bookmark.top_ptr_pos = screen_top_ptr - buffer; 1971{
1972 int sfd = rb->open(GLOBAL_SETTINGS_TMP_FILE, O_WRONLY|O_CREAT|O_TRUNC);
1299 1973
1300 rb->memset(&this_bookmark.filename[0],0,MAX_PATH); 1974 if (sfd < 0)
1301 rb->strcpy(this_bookmark.filename,file_name); 1975 return false;
1302 1976
1303 /* prevent potential slot overflow */ 1977 if (rb->write(sfd, &GLOBAL_SETTINGS_HEADER, GLOBAL_SETTINGS_H_SIZE)
1304 if (i >= data->bookmarked_files_count) 1978 != GLOBAL_SETTINGS_H_SIZE ||
1979 !viewer_write_preferences(sfd))
1305 { 1980 {
1306 if (i < MAX_BOOKMARKED_FILES) 1981 rb->close(sfd);
1307 data->bookmarked_files_count++; 1982 rb->remove(GLOBAL_SETTINGS_TMP_FILE);
1308 else 1983 return false;
1309 i = MAX_BOOKMARKED_FILES-1;
1310 } 1984 }
1985 rb->close(sfd);
1986 rb->remove(GLOBAL_SETTINGS_FILE);
1987 rb->rename(GLOBAL_SETTINGS_TMP_FILE, GLOBAL_SETTINGS_FILE);
1988 return true;
1989}
1311 1990
1312 /* write bookmark file with spare slot in first position 1991static void viewer_load_settings(void)
1313 to be filled in by viewer_save_settings */ 1992{
1314 settings_fd = rb->open(BOOKMARKS_FILE, O_WRONLY|O_CREAT); 1993 unsigned char buf[MAX_PATH+2];
1315 if (settings_fd >=0 ) 1994 unsigned int fcount;
1995 unsigned int i;
1996 bool res = false;
1997 int sfd;
1998 unsigned int size;
1999
2000 sfd = rb->open(SETTINGS_FILE, O_RDONLY);
2001 if (sfd < 0)
2002 goto read_end;
2003
2004 if ((rb->read(sfd, buf, SETTINGS_H_SIZE+2) != SETTINGS_H_SIZE+2) ||
2005 rb->memcmp(buf, SETTINGS_HEADER, SETTINGS_H_SIZE))
1316 { 2006 {
1317 /* write count */ 2007 /* illegal setting file */
1318 rb->write (settings_fd, &data->bookmarked_files_count, sizeof(signed int)); 2008 rb->close(sfd);
2009
2010 if (rb->file_exists(SETTINGS_FILE))
2011 rb->remove(SETTINGS_FILE);
1319 2012
1320 /* write the current bookmark */ 2013 goto read_end;
1321 rb->write (settings_fd, &this_bookmark, sizeof(struct bookmarked_file_info)); 2014 }
2015
2016 fcount = (buf[SETTINGS_H_SIZE] << 8) | buf[SETTINGS_H_SIZE+1];
2017 for (i = 0; i < fcount; i++)
2018 {
2019 if (rb->read(sfd, buf, MAX_PATH+2) != MAX_PATH+2)
2020 break;
1322 2021
1323 /* write everything that was before this bookmark */ 2022 size = (buf[MAX_PATH] << 8) | buf[MAX_PATH+1];
1324 rb->write (settings_fd, data->bookmarks, sizeof(struct bookmarked_file_info)*i); 2023 if (rb->strcmp(buf, file_name))
2024 {
2025 if (rb->lseek(sfd, size, SEEK_CUR) < 0)
2026 break;
2027 continue;
2028 }
2029 if (!viewer_read_preferences(sfd))
2030 break;
1325 2031
1326 rb->close(settings_fd); 2032 res = viewer_read_bookmark_infos(sfd);
2033 break;
1327 } 2034 }
1328 2035
1329 buffer_end = BUFFER_END(); /* Update whenever file_pos changes */ 2036 rb->close(sfd);
1330 2037
1331 if (BUFFER_OOB(screen_top_ptr)) 2038read_end:
2039 if (!res)
1332 { 2040 {
2041 /* load global settings */
2042 if (!viewer_load_global_settings())
2043 viewer_default_preferences();
2044
2045 file_pos = 0;
1333 screen_top_ptr = buffer; 2046 screen_top_ptr = buffer;
2047 cpage = 1;
2048 cline = 1;
2049 bookmark_count = 0;
2050 }
2051
2052 rb->memcpy(&old_prefs, &prefs, sizeof(struct preferences));
2053 calc_max_width();
2054
2055 if (bookmark_count > 1)
2056 viewer_select_bookmark(-1);
2057 else if (bookmark_count == 1)
2058 {
2059 int screen_pos;
2060 int screen_top;
2061
2062 screen_pos = bookmarks[0].file_position;
2063 screen_top = screen_pos % buffer_size;
2064 file_pos = screen_pos - screen_top;
2065 screen_top_ptr = buffer + screen_top;
2066 cpage = bookmarks[0].page;
2067 cline = bookmarks[0].line;
1334 } 2068 }
1335 2069
2070 viewer_remove_last_read_bookmark();
2071
2072 check_bom();
2073 get_filesize();
2074
2075 buffer_end = BUFFER_END(); /* Update whenever file_pos changes */
2076
2077 if (BUFFER_OOB(screen_top_ptr))
2078 screen_top_ptr = buffer;
2079
1336 fill_buffer(file_pos, buffer, buffer_size); 2080 fill_buffer(file_pos, buffer, buffer_size);
2081 if (prefs.scroll_mode == PAGE && cline > 1)
2082 viewer_scroll_to_top_line();
1337 2083
1338 /* remember the current position */ 2084 /* remember the current position */
1339 start_position = file_pos + screen_top_ptr - buffer; 2085 start_position = file_pos + screen_top_ptr - buffer;
1340 2086
2087#ifdef HAVE_LCD_BITMAP
2088 if (strcmp(prefs.font, rb->global_settings->font_file))
2089 change_font(prefs.font);
2090
1341 init_need_scrollbar(); 2091 init_need_scrollbar();
2092 init_header_and_footer();
2093#endif
1342} 2094}
1343 2095
1344static void viewer_save_settings(void)/* same name as global, but not the same file.. */ 2096static bool copy_bookmark_file(int sfd, int dfd, off_t start, off_t size)
1345{ 2097{
1346 int settings_fd; 2098 off_t rsize;
2099
2100 if (rb->lseek(sfd, start, SEEK_SET) < 0)
2101 return false;
1347 2102
1348 /* save the viewer settings if they have been changed */ 2103 while (size > 0)
1349 if (rb->memcmp(&prefs, &old_prefs, sizeof(struct preferences)))
1350 { 2104 {
1351 settings_fd = rb->creat(SETTINGS_FILE); /* create the settings file */ 2105 if (size > buffer_size)
2106 rsize = buffer_size;
2107 else
2108 rsize = size;
2109 size -= rsize;
1352 2110
1353 if (settings_fd >= 0 ) 2111 if (rb->read(sfd, buffer, rsize) != rsize ||
1354 { 2112 rb->write(dfd, buffer, rsize) != rsize)
1355 rb->write (settings_fd, &prefs, sizeof(struct preferences)); 2113 return false;
1356 rb->close(settings_fd); 2114 }
1357 } 2115 return true;
2116}
2117
2118static bool viewer_save_settings(void)
2119{
2120 unsigned char buf[MAX_PATH+2];
2121 unsigned int fcount = 0;
2122 unsigned int i;
2123 int idx;
2124 int ofd;
2125 int tfd;
2126 off_t first_copy_size = 0;
2127 off_t second_copy_start_pos = 0;
2128 off_t size;
2129
2130 /* add reading page to bookmarks */
2131 idx = viewer_find_bookmark(cpage, cline);
2132 if (idx >= 0)
2133 bookmarks[idx].flag |= BOOKMARK_LAST;
2134 else
2135 {
2136 viewer_add_bookmark();
2137 bookmarks[bookmark_count-1].flag = BOOKMARK_LAST;
1358 } 2138 }
2139
2140 tfd = rb->open(SETTINGS_TMP_FILE, O_WRONLY|O_CREAT|O_TRUNC);
2141 if (tfd < 0)
2142 return false;
1359 2143
1360 /* save the bookmark if the position has changed */ 2144 ofd = rb->open(SETTINGS_FILE, O_RDWR);
1361 if (file_pos + screen_top_ptr - buffer != start_position) 2145 if (ofd >= 0)
1362 { 2146 {
1363 settings_fd = rb->open(BOOKMARKS_FILE, O_WRONLY|O_CREAT); 2147 if ((rb->read(ofd, buf, SETTINGS_H_SIZE+2) != SETTINGS_H_SIZE+2) ||
2148 rb->memcmp(buf, SETTINGS_HEADER, SETTINGS_H_SIZE))
2149 {
2150 rb->close(ofd);
2151 goto save_err;
2152 }
2153 fcount = (buf[SETTINGS_H_SIZE] << 8) | buf[SETTINGS_H_SIZE+1];
2154
2155 for (i = 0; i < fcount; i++)
2156 {
2157 if (rb->read(ofd, buf, MAX_PATH+2) != MAX_PATH+2)
2158 {
2159 rb->close(ofd);
2160 goto save_err;
2161 }
2162 size = (buf[MAX_PATH] << 8) | buf[MAX_PATH+1];
2163 if (rb->strcmp(buf, file_name))
2164 {
2165 if (rb->lseek(ofd, size, SEEK_CUR) < 0)
2166 {
2167 rb->close(ofd);
2168 goto save_err;
2169 }
2170 }
2171 else
2172 {
2173 first_copy_size = rb->lseek(ofd, 0, SEEK_CUR);
2174 if (first_copy_size < 0)
2175 {
2176 rb->close(ofd);
2177 goto save_err;
2178 }
2179 second_copy_start_pos = first_copy_size + size;
2180 first_copy_size -= MAX_PATH+2;
2181 fcount--;
2182 break;
2183 }
2184 }
2185 if (first_copy_size == 0)
2186 first_copy_size = rb->filesize(ofd);
1364 2187
1365 if (settings_fd >= 0 ) 2188 if (!copy_bookmark_file(ofd, tfd, 0, first_copy_size))
1366 { 2189 {
1367 struct bookmarked_file_info b; 2190 rb->close(ofd);
1368 b.file_position = file_pos + screen_top_ptr - buffer; 2191 goto save_err;
1369 b.top_ptr_pos = 0; /* this is only kept for legassy reasons */ 2192 }
1370 rb->memset(&b.filename[0],0,MAX_PATH); 2193 if (second_copy_start_pos > 0)
1371 rb->strcpy(b.filename,file_name); 2194 {
1372 rb->lseek(settings_fd,sizeof(signed int),SEEK_SET); 2195 if (!copy_bookmark_file(ofd, tfd, second_copy_start_pos,
1373 rb->write (settings_fd, &b, sizeof(struct bookmarked_file_info)); 2196 rb->filesize(ofd) - second_copy_start_pos))
1374 rb->close(settings_fd); 2197 {
2198 rb->close(ofd);
2199 goto save_err;
2200 }
1375 } 2201 }
2202 rb->close(ofd);
1376 } 2203 }
2204 else
2205 {
2206 rb->memcpy(buf, SETTINGS_HEADER, SETTINGS_H_SIZE);
2207 buf[SETTINGS_H_SIZE] = 0;
2208 buf[SETTINGS_H_SIZE+1] = 0;
2209 if (rb->write(tfd, buf, SETTINGS_H_SIZE+2) != SETTINGS_H_SIZE+2)
2210 goto save_err;
2211 }
2212
2213 /* copy to current read file's bookmarks */
2214 rb->memset(buf, 0, MAX_PATH);
2215 rb->snprintf(buf, MAX_PATH, "%s", file_name);
2216
2217 size = PREFERENCES_SIZE + bookmark_count * BOOKMARK_SIZE + 1;
2218 buf[MAX_PATH] = size >> 8;
2219 buf[MAX_PATH+1] = size;
2220
2221 if (rb->write(tfd, buf, MAX_PATH+2) != MAX_PATH+2)
2222 goto save_err;
2223
2224 if (!viewer_write_preferences(tfd))
2225 goto save_err;
2226
2227 if (!viewer_write_bookmark_infos(tfd))
2228 goto save_err;
2229
2230 if (rb->lseek(tfd, SETTINGS_H_SIZE, SEEK_SET) < 0)
2231 goto save_err;
2232
2233 fcount++;
2234 buf[0] = fcount >> 8;
2235 buf[1] = fcount;
2236
2237 if (rb->write(tfd, buf, 2) != 2)
2238 goto save_err;
2239
2240 rb->close(tfd);
2241
2242 rb->remove(SETTINGS_FILE);
2243 rb->rename(SETTINGS_TMP_FILE, SETTINGS_FILE);
2244
2245 return true;
2246
2247save_err:
2248 rb->close(tfd);
2249 rb->remove(SETTINGS_TMP_FILE);
2250 return false;
1377} 2251}
1378 2252
1379static void viewer_exit(void *parameter) 2253static void viewer_exit(void *parameter)
1380{ 2254{
1381 (void)parameter; 2255 (void)parameter;
1382 2256
1383 viewer_save_settings(); 2257 /* save preference and bookmarks */
2258 if (!viewer_save_settings())
2259 rb->splash(HZ, "Can't save preference and bookmarks.");
2260
1384 rb->close(fd); 2261 rb->close(fd);
2262#ifdef HAVE_LCD_BITMAP
2263 if (strcmp(prefs.font, rb->global_settings->font_file))
2264 change_font(rb->global_settings->font_file);
2265#endif
2266}
2267
2268static void calc_page(void)
2269{
2270 int i;
2271 unsigned char *line_begin;
2272 unsigned char *line_end;
2273 off_t sfp;
2274 unsigned char *sstp;
2275
2276 rb->splash(0, "Calculating page/line number...");
2277
2278 /* add reading page to bookmarks */
2279 viewer_add_last_read_bookmark();
2280
2281 rb->qsort(bookmarks, bookmark_count, sizeof(struct bookmark_info),
2282 bm_comp);
2283
2284 cpage = 1;
2285 cline = 1;
2286 file_pos = 0;
2287 screen_top_ptr = buffer;
2288 buffer_end = BUFFER_END();
2289
2290 fill_buffer(file_pos, buffer, buffer_size);
2291 line_end = line_begin = buffer;
2292
2293 for (i = 0; i < bookmark_count; i++)
2294 {
2295 sfp = bookmarks[i].file_position;
2296 sstp = buffer;
2297
2298 while ((line_begin > sstp || sstp >= line_end) ||
2299 (file_pos > sfp || sfp >= file_pos + BUFFER_END() - buffer))
2300 {
2301 get_next_line_position(&line_begin, &line_end, NULL);
2302 if (line_end == NULL)
2303 break;
2304
2305 next_line_ptr = line_end;
2306
2307 if (sstp == buffer &&
2308 file_pos <= sfp && sfp < file_pos + BUFFER_END() - buffer)
2309 sstp = sfp - file_pos + buffer;
2310
2311 increment_current_line();
2312 }
2313
2314 decrement_current_line();
2315 bookmarks[i].page = cpage;
2316 bookmarks[i].line = cline;
2317 bookmarks[i].file_position = file_pos + (line_begin - buffer);
2318 increment_current_line();
2319 }
2320
2321 /* remove reading page's bookmark */
2322 for (i = 0; i < bookmark_count; i++)
2323 {
2324 if (bookmarks[i].flag & BOOKMARK_LAST)
2325 {
2326 int screen_pos;
2327 int screen_top;
2328
2329 screen_pos = bookmarks[i].file_position;
2330 screen_top = screen_pos % buffer_size;
2331 file_pos = screen_pos - screen_top;
2332 screen_top_ptr = buffer + screen_top;
2333
2334 cpage = bookmarks[i].page;
2335 cline = bookmarks[i].line;
2336 bookmarks[i].flag ^= BOOKMARK_LAST;
2337 buffer_end = BUFFER_END();
2338
2339 fill_buffer(file_pos, buffer, buffer_size);
2340
2341 if (bookmarks[i].flag == 0)
2342 viewer_remove_bookmark(i);
2343
2344 if (prefs.scroll_mode == PAGE && cline > 1)
2345 viewer_scroll_to_top_line();
2346 break;
2347 }
2348 }
1385} 2349}
1386 2350
1387static int col_limit(int col) 2351static int col_limit(int col)
@@ -1389,8 +2353,8 @@ static int col_limit(int col)
1389 if (col < 0) 2353 if (col < 0)
1390 col = 0; 2354 col = 0;
1391 else 2355 else
1392 if (col > max_line_len - 2*glyph_width('o')) 2356 if (col >= max_width)
1393 col = max_line_len - 2*glyph_width('o'); 2357 col = max_width - draw_columns;
1394 2358
1395 return col; 2359 return col;
1396} 2360}
@@ -1401,6 +2365,8 @@ static bool encoding_setting(void)
1401{ 2365{
1402 static struct opt_items names[NUM_CODEPAGES]; 2366 static struct opt_items names[NUM_CODEPAGES];
1403 int idx; 2367 int idx;
2368 bool res;
2369 enum codepages oldenc = prefs.encoding;
1404 2370
1405 for (idx = 0; idx < NUM_CODEPAGES; idx++) 2371 for (idx = 0; idx < NUM_CODEPAGES; idx++)
1406 { 2372 {
@@ -1408,8 +2374,21 @@ static bool encoding_setting(void)
1408 names[idx].voice_id = -1; 2374 names[idx].voice_id = -1;
1409 } 2375 }
1410 2376
1411 return rb->set_option("Encoding", &prefs.encoding, INT, names, 2377 res = rb->set_option("Encoding", &prefs.encoding, INT, names,
1412 sizeof(names) / sizeof(names[0]), NULL); 2378 sizeof(names) / sizeof(names[0]), NULL);
2379
2380 /* When prefs.encoding changes into UTF-8 or changes from UTF-8,
2381 * filesize (file_size) might change.
2382 * In addition, if prefs.encoding is UTF-8, then BOM does not read.
2383 */
2384 if (oldenc != prefs.encoding && (oldenc == UTF_8 || prefs.encoding == UTF_8))
2385 {
2386 check_bom();
2387 get_filesize();
2388 fill_buffer(file_pos, buffer, buffer_size);
2389 }
2390
2391 return res;
1413} 2392}
1414 2393
1415static bool word_wrap_setting(void) 2394static bool word_wrap_setting(void)
@@ -1449,6 +2428,7 @@ static bool view_mode_setting(void)
1449 names , 2, NULL); 2428 names , 2, NULL);
1450 if (prefs.view_mode == NARROW) 2429 if (prefs.view_mode == NARROW)
1451 col = 0; 2430 col = 0;
2431 calc_max_width();
1452 return ret; 2432 return ret;
1453} 2433}
1454 2434
@@ -1485,6 +2465,152 @@ static bool scrollbar_setting(void)
1485 return rb->set_option("Show Scrollbar", &prefs.scrollbar_mode, INT, 2465 return rb->set_option("Show Scrollbar", &prefs.scrollbar_mode, INT,
1486 names, 2, NULL); 2466 names, 2, NULL);
1487} 2467}
2468
2469static bool header_setting(void)
2470{
2471 int len = (rb->global_settings->statusbar == STATUSBAR_TOP)? 4 : 2;
2472 struct opt_items names[len];
2473
2474 names[0].string = "None";
2475 names[0].voice_id = -1;
2476 names[1].string = "File path";
2477 names[1].voice_id = -1;
2478
2479 if (rb->global_settings->statusbar == STATUSBAR_TOP)
2480 {
2481 names[2].string = "Status bar";
2482 names[2].voice_id = -1;
2483 names[3].string = "Both";
2484 names[3].voice_id = -1;
2485 }
2486
2487 return rb->set_option("Show Header", &prefs.header_mode, INT,
2488 names, len, NULL);
2489}
2490
2491static bool footer_setting(void)
2492{
2493 int len = (rb->global_settings->statusbar == STATUSBAR_BOTTOM)? 4 : 2;
2494 struct opt_items names[len];
2495
2496 names[0].string = "None";
2497 names[0].voice_id = -1;
2498 names[1].string = "Page Num";
2499 names[1].voice_id = -1;
2500
2501 if (rb->global_settings->statusbar == STATUSBAR_BOTTOM)
2502 {
2503 names[2].string = "Status bar";
2504 names[2].voice_id = -1;
2505 names[3].string = "Both";
2506 names[3].voice_id = -1;
2507 }
2508
2509 return rb->set_option("Show Footer", &prefs.footer_mode, INT,
2510 names, len, NULL);
2511}
2512
2513static int font_comp(const void *a, const void *b)
2514{
2515 struct opt_items *pa;
2516 struct opt_items *pb;
2517
2518 pa = (struct opt_items *)a;
2519 pb = (struct opt_items *)b;
2520
2521 return rb->strcmp(pa->string, pb->string);
2522}
2523
2524static bool font_setting(void)
2525{
2526 int count = 0;
2527 DIR *dir;
2528 struct dirent *entry;
2529 int i = 0;
2530 int len;
2531 int new_font = 0;
2532 int old_font;
2533 bool res;
2534 int size = 0;
2535
2536 dir = rb->opendir(FONT_DIR);
2537 if (!dir)
2538 {
2539 rb->splash(HZ/2, "font dir does not access.");
2540 return false;
2541 }
2542
2543 while (1)
2544 {
2545 entry = rb->readdir(dir);
2546
2547 if (entry == NULL)
2548 break;
2549
2550 len = rb->strlen(entry->d_name);
2551 if (len < 4 || rb->strcmp(entry->d_name + len-4, ".fnt"))
2552 continue;
2553 size += len-3;
2554 count++;
2555 }
2556 rb->closedir(dir);
2557
2558 struct opt_items names[count];
2559 unsigned char font_names[size];
2560 unsigned char *p = font_names;
2561
2562 dir = rb->opendir(FONT_DIR);
2563 if (!dir)
2564 {
2565 rb->splash(HZ/2, "font dir does not access.");
2566 return false;
2567 }
2568
2569 while (1)
2570 {
2571 entry = rb->readdir(dir);
2572
2573 if (entry == NULL)
2574 break;
2575
2576 len = rb->strlen(entry->d_name);
2577 if (len < 4 || rb->strcmp(entry->d_name + len-4, ".fnt"))
2578 continue;
2579
2580 rb->snprintf(p, len-3, "%s", entry->d_name);
2581 names[i].string = p;
2582 names[i].voice_id = -1;
2583 p += len-3;
2584 i++;
2585 if (i >= count)
2586 break;
2587 }
2588 rb->closedir(dir);
2589
2590 rb->qsort(names, count, sizeof(struct opt_items), font_comp);
2591
2592 for (i = 0; i < count; i++)
2593 {
2594 if (!rb->strcmp(names[i].string, prefs.font))
2595 {
2596 new_font = i;
2597 break;
2598 }
2599 }
2600 old_font = new_font;
2601
2602 res = rb->set_option("Select Font", &new_font, INT,
2603 names, count, NULL);
2604
2605 if (new_font != old_font)
2606 {
2607 rb->memset(prefs.font, 0, MAX_PATH);
2608 rb->snprintf(prefs.font, MAX_PATH, "%s", names[new_font].string);
2609 change_font(prefs.font);
2610 }
2611
2612 return res;
2613}
1488#endif 2614#endif
1489 2615
1490static bool autoscroll_speed_setting(void) 2616static bool autoscroll_speed_setting(void)
@@ -1506,6 +2632,12 @@ MENUITEM_FUNCTION(scrollbar_item, 0, "Show Scrollbar", scrollbar_setting,
1506 NULL, NULL, Icon_NOICON); 2632 NULL, NULL, Icon_NOICON);
1507MENUITEM_FUNCTION(page_mode_item, 0, "Overlap Pages", page_mode_setting, 2633MENUITEM_FUNCTION(page_mode_item, 0, "Overlap Pages", page_mode_setting,
1508 NULL, NULL, Icon_NOICON); 2634 NULL, NULL, Icon_NOICON);
2635MENUITEM_FUNCTION(header_item, 0, "Show Header", header_setting,
2636 NULL, NULL, Icon_NOICON);
2637MENUITEM_FUNCTION(footer_item, 0, "Show Footer", footer_setting,
2638 NULL, NULL, Icon_NOICON);
2639MENUITEM_FUNCTION(font_item, 0, "Font", font_setting,
2640 NULL, NULL, Icon_NOICON);
1509#endif 2641#endif
1510MENUITEM_FUNCTION(scroll_mode_item, 0, "Scroll Mode", scroll_mode_setting, 2642MENUITEM_FUNCTION(scroll_mode_item, 0, "Scroll Mode", scroll_mode_setting,
1511 NULL, NULL, Icon_NOICON); 2643 NULL, NULL, Icon_NOICON);
@@ -1514,28 +2646,39 @@ MENUITEM_FUNCTION(autoscroll_speed_item, 0, "Auto-Scroll Speed",
1514MAKE_MENU(option_menu, "Viewer Options", NULL, Icon_NOICON, 2646MAKE_MENU(option_menu, "Viewer Options", NULL, Icon_NOICON,
1515 &encoding_item, &word_wrap_item, &line_mode_item, &view_mode_item, 2647 &encoding_item, &word_wrap_item, &line_mode_item, &view_mode_item,
1516#ifdef HAVE_LCD_BITMAP 2648#ifdef HAVE_LCD_BITMAP
1517 &scrollbar_item, &page_mode_item, 2649 &scrollbar_item, &page_mode_item, &header_item, &footer_item, &font_item,
1518#endif 2650#endif
1519 &scroll_mode_item, &autoscroll_speed_item); 2651 &scroll_mode_item, &autoscroll_speed_item);
1520 2652
1521static bool viewer_options_menu(void) 2653static bool viewer_options_menu(bool is_global)
1522{ 2654{
1523 bool result; 2655 bool result;
2656 struct preferences tmp_prefs;
2657
2658 rb->memcpy(&tmp_prefs, &prefs, sizeof(struct preferences));
2659
1524 result = (rb->do_menu(&option_menu, NULL, NULL, false) == MENU_ATTACHED_USB); 2660 result = (rb->do_menu(&option_menu, NULL, NULL, false) == MENU_ATTACHED_USB);
1525 2661
2662 if (!is_global && rb->memcmp(&tmp_prefs, &prefs, sizeof(struct preferences)))
2663 {
2664 /* Show-scrollbar mode for current view-width mode */
1526#ifdef HAVE_LCD_BITMAP 2665#ifdef HAVE_LCD_BITMAP
1527 /* Show-scrollbar mode for current view-width mode */ 2666 init_need_scrollbar();
1528 init_need_scrollbar(); 2667 init_header_and_footer();
1529#endif 2668#endif
2669 calc_page();
2670 }
1530 return result; 2671 return result;
1531} 2672}
1532 2673
1533static void viewer_menu(void) 2674static void viewer_menu(void)
1534{ 2675{
1535 int result; 2676 int result;
2677
1536 MENUITEM_STRINGLIST(menu, "Viewer Menu", NULL, 2678 MENUITEM_STRINGLIST(menu, "Viewer Menu", NULL,
1537 "Return", "Viewer Options", 2679 "Return", "Viewer Options",
1538 "Show Playback Menu", "Quit"); 2680 "Show Playback Menu", "Select Bookmark",
2681 "Global Settings", "Quit");
1539 2682
1540 result = rb->do_menu(&menu, NULL, NULL, false); 2683 result = rb->do_menu(&menu, NULL, NULL, false);
1541 switch (result) 2684 switch (result)
@@ -1543,12 +2686,31 @@ static void viewer_menu(void)
1543 case 0: /* return */ 2686 case 0: /* return */
1544 break; 2687 break;
1545 case 1: /* change settings */ 2688 case 1: /* change settings */
1546 done = viewer_options_menu(); 2689 done = viewer_options_menu(false);
1547 break; 2690 break;
1548 case 2: /* playback control */ 2691 case 2: /* playback control */
1549 playback_control(NULL); 2692 playback_control(NULL);
1550 break; 2693 break;
1551 case 3: /* quit */ 2694 case 3: /* select bookmark */
2695 viewer_select_bookmark(viewer_add_last_read_bookmark());
2696 viewer_remove_last_read_bookmark();
2697 fill_buffer(file_pos, buffer, buffer_size);
2698 if (prefs.scroll_mode == PAGE && cline > 1)
2699 viewer_scroll_to_top_line();
2700 break;
2701 case 4: /* change global settings */
2702 {
2703 struct preferences orig_prefs;
2704
2705 rb->memcpy(&orig_prefs, &prefs, sizeof(struct preferences));
2706 if (!viewer_load_global_settings())
2707 viewer_default_preferences();
2708 done = viewer_options_menu(true);
2709 viewer_save_global_settings();
2710 rb->memcpy(&prefs, &orig_prefs, sizeof(struct preferences));
2711 }
2712 break;
2713 case 5: /* quit */
1552 viewer_exit(NULL); 2714 viewer_exit(NULL);
1553 done = true; 2715 done = true;
1554 break; 2716 break;
@@ -1567,6 +2729,13 @@ enum plugin_status plugin_start(const void* file)
1567 2729
1568 /* get the plugin buffer */ 2730 /* get the plugin buffer */
1569 buffer = rb->plugin_get_buffer((size_t *)&buffer_size); 2731 buffer = rb->plugin_get_buffer((size_t *)&buffer_size);
2732 if (buffer_size == 0)
2733 {
2734 rb->splash(HZ, "buffer does not allocate !!");
2735 return PLUGIN_ERROR;
2736 }
2737 block_size = buffer_size / 3;
2738 buffer_size = 3 * block_size;
1570 2739
1571 if (!file) 2740 if (!file)
1572 return PLUGIN_ERROR; 2741 return PLUGIN_ERROR;
@@ -1592,13 +2761,14 @@ enum plugin_status plugin_start(const void* file)
1592 { 2761 {
1593 if(old_tick <= *rb->current_tick - (110-prefs.autoscroll_speed*10)) 2762 if(old_tick <= *rb->current_tick - (110-prefs.autoscroll_speed*10))
1594 { 2763 {
1595 viewer_scroll_down(); 2764 viewer_scroll_down(true);
1596 viewer_draw(col); 2765 viewer_draw(col);
1597 old_tick = *rb->current_tick; 2766 old_tick = *rb->current_tick;
1598 } 2767 }
1599 } 2768 }
1600 2769
1601 button = rb->button_get_w_tmo(HZ/10); 2770 button = rb->button_get_w_tmo(HZ/10);
2771
1602 switch (button) { 2772 switch (button) {
1603 case VIEWER_MENU: 2773 case VIEWER_MENU:
1604#ifdef VIEWER_MENU2 2774#ifdef VIEWER_MENU2
@@ -1647,10 +2817,14 @@ enum plugin_status plugin_start(const void* file)
1647 { 2817 {
1648 /* Page down */ 2818 /* Page down */
1649 if (next_screen_ptr != NULL) 2819 if (next_screen_ptr != NULL)
2820 {
1650 screen_top_ptr = next_screen_to_draw_ptr; 2821 screen_top_ptr = next_screen_to_draw_ptr;
2822 if (cpage < MAX_PAGE)
2823 cpage++;
2824 }
1651 } 2825 }
1652 else 2826 else
1653 viewer_scroll_down(); 2827 viewer_scroll_down(autoscroll);
1654 old_tick = *rb->current_tick; 2828 old_tick = *rb->current_tick;
1655 viewer_draw(col); 2829 viewer_draw(col);
1656 break; 2830 break;
@@ -1697,8 +2871,8 @@ enum plugin_status plugin_start(const void* file)
1697 case VIEWER_LINE_DOWN: 2871 case VIEWER_LINE_DOWN:
1698 case VIEWER_LINE_DOWN | BUTTON_REPEAT: 2872 case VIEWER_LINE_DOWN | BUTTON_REPEAT:
1699 /* Scroll down one line */ 2873 /* Scroll down one line */
1700 if (next_screen_ptr != NULL) 2874 viewer_scroll_down(autoscroll);
1701 screen_top_ptr = next_line_ptr; 2875 increment_current_line();
1702 old_tick = *rb->current_tick; 2876 old_tick = *rb->current_tick;
1703 viewer_draw(col); 2877 viewer_draw(col);
1704 break; 2878 break;
@@ -1736,6 +2910,29 @@ enum plugin_status plugin_start(const void* file)
1736 done = true; 2910 done = true;
1737 break; 2911 break;
1738 2912
2913 case VIEWER_BOOKMARK:
2914 {
2915 int idx = viewer_find_bookmark(cpage, cline);
2916
2917 if (idx < 0)
2918 {
2919 if (bookmark_count >= MAX_BOOKMARKS-1)
2920 rb->splash(HZ/2, "No more add bookmark.");
2921 else
2922 {
2923 viewer_add_bookmark();
2924 rb->splash(HZ/2, "Bookmark add.");
2925 }
2926 }
2927 else
2928 {
2929 viewer_remove_bookmark(idx);
2930 rb->splash(HZ/2, "Bookmark remove.");
2931 }
2932 viewer_draw(col);
2933 }
2934 break;
2935
1739 default: 2936 default:
1740 if (rb->default_event_handler_ex(button, viewer_exit, NULL) 2937 if (rb->default_event_handler_ex(button, viewer_exit, NULL)
1741 == SYS_USB_CONNECTED) 2938 == SYS_USB_CONNECTED)
@@ -1750,5 +2947,3 @@ enum plugin_status plugin_start(const void* file)
1750 } 2947 }
1751 return PLUGIN_OK; 2948 return PLUGIN_OK;
1752} 2949}
1753
1754