1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Gilles Roux, 2003 Garrett Derner
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include "lib/playback_control.h"
27 /* global settings file
28 * binary file, so dont use .cfg
33 * --------------------------------
50 #define GLOBAL_SETTINGS_FILE VIEWERS_DIR "/viewer.dat"
53 #define GLOBAL_SETTINGS_TMP_FILE VIEWERS_DIR "/viewer_file.tmp"
55 #define GLOBAL_SETTINGS_HEADER "\x54\x56\x47\x53" /* header="TVGS" */
56 #define GLOBAL_SETTINGS_H_SIZE 5
57 #define GLOBAL_SETTINGS_VERSION 0x32 /* version=2 */
58 #define GLOBAL_SETTINGS_FIRST_VERSION 0x31
60 /* preferences and bookmarks at each file
61 * binary file, so dont use .cfg
66 * --------------------------------
100 #define SETTINGS_FILE VIEWERS_DIR "/viewer_file.dat"
103 #define SETTINGS_TMP_FILE VIEWERS_DIR "/viewer_file.tmp"
105 #define SETTINGS_HEADER "\x54\x56\x53" /* header="TVS" */
106 #define SETTINGS_H_SIZE 4
107 #define SETTINGS_VERSION 0x33 /* version=3 */
108 #define SETTINGS_FIRST_VERSION 0x32
110 #define WRAP_TRIM 44 /* Max number of spaces to trim (arbitrary) */
111 #define NARROW_MAX_COLUMNS 64 /* Max displayable string len [narrow] (over-estimate) */
112 #define WIDE_MAX_COLUMNS 128 /* Max displayable string len [wide] (over-estimate) */
113 #define MAX_WIDTH 910 /* Max line length in WIDE mode */
114 #define READ_PREV_ZONE (block_size*9/10) /* Arbitrary number less than SMALL_BLOCK_SIZE */
115 #define SMALL_BLOCK_SIZE block_size /* Smallest file chunk we will read */
116 #define LARGE_BLOCK_SIZE (block_size << 1) /* Preferable size of file chunk to read */
117 #define TOP_SECTOR buffer
118 #define MID_SECTOR (buffer + SMALL_BLOCK_SIZE)
119 #define BOTTOM_SECTOR (buffer + (SMALL_BLOCK_SIZE << 1))
120 #undef SCROLLBAR_WIDTH
121 #define SCROLLBAR_WIDTH rb->global_settings->scrollbar_width
122 #define MAX_PAGE 9999
124 #define BOOKMARK_SIZE 8
125 #define MAX_BOOKMARKS 10 /* user setting bookmarks + last read page */
127 #define BOOKMARK_LAST 1
128 #define BOOKMARK_USER 2
130 #ifndef HAVE_LCD_BITMAP
131 #define BOOKMARK_ICON "\xee\x84\x81\x00"
134 #define PREFERENCES_SIZE (12 + MAX_PATH)
136 /* Out-Of-Bounds test for any pointer to data in the buffer */
137 #define BUFFER_OOB(p) ((p) < buffer || (p) >= buffer_end)
139 /* Does the buffer contain the beginning of the file? */
140 #define BUFFER_BOF() (file_pos==0)
142 /* Does the buffer contain the end of the file? */
143 #define BUFFER_EOF() (file_size-file_pos <= buffer_size)
145 /* Formula for the endpoint address outside of buffer data */
146 #define BUFFER_END() \
147 ((BUFFER_EOF()) ? (file_size-file_pos+buffer) : (buffer+buffer_size))
149 /* Is the entire file being shown in one screen? */
150 #define ONE_SCREEN_FITS_ALL() \
151 (next_screen_ptr==NULL && screen_top_ptr==buffer && BUFFER_BOF())
153 /* Is a scrollbar called for on the current screen? */
154 #define NEED_SCROLLBAR() \
155 ((!(ONE_SCREEN_FITS_ALL())) && (prefs.scrollbar_mode==SB_ON))
157 /* variable button definitions */
160 #if CONFIG_KEYPAD == RECORDER_PAD
161 #define VIEWER_QUIT BUTTON_OFF
162 #define VIEWER_PAGE_UP BUTTON_UP
163 #define VIEWER_PAGE_DOWN BUTTON_DOWN
164 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
165 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
166 #define VIEWER_MENU BUTTON_F1
167 #define VIEWER_AUTOSCROLL BUTTON_PLAY
168 #define VIEWER_LINE_UP (BUTTON_ON | BUTTON_UP)
169 #define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN)
170 #define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT)
171 #define VIEWER_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT)
172 #define VIEWER_BOOKMARK BUTTON_F2
174 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
175 #define VIEWER_QUIT BUTTON_OFF
176 #define VIEWER_PAGE_UP BUTTON_UP
177 #define VIEWER_PAGE_DOWN BUTTON_DOWN
178 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
179 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
180 #define VIEWER_MENU BUTTON_F1
181 #define VIEWER_AUTOSCROLL BUTTON_SELECT
182 #define VIEWER_LINE_UP (BUTTON_ON | BUTTON_UP)
183 #define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN)
184 #define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT)
185 #define VIEWER_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT)
186 #define VIEWER_BOOKMARK BUTTON_F2
189 #elif CONFIG_KEYPAD == ONDIO_PAD
190 #define VIEWER_QUIT BUTTON_OFF
191 #define VIEWER_PAGE_UP BUTTON_UP
192 #define VIEWER_PAGE_DOWN BUTTON_DOWN
193 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
194 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
195 #define VIEWER_MENU (BUTTON_MENU|BUTTON_REPEAT)
196 #define VIEWER_AUTOSCROLL_PRE BUTTON_MENU
197 #define VIEWER_AUTOSCROLL (BUTTON_MENU|BUTTON_REL)
198 #define VIEWER_BOOKMARK (BUTTON_MENU|BUTTON_OFF)
201 #elif CONFIG_KEYPAD == PLAYER_PAD
202 #define VIEWER_QUIT BUTTON_STOP
203 #define VIEWER_PAGE_UP BUTTON_LEFT
204 #define VIEWER_PAGE_DOWN BUTTON_RIGHT
205 #define VIEWER_SCREEN_LEFT (BUTTON_ON|BUTTON_LEFT)
206 #define VIEWER_SCREEN_RIGHT (BUTTON_ON|BUTTON_RIGHT)
207 #define VIEWER_MENU BUTTON_MENU
208 #define VIEWER_AUTOSCROLL BUTTON_PLAY
209 #define VIEWER_BOOKMARK BUTTON_ON
211 /* iRiver H1x0 && H3x0 keys */
212 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
213 (CONFIG_KEYPAD == IRIVER_H300_PAD)
214 #define VIEWER_QUIT BUTTON_OFF
215 #define VIEWER_PAGE_UP BUTTON_UP
216 #define VIEWER_PAGE_DOWN BUTTON_DOWN
217 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
218 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
219 #define VIEWER_MENU BUTTON_MODE
220 #define VIEWER_AUTOSCROLL BUTTON_SELECT
221 #define VIEWER_LINE_UP (BUTTON_ON | BUTTON_UP)
222 #define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN)
223 #define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT)
224 #define VIEWER_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT)
225 #define VIEWER_BOOKMARK (BUTTON_ON | BUTTON_SELECT)
227 #define VIEWER_RC_QUIT BUTTON_RC_STOP
230 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
231 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
232 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
233 #define VIEWER_QUIT_PRE BUTTON_SELECT
234 #define VIEWER_QUIT (BUTTON_SELECT | BUTTON_MENU)
235 #define VIEWER_PAGE_UP BUTTON_SCROLL_BACK
236 #define VIEWER_PAGE_DOWN BUTTON_SCROLL_FWD
237 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
238 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
239 #define VIEWER_MENU BUTTON_MENU
240 #define VIEWER_AUTOSCROLL BUTTON_PLAY
241 #define VIEWER_BOOKMARK BUTTON_SELECT
244 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
245 #define VIEWER_QUIT BUTTON_PLAY
246 #define VIEWER_PAGE_UP BUTTON_UP
247 #define VIEWER_PAGE_DOWN BUTTON_DOWN
248 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
249 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
250 #define VIEWER_MENU BUTTON_MODE
251 #define VIEWER_AUTOSCROLL BUTTON_SELECT
252 #define VIEWER_BOOKMARK (BUTTON_LEFT|BUTTON_SELECT)
255 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
256 #define VIEWER_QUIT BUTTON_POWER
257 #define VIEWER_PAGE_UP BUTTON_UP
258 #define VIEWER_PAGE_DOWN BUTTON_DOWN
259 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
260 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
261 #define VIEWER_MENU BUTTON_SELECT
262 #define VIEWER_AUTOSCROLL BUTTON_PLAY
263 #define VIEWER_BOOKMARK BUTTON_REC
266 #elif CONFIG_KEYPAD == GIGABEAT_PAD
267 #define VIEWER_QUIT BUTTON_POWER
268 #define VIEWER_PAGE_UP BUTTON_UP
269 #define VIEWER_PAGE_DOWN BUTTON_DOWN
270 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
271 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
272 #define VIEWER_MENU BUTTON_MENU
273 #define VIEWER_AUTOSCROLL BUTTON_A
274 #define VIEWER_BOOKMARK BUTTON_SELECT
276 /* Sansa E200 keys */
277 #elif CONFIG_KEYPAD == SANSA_E200_PAD
278 #define VIEWER_QUIT BUTTON_POWER
279 #define VIEWER_PAGE_UP BUTTON_UP
280 #define VIEWER_PAGE_DOWN BUTTON_DOWN
281 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
282 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
283 #define VIEWER_MENU BUTTON_SELECT
284 #define VIEWER_AUTOSCROLL BUTTON_REC
285 #define VIEWER_LINE_UP BUTTON_SCROLL_BACK
286 #define VIEWER_LINE_DOWN BUTTON_SCROLL_FWD
287 #define VIEWER_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT)
289 /* Sansa Fuze keys */
290 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
291 #define VIEWER_QUIT (BUTTON_HOME|BUTTON_REPEAT)
292 #define VIEWER_PAGE_UP BUTTON_UP
293 #define VIEWER_PAGE_DOWN BUTTON_DOWN
294 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
295 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
296 #define VIEWER_MENU BUTTON_SELECT|BUTTON_REPEAT
297 #define VIEWER_AUTOSCROLL BUTTON_SELECT|BUTTON_DOWN
298 #define VIEWER_LINE_UP BUTTON_SCROLL_BACK
299 #define VIEWER_LINE_DOWN BUTTON_SCROLL_FWD
300 #define VIEWER_BOOKMARK BUTTON_SELECT
302 /* Sansa C200 keys */
303 #elif CONFIG_KEYPAD == SANSA_C200_PAD
304 #define VIEWER_QUIT BUTTON_POWER
305 #define VIEWER_PAGE_UP BUTTON_VOL_UP
306 #define VIEWER_PAGE_DOWN BUTTON_VOL_DOWN
307 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
308 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
309 #define VIEWER_MENU BUTTON_SELECT
310 #define VIEWER_AUTOSCROLL BUTTON_REC
311 #define VIEWER_LINE_UP BUTTON_UP
312 #define VIEWER_LINE_DOWN BUTTON_DOWN
313 #define VIEWER_BOOKMARK (BUTTON_DOWN | BUTTON_SELECT)
315 /* Sansa Clip keys */
316 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
317 #define VIEWER_QUIT BUTTON_POWER
318 #define VIEWER_PAGE_UP BUTTON_VOL_UP
319 #define VIEWER_PAGE_DOWN BUTTON_VOL_DOWN
320 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
321 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
322 #define VIEWER_MENU BUTTON_SELECT
323 #define VIEWER_AUTOSCROLL BUTTON_HOME
324 #define VIEWER_LINE_UP BUTTON_UP
325 #define VIEWER_LINE_DOWN BUTTON_DOWN
326 #define VIEWER_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT)
328 /* Sansa M200 keys */
329 #elif CONFIG_KEYPAD == SANSA_M200_PAD
330 #define VIEWER_QUIT BUTTON_POWER
331 #define VIEWER_PAGE_UP BUTTON_VOL_UP
332 #define VIEWER_PAGE_DOWN BUTTON_VOL_DOWN
333 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
334 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
335 #define VIEWER_MENU (BUTTON_SELECT | BUTTON_UP)
336 #define VIEWER_AUTOSCROLL (BUTTON_SELECT | BUTTON_REL)
337 #define VIEWER_LINE_UP BUTTON_UP
338 #define VIEWER_LINE_DOWN BUTTON_DOWN
339 #define VIEWER_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT)
341 /* iriver H10 keys */
342 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
343 #define VIEWER_QUIT BUTTON_POWER
344 #define VIEWER_PAGE_UP BUTTON_SCROLL_UP
345 #define VIEWER_PAGE_DOWN BUTTON_SCROLL_DOWN
346 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
347 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
348 #define VIEWER_MENU BUTTON_REW
349 #define VIEWER_AUTOSCROLL BUTTON_PLAY
350 #define VIEWER_BOOKMARK BUTTON_FF
353 #elif CONFIG_KEYPAD == MROBE500_PAD
354 #define VIEWER_QUIT BUTTON_POWER
355 #define VIEWER_PAGE_UP BUTTON_RC_PLAY
356 #define VIEWER_PAGE_DOWN BUTTON_RC_DOWN
357 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
358 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
359 #define VIEWER_MENU BUTTON_RC_HEART
360 #define VIEWER_AUTOSCROLL BUTTON_RC_MODE
361 #define VIEWER_BOOKMARK BUTTON_CENTER
364 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
365 #define VIEWER_QUIT BUTTON_BACK
366 #define VIEWER_PAGE_UP BUTTON_PREV
367 #define VIEWER_PAGE_DOWN BUTTON_NEXT
368 #define VIEWER_SCREEN_LEFT (BUTTON_PLAY | BUTTON_LEFT)
369 #define VIEWER_SCREEN_RIGHT (BUTTON_PLAY | BUTTON_RIGHT)
370 #define VIEWER_MENU BUTTON_MENU
371 #define VIEWER_AUTOSCROLL_PRE BUTTON_PLAY
372 #define VIEWER_AUTOSCROLL (BUTTON_PLAY|BUTTON_REL)
373 #define VIEWER_LINE_UP BUTTON_UP
374 #define VIEWER_LINE_DOWN BUTTON_DOWN
375 #define VIEWER_COLUMN_LEFT BUTTON_LEFT
376 #define VIEWER_COLUMN_RIGHT BUTTON_RIGHT
377 #define VIEWER_BOOKMARK BUTTON_SELECT
380 #elif CONFIG_KEYPAD == MROBE100_PAD
381 #define VIEWER_QUIT BUTTON_POWER
382 #define VIEWER_PAGE_UP BUTTON_UP
383 #define VIEWER_PAGE_DOWN BUTTON_DOWN
384 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
385 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
386 #define VIEWER_MENU BUTTON_MENU
387 #define VIEWER_AUTOSCROLL BUTTON_DISPLAY
388 #define VIEWER_BOOKMARK BUTTON_SELECT
391 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
392 #define VIEWER_QUIT BUTTON_REC
393 #define VIEWER_PAGE_UP BUTTON_RC_VOL_UP
394 #define VIEWER_PAGE_DOWN BUTTON_RC_VOL_DOWN
395 #define VIEWER_SCREEN_LEFT BUTTON_RC_REW
396 #define VIEWER_SCREEN_RIGHT BUTTON_RC_FF
397 #define VIEWER_MENU BUTTON_RC_MENU
398 #define VIEWER_AUTOSCROLL BUTTON_RC_MODE
399 #define VIEWER_RC_QUIT BUTTON_RC_REC
400 #define VIEWER_BOOKMARK BUTTON_RC_PLAY
403 #elif CONFIG_KEYPAD == COWON_D2_PAD
404 #define VIEWER_QUIT BUTTON_POWER
405 #define VIEWER_MENU BUTTON_MENU
406 #define VIEWER_PAGE_UP BUTTON_MINUS
407 #define VIEWER_PAGE_DOWN BUTTON_PLUS
408 #define VIEWER_BOOKMARK (BUTTON_MENU|BUTTON_PLUS)
410 #elif CONFIG_KEYPAD == IAUDIO67_PAD
411 #define VIEWER_QUIT BUTTON_POWER
412 #define VIEWER_PAGE_UP BUTTON_VOLUP
413 #define VIEWER_PAGE_DOWN BUTTON_VOLDOWN
414 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
415 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
416 #define VIEWER_MENU BUTTON_MENU
417 #define VIEWER_AUTOSCROLL BUTTON_PLAY
418 #define VIEWER_RC_QUIT BUTTON_STOP
419 #define VIEWER_BOOKMARK (BUTTON_LEFT|BUTTON_PLAY)
421 /* Creative Zen Vision:M keys */
422 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
423 #define VIEWER_QUIT BUTTON_BACK
424 #define VIEWER_PAGE_UP BUTTON_UP
425 #define VIEWER_PAGE_DOWN BUTTON_DOWN
426 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
427 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
428 #define VIEWER_MENU BUTTON_MENU
429 #define VIEWER_AUTOSCROLL BUTTON_SELECT
430 #define VIEWER_BOOKMARK BUTTON_PLAY
432 /* Philips HDD1630 keys */
433 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
434 #define VIEWER_QUIT BUTTON_POWER
435 #define VIEWER_PAGE_UP BUTTON_UP
436 #define VIEWER_PAGE_DOWN BUTTON_DOWN
437 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
438 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
439 #define VIEWER_MENU BUTTON_MENU
440 #define VIEWER_AUTOSCROLL BUTTON_VIEW
441 #define VIEWER_BOOKMARK BUTTON_SELECT
443 /* Philips SA9200 keys */
444 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
445 #define VIEWER_QUIT BUTTON_POWER
446 #define VIEWER_PAGE_UP BUTTON_UP
447 #define VIEWER_PAGE_DOWN BUTTON_DOWN
448 #define VIEWER_SCREEN_LEFT BUTTON_PREV
449 #define VIEWER_SCREEN_RIGHT BUTTON_NEXT
450 #define VIEWER_MENU BUTTON_MENU
451 #define VIEWER_AUTOSCROLL BUTTON_PLAY
452 #define VIEWER_BOOKMARK BUTTON_RIGHT
454 /* Onda VX747 keys */
455 #elif CONFIG_KEYPAD == ONDAVX747_PAD
456 #define VIEWER_QUIT BUTTON_POWER
457 #define VIEWER_MENU BUTTON_MENU
458 #define VIEWER_BOOKMARK (BUTTON_RIGHT|BUTTON_POWER)
460 /* Onda VX777 keys */
461 #elif CONFIG_KEYPAD == ONDAVX777_PAD
462 #define VIEWER_QUIT BUTTON_POWER
463 #define VIEWER_BOOKMARK (BUTTON_RIGHT|BUTTON_POWER)
465 /* SAMSUNG YH-820 / YH-920 / YH-925 keys */
466 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
467 #define VIEWER_QUIT BUTTON_REC
468 #define VIEWER_PAGE_UP BUTTON_UP
469 #define VIEWER_PAGE_DOWN BUTTON_DOWN
470 #define VIEWER_SCREEN_LEFT BUTTON_LEFT
471 #define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
472 #define VIEWER_MENU BUTTON_PLAY
473 #define VIEWER_AUTOSCROLL BUTTON_REW
474 #define VIEWER_BOOKMARK BUTTON_FFWD
476 /* Packard Bell Vibe 500 keys */
477 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
478 #define VIEWER_QUIT BUTTON_REC
479 #define VIEWER_PAGE_UP BUTTON_OK
480 #define VIEWER_PAGE_DOWN BUTTON_CANCEL
481 #define VIEWER_LINE_UP BUTTON_UP
482 #define VIEWER_LINE_DOWN BUTTON_DOWN
483 #define VIEWER_SCREEN_LEFT BUTTON_PREV
484 #define VIEWER_SCREEN_RIGHT BUTTON_NEXT
485 #define VIEWER_MENU BUTTON_MENU
486 #define VIEWER_AUTOSCROLL BUTTON_PLAY
487 #define VIEWER_BOOKMARK BUTTON_POWER
490 #error No keymap defined!
493 #ifdef HAVE_TOUCHSCREEN
495 #define VIEWER_QUIT2 BUTTON_TOPLEFT
497 #define VIEWER_QUIT BUTTON_TOPLEFT
499 #ifdef VIEWER_PAGE_UP
500 #define VIEWER_PAGE_UP2 BUTTON_TOPMIDDLE
502 #define VIEWER_PAGE_UP BUTTON_TOPMIDDLE
504 #ifdef VIEWER_PAGE_DOWN
505 #define VIEWER_PAGE_DOWN2 BUTTON_BOTTOMMIDDLE
507 #define VIEWER_PAGE_DOWN BUTTON_BOTTOMMIDDLE
509 #ifndef VIEWER_SCREEN_LEFT
510 #define VIEWER_SCREEN_LEFT BUTTON_MIDLEFT
512 #ifndef VIEWER_SCREEN_RIGHT
513 #define VIEWER_SCREEN_RIGHT BUTTON_MIDRIGHT
516 #define VIEWER_MENU2 BUTTON_TOPRIGHT
518 #define VIEWER_MENU BUTTON_TOPRIGHT
520 #ifndef VIEWER_AUTOSCROLL
521 #define VIEWER_AUTOSCROLL BUTTON_CENTER
525 /* stuff for the bookmarking */
526 struct bookmark_info
{
543 REFLOW
, /* won't be set on charcell LCD, must be last */
556 enum codepages encoding
;
588 int autoscroll_speed
;
590 unsigned char font
[MAX_PATH
];
594 VIEWER_FONT_MENU
= 0,
598 struct preferences prefs
;
599 struct preferences old_prefs
;
601 static unsigned char *buffer
;
602 static long buffer_size
;
603 static long block_size
= 0x1000;
604 static unsigned char line_break
[] = {0,0x20,9,0xB,0xC,'-'};
605 static int display_columns
; /* number of (pixel) columns on the display */
606 static int display_lines
; /* number of lines on the display */
607 static int draw_columns
; /* number of (pixel) columns available for text */
608 static int par_indent_spaces
; /* number of spaces to indent first paragraph */
610 static const char *file_name
;
611 static long file_size
;
612 static long start_position
; /* position in the file after the viewer is started */
613 static bool mac_text
;
614 static long file_pos
; /* Position of the top of the buffer in the file */
615 static long last_file_pos
;
616 static unsigned char *buffer_end
; /*Set to BUFFER_END() when file_pos changes*/
617 static int max_line_len
;
618 static int max_width
;
619 static int max_columns
;
620 static int cline
= 1;
621 static int cpage
= 1;
622 static int lpage
= 0;
623 static unsigned char *screen_top_ptr
;
624 static unsigned char *next_screen_ptr
;
625 static unsigned char *next_screen_to_draw_ptr
;
626 static unsigned char *next_line_ptr
;
627 static unsigned char *last_screen_top_ptr
= NULL
;
628 #ifdef HAVE_LCD_BITMAP
629 static struct font
*pf
;
630 static int header_height
= 0;
631 static int footer_height
= 0;
633 struct bookmark_info bookmarks
[MAX_BOOKMARKS
];
634 static int bookmark_count
;
637 #define BOM "\xef\xbb\xbf"
640 static bool is_bom
= false;
642 /* We draw a diacritic char over a non-diacritic one. Therefore, such chars are
643 * not considered to occupy space, therefore buffers might have more than
644 * max_columns characters. The DIACRITIC_FACTOR is the max ratio between all
645 * characters and non-diacritic characters in the buffer
647 #define DIACRITIC_FACTOR 2
649 /* calculate the width of a UCS character (zero width for diacritics) */
650 static int glyph_width(unsigned short ch
)
655 #ifdef HAVE_LCD_BITMAP
656 if (rb
->is_diacritic(ch
, NULL
))
659 return rb
->font_get_width(pf
, ch
);
665 /* get UCS character from string */
666 static unsigned char* get_ucs(const unsigned char* str
, unsigned short* ch
)
668 unsigned char utf8_tmp
[6];
671 if (prefs
.encoding
== UTF_8
)
672 return (unsigned char*)rb
->utf8decode(str
, ch
);
674 rb
->iso_decode(str
, utf8_tmp
, prefs
.encoding
, count
);
675 rb
->utf8decode(utf8_tmp
, ch
);
677 /* return a pointer after the parsed section of the string */
678 #ifdef HAVE_LCD_BITMAP
679 if (prefs
.encoding
>= SJIS
&& *str
>= 0x80
680 && !(prefs
.encoding
== SJIS
&& *str
> 0xA0 && *str
< 0xE0))
681 return (unsigned char*)str
+2;
684 return (unsigned char*)str
+1;
687 /* decode iso string into UTF-8 string */
688 static unsigned char *decode2utf8(const unsigned char *src
, unsigned char *dst
,
689 int skip_width
, int disp_width
)
691 unsigned short ucs
[max_columns
* DIACRITIC_FACTOR
+ 1];
693 const unsigned char *oldstr
= src
;
694 const unsigned char *str
= src
;
695 unsigned char *utf8
= dst
;
698 int width
= max_width
;
700 if (prefs
.alignment
== LEFT
)
702 /* skip the skip_width */
705 while (skip_width
> 0 && *str
!= '\0')
708 str
= get_ucs(oldstr
, &ch
);
709 skip_width
-= glyph_width(ch
);
715 /* decode until string end or disp_width reached */
718 str
= get_ucs(str
, &ch
);
719 disp_width
-= glyph_width(ch
);
722 utf8
= rb
->utf8encode(ch
, utf8
);
727 while (width
> 0 && *str
!= '\0')
729 str
= get_ucs(str
, &ch
);
734 skip_width
= max_width
- skip_width
- disp_width
;
737 while (skip_width
> 0 && chars
-- > 0)
738 skip_width
-= glyph_width(ucs
[chars
]);
746 while (disp_width
> 0 && idx
-- > 0)
747 disp_width
-= glyph_width(ucs
[idx
]);
749 if (disp_width
< 0 || idx
< 0)
753 for ( ; idx
< chars
; idx
++)
754 utf8
= rb
->utf8encode(ucs
[idx
], utf8
);
759 /* return a pointer after the dst string ends */
763 /* set max_columns and max_width */
764 static void calc_max_width(void)
766 if (prefs
.view_mode
== NARROW
)
768 max_columns
= NARROW_MAX_COLUMNS
;
769 max_width
= draw_columns
;
773 max_columns
= WIDE_MAX_COLUMNS
;
774 max_width
= 2 * draw_columns
;
778 static bool done
= false;
781 static inline void advance_conters(unsigned short ch
, int* k
, int* width
)
783 #ifdef HAVE_LCD_BITMAP
784 /* diacritics do not count */
785 if (rb
->is_diacritic(ch
, NULL
))
789 *width
+= glyph_width(ch
);
793 static inline bool line_is_full(int k
, int width
)
795 return ((k
>= max_columns
- 1) || (width
>= max_width
));
798 static unsigned char* crop_at_width(const unsigned char* p
)
802 const unsigned char *oldp
= p
;
806 while (!line_is_full(k
, width
)) {
811 advance_conters(ch
, &k
, &width
);
814 return (unsigned char*)oldp
;
817 static unsigned char* find_first_feed(const unsigned char* p
, int size
)
821 const unsigned char *oldp
= p
;
822 const unsigned char *lbrkp
= NULL
;
829 return (unsigned char*)p
;
833 if (prefs
.word_mode
== WRAP
)
835 for (j
= 0; j
< ((int) sizeof(line_break
)); j
++)
837 if (ch
== line_break
[j
])
845 width
+= glyph_width(ch
);
846 if (width
> max_width
)
847 return (lbrkp
== NULL
)? (unsigned char*)oldp
: (unsigned char*)lbrkp
;
855 static unsigned char* find_last_feed(const unsigned char* p
, int size
)
859 for (i
=size
-1; i
>=0; i
--)
861 return (unsigned char*) p
+i
;
866 static unsigned char* find_last_space(const unsigned char* p
, int size
)
870 k
= (prefs
.line_mode
==JOIN
) || (prefs
.line_mode
==REFLOW
) ? 0:1;
873 if (!BUFFER_OOB(&p
[i
]))
874 for (j
=k
; j
< ((int) sizeof(line_break
)) - 1; j
++) {
875 if (p
[i
] == line_break
[j
])
876 return (unsigned char*) p
+i
;
879 if (prefs
.word_mode
== WRAP
) {
880 for (i
=size
-1; i
>=0; i
--) {
881 for (j
=k
; j
< (int) sizeof(line_break
) - 1; j
++) {
882 if (p
[i
] == line_break
[j
])
883 return (unsigned char*) p
+i
;
891 static unsigned char* find_next_line(const unsigned char* cur_line
, bool *is_short
)
893 const unsigned char *next_line
= NULL
;
894 int size
, i
, j
, j_next
, j_prev
, k
, width
, search_len
, spaces
, newlines
;
898 if (is_short
!= NULL
)
901 if BUFFER_OOB(cur_line
)
904 if (prefs
.view_mode
== WIDE
) {
905 search_len
= MAX_WIDTH
;
907 else { /* prefs.view_mode == NARROW */
908 search_len
= crop_at_width(cur_line
) - cur_line
;
911 size
= BUFFER_OOB(cur_line
+search_len
) ? buffer_end
-cur_line
: search_len
;
913 if ((prefs
.line_mode
== JOIN
) || (prefs
.line_mode
== REFLOW
)) {
914 /* Need to scan ahead and possibly increase search_len and size,
915 or possibly set next_line at second hard return in a row. */
918 j_next
=j
=k
=width
=spaces
=newlines
=0;
920 const unsigned char *p
, *oldp
;
925 if (BUFFER_OOB(cur_line
+j
))
927 if (line_is_full(k
, width
)) {
928 size
= search_len
= j_prev
;
932 oldp
= p
= &cur_line
[j
];
934 j_next
= j
+ (p
- oldp
);
938 if (prefs
.line_mode
== REFLOW
) {
941 next_line
= cur_line
+ size
;
942 return (unsigned char*) next_line
;
944 if (j
==0) /* i=1 is intentional */
945 for (i
=0; i
<par_indent_spaces
; i
++)
946 advance_conters(' ', &k
, &width
);
948 if (!first_chars
) spaces
++;
954 next_line
= cur_line
+ size
- spaces
;
955 if (next_line
!= cur_line
)
956 return (unsigned char*) next_line
;
962 if (BUFFER_OOB(cur_line
+size
) || size
> 2*search_len
)
965 spaces
= first_chars
? 0:1;
969 if (prefs
.line_mode
==JOIN
|| newlines
>0) {
972 advance_conters(' ', &k
, &width
);
973 if (line_is_full(k
, width
)) {
974 size
= search_len
= j
;
980 /* REFLOW, multiple spaces between words: count only
981 * one. If more are needed, they will be added
985 advance_conters(' ', &k
, &width
);
986 if (line_is_full(k
, width
)) {
987 size
= search_len
= j
;
992 advance_conters(ch
, &k
, &width
);
998 /* find first hard return */
999 next_line
= find_first_feed(cur_line
, size
);
1002 if (next_line
== NULL
)
1003 if (size
== search_len
) {
1004 if (prefs
.word_mode
== WRAP
) /* Find last space */
1005 next_line
= find_last_space(cur_line
, size
);
1007 if (next_line
== NULL
) {
1008 next_line
= crop_at_width(cur_line
);
1011 if (prefs
.word_mode
== WRAP
) {
1012 for (i
=0;i
<WRAP_TRIM
;i
++) {
1013 if (!(isspace(next_line
[0]) && !BUFFER_OOB(next_line
)))
1021 if (prefs
.line_mode
== EXPAND
)
1022 if (!BUFFER_OOB(next_line
)) /* Not Null & not out of bounds */
1023 if (next_line
[0] == 0)
1024 if (next_line
!= cur_line
)
1025 return (unsigned char*) next_line
;
1027 /* If next_line is pointing to a zero, increment it; i.e.,
1028 leave the terminator at the end of cur_line. If pointing
1029 to a hyphen, increment only if there is room to display
1030 the hyphen on current line (won't apply in WIDE mode,
1031 since it's guarenteed there won't be room). */
1032 if (!BUFFER_OOB(next_line
)) /* Not Null & not out of bounds */
1033 if (next_line
[0] == 0)/* ||
1034 (next_line[0] == '-' && next_line-cur_line < draw_columns)) */
1037 if (BUFFER_OOB(next_line
))
1039 if (BUFFER_EOF() && next_line
!= cur_line
)
1040 return (unsigned char*) next_line
;
1047 return (unsigned char*) next_line
;
1050 static unsigned char* find_prev_line(const unsigned char* cur_line
)
1052 const unsigned char *prev_line
= NULL
;
1053 const unsigned char *p
;
1055 if BUFFER_OOB(cur_line
)
1058 /* To wrap consistently at the same places, we must
1059 start with a known hard return, then work downwards.
1060 We can either search backwards for a hard return,
1061 or simply start wrapping downwards from top of buffer.
1062 If current line is not near top of buffer, this is
1063 a file with long lines (paragraphs). We would need to
1064 read earlier sectors before we could decide how to
1065 properly wrap the lines above the current line, but
1066 it probably is not worth the disk access. Instead,
1067 start with top of buffer and wrap down from there.
1068 This may result in some lines wrapping at different
1069 points from where they wrap when scrolling down.
1070 If buffer is at top of file, start at top of buffer. */
1072 if ((prefs
.line_mode
== JOIN
) || (prefs
.line_mode
== REFLOW
))
1073 prev_line
= p
= NULL
;
1075 prev_line
= p
= find_last_feed(buffer
, cur_line
-buffer
-1);
1076 /* Null means no line feeds in buffer above current line. */
1078 if (prev_line
== NULL
)
1079 if (BUFFER_BOF() || cur_line
- buffer
> READ_PREV_ZONE
)
1080 prev_line
= p
= buffer
;
1081 /* (else return NULL and read previous block) */
1083 /* Wrap downwards until too far, then use the one before. */
1084 while (p
!= NULL
&& p
< cur_line
) {
1086 p
= find_next_line(prev_line
, NULL
);
1089 if (BUFFER_OOB(prev_line
))
1092 return (unsigned char*) prev_line
;
1095 static void check_bom(void)
1097 unsigned char bom
[BOM_SIZE
];
1098 off_t orig
= rb
->lseek(fd
, 0, SEEK_CUR
);
1102 rb
->lseek(fd
, 0, SEEK_SET
);
1104 if (rb
->read(fd
, bom
, BOM_SIZE
) == BOM_SIZE
)
1105 is_bom
= !memcmp(bom
, BOM
, BOM_SIZE
);
1107 rb
->lseek(fd
, orig
, SEEK_SET
);
1110 static void fill_buffer(long pos
, unsigned char* buf
, unsigned size
)
1112 /* Read from file and preprocess the data */
1113 /* To minimize disk access, always read on sector boundaries */
1114 unsigned numread
, i
;
1115 bool found_CR
= false;
1116 off_t offset
= rb
->lseek(fd
, pos
, SEEK_SET
);
1118 if (offset
== 0 && prefs
.encoding
== UTF_8
&& is_bom
)
1119 rb
->lseek(fd
, BOM_SIZE
, SEEK_SET
);
1121 numread
= rb
->read(fd
, buf
, size
- 1);
1123 rb
->button_clear_queue(); /* clear button queue */
1125 for(i
= 0; i
< numread
; i
++) {
1142 case 0: /* No break between case 0 and default, intentionally */
1155 static int viewer_find_bookmark(int page
, int line
)
1159 for (i
= 0; i
< bookmark_count
; i
++)
1161 if (bookmarks
[i
].page
== page
&& bookmarks
[i
].line
== line
)
1167 static int read_and_synch(int direction
)
1169 /* Read next (or prev) block, and reposition global pointers. */
1170 /* direction: 1 for down (i.e., further into file), -1 for up */
1171 int move_size
, move_vector
, offset
;
1172 unsigned char *fill_buf
;
1174 if (direction
== -1) /* up */ {
1175 move_size
= SMALL_BLOCK_SIZE
;
1177 fill_buf
= TOP_SECTOR
;
1178 rb
->memcpy(BOTTOM_SECTOR
, MID_SECTOR
, SMALL_BLOCK_SIZE
);
1179 rb
->memcpy(MID_SECTOR
, TOP_SECTOR
, SMALL_BLOCK_SIZE
);
1182 if (prefs
.view_mode
== WIDE
) {
1183 /* WIDE mode needs more buffer so we have to read smaller blocks */
1184 move_size
= SMALL_BLOCK_SIZE
;
1185 offset
= LARGE_BLOCK_SIZE
;
1186 fill_buf
= BOTTOM_SECTOR
;
1187 rb
->memcpy(TOP_SECTOR
, MID_SECTOR
, SMALL_BLOCK_SIZE
);
1188 rb
->memcpy(MID_SECTOR
, BOTTOM_SECTOR
, SMALL_BLOCK_SIZE
);
1191 move_size
= LARGE_BLOCK_SIZE
;
1192 offset
= SMALL_BLOCK_SIZE
;
1193 fill_buf
= MID_SECTOR
;
1194 rb
->memcpy(TOP_SECTOR
, BOTTOM_SECTOR
, SMALL_BLOCK_SIZE
);
1197 move_vector
= direction
* move_size
;
1198 screen_top_ptr
-= move_vector
;
1199 file_pos
+= move_vector
;
1200 buffer_end
= BUFFER_END(); /* Update whenever file_pos changes */
1201 fill_buffer(file_pos
+ offset
, fill_buf
, move_size
);
1205 static void get_next_line_position(unsigned char **line_begin
,
1206 unsigned char **line_end
,
1211 *line_begin
= *line_end
;
1212 *line_end
= find_next_line(*line_begin
, is_short
);
1214 if (*line_end
== NULL
&& !BUFFER_EOF())
1216 resynch_move
= read_and_synch(1); /* Read block & move ptrs */
1217 *line_begin
-= resynch_move
;
1218 if (next_line_ptr
> buffer
)
1219 next_line_ptr
-= resynch_move
;
1221 *line_end
= find_next_line(*line_begin
, is_short
);
1225 static void increment_current_line(void)
1227 if (cline
< display_lines
)
1229 else if (cpage
< MAX_PAGE
)
1236 static void decrement_current_line(void)
1243 cline
= display_lines
;
1247 static void viewer_scroll_up(void)
1251 p
= find_prev_line(screen_top_ptr
);
1252 if (p
== NULL
&& !BUFFER_BOF()) {
1254 p
= find_prev_line(screen_top_ptr
);
1259 decrement_current_line();
1262 static void viewer_scroll_down(bool autoscroll
)
1267 if (next_line_ptr
!= NULL
)
1268 screen_top_ptr
= next_line_ptr
;
1270 if (prefs
.scroll_mode
== LINE
|| autoscroll
)
1271 increment_current_line();
1274 static void viewer_scroll_to_top_line(void)
1278 for (line
= cline
; line
> 1; line
--)
1282 #ifdef HAVE_LCD_BITMAP
1283 static void viewer_scrollbar(void) {
1284 int items
, min_shown
, max_shown
, sb_begin_y
, sb_height
;
1286 items
= (int) file_size
; /* (SH1 int is same as long) */
1287 min_shown
= (int) file_pos
+ (screen_top_ptr
- buffer
);
1289 if (next_screen_ptr
== NULL
)
1292 max_shown
= min_shown
+ (next_screen_ptr
- screen_top_ptr
);
1294 sb_begin_y
= header_height
;
1295 sb_height
= LCD_HEIGHT
- header_height
- footer_height
;
1297 rb
->gui_scrollbar_draw(rb
->screens
[SCREEN_MAIN
],0, sb_begin_y
,
1298 SCROLLBAR_WIDTH
-1, sb_height
,
1299 items
, min_shown
, max_shown
, VERTICAL
);
1303 #ifdef HAVE_LCD_BITMAP
1304 static void viewer_show_header(void)
1306 if (prefs
.header_mode
== HD_SBAR
|| prefs
.header_mode
== HD_BOTH
)
1307 rb
->gui_syncstatusbar_draw(rb
->statusbars
, true);
1309 if (prefs
.header_mode
== HD_PATH
|| prefs
.header_mode
== HD_BOTH
)
1310 rb
->lcd_putsxy(0, header_height
- pf
->height
, file_name
);
1313 static void viewer_show_footer(void)
1315 if (prefs
.footer_mode
== FT_SBAR
|| prefs
.footer_mode
== FT_BOTH
)
1316 rb
->gui_syncstatusbar_draw(rb
->statusbars
, true);
1318 if (prefs
.footer_mode
== FT_PAGE
|| prefs
.footer_mode
== FT_BOTH
)
1320 unsigned char buf
[12];
1323 rb
->snprintf(buf
, sizeof(buf
), "%d", cpage
);
1325 rb
->snprintf(buf
, sizeof(buf
), "%d - %d", cpage
, cpage
+1);
1327 rb
->lcd_putsxy(0, LCD_HEIGHT
- footer_height
, buf
);
1332 static void viewer_draw(int col
)
1334 int i
, j
, k
, line_len
, line_width
, spaces
, left_col
=0;
1335 int width
, extra_spaces
, indent_spaces
, spaces_per_word
, spaces_width
, disp_width
= 0;
1336 bool multiple_spacing
, line_is_short
;
1338 unsigned char *str
, *oldstr
;
1339 unsigned char *line_begin
;
1340 unsigned char *line_end
;
1342 int max_chars
= max_columns
* DIACRITIC_FACTOR
;
1343 unsigned char scratch_buffer
[max_chars
* 4 + 1];
1344 unsigned char utf8_buffer
[max_chars
* 4 + 1];
1346 /* If col==-1 do all calculations but don't display */
1348 #ifdef HAVE_LCD_BITMAP
1349 left_col
= prefs
.need_scrollbar
? SCROLLBAR_WIDTH
:0;
1353 rb
->lcd_clear_display();
1356 line_begin
= line_end
= screen_top_ptr
;
1358 for (i
= 0; i
< display_lines
; i
++) {
1359 if (BUFFER_OOB(line_end
))
1362 break; /* Happens after display last line at BUFFER_EOF() */
1364 if (lpage
== 0 && cline
== 1)
1367 last_screen_top_ptr
= screen_top_ptr
;
1368 last_file_pos
= file_pos
;
1372 get_next_line_position(&line_begin
, &line_end
, &line_is_short
);
1373 if (line_end
== NULL
)
1375 if (BUFFER_OOB(line_begin
))
1377 line_end
= buffer_end
+ 1;
1380 line_len
= line_end
- line_begin
;
1382 /* calculate line_len */
1383 str
= oldstr
= line_begin
;
1385 while (str
< line_end
) {
1387 str
= crop_at_width(str
);
1395 /* width of un-displayed part of the line */
1396 line_width
= j
*draw_columns
;
1398 while (oldstr
< line_end
) {
1399 oldstr
= get_ucs(oldstr
, &ch
);
1400 /* add width of displayed part of the line */
1403 int dw
= glyph_width(ch
);
1405 /* avoid counting spaces at the end of the line */
1412 line_width
+= dw
+ spaces_width
;
1418 if (prefs
.line_mode
== JOIN
) {
1419 if (line_begin
[0] == 0) {
1421 if (prefs
.word_mode
== CHOP
)
1426 for (j
=k
=spaces
=0; j
< line_len
; j
++) {
1437 scratch_buffer
[k
++] = ' ';
1442 scratch_buffer
[k
++] = ' ';
1443 if (k
== max_chars
- 1)
1446 scratch_buffer
[k
++] = c
;
1450 scratch_buffer
[k
] = 0;
1452 else if (prefs
.line_mode
== REFLOW
) {
1453 if (line_begin
[0] == 0) {
1455 if (prefs
.word_mode
== CHOP
)
1462 if (!line_is_short
) {
1463 multiple_spacing
= false;
1465 for (str
= line_begin
; str
< line_end
; ) {
1466 str
= get_ucs(str
, &ch
);
1470 if (str
== line_begin
)
1472 if (prefs
.word_mode
== WRAP
&& prefs
.alignment
== LEFT
)
1474 /* special case: indent the paragraph,
1475 * don't count spaces */
1476 indent_spaces
= par_indent_spaces
;
1479 else if (!multiple_spacing
)
1481 multiple_spacing
= true;
1484 multiple_spacing
= false;
1485 width
+= glyph_width(ch
);
1489 if (multiple_spacing
) spaces
--;
1492 /* total number of spaces to insert between words */
1493 extra_spaces
= (max_width
-width
)/glyph_width(' ')
1495 /* number of spaces between each word*/
1496 spaces_per_word
= extra_spaces
/ spaces
;
1497 /* number of words with n+1 spaces (to fill up) */
1498 extra_spaces
= extra_spaces
% spaces
;
1499 if (spaces_per_word
> 2) { /* too much spacing is awful */
1500 spaces_per_word
= 3;
1503 } else { /* this doesn't matter much... no spaces anyway */
1504 spaces_per_word
= extra_spaces
= 0;
1506 } else { /* end of a paragraph: don't fill line */
1507 spaces_per_word
= 1;
1510 multiple_spacing
= false;
1511 for (j
=k
=spaces
=0; j
< line_len
; j
++) {
1518 if (j
== line_len
- 1)
1522 /* indent paragraph */
1523 if (prefs
.word_mode
== WRAP
&& prefs
.alignment
== LEFT
)
1525 for (j
=0; j
<par_indent_spaces
; j
++)
1526 scratch_buffer
[k
++] = ' ';
1530 else if (!multiple_spacing
) {
1531 for (width
= spaces
<extra_spaces
? -1:0; width
< spaces_per_word
; width
++)
1532 scratch_buffer
[k
++] = ' ';
1535 multiple_spacing
= true;
1538 scratch_buffer
[k
++] = c
;
1539 multiple_spacing
= false;
1543 while (scratch_buffer
[k
-1] == ' ')
1545 scratch_buffer
[k
] = 0;
1547 else { /* prefs.line_mode != JOIN && prefs.line_mode != REFLOW */
1550 rb
->memcpy(scratch_buffer
, line_begin
, line_len
);
1551 scratch_buffer
[line_len
] = '\0';
1555 /* create displayed line */
1558 decode2utf8(scratch_buffer
, utf8_buffer
, col
, draw_columns
);
1559 rb
->lcd_getstringsize(utf8_buffer
, &disp_width
, NULL
);
1562 /* display on screen the displayed part of the line */
1565 int dpage
= (cline
+i
<= display_lines
)?cpage
:cpage
+1;
1566 int dline
= cline
+i
- ((cline
+i
<= display_lines
)?0:display_lines
);
1567 bool bflag
= (viewer_find_bookmark(dpage
, dline
) >= 0);
1568 #ifdef HAVE_LCD_BITMAP
1569 int dy
= i
* pf
->height
+ header_height
;
1570 int dx
= (prefs
.alignment
== LEFT
)? left_col
: LCD_WIDTH
- disp_width
;
1573 #ifdef HAVE_LCD_BITMAP
1575 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_FG
);
1576 rb
->lcd_fillrect(left_col
, dy
, LCD_WIDTH
- left_col
, pf
->height
);
1577 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
1579 rb
->lcd_putsxy(dx
, dy
, utf8_buffer
);
1580 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1583 rb
->lcd_puts(left_col
, i
, BOOKMARK_ICON
);
1585 rb
->lcd_puts(left_col
+1, i
, utf8_buffer
);
1588 if (line_width
> max_line_len
)
1589 max_line_len
= line_width
;
1592 next_line_ptr
= line_end
;
1594 next_screen_ptr
= line_end
;
1595 if (BUFFER_OOB(next_screen_ptr
))
1596 next_screen_ptr
= NULL
;
1598 #ifdef HAVE_LCD_BITMAP
1599 next_screen_to_draw_ptr
= prefs
.page_mode
==OVERLAP
? line_begin
: next_screen_ptr
;
1601 if (prefs
.need_scrollbar
)
1604 next_screen_to_draw_ptr
= next_screen_ptr
;
1607 #ifdef HAVE_LCD_BITMAP
1609 viewer_show_header();
1612 viewer_show_footer();
1619 static void viewer_top(void)
1621 /* Read top of file into buffer
1622 and point screen pointer to top */
1625 rb
->splash(0, "Loading...");
1628 buffer_end
= BUFFER_END(); /* Update whenever file_pos changes */
1629 fill_buffer(0, buffer
, buffer_size
);
1632 screen_top_ptr
= buffer
;
1637 static void viewer_bottom(void)
1639 unsigned char *line_begin
;
1640 unsigned char *line_end
;
1642 rb
->splash(0, "Loading...");
1644 if (last_screen_top_ptr
)
1648 screen_top_ptr
= last_screen_top_ptr
;
1649 file_pos
= last_file_pos
;
1650 fill_buffer(file_pos
, buffer
, buffer_size
);
1651 buffer_end
= BUFFER_END();
1655 line_end
= screen_top_ptr
;
1657 while (!BUFFER_EOF() || !BUFFER_OOB(line_end
))
1659 get_next_line_position(&line_begin
, &line_end
, NULL
);
1660 if (line_end
== NULL
)
1663 increment_current_line();
1665 screen_top_ptr
= line_end
;
1669 last_screen_top_ptr
= screen_top_ptr
;
1670 last_file_pos
= file_pos
;
1671 buffer_end
= BUFFER_END();
1674 #ifdef HAVE_LCD_BITMAP
1675 static void init_need_scrollbar(void) {
1676 /* Call viewer_draw in quiet mode to initialize next_screen_ptr,
1677 and thus ONE_SCREEN_FITS_ALL(), and thus NEED_SCROLLBAR() */
1679 prefs
.need_scrollbar
= NEED_SCROLLBAR();
1680 draw_columns
= prefs
.need_scrollbar
? display_columns
-SCROLLBAR_WIDTH
: display_columns
;
1681 par_indent_spaces
= draw_columns
/(5*glyph_width(' '));
1685 static void init_header_and_footer(void)
1689 if (rb
->global_settings
->statusbar
== STATUSBAR_TOP
)
1691 if (prefs
.header_mode
== HD_SBAR
|| prefs
.header_mode
== HD_BOTH
)
1692 header_height
= STATUSBAR_HEIGHT
;
1694 if (prefs
.footer_mode
== FT_SBAR
)
1695 prefs
.footer_mode
= FT_NONE
;
1696 else if (prefs
.footer_mode
== FT_BOTH
)
1697 prefs
.footer_mode
= FT_PAGE
;
1699 else if (rb
->global_settings
->statusbar
== STATUSBAR_BOTTOM
)
1701 if (prefs
.footer_mode
== FT_SBAR
|| prefs
.footer_mode
== FT_BOTH
)
1702 footer_height
= STATUSBAR_HEIGHT
;
1704 if (prefs
.header_mode
== HD_SBAR
)
1705 prefs
.header_mode
= HD_NONE
;
1706 else if (prefs
.header_mode
== HD_BOTH
)
1707 prefs
.header_mode
= HD_PATH
;
1709 else /* STATUSBAR_OFF || STATUSBAR_CUSTOM */
1711 if (prefs
.header_mode
== HD_SBAR
)
1712 prefs
.header_mode
= HD_NONE
;
1713 else if (prefs
.header_mode
== HD_BOTH
)
1714 prefs
.header_mode
= HD_PATH
;
1716 if (prefs
.footer_mode
== FT_SBAR
)
1717 prefs
.footer_mode
= FT_NONE
;
1718 else if (prefs
.footer_mode
== FT_BOTH
)
1719 prefs
.footer_mode
= FT_PAGE
;
1722 if (prefs
.header_mode
== HD_NONE
|| prefs
.header_mode
== HD_PATH
||
1723 prefs
.footer_mode
== FT_NONE
|| prefs
.footer_mode
== FT_PAGE
)
1724 rb
->gui_syncstatusbar_draw(rb
->statusbars
, false);
1726 if (prefs
.header_mode
== HD_PATH
|| prefs
.header_mode
== HD_BOTH
)
1727 header_height
+= pf
->height
;
1728 if (prefs
.footer_mode
== FT_PAGE
|| prefs
.footer_mode
== FT_BOTH
)
1729 footer_height
+= pf
->height
;
1731 display_lines
= (LCD_HEIGHT
- header_height
- footer_height
) / pf
->height
;
1735 last_screen_top_ptr
= NULL
;
1738 static bool change_font(unsigned char *font
)
1740 unsigned char buf
[MAX_PATH
];
1742 if (font
== NULL
|| *font
== '\0')
1745 rb
->snprintf(buf
, MAX_PATH
, "%s/%s.fnt", FONT_DIR
, font
);
1746 if (rb
->font_load(NULL
, buf
) < 0) {
1747 rb
->splash(HZ
/2, "Font load failed.");
1755 static bool viewer_init(void)
1757 #ifdef HAVE_LCD_BITMAP
1758 /* initialize fonts */
1759 pf
= rb
->font_get(FONT_UI
);
1763 draw_columns
= display_columns
= LCD_WIDTH
;
1765 /* REAL fixed pitch :) all chars use up 1 cell */
1767 draw_columns
= display_columns
= 11;
1768 par_indent_spaces
= 2;
1771 fd
= rb
->open(file_name
, O_RDONLY
);
1775 /* Init mac_text value used in processing buffer */
1781 /* When a file is UTF-8 file with BOM, if prefs.encoding is UTF-8,
1782 * then file size decreases only BOM_SIZE.
1784 static void get_filesize(void)
1786 file_size
= rb
->filesize(fd
);
1787 if (file_size
== -1)
1790 if (prefs
.encoding
== UTF_8
&& is_bom
)
1791 file_size
-= BOM_SIZE
;
1794 static int bm_comp(const void *a
, const void *b
)
1796 struct bookmark_info
*pa
;
1797 struct bookmark_info
*pb
;
1799 pa
= (struct bookmark_info
*)a
;
1800 pb
= (struct bookmark_info
*)b
;
1802 if (pa
->page
!= pb
->page
)
1803 return pa
->page
- pb
->page
;
1805 return pa
->line
- pb
->line
;
1808 static void viewer_add_bookmark(void)
1810 if (bookmark_count
>= MAX_BOOKMARKS
-1)
1813 bookmarks
[bookmark_count
].file_position
1814 = file_pos
+ screen_top_ptr
- buffer
;
1815 bookmarks
[bookmark_count
].page
= cpage
;
1816 bookmarks
[bookmark_count
].line
= cline
;
1817 bookmarks
[bookmark_count
].flag
= BOOKMARK_USER
;
1821 static int viewer_add_last_read_bookmark(void)
1825 i
= viewer_find_bookmark(cpage
, cline
);
1827 bookmarks
[i
].flag
|= BOOKMARK_LAST
;
1830 viewer_add_bookmark();
1831 i
= bookmark_count
-1;
1832 bookmarks
[i
].flag
= BOOKMARK_LAST
;
1837 static void viewer_remove_bookmark(int i
)
1841 if (i
< 0 || i
>= bookmark_count
)
1844 for (j
= i
+1; j
< bookmark_count
; j
++)
1845 rb
->memcpy(&bookmarks
[j
-1], &bookmarks
[j
],
1846 sizeof(struct bookmark_info
));
1851 static void viewer_remove_last_read_bookmark(void)
1855 for (i
= 0; i
< bookmark_count
; i
++)
1857 if (bookmarks
[i
].flag
& BOOKMARK_LAST
)
1859 if (bookmarks
[i
].flag
== BOOKMARK_LAST
)
1861 for (j
= i
+1; j
< bookmark_count
; j
++)
1862 rb
->memcpy(&bookmarks
[j
-1], &bookmarks
[j
],
1863 sizeof(struct bookmark_info
));
1868 bookmarks
[i
].flag
= BOOKMARK_USER
;
1874 static int viewer_get_last_read_bookmark(void)
1878 for (i
= 0; i
< bookmark_count
; i
++)
1880 if (bookmarks
[i
].flag
& BOOKMARK_LAST
)
1886 static void viewer_select_bookmark(int initval
)
1895 struct opt_items items
[bookmark_count
];
1896 unsigned char names
[bookmark_count
][38];
1898 if (initval
>= 0 && initval
< bookmark_count
)
1900 ipage
= bookmarks
[initval
].page
;
1901 iline
= bookmarks
[initval
].line
;
1904 rb
->qsort(bookmarks
, bookmark_count
, sizeof(struct bookmark_info
),
1907 for (i
= 0; i
< bookmark_count
; i
++)
1909 rb
->snprintf(names
[i
], sizeof(names
[0]),
1910 #if CONFIG_KEYPAD != PLAYER_PAD
1911 "%sPage: %d Line: %d",
1915 (bookmarks
[i
].flag
&BOOKMARK_LAST
)? "*":" ",
1918 items
[i
].string
= names
[i
];
1919 items
[i
].voice_id
= -1;
1920 if (selected
< 0 && bookmarks
[i
].page
== ipage
&& bookmarks
[i
].line
== iline
)
1924 rb
->set_option("Select bookmark", &selected
, INT
, items
,
1925 sizeof(items
) / sizeof(items
[0]), NULL
);
1927 if (selected
< 0 || selected
>= bookmark_count
)
1929 if (initval
< 0 || (selected
= viewer_get_last_read_bookmark()) < 0)
1932 rb
->splash(HZ
, "Start the first page.");
1934 screen_top_ptr
= buffer
;
1937 buffer_end
= BUFFER_END();
1942 screen_pos
= bookmarks
[selected
].file_position
;
1943 screen_top
= screen_pos
% buffer_size
;
1944 file_pos
= screen_pos
- screen_top
;
1945 screen_top_ptr
= buffer
+ screen_top
;
1946 cpage
= bookmarks
[selected
].page
;
1947 cline
= bookmarks
[selected
].line
;
1948 buffer_end
= BUFFER_END();
1951 static void viewer_default_preferences(void)
1953 prefs
.word_mode
= WRAP
;
1954 prefs
.line_mode
= NORMAL
;
1955 prefs
.view_mode
= NARROW
;
1956 prefs
.alignment
= LEFT
;
1957 prefs
.scroll_mode
= PAGE
;
1958 prefs
.page_mode
= NO_OVERLAP
;
1959 prefs
.scrollbar_mode
= SB_OFF
;
1960 rb
->memset(prefs
.font
, 0, MAX_PATH
);
1961 #ifdef HAVE_LCD_BITMAP
1962 prefs
.header_mode
= HD_BOTH
;
1963 prefs
.footer_mode
= FT_BOTH
;
1964 rb
->snprintf(prefs
.font
, MAX_PATH
, "%s", rb
->global_settings
->font_file
);
1966 prefs
.header_mode
= HD_NONE
;
1967 prefs
.footer_mode
= FT_NONE
;
1969 prefs
.autoscroll_speed
= 1;
1970 /* Set codepage to system default */
1971 prefs
.encoding
= rb
->global_settings
->default_codepage
;
1974 static bool viewer_read_preferences(int pfd
, int version
, struct preferences
*prf
)
1976 unsigned char buf
[PREFERENCES_SIZE
];
1977 unsigned char *p
= buf
;
1978 int read_size
= PREFERENCES_SIZE
;
1983 if (rb
->read(pfd
, buf
, read_size
) != read_size
)
1986 prf
->word_mode
= *p
++;
1987 prf
->line_mode
= *p
++;
1988 prf
->view_mode
= *p
++;
1990 prf
->alignment
= *p
++;
1992 prf
->alignment
= LEFT
;
1993 prf
->encoding
= *p
++;
1994 prf
->scrollbar_mode
= *p
++;
1995 prf
->need_scrollbar
= *p
++;
1996 prf
->page_mode
= *p
++;
1997 prf
->header_mode
= *p
++;
1998 prf
->footer_mode
= *p
++;
1999 prf
->scroll_mode
= *p
++;
2000 prf
->autoscroll_speed
= *p
++;
2001 rb
->memcpy(prf
->font
, p
, MAX_PATH
);
2005 static bool viewer_write_preferences(int pfd
, const struct preferences
*prf
)
2007 unsigned char buf
[PREFERENCES_SIZE
];
2008 unsigned char *p
= buf
;
2010 *p
++ = prf
->word_mode
;
2011 *p
++ = prf
->line_mode
;
2012 *p
++ = prf
->view_mode
;
2013 *p
++ = prf
->alignment
;
2014 *p
++ = prf
->encoding
;
2015 *p
++ = prf
->scrollbar_mode
;
2016 *p
++ = prf
->need_scrollbar
;
2017 *p
++ = prf
->page_mode
;
2018 *p
++ = prf
->header_mode
;
2019 *p
++ = prf
->footer_mode
;
2020 *p
++ = prf
->scroll_mode
;
2021 *p
++ = prf
->autoscroll_speed
;
2022 rb
->memcpy(p
, prf
->font
, MAX_PATH
);
2024 return (rb
->write(pfd
, buf
, sizeof(buf
)) == sizeof(buf
));
2027 static bool viewer_read_bookmark_info(int bfd
, struct bookmark_info
*b
)
2029 unsigned char buf
[BOOKMARK_SIZE
];
2031 if (rb
->read(bfd
, buf
, sizeof(buf
)) != sizeof(buf
))
2034 b
->file_position
= (buf
[0] << 24)|(buf
[1] << 16)|(buf
[2] << 8)|buf
[3];
2035 b
->page
= (buf
[4] << 8)|buf
[5];
2042 static bool viewer_read_bookmark_infos(int bfd
)
2047 if (rb
->read(bfd
, &c
, 1) != 1)
2054 if (bookmark_count
> MAX_BOOKMARKS
)
2055 bookmark_count
= MAX_BOOKMARKS
;
2057 for (i
= 0; i
< bookmark_count
; i
++)
2059 if (!viewer_read_bookmark_info(bfd
, &bookmarks
[i
]))
2068 static bool viewer_write_bookmark_info(int bfd
, struct bookmark_info
*b
)
2070 unsigned char buf
[BOOKMARK_SIZE
];
2071 unsigned char *p
= buf
;
2074 ul
= b
->file_position
;
2087 return (rb
->write(bfd
, buf
, sizeof(buf
)) == sizeof(buf
));
2090 static bool viewer_write_bookmark_infos(int bfd
)
2092 unsigned char c
= bookmark_count
;
2095 if (rb
->write(bfd
, &c
, 1) != 1)
2098 for (i
= 0; i
< bookmark_count
; i
++)
2100 if (!viewer_write_bookmark_info(bfd
, &bookmarks
[i
]))
2107 static bool viewer_load_global_settings(void)
2109 unsigned buf
[GLOBAL_SETTINGS_H_SIZE
];
2110 int sfd
= rb
->open(GLOBAL_SETTINGS_FILE
, O_RDONLY
);
2117 if ((rb
->read(sfd
, buf
, GLOBAL_SETTINGS_H_SIZE
) == GLOBAL_SETTINGS_H_SIZE
) ||
2118 (rb
->memcmp(buf
, GLOBAL_SETTINGS_HEADER
, GLOBAL_SETTINGS_H_SIZE
- 1) == 0))
2120 version
= buf
[GLOBAL_SETTINGS_H_SIZE
- 1] - GLOBAL_SETTINGS_FIRST_VERSION
;
2121 res
= viewer_read_preferences(sfd
, version
, &prefs
);
2127 static bool viewer_save_global_settings(void)
2129 int sfd
= rb
->open(GLOBAL_SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
);
2130 unsigned char buf
[GLOBAL_SETTINGS_H_SIZE
];
2135 rb
->memcpy(buf
, GLOBAL_SETTINGS_HEADER
, GLOBAL_SETTINGS_H_SIZE
- 1);
2136 buf
[GLOBAL_SETTINGS_H_SIZE
- 1] = GLOBAL_SETTINGS_VERSION
;
2138 if (rb
->write(sfd
, buf
, GLOBAL_SETTINGS_H_SIZE
) != GLOBAL_SETTINGS_H_SIZE
||
2139 !viewer_write_preferences(sfd
, &prefs
))
2142 rb
->remove(GLOBAL_SETTINGS_TMP_FILE
);
2146 rb
->remove(GLOBAL_SETTINGS_FILE
);
2147 rb
->rename(GLOBAL_SETTINGS_TMP_FILE
, GLOBAL_SETTINGS_FILE
);
2151 static bool viewer_convert_settings(int sfd
, int dfd
, int old_ver
)
2153 struct preferences new_prefs
;
2156 unsigned char buf
[MAX_PATH
+ 2];
2159 rb
->read(sfd
, buf
, MAX_PATH
+ 2);
2160 rb
->write(dfd
, buf
, MAX_PATH
+ 2);
2162 settings_size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+ 1];
2164 old_pos
= rb
->lseek(sfd
, 0, SEEK_CUR
);
2165 new_pos
= rb
->lseek(dfd
, 0, SEEK_CUR
);
2168 * when the settings size != preferences size + bookmarks size,
2169 * settings data are considered to be old version.
2171 if (old_ver
> 0 && ((settings_size
- PREFERENCES_SIZE
) % 8) == 0)
2174 if (!viewer_read_preferences(sfd
, old_ver
, &new_prefs
))
2177 if (!viewer_write_preferences(dfd
, &new_prefs
))
2180 settings_size
-= (rb
->lseek(sfd
, 0, SEEK_CUR
) - old_pos
);
2182 if (settings_size
> 0)
2184 rb
->read(sfd
, buf
, settings_size
);
2185 rb
->write(dfd
, buf
, settings_size
);
2188 settings_size
= rb
->lseek(dfd
, 0, SEEK_CUR
) - new_pos
;
2189 buf
[0] = settings_size
>> 8;
2190 buf
[1] = settings_size
;
2191 rb
->lseek(dfd
, new_pos
- 2, SEEK_SET
);
2192 rb
->write(dfd
, buf
, 2);
2193 rb
->lseek(dfd
, settings_size
, SEEK_CUR
);
2197 static bool viewer_convert_settings_file(void)
2199 unsigned char buf
[SETTINGS_H_SIZE
+2];
2207 if ((sfd
= rb
->open(SETTINGS_FILE
, O_RDONLY
)) < 0)
2210 if ((tfd
= rb
->open(SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
)) < 0)
2216 rb
->read(sfd
, buf
, SETTINGS_H_SIZE
+ 2);
2218 version
= buf
[SETTINGS_H_SIZE
- 1] - SETTINGS_FIRST_VERSION
;
2219 fcount
= (buf
[SETTINGS_H_SIZE
] << 8) | buf
[SETTINGS_H_SIZE
+ 1];
2220 buf
[SETTINGS_H_SIZE
- 1] = SETTINGS_VERSION
;
2222 rb
->write(tfd
, buf
, SETTINGS_H_SIZE
+ 2);
2224 for (i
= 0; i
< fcount
; i
++)
2226 if (!viewer_convert_settings(sfd
, tfd
, version
))
2237 rb
->remove(SETTINGS_TMP_FILE
);
2240 rb
->remove(SETTINGS_FILE
);
2241 rb
->rename(SETTINGS_TMP_FILE
, SETTINGS_FILE
);
2246 static bool viewer_load_settings(void)
2248 unsigned char buf
[MAX_PATH
+2];
2249 unsigned int fcount
;
2256 sfd
= rb
->open(SETTINGS_FILE
, O_RDONLY
);
2260 if ((rb
->read(sfd
, buf
, SETTINGS_H_SIZE
+2) != SETTINGS_H_SIZE
+2) ||
2261 rb
->memcmp(buf
, SETTINGS_HEADER
, SETTINGS_H_SIZE
- 1))
2263 /* illegal setting file */
2266 if (rb
->file_exists(SETTINGS_FILE
))
2267 rb
->remove(SETTINGS_FILE
);
2272 if (buf
[SETTINGS_H_SIZE
- 1] != SETTINGS_VERSION
)
2275 if (!viewer_convert_settings_file())
2278 return viewer_load_settings();
2281 version
= buf
[SETTINGS_H_SIZE
- 1] - SETTINGS_FIRST_VERSION
;
2282 fcount
= (buf
[SETTINGS_H_SIZE
] << 8) | buf
[SETTINGS_H_SIZE
+1];
2283 for (i
= 0; i
< fcount
; i
++)
2285 if (rb
->read(sfd
, buf
, MAX_PATH
+2) != MAX_PATH
+2)
2288 size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+1];
2291 * when the settings size != preferences size + bookmarks size,
2292 * the settings file converts to the newer.
2294 if (version
> 0 && ((size
- PREFERENCES_SIZE
) % 8) == 0)
2297 if (!viewer_convert_settings_file())
2300 return viewer_load_settings();
2303 if (rb
->strcmp(buf
, file_name
))
2305 if (rb
->lseek(sfd
, size
, SEEK_CUR
) < 0)
2309 if (!viewer_read_preferences(sfd
, version
, &prefs
))
2312 res
= viewer_read_bookmark_infos(sfd
);
2321 /* load global settings */
2322 if (!viewer_load_global_settings())
2323 viewer_default_preferences();
2326 screen_top_ptr
= buffer
;
2332 rb
->memcpy(&old_prefs
, &prefs
, sizeof(struct preferences
));
2335 if (bookmark_count
> 1)
2336 viewer_select_bookmark(-1);
2337 else if (bookmark_count
== 1)
2342 screen_pos
= bookmarks
[0].file_position
;
2343 screen_top
= screen_pos
% buffer_size
;
2344 file_pos
= screen_pos
- screen_top
;
2345 screen_top_ptr
= buffer
+ screen_top
;
2346 cpage
= bookmarks
[0].page
;
2347 cline
= bookmarks
[0].line
;
2350 viewer_remove_last_read_bookmark();
2355 buffer_end
= BUFFER_END(); /* Update whenever file_pos changes */
2357 if (BUFFER_OOB(screen_top_ptr
))
2358 screen_top_ptr
= buffer
;
2360 fill_buffer(file_pos
, buffer
, buffer_size
);
2361 if (prefs
.scroll_mode
== PAGE
&& cline
> 1)
2362 viewer_scroll_to_top_line();
2364 /* remember the current position */
2365 start_position
= file_pos
+ screen_top_ptr
- buffer
;
2367 #ifdef HAVE_LCD_BITMAP
2368 /* load prefs font if it is different than the global settings font */
2369 if (rb
->strcmp(prefs
.font
, rb
->global_settings
->font_file
)) {
2370 if (!change_font(prefs
.font
)) {
2371 /* fallback by resetting prefs font to the global settings font */
2372 rb
->memset(prefs
.font
, 0, MAX_PATH
);
2373 rb
->snprintf(prefs
.font
, MAX_PATH
, "%s",
2374 rb
->global_settings
->font_file
);
2376 if (!change_font(prefs
.font
))
2381 init_need_scrollbar();
2382 init_header_and_footer();
2388 static bool copy_bookmark_file(int sfd
, int dfd
, off_t start
, off_t size
)
2392 if (rb
->lseek(sfd
, start
, SEEK_SET
) < 0)
2397 if (size
> buffer_size
)
2398 rsize
= buffer_size
;
2403 if (rb
->read(sfd
, buffer
, rsize
) != rsize
||
2404 rb
->write(dfd
, buffer
, rsize
) != rsize
)
2410 static bool viewer_save_settings(void)
2412 unsigned char buf
[MAX_PATH
+2];
2413 unsigned int fcount
= 0;
2418 off_t first_copy_size
= 0;
2419 off_t second_copy_start_pos
= 0;
2422 /* add reading page to bookmarks */
2423 idx
= viewer_find_bookmark(cpage
, cline
);
2425 bookmarks
[idx
].flag
|= BOOKMARK_LAST
;
2428 viewer_add_bookmark();
2429 bookmarks
[bookmark_count
-1].flag
= BOOKMARK_LAST
;
2432 tfd
= rb
->open(SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
);
2436 ofd
= rb
->open(SETTINGS_FILE
, O_RDWR
);
2439 if ((rb
->read(ofd
, buf
, SETTINGS_H_SIZE
+2) != SETTINGS_H_SIZE
+2) ||
2440 rb
->memcmp(buf
, SETTINGS_HEADER
, SETTINGS_H_SIZE
- 1))
2446 if (buf
[SETTINGS_H_SIZE
- 1] != SETTINGS_VERSION
)
2449 if (!viewer_convert_settings_file())
2452 viewer_save_settings();
2455 fcount
= (buf
[SETTINGS_H_SIZE
] << 8) | buf
[SETTINGS_H_SIZE
+1];
2457 for (i
= 0; i
< fcount
; i
++)
2459 if (rb
->read(ofd
, buf
, MAX_PATH
+2) != MAX_PATH
+2)
2464 size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+1];
2465 if (rb
->strcmp(buf
, file_name
))
2467 if (rb
->lseek(ofd
, size
, SEEK_CUR
) < 0)
2475 first_copy_size
= rb
->lseek(ofd
, 0, SEEK_CUR
);
2476 if (first_copy_size
< 0)
2481 second_copy_start_pos
= first_copy_size
+ size
;
2482 first_copy_size
-= MAX_PATH
+2;
2487 if (first_copy_size
== 0)
2488 first_copy_size
= rb
->filesize(ofd
);
2490 if (!copy_bookmark_file(ofd
, tfd
, 0, first_copy_size
))
2495 if (second_copy_start_pos
> 0)
2497 if (!copy_bookmark_file(ofd
, tfd
, second_copy_start_pos
,
2498 rb
->filesize(ofd
) - second_copy_start_pos
))
2508 rb
->memcpy(buf
, SETTINGS_HEADER
, SETTINGS_H_SIZE
- 1);
2509 buf
[SETTINGS_H_SIZE
-1] = SETTINGS_VERSION
;
2510 buf
[SETTINGS_H_SIZE
] = 0;
2511 buf
[SETTINGS_H_SIZE
+1] = 0;
2512 if (rb
->write(tfd
, buf
, SETTINGS_H_SIZE
+2) != SETTINGS_H_SIZE
+2)
2516 /* copy to current read file's bookmarks */
2517 rb
->memset(buf
, 0, MAX_PATH
);
2518 rb
->snprintf(buf
, MAX_PATH
, "%s", file_name
);
2520 size
= PREFERENCES_SIZE
+ bookmark_count
* BOOKMARK_SIZE
+ 1;
2521 buf
[MAX_PATH
] = size
>> 8;
2522 buf
[MAX_PATH
+1] = size
;
2524 if (rb
->write(tfd
, buf
, MAX_PATH
+2) != MAX_PATH
+2)
2527 if (!viewer_write_preferences(tfd
, &prefs
))
2530 if (!viewer_write_bookmark_infos(tfd
))
2533 if (rb
->lseek(tfd
, SETTINGS_H_SIZE
, SEEK_SET
) < 0)
2537 buf
[0] = fcount
>> 8;
2540 if (rb
->write(tfd
, buf
, 2) != 2)
2545 rb
->remove(SETTINGS_FILE
);
2546 rb
->rename(SETTINGS_TMP_FILE
, SETTINGS_FILE
);
2552 rb
->remove(SETTINGS_TMP_FILE
);
2556 static void viewer_exit(void *parameter
)
2560 /* save preference and bookmarks */
2561 if (!viewer_save_settings())
2562 rb
->splash(HZ
, "Can't save preference and bookmarks.");
2565 #ifdef HAVE_LCD_BITMAP
2566 if (rb
->strcmp(prefs
.font
, rb
->global_settings
->font_file
))
2567 change_font(rb
->global_settings
->font_file
);
2571 static void calc_page(void)
2574 unsigned char *line_begin
;
2575 unsigned char *line_end
;
2577 unsigned char *sstp
;
2579 rb
->splash(0, "Calculating page/line number...");
2581 /* add reading page to bookmarks */
2582 viewer_add_last_read_bookmark();
2584 rb
->qsort(bookmarks
, bookmark_count
, sizeof(struct bookmark_info
),
2590 screen_top_ptr
= buffer
;
2591 buffer_end
= BUFFER_END();
2593 fill_buffer(file_pos
, buffer
, buffer_size
);
2594 line_end
= line_begin
= buffer
;
2596 for (i
= 0; i
< bookmark_count
; i
++)
2598 sfp
= bookmarks
[i
].file_position
;
2601 while ((line_begin
> sstp
|| sstp
>= line_end
) ||
2602 (file_pos
> sfp
|| sfp
>= file_pos
+ BUFFER_END() - buffer
))
2604 get_next_line_position(&line_begin
, &line_end
, NULL
);
2605 if (line_end
== NULL
)
2608 next_line_ptr
= line_end
;
2610 if (sstp
== buffer
&&
2611 file_pos
<= sfp
&& sfp
< file_pos
+ BUFFER_END() - buffer
)
2612 sstp
= sfp
- file_pos
+ buffer
;
2614 increment_current_line();
2617 decrement_current_line();
2618 bookmarks
[i
].page
= cpage
;
2619 bookmarks
[i
].line
= cline
;
2620 bookmarks
[i
].file_position
= file_pos
+ (line_begin
- buffer
);
2621 increment_current_line();
2624 /* remove reading page's bookmark */
2625 for (i
= 0; i
< bookmark_count
; i
++)
2627 if (bookmarks
[i
].flag
& BOOKMARK_LAST
)
2632 screen_pos
= bookmarks
[i
].file_position
;
2633 screen_top
= screen_pos
% buffer_size
;
2634 file_pos
= screen_pos
- screen_top
;
2635 screen_top_ptr
= buffer
+ screen_top
;
2637 cpage
= bookmarks
[i
].page
;
2638 cline
= bookmarks
[i
].line
;
2639 bookmarks
[i
].flag
^= BOOKMARK_LAST
;
2640 buffer_end
= BUFFER_END();
2642 fill_buffer(file_pos
, buffer
, buffer_size
);
2644 if (bookmarks
[i
].flag
== 0)
2645 viewer_remove_bookmark(i
);
2647 if (prefs
.scroll_mode
== PAGE
&& cline
> 1)
2648 viewer_scroll_to_top_line();
2654 static int col_limit(int col
)
2659 if (col
>= max_width
- draw_columns
)
2660 col
= max_width
- draw_columns
;
2665 /* settings helper functions */
2667 static bool encoding_setting(void)
2669 static struct opt_items names
[NUM_CODEPAGES
];
2672 enum codepages oldenc
= prefs
.encoding
;
2674 for (idx
= 0; idx
< NUM_CODEPAGES
; idx
++)
2676 names
[idx
].string
= rb
->get_codepage_name(idx
);
2677 names
[idx
].voice_id
= -1;
2680 res
= rb
->set_option("Encoding", &prefs
.encoding
, INT
, names
,
2681 sizeof(names
) / sizeof(names
[0]), NULL
);
2683 /* When prefs.encoding changes into UTF-8 or changes from UTF-8,
2684 * filesize (file_size) might change.
2685 * In addition, if prefs.encoding is UTF-8, then BOM does not read.
2687 if (oldenc
!= prefs
.encoding
&& (oldenc
== UTF_8
|| prefs
.encoding
== UTF_8
))
2691 fill_buffer(file_pos
, buffer
, buffer_size
);
2697 static bool word_wrap_setting(void)
2699 static const struct opt_items names
[] = {
2701 {"Off (Chop Words)", -1},
2704 return rb
->set_option("Word Wrap", &prefs
.word_mode
, INT
,
2708 static bool line_mode_setting(void)
2710 static const struct opt_items names
[] = {
2713 {"Expand Lines", -1},
2714 #ifdef HAVE_LCD_BITMAP
2715 {"Reflow Lines", -1},
2719 return rb
->set_option("Line Mode", &prefs
.line_mode
, INT
, names
,
2720 sizeof(names
) / sizeof(names
[0]), NULL
);
2723 static bool view_mode_setting(void)
2725 static const struct opt_items names
[] = {
2726 {"No (Narrow)", -1},
2730 ret
= rb
->set_option("Wide View", &prefs
.view_mode
, INT
,
2732 if (prefs
.view_mode
== NARROW
)
2738 static bool scroll_mode_setting(void)
2740 static const struct opt_items names
[] = {
2741 {"Scroll by Page", -1},
2742 {"Scroll by Line", -1},
2745 return rb
->set_option("Scroll Mode", &prefs
.scroll_mode
, INT
,
2749 #ifdef HAVE_LCD_BITMAP
2750 static bool page_mode_setting(void)
2752 static const struct opt_items names
[] = {
2757 return rb
->set_option("Overlap Pages", &prefs
.page_mode
, INT
,
2761 static bool scrollbar_setting(void)
2763 static const struct opt_items names
[] = {
2768 return rb
->set_option("Show Scrollbar", &prefs
.scrollbar_mode
, INT
,
2772 static bool header_setting(void)
2774 int len
= (rb
->global_settings
->statusbar
== STATUSBAR_TOP
)? 4 : 2;
2775 struct opt_items names
[len
];
2777 names
[0].string
= "None";
2778 names
[0].voice_id
= -1;
2779 names
[1].string
= "File path";
2780 names
[1].voice_id
= -1;
2782 if (rb
->global_settings
->statusbar
== STATUSBAR_TOP
)
2784 names
[2].string
= "Status bar";
2785 names
[2].voice_id
= -1;
2786 names
[3].string
= "Both";
2787 names
[3].voice_id
= -1;
2790 return rb
->set_option("Show Header", &prefs
.header_mode
, INT
,
2794 static bool footer_setting(void)
2796 int len
= (rb
->global_settings
->statusbar
== STATUSBAR_BOTTOM
)? 4 : 2;
2797 struct opt_items names
[len
];
2799 names
[0].string
= "None";
2800 names
[0].voice_id
= -1;
2801 names
[1].string
= "Page Num";
2802 names
[1].voice_id
= -1;
2804 if (rb
->global_settings
->statusbar
== STATUSBAR_BOTTOM
)
2806 names
[2].string
= "Status bar";
2807 names
[2].voice_id
= -1;
2808 names
[3].string
= "Both";
2809 names
[3].voice_id
= -1;
2812 return rb
->set_option("Show Footer", &prefs
.footer_mode
, INT
,
2816 static int font_comp(const void *a
, const void *b
)
2818 struct opt_items
*pa
;
2819 struct opt_items
*pb
;
2821 pa
= (struct opt_items
*)a
;
2822 pb
= (struct opt_items
*)b
;
2824 return rb
->strcmp(pa
->string
, pb
->string
);
2827 static bool font_setting(void)
2831 struct dirent
*entry
;
2839 dir
= rb
->opendir(FONT_DIR
);
2842 rb
->splash(HZ
/2, "Font dir is not accessible");
2848 entry
= rb
->readdir(dir
);
2853 len
= rb
->strlen(entry
->d_name
);
2854 if (len
< 4 || rb
->strcmp(entry
->d_name
+ len
-4, ".fnt"))
2861 struct opt_items names
[count
];
2862 unsigned char font_names
[size
];
2863 unsigned char *p
= font_names
;
2865 dir
= rb
->opendir(FONT_DIR
);
2868 rb
->splash(HZ
/2, "Font dir is not accessible");
2874 entry
= rb
->readdir(dir
);
2879 len
= rb
->strlen(entry
->d_name
);
2880 if (len
< 4 || rb
->strcmp(entry
->d_name
+ len
-4, ".fnt"))
2883 rb
->snprintf(p
, len
-3, "%s", entry
->d_name
);
2884 names
[i
].string
= p
;
2885 names
[i
].voice_id
= -1;
2893 rb
->qsort(names
, count
, sizeof(struct opt_items
), font_comp
);
2895 for (i
= 0; i
< count
; i
++)
2897 if (!rb
->strcmp(names
[i
].string
, prefs
.font
))
2903 old_font
= new_font
;
2905 res
= rb
->set_option("Select Font", &new_font
, INT
,
2906 names
, count
, NULL
);
2908 if (new_font
!= old_font
)
2910 /* load selected font */
2911 if (!change_font((unsigned char *)names
[new_font
].string
)) {
2912 /* revert by re-loading the preferences font */
2913 change_font(prefs
.font
);
2916 rb
->memset(prefs
.font
, 0, MAX_PATH
);
2917 rb
->snprintf(prefs
.font
, MAX_PATH
, "%s", names
[new_font
].string
);
2923 static bool alignment_setting(void)
2925 static const struct opt_items names
[] = {
2930 return rb
->set_option("Alignment", &prefs
.alignment
, INT
,
2935 static bool autoscroll_speed_setting(void)
2937 return rb
->set_int("Auto-scroll Speed", "", UNIT_INT
,
2938 &prefs
.autoscroll_speed
, NULL
, 1, 1, 10, NULL
);
2941 MENUITEM_FUNCTION(encoding_item
, 0, "Encoding", encoding_setting
,
2942 NULL
, NULL
, Icon_NOICON
);
2943 MENUITEM_FUNCTION(word_wrap_item
, 0, "Word Wrap", word_wrap_setting
,
2944 NULL
, NULL
, Icon_NOICON
);
2945 MENUITEM_FUNCTION(line_mode_item
, 0, "Line Mode", line_mode_setting
,
2946 NULL
, NULL
, Icon_NOICON
);
2947 MENUITEM_FUNCTION(view_mode_item
, 0, "Wide View", view_mode_setting
,
2948 NULL
, NULL
, Icon_NOICON
);
2949 #ifdef HAVE_LCD_BITMAP
2950 MENUITEM_FUNCTION(alignment_item
, 0, "Alignment", alignment_setting
,
2951 NULL
, NULL
, Icon_NOICON
);
2952 MENUITEM_FUNCTION(scrollbar_item
, 0, "Show Scrollbar", scrollbar_setting
,
2953 NULL
, NULL
, Icon_NOICON
);
2954 MENUITEM_FUNCTION(page_mode_item
, 0, "Overlap Pages", page_mode_setting
,
2955 NULL
, NULL
, Icon_NOICON
);
2956 MENUITEM_FUNCTION(header_item
, 0, "Show Header", header_setting
,
2957 NULL
, NULL
, Icon_NOICON
);
2958 MENUITEM_FUNCTION(footer_item
, 0, "Show Footer", footer_setting
,
2959 NULL
, NULL
, Icon_NOICON
);
2960 MENUITEM_FUNCTION(font_item
, 0, "Font", font_setting
,
2961 NULL
, NULL
, Icon_NOICON
);
2963 MENUITEM_FUNCTION(scroll_mode_item
, 0, "Scroll Mode", scroll_mode_setting
,
2964 NULL
, NULL
, Icon_NOICON
);
2965 MENUITEM_FUNCTION(autoscroll_speed_item
, 0, "Auto-Scroll Speed",
2966 autoscroll_speed_setting
, NULL
, NULL
, Icon_NOICON
);
2967 MAKE_MENU(option_menu
, "Viewer Options", NULL
, Icon_NOICON
,
2968 &encoding_item
, &word_wrap_item
, &line_mode_item
, &view_mode_item
,
2969 #ifdef HAVE_LCD_BITMAP
2970 &alignment_item
, &scrollbar_item
, &page_mode_item
, &header_item
,
2971 &footer_item
, &font_item
,
2973 &scroll_mode_item
, &autoscroll_speed_item
);
2975 static bool viewer_options_menu(bool is_global
)
2978 struct preferences tmp_prefs
;
2980 rb
->memcpy(&tmp_prefs
, &prefs
, sizeof(struct preferences
));
2982 result
= (rb
->do_menu(&option_menu
, NULL
, NULL
, false) == MENU_ATTACHED_USB
);
2984 if (!is_global
&& rb
->memcmp(&tmp_prefs
, &prefs
, sizeof(struct preferences
)))
2986 /* Show-scrollbar mode for current view-width mode */
2987 #ifdef HAVE_LCD_BITMAP
2988 init_need_scrollbar();
2989 init_header_and_footer();
2996 static void viewer_menu(void)
3000 MENUITEM_STRINGLIST(menu
, "Viewer Menu", NULL
,
3001 "Return", "Viewer Options",
3002 "Show Playback Menu", "Select Bookmark",
3003 "Global Settings", "Quit");
3005 result
= rb
->do_menu(&menu
, NULL
, NULL
, false);
3008 case 0: /* return */
3010 case 1: /* change settings */
3011 done
= viewer_options_menu(false);
3013 case 2: /* playback control */
3014 playback_control(NULL
);
3016 case 3: /* select bookmark */
3017 viewer_select_bookmark(viewer_add_last_read_bookmark());
3018 viewer_remove_last_read_bookmark();
3019 fill_buffer(file_pos
, buffer
, buffer_size
);
3020 if (prefs
.scroll_mode
== PAGE
&& cline
> 1)
3021 viewer_scroll_to_top_line();
3023 case 4: /* change global settings */
3025 struct preferences orig_prefs
;
3027 rb
->memcpy(&orig_prefs
, &prefs
, sizeof(struct preferences
));
3028 if (!viewer_load_global_settings())
3029 viewer_default_preferences();
3030 done
= viewer_options_menu(true);
3031 viewer_save_global_settings();
3032 rb
->memcpy(&prefs
, &orig_prefs
, sizeof(struct preferences
));
3043 enum plugin_status
plugin_start(const void* file
)
3046 int lastbutton
= BUTTON_NONE
;
3047 bool autoscroll
= false;
3050 old_tick
= *rb
->current_tick
;
3052 /* get the plugin buffer */
3053 buffer
= rb
->plugin_get_buffer((size_t *)&buffer_size
);
3054 if (buffer_size
== 0)
3056 rb
->splash(HZ
, "buffer does not allocate !!");
3057 return PLUGIN_ERROR
;
3059 block_size
= buffer_size
/ 3;
3060 buffer_size
= 3 * block_size
;
3063 return PLUGIN_ERROR
;
3068 rb
->splash(HZ
, "Error opening file.");
3069 return PLUGIN_ERROR
;
3072 if (!viewer_load_settings()) /* load the preferences and bookmark */
3073 return PLUGIN_ERROR
;
3076 rb
->lcd_set_backdrop(NULL
);
3085 if(old_tick
<= *rb
->current_tick
- (110-prefs
.autoscroll_speed
*10))
3087 viewer_scroll_down(true);
3089 old_tick
= *rb
->current_tick
;
3093 button
= rb
->button_get_w_tmo(HZ
/10);
3095 if (prefs
.view_mode
!= WIDE
) {
3096 /* when not in wide view mode, the SCREEN_LEFT and SCREEN_RIGHT
3097 buttons jump to the beginning and end of the file. To stop
3098 users doing this by accident, replace non-held occurrences
3099 with page up/down instead. */
3100 if (button
== VIEWER_SCREEN_LEFT
)
3101 button
= VIEWER_PAGE_UP
;
3102 else if (button
== VIEWER_SCREEN_RIGHT
)
3103 button
= VIEWER_PAGE_DOWN
;
3114 case VIEWER_AUTOSCROLL
:
3115 #ifdef VIEWER_AUTOSCROLL_PRE
3116 if (lastbutton
!= VIEWER_AUTOSCROLL_PRE
)
3119 autoscroll
= !autoscroll
;
3122 case VIEWER_PAGE_UP
:
3123 case VIEWER_PAGE_UP
| BUTTON_REPEAT
:
3124 #ifdef VIEWER_PAGE_UP2
3125 case VIEWER_PAGE_UP2
:
3126 case VIEWER_PAGE_UP2
| BUTTON_REPEAT
:
3128 if (prefs
.scroll_mode
== PAGE
)
3131 #ifdef HAVE_LCD_BITMAP
3132 for (i
= prefs
.page_mode
==OVERLAP
? 1:0; i
< display_lines
; i
++)
3134 for (i
= 0; i
< display_lines
; i
++)
3140 old_tick
= *rb
->current_tick
;
3144 case VIEWER_PAGE_DOWN
:
3145 case VIEWER_PAGE_DOWN
| BUTTON_REPEAT
:
3146 #ifdef VIEWER_PAGE_DOWN2
3147 case VIEWER_PAGE_DOWN2
:
3148 case VIEWER_PAGE_DOWN2
| BUTTON_REPEAT
:
3150 if (prefs
.scroll_mode
== PAGE
)
3153 if (next_screen_ptr
!= NULL
)
3155 screen_top_ptr
= next_screen_to_draw_ptr
;
3156 if (cpage
< MAX_PAGE
)
3161 viewer_scroll_down(autoscroll
);
3162 old_tick
= *rb
->current_tick
;
3166 case VIEWER_SCREEN_LEFT
:
3167 case VIEWER_SCREEN_LEFT
| BUTTON_REPEAT
:
3168 if (prefs
.view_mode
== WIDE
) {
3170 col
= col_limit(col
- draw_columns
);
3172 else { /* prefs.view_mode == NARROW */
3180 case VIEWER_SCREEN_RIGHT
:
3181 case VIEWER_SCREEN_RIGHT
| BUTTON_REPEAT
:
3182 if (prefs
.view_mode
== WIDE
) {
3184 col
= col_limit(col
+ draw_columns
);
3186 else { /* prefs.view_mode == NARROW */
3187 /* Bottom of file */
3194 #ifdef VIEWER_LINE_UP
3195 case VIEWER_LINE_UP
:
3196 case VIEWER_LINE_UP
| BUTTON_REPEAT
:
3197 /* Scroll up one line */
3199 old_tick
= *rb
->current_tick
;
3203 case VIEWER_LINE_DOWN
:
3204 case VIEWER_LINE_DOWN
| BUTTON_REPEAT
:
3205 /* Scroll down one line */
3206 viewer_scroll_down(autoscroll
);
3207 increment_current_line();
3208 old_tick
= *rb
->current_tick
;
3212 #ifdef VIEWER_COLUMN_LEFT
3213 case VIEWER_COLUMN_LEFT
:
3214 case VIEWER_COLUMN_LEFT
| BUTTON_REPEAT
:
3215 if (prefs
.view_mode
== WIDE
) {
3216 /* Scroll left one column */
3217 col
= col_limit(col
- glyph_width('o'));
3222 case VIEWER_COLUMN_RIGHT
:
3223 case VIEWER_COLUMN_RIGHT
| BUTTON_REPEAT
:
3224 if (prefs
.view_mode
== WIDE
) {
3225 /* Scroll right one column */
3226 col
= col_limit(col
+ glyph_width('o'));
3232 #ifdef VIEWER_RC_QUIT
3233 case VIEWER_RC_QUIT
:
3243 case VIEWER_BOOKMARK
:
3245 int idx
= viewer_find_bookmark(cpage
, cline
);
3249 if (bookmark_count
>= MAX_BOOKMARKS
-1)
3250 rb
->splash(HZ
/2, "No more add bookmark.");
3253 viewer_add_bookmark();
3254 rb
->splash(HZ
/2, "Bookmark add.");
3259 viewer_remove_bookmark(idx
);
3260 rb
->splash(HZ
/2, "Bookmark remove.");
3267 if (rb
->default_event_handler_ex(button
, viewer_exit
, NULL
)
3268 == SYS_USB_CONNECTED
)
3269 return PLUGIN_USB_CONNECTED
;
3272 if (button
!= BUTTON_NONE
)
3274 lastbutton
= button
;