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_width
;
618 static int max_columns
;
619 static int cline
= 1;
620 static int cpage
= 1;
621 static int lpage
= 0;
622 static unsigned char *screen_top_ptr
;
623 static unsigned char *next_screen_ptr
;
624 static unsigned char *next_screen_to_draw_ptr
;
625 static unsigned char *next_line_ptr
;
626 static unsigned char *last_screen_top_ptr
= NULL
;
627 #ifdef HAVE_LCD_BITMAP
628 static struct font
*pf
;
629 static int header_height
= 0;
630 static int footer_height
= 0;
632 struct bookmark_info bookmarks
[MAX_BOOKMARKS
];
633 static int bookmark_count
;
636 #define BOM "\xef\xbb\xbf"
639 static bool is_bom
= false;
641 /* We draw a diacritic char over a non-diacritic one. Therefore, such chars are
642 * not considered to occupy space, therefore buffers might have more than
643 * max_columns characters. The DIACRITIC_FACTOR is the max ratio between all
644 * characters and non-diacritic characters in the buffer
646 #define DIACRITIC_FACTOR 2
648 /* calculate the width of a UCS character (zero width for diacritics) */
649 static int glyph_width(unsigned short ch
)
654 #ifdef HAVE_LCD_BITMAP
655 if (rb
->is_diacritic(ch
, NULL
))
658 return rb
->font_get_width(pf
, ch
);
664 /* get UCS character from string */
665 static unsigned char* get_ucs(const unsigned char* str
, unsigned short* ch
)
667 unsigned char utf8_tmp
[6];
670 if (prefs
.encoding
== UTF_8
)
671 return (unsigned char*)rb
->utf8decode(str
, ch
);
673 rb
->iso_decode(str
, utf8_tmp
, prefs
.encoding
, count
);
674 rb
->utf8decode(utf8_tmp
, ch
);
676 /* return a pointer after the parsed section of the string */
677 #ifdef HAVE_LCD_BITMAP
678 if (prefs
.encoding
>= SJIS
&& *str
>= 0x80
679 && !(prefs
.encoding
== SJIS
&& *str
> 0xA0 && *str
< 0xE0))
680 return (unsigned char*)str
+2;
683 return (unsigned char*)str
+1;
686 /* decode iso string into UTF-8 string */
687 static unsigned char *decode2utf8(const unsigned char *src
, unsigned char *dst
,
688 int skip_width
, int disp_width
)
690 unsigned short ucs
[max_columns
* DIACRITIC_FACTOR
+ 1];
692 const unsigned char *oldstr
= src
;
693 const unsigned char *str
= src
;
694 unsigned char *utf8
= dst
;
697 int width
= max_width
;
699 if (prefs
.alignment
== LEFT
)
701 /* skip the skip_width */
704 while (skip_width
> 0 && *str
!= '\0')
707 str
= get_ucs(oldstr
, &ch
);
708 skip_width
-= glyph_width(ch
);
714 /* decode until string end or disp_width reached */
717 str
= get_ucs(str
, &ch
);
718 disp_width
-= glyph_width(ch
);
721 utf8
= rb
->utf8encode(ch
, utf8
);
726 while (width
> 0 && *str
!= '\0')
728 str
= get_ucs(str
, &ch
);
733 skip_width
= max_width
- skip_width
- disp_width
;
736 while (skip_width
> 0 && chars
-- > 0)
737 skip_width
-= glyph_width(ucs
[chars
]);
745 while (disp_width
> 0 && idx
-- > 0)
746 disp_width
-= glyph_width(ucs
[idx
]);
748 if (disp_width
< 0 || idx
< 0)
752 for ( ; idx
< chars
; idx
++)
753 utf8
= rb
->utf8encode(ucs
[idx
], utf8
);
758 /* return a pointer after the dst string ends */
762 /* set max_columns and max_width */
763 static void calc_max_width(void)
765 if (prefs
.view_mode
== NARROW
)
767 max_columns
= NARROW_MAX_COLUMNS
;
768 max_width
= draw_columns
;
772 max_columns
= WIDE_MAX_COLUMNS
;
773 max_width
= 2 * draw_columns
;
777 static bool done
= false;
780 static inline void advance_conters(unsigned short ch
, int* k
, int* width
)
782 #ifdef HAVE_LCD_BITMAP
783 /* diacritics do not count */
784 if (rb
->is_diacritic(ch
, NULL
))
788 *width
+= glyph_width(ch
);
792 static inline bool line_is_full(int k
, int width
)
794 return ((k
>= max_columns
- 1) || (width
>= max_width
));
797 static unsigned char* crop_at_width(const unsigned char* p
)
801 const unsigned char *oldp
= p
;
805 while (!line_is_full(k
, width
)) {
810 advance_conters(ch
, &k
, &width
);
813 return (unsigned char*)oldp
;
816 static unsigned char* find_first_feed(const unsigned char* p
, int size
)
820 const unsigned char *oldp
= p
;
821 const unsigned char *lbrkp
= NULL
;
828 return (unsigned char*)p
;
832 if (prefs
.word_mode
== WRAP
)
834 for (j
= 0; j
< ((int) sizeof(line_break
)); j
++)
836 if (ch
== line_break
[j
])
844 width
+= glyph_width(ch
);
845 if (width
> max_width
)
846 return (lbrkp
== NULL
)? (unsigned char*)oldp
: (unsigned char*)lbrkp
;
854 static unsigned char* find_last_feed(const unsigned char* p
, int size
)
858 for (i
=size
-1; i
>=0; i
--)
860 return (unsigned char*) p
+i
;
865 static unsigned char* find_last_space(const unsigned char* p
, int size
)
869 k
= (prefs
.line_mode
==JOIN
) || (prefs
.line_mode
==REFLOW
) ? 0:1;
872 if (!BUFFER_OOB(&p
[i
]))
873 for (j
=k
; j
< ((int) sizeof(line_break
)) - 1; j
++) {
874 if (p
[i
] == line_break
[j
])
875 return (unsigned char*) p
+i
;
878 if (prefs
.word_mode
== WRAP
) {
879 for (i
=size
-1; i
>=0; i
--) {
880 for (j
=k
; j
< (int) sizeof(line_break
) - 1; j
++) {
881 if (p
[i
] == line_break
[j
])
882 return (unsigned char*) p
+i
;
890 static unsigned char* find_next_line(const unsigned char* cur_line
, bool *is_short
)
892 const unsigned char *next_line
= NULL
;
893 int size
, i
, j
, j_next
, j_prev
, k
, width
, search_len
, spaces
, newlines
;
897 if (is_short
!= NULL
)
900 if BUFFER_OOB(cur_line
)
903 if (prefs
.view_mode
== WIDE
) {
904 search_len
= MAX_WIDTH
;
906 else { /* prefs.view_mode == NARROW */
907 search_len
= crop_at_width(cur_line
) - cur_line
;
910 size
= BUFFER_OOB(cur_line
+search_len
) ? buffer_end
-cur_line
: search_len
;
912 if ((prefs
.line_mode
== JOIN
) || (prefs
.line_mode
== REFLOW
)) {
913 /* Need to scan ahead and possibly increase search_len and size,
914 or possibly set next_line at second hard return in a row. */
917 j_next
=j
=k
=width
=spaces
=newlines
=0;
919 const unsigned char *p
, *oldp
;
924 if (BUFFER_OOB(cur_line
+j
))
926 if (line_is_full(k
, width
)) {
927 size
= search_len
= j_prev
;
931 oldp
= p
= &cur_line
[j
];
933 j_next
= j
+ (p
- oldp
);
937 if (prefs
.line_mode
== REFLOW
) {
940 next_line
= cur_line
+ size
;
941 return (unsigned char*) next_line
;
943 if (j
==0) /* i=1 is intentional */
944 for (i
=0; i
<par_indent_spaces
; i
++)
945 advance_conters(' ', &k
, &width
);
947 if (!first_chars
) spaces
++;
953 next_line
= cur_line
+ size
- spaces
;
954 if (next_line
!= cur_line
)
955 return (unsigned char*) next_line
;
961 if (BUFFER_OOB(cur_line
+size
) || size
> 2*search_len
)
964 spaces
= first_chars
? 0:1;
968 if (prefs
.line_mode
==JOIN
|| newlines
>0) {
971 advance_conters(' ', &k
, &width
);
972 if (line_is_full(k
, width
)) {
973 size
= search_len
= j
;
979 /* REFLOW, multiple spaces between words: count only
980 * one. If more are needed, they will be added
984 advance_conters(' ', &k
, &width
);
985 if (line_is_full(k
, width
)) {
986 size
= search_len
= j
;
991 advance_conters(ch
, &k
, &width
);
997 /* find first hard return */
998 next_line
= find_first_feed(cur_line
, size
);
1001 if (next_line
== NULL
)
1002 if (size
== search_len
) {
1003 if (prefs
.word_mode
== WRAP
) /* Find last space */
1004 next_line
= find_last_space(cur_line
, size
);
1006 if (next_line
== NULL
) {
1007 next_line
= crop_at_width(cur_line
);
1010 if (prefs
.word_mode
== WRAP
) {
1011 for (i
=0;i
<WRAP_TRIM
;i
++) {
1012 if (!(isspace(next_line
[0]) && !BUFFER_OOB(next_line
)))
1020 if (prefs
.line_mode
== EXPAND
)
1021 if (!BUFFER_OOB(next_line
)) /* Not Null & not out of bounds */
1022 if (next_line
[0] == 0)
1023 if (next_line
!= cur_line
)
1024 return (unsigned char*) next_line
;
1026 /* If next_line is pointing to a zero, increment it; i.e.,
1027 leave the terminator at the end of cur_line. If pointing
1028 to a hyphen, increment only if there is room to display
1029 the hyphen on current line (won't apply in WIDE mode,
1030 since it's guarenteed there won't be room). */
1031 if (!BUFFER_OOB(next_line
)) /* Not Null & not out of bounds */
1032 if (next_line
[0] == 0)/* ||
1033 (next_line[0] == '-' && next_line-cur_line < draw_columns)) */
1036 if (BUFFER_OOB(next_line
))
1038 if (BUFFER_EOF() && next_line
!= cur_line
)
1039 return (unsigned char*) next_line
;
1046 return (unsigned char*) next_line
;
1049 static unsigned char* find_prev_line(const unsigned char* cur_line
)
1051 const unsigned char *prev_line
= NULL
;
1052 const unsigned char *p
;
1054 if BUFFER_OOB(cur_line
)
1057 /* To wrap consistently at the same places, we must
1058 start with a known hard return, then work downwards.
1059 We can either search backwards for a hard return,
1060 or simply start wrapping downwards from top of buffer.
1061 If current line is not near top of buffer, this is
1062 a file with long lines (paragraphs). We would need to
1063 read earlier sectors before we could decide how to
1064 properly wrap the lines above the current line, but
1065 it probably is not worth the disk access. Instead,
1066 start with top of buffer and wrap down from there.
1067 This may result in some lines wrapping at different
1068 points from where they wrap when scrolling down.
1069 If buffer is at top of file, start at top of buffer. */
1071 if ((prefs
.line_mode
== JOIN
) || (prefs
.line_mode
== REFLOW
))
1072 prev_line
= p
= NULL
;
1074 prev_line
= p
= find_last_feed(buffer
, cur_line
-buffer
-1);
1075 /* Null means no line feeds in buffer above current line. */
1077 if (prev_line
== NULL
)
1078 if (BUFFER_BOF() || cur_line
- buffer
> READ_PREV_ZONE
)
1079 prev_line
= p
= buffer
;
1080 /* (else return NULL and read previous block) */
1082 /* Wrap downwards until too far, then use the one before. */
1083 while (p
!= NULL
&& p
< cur_line
) {
1085 p
= find_next_line(prev_line
, NULL
);
1088 if (BUFFER_OOB(prev_line
))
1091 return (unsigned char*) prev_line
;
1094 static void check_bom(void)
1096 unsigned char bom
[BOM_SIZE
];
1097 off_t orig
= rb
->lseek(fd
, 0, SEEK_CUR
);
1101 rb
->lseek(fd
, 0, SEEK_SET
);
1103 if (rb
->read(fd
, bom
, BOM_SIZE
) == BOM_SIZE
)
1104 is_bom
= !memcmp(bom
, BOM
, BOM_SIZE
);
1106 rb
->lseek(fd
, orig
, SEEK_SET
);
1109 static void fill_buffer(long pos
, unsigned char* buf
, unsigned size
)
1111 /* Read from file and preprocess the data */
1112 /* To minimize disk access, always read on sector boundaries */
1113 unsigned numread
, i
;
1114 bool found_CR
= false;
1115 off_t offset
= rb
->lseek(fd
, pos
, SEEK_SET
);
1117 if (offset
== 0 && prefs
.encoding
== UTF_8
&& is_bom
)
1118 rb
->lseek(fd
, BOM_SIZE
, SEEK_SET
);
1120 numread
= rb
->read(fd
, buf
, size
- 1);
1122 rb
->button_clear_queue(); /* clear button queue */
1124 for(i
= 0; i
< numread
; i
++) {
1141 case 0: /* No break between case 0 and default, intentionally */
1154 static int viewer_find_bookmark(int page
, int line
)
1158 for (i
= 0; i
< bookmark_count
; i
++)
1160 if (bookmarks
[i
].page
== page
&& bookmarks
[i
].line
== line
)
1166 static int read_and_synch(int direction
)
1168 /* Read next (or prev) block, and reposition global pointers. */
1169 /* direction: 1 for down (i.e., further into file), -1 for up */
1170 int move_size
, move_vector
, offset
;
1171 unsigned char *fill_buf
;
1173 if (direction
== -1) /* up */ {
1174 move_size
= SMALL_BLOCK_SIZE
;
1176 fill_buf
= TOP_SECTOR
;
1177 rb
->memcpy(BOTTOM_SECTOR
, MID_SECTOR
, SMALL_BLOCK_SIZE
);
1178 rb
->memcpy(MID_SECTOR
, TOP_SECTOR
, SMALL_BLOCK_SIZE
);
1181 if (prefs
.view_mode
== WIDE
) {
1182 /* WIDE mode needs more buffer so we have to read smaller blocks */
1183 move_size
= SMALL_BLOCK_SIZE
;
1184 offset
= LARGE_BLOCK_SIZE
;
1185 fill_buf
= BOTTOM_SECTOR
;
1186 rb
->memcpy(TOP_SECTOR
, MID_SECTOR
, SMALL_BLOCK_SIZE
);
1187 rb
->memcpy(MID_SECTOR
, BOTTOM_SECTOR
, SMALL_BLOCK_SIZE
);
1190 move_size
= LARGE_BLOCK_SIZE
;
1191 offset
= SMALL_BLOCK_SIZE
;
1192 fill_buf
= MID_SECTOR
;
1193 rb
->memcpy(TOP_SECTOR
, BOTTOM_SECTOR
, SMALL_BLOCK_SIZE
);
1196 move_vector
= direction
* move_size
;
1197 screen_top_ptr
-= move_vector
;
1198 file_pos
+= move_vector
;
1199 buffer_end
= BUFFER_END(); /* Update whenever file_pos changes */
1200 fill_buffer(file_pos
+ offset
, fill_buf
, move_size
);
1204 static void get_next_line_position(unsigned char **line_begin
,
1205 unsigned char **line_end
,
1210 *line_begin
= *line_end
;
1211 *line_end
= find_next_line(*line_begin
, is_short
);
1213 if (*line_end
== NULL
&& !BUFFER_EOF())
1215 resynch_move
= read_and_synch(1); /* Read block & move ptrs */
1216 *line_begin
-= resynch_move
;
1217 if (next_line_ptr
> buffer
)
1218 next_line_ptr
-= resynch_move
;
1220 *line_end
= find_next_line(*line_begin
, is_short
);
1224 static void increment_current_line(void)
1226 if (cline
< display_lines
)
1228 else if (cpage
< MAX_PAGE
)
1235 static void decrement_current_line(void)
1242 cline
= display_lines
;
1246 static void viewer_scroll_up(void)
1250 p
= find_prev_line(screen_top_ptr
);
1251 if (p
== NULL
&& !BUFFER_BOF()) {
1253 p
= find_prev_line(screen_top_ptr
);
1258 decrement_current_line();
1261 static void viewer_scroll_down(bool autoscroll
)
1266 if (next_line_ptr
!= NULL
)
1267 screen_top_ptr
= next_line_ptr
;
1269 if (prefs
.scroll_mode
== LINE
|| autoscroll
)
1270 increment_current_line();
1272 if (cline
> display_lines
) {
1278 static void viewer_scroll_to_top_line(void)
1282 for (line
= cline
; line
> 1; line
--)
1286 #ifdef HAVE_LCD_BITMAP
1287 static void viewer_scrollbar(void) {
1288 int items
, min_shown
, max_shown
, sb_begin_y
, sb_height
;
1290 items
= (int) file_size
; /* (SH1 int is same as long) */
1291 min_shown
= (int) file_pos
+ (screen_top_ptr
- buffer
);
1293 if (next_screen_ptr
== NULL
)
1296 max_shown
= min_shown
+ (next_screen_ptr
- screen_top_ptr
);
1298 sb_begin_y
= header_height
;
1299 sb_height
= LCD_HEIGHT
- header_height
- footer_height
;
1301 rb
->gui_scrollbar_draw(rb
->screens
[SCREEN_MAIN
],0, sb_begin_y
,
1302 SCROLLBAR_WIDTH
-1, sb_height
,
1303 items
, min_shown
, max_shown
, VERTICAL
);
1307 #ifdef HAVE_LCD_BITMAP
1308 static void viewer_show_header(void)
1310 if (prefs
.header_mode
== HD_SBAR
|| prefs
.header_mode
== HD_BOTH
)
1311 rb
->gui_syncstatusbar_draw(rb
->statusbars
, true);
1313 if (prefs
.header_mode
== HD_PATH
|| prefs
.header_mode
== HD_BOTH
)
1314 rb
->lcd_putsxy(0, header_height
- pf
->height
, file_name
);
1317 static void viewer_show_footer(void)
1319 if (prefs
.footer_mode
== FT_SBAR
|| prefs
.footer_mode
== FT_BOTH
)
1320 rb
->gui_syncstatusbar_draw(rb
->statusbars
, true);
1322 if (prefs
.footer_mode
== FT_PAGE
|| prefs
.footer_mode
== FT_BOTH
)
1324 unsigned char buf
[12];
1327 rb
->snprintf(buf
, sizeof(buf
), "%d", cpage
);
1329 rb
->snprintf(buf
, sizeof(buf
), "%d - %d", cpage
, cpage
+1);
1331 rb
->lcd_putsxy(0, LCD_HEIGHT
- footer_height
, buf
);
1336 static void viewer_draw(int col
)
1338 int i
, j
, k
, line_len
, line_width
, spaces
, left_col
=0;
1339 int width
, extra_spaces
, indent_spaces
, spaces_per_word
, spaces_width
, disp_width
= 0;
1340 bool multiple_spacing
, line_is_short
;
1342 unsigned char *str
, *oldstr
;
1343 unsigned char *line_begin
;
1344 unsigned char *line_end
;
1346 int max_chars
= max_columns
* DIACRITIC_FACTOR
;
1347 unsigned char scratch_buffer
[max_chars
* 4 + 1];
1348 unsigned char utf8_buffer
[max_chars
* 4 + 1];
1350 /* If col==-1 do all calculations but don't display */
1352 #ifdef HAVE_LCD_BITMAP
1353 left_col
= prefs
.need_scrollbar
? SCROLLBAR_WIDTH
:0;
1357 rb
->lcd_clear_display();
1359 line_begin
= line_end
= screen_top_ptr
;
1361 for (i
= 0; i
< display_lines
; i
++) {
1362 if (BUFFER_OOB(line_end
))
1365 break; /* Happens after display last line at BUFFER_EOF() */
1367 if (lpage
== 0 && cline
== 1)
1370 last_screen_top_ptr
= screen_top_ptr
;
1371 last_file_pos
= file_pos
;
1375 get_next_line_position(&line_begin
, &line_end
, &line_is_short
);
1376 if (line_end
== NULL
)
1378 if (BUFFER_OOB(line_begin
))
1380 line_end
= buffer_end
+ 1;
1383 line_len
= line_end
- line_begin
;
1385 /* calculate line_len */
1386 str
= oldstr
= line_begin
;
1388 while (str
< line_end
) {
1390 str
= crop_at_width(str
);
1398 /* width of un-displayed part of the line */
1399 line_width
= j
*draw_columns
;
1401 while (oldstr
< line_end
) {
1402 oldstr
= get_ucs(oldstr
, &ch
);
1403 /* add width of displayed part of the line */
1406 int dw
= glyph_width(ch
);
1408 /* avoid counting spaces at the end of the line */
1415 line_width
+= dw
+ spaces_width
;
1421 if (prefs
.line_mode
== JOIN
) {
1422 if (line_begin
[0] == 0) {
1424 if (prefs
.word_mode
== CHOP
)
1429 for (j
=k
=spaces
=0; j
< line_len
; j
++) {
1440 scratch_buffer
[k
++] = ' ';
1445 scratch_buffer
[k
++] = ' ';
1446 if (k
== max_chars
- 1)
1449 scratch_buffer
[k
++] = c
;
1453 scratch_buffer
[k
] = 0;
1455 else if (prefs
.line_mode
== REFLOW
) {
1456 if (line_begin
[0] == 0) {
1458 if (prefs
.word_mode
== CHOP
)
1465 if (!line_is_short
) {
1466 multiple_spacing
= false;
1468 for (str
= line_begin
; str
< line_end
; ) {
1469 str
= get_ucs(str
, &ch
);
1473 if (str
== line_begin
)
1475 if (prefs
.word_mode
== WRAP
&& prefs
.alignment
== LEFT
)
1477 /* special case: indent the paragraph,
1478 * don't count spaces */
1479 indent_spaces
= par_indent_spaces
;
1482 else if (!multiple_spacing
)
1484 multiple_spacing
= true;
1487 multiple_spacing
= false;
1488 width
+= glyph_width(ch
);
1492 if (multiple_spacing
) spaces
--;
1495 /* total number of spaces to insert between words */
1496 extra_spaces
= (max_width
-width
)/glyph_width(' ')
1498 /* number of spaces between each word*/
1499 spaces_per_word
= extra_spaces
/ spaces
;
1500 /* number of words with n+1 spaces (to fill up) */
1501 extra_spaces
= extra_spaces
% spaces
;
1502 if (spaces_per_word
> 2) { /* too much spacing is awful */
1503 spaces_per_word
= 3;
1506 } else { /* this doesn't matter much... no spaces anyway */
1507 spaces_per_word
= extra_spaces
= 0;
1509 } else { /* end of a paragraph: don't fill line */
1510 spaces_per_word
= 1;
1513 multiple_spacing
= false;
1514 for (j
=k
=spaces
=0; j
< line_len
; j
++) {
1521 if (j
== line_len
- 1)
1525 /* indent paragraph */
1526 if (prefs
.word_mode
== WRAP
&& prefs
.alignment
== LEFT
)
1528 for (j
=0; j
<par_indent_spaces
; j
++)
1529 scratch_buffer
[k
++] = ' ';
1533 else if (!multiple_spacing
) {
1534 for (width
= spaces
<extra_spaces
? -1:0; width
< spaces_per_word
; width
++)
1535 scratch_buffer
[k
++] = ' ';
1538 multiple_spacing
= true;
1541 scratch_buffer
[k
++] = c
;
1542 multiple_spacing
= false;
1546 while (scratch_buffer
[k
-1] == ' ')
1548 scratch_buffer
[k
] = 0;
1550 else { /* prefs.line_mode != JOIN && prefs.line_mode != REFLOW */
1553 rb
->memcpy(scratch_buffer
, line_begin
, line_len
);
1554 scratch_buffer
[line_len
] = '\0';
1558 /* create displayed line */
1561 decode2utf8(scratch_buffer
, utf8_buffer
, col
, draw_columns
);
1562 rb
->lcd_getstringsize(utf8_buffer
, &disp_width
, NULL
);
1565 /* display on screen the displayed part of the line */
1568 bool in_page
= (cline
+i
<= display_lines
);
1569 int dpage
= cpage
+ (in_page
? 0 : 1);
1570 int dline
= cline
+ i
- (in_page
? 0 : display_lines
);
1571 bool bflag
= (viewer_find_bookmark(dpage
, dline
) >= 0);
1572 #ifdef HAVE_LCD_BITMAP
1573 int dy
= i
* pf
->height
+ header_height
;
1574 int dx
= (prefs
.alignment
== LEFT
)? left_col
: LCD_WIDTH
- disp_width
;
1577 #ifdef HAVE_LCD_BITMAP
1579 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_FG
);
1580 rb
->lcd_fillrect(left_col
, dy
, LCD_WIDTH
- left_col
, pf
->height
);
1581 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
1583 rb
->lcd_putsxy(dx
, dy
, utf8_buffer
);
1584 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1587 rb
->lcd_puts(left_col
, i
, BOOKMARK_ICON
);
1589 rb
->lcd_puts(left_col
+1, i
, utf8_buffer
);
1594 next_line_ptr
= line_end
;
1596 next_screen_ptr
= line_end
;
1597 if (BUFFER_OOB(next_screen_ptr
))
1598 next_screen_ptr
= NULL
;
1600 #ifdef HAVE_LCD_BITMAP
1601 next_screen_to_draw_ptr
= prefs
.page_mode
==OVERLAP
? line_begin
: next_screen_ptr
;
1603 if (prefs
.need_scrollbar
)
1606 next_screen_to_draw_ptr
= next_screen_ptr
;
1609 #ifdef HAVE_LCD_BITMAP
1611 viewer_show_header();
1614 viewer_show_footer();
1621 static void viewer_top(void)
1623 /* Read top of file into buffer
1624 and point screen pointer to top */
1627 rb
->splash(0, "Loading...");
1630 buffer_end
= BUFFER_END(); /* Update whenever file_pos changes */
1631 fill_buffer(0, buffer
, buffer_size
);
1634 screen_top_ptr
= buffer
;
1639 static void viewer_bottom(void)
1641 unsigned char *line_begin
;
1642 unsigned char *line_end
;
1644 rb
->splash(0, "Loading...");
1646 if (last_screen_top_ptr
)
1650 screen_top_ptr
= last_screen_top_ptr
;
1651 file_pos
= last_file_pos
;
1652 fill_buffer(file_pos
, buffer
, buffer_size
);
1653 buffer_end
= BUFFER_END();
1657 line_end
= screen_top_ptr
;
1659 while (!BUFFER_EOF() || !BUFFER_OOB(line_end
))
1661 get_next_line_position(&line_begin
, &line_end
, NULL
);
1662 if (line_end
== NULL
)
1665 increment_current_line();
1667 screen_top_ptr
= line_end
;
1671 last_screen_top_ptr
= screen_top_ptr
;
1672 last_file_pos
= file_pos
;
1673 buffer_end
= BUFFER_END();
1676 #ifdef HAVE_LCD_BITMAP
1677 static void init_need_scrollbar(void) {
1678 /* Call viewer_draw in quiet mode to initialize next_screen_ptr,
1679 and thus ONE_SCREEN_FITS_ALL(), and thus NEED_SCROLLBAR() */
1681 prefs
.need_scrollbar
= NEED_SCROLLBAR();
1682 draw_columns
= prefs
.need_scrollbar
? display_columns
-SCROLLBAR_WIDTH
: display_columns
;
1683 par_indent_spaces
= draw_columns
/(5*glyph_width(' '));
1687 static void init_header_and_footer(void)
1691 if (rb
->global_settings
->statusbar
== STATUSBAR_TOP
)
1693 if (prefs
.header_mode
== HD_SBAR
|| prefs
.header_mode
== HD_BOTH
)
1694 header_height
= STATUSBAR_HEIGHT
;
1696 if (prefs
.footer_mode
== FT_SBAR
)
1697 prefs
.footer_mode
= FT_NONE
;
1698 else if (prefs
.footer_mode
== FT_BOTH
)
1699 prefs
.footer_mode
= FT_PAGE
;
1701 else if (rb
->global_settings
->statusbar
== STATUSBAR_BOTTOM
)
1703 if (prefs
.footer_mode
== FT_SBAR
|| prefs
.footer_mode
== FT_BOTH
)
1704 footer_height
= STATUSBAR_HEIGHT
;
1706 if (prefs
.header_mode
== HD_SBAR
)
1707 prefs
.header_mode
= HD_NONE
;
1708 else if (prefs
.header_mode
== HD_BOTH
)
1709 prefs
.header_mode
= HD_PATH
;
1711 else /* STATUSBAR_OFF || STATUSBAR_CUSTOM */
1713 if (prefs
.header_mode
== HD_SBAR
)
1714 prefs
.header_mode
= HD_NONE
;
1715 else if (prefs
.header_mode
== HD_BOTH
)
1716 prefs
.header_mode
= HD_PATH
;
1718 if (prefs
.footer_mode
== FT_SBAR
)
1719 prefs
.footer_mode
= FT_NONE
;
1720 else if (prefs
.footer_mode
== FT_BOTH
)
1721 prefs
.footer_mode
= FT_PAGE
;
1724 if (prefs
.header_mode
== HD_NONE
|| prefs
.header_mode
== HD_PATH
||
1725 prefs
.footer_mode
== FT_NONE
|| prefs
.footer_mode
== FT_PAGE
)
1726 rb
->gui_syncstatusbar_draw(rb
->statusbars
, false);
1728 if (prefs
.header_mode
== HD_PATH
|| prefs
.header_mode
== HD_BOTH
)
1729 header_height
+= pf
->height
;
1730 if (prefs
.footer_mode
== FT_PAGE
|| prefs
.footer_mode
== FT_BOTH
)
1731 footer_height
+= pf
->height
;
1733 display_lines
= (LCD_HEIGHT
- header_height
- footer_height
) / pf
->height
;
1737 last_screen_top_ptr
= NULL
;
1740 static bool change_font(unsigned char *font
)
1742 unsigned char buf
[MAX_PATH
];
1744 if (font
== NULL
|| *font
== '\0')
1747 rb
->snprintf(buf
, MAX_PATH
, "%s/%s.fnt", FONT_DIR
, font
);
1748 if (rb
->font_load(NULL
, buf
) < 0) {
1749 rb
->splash(HZ
/2, "Font load failed.");
1757 static bool viewer_init(void)
1759 #ifdef HAVE_LCD_BITMAP
1760 /* initialize fonts */
1761 pf
= rb
->font_get(FONT_UI
);
1765 draw_columns
= display_columns
= LCD_WIDTH
;
1767 /* REAL fixed pitch :) all chars use up 1 cell */
1769 draw_columns
= display_columns
= 11;
1770 par_indent_spaces
= 2;
1773 fd
= rb
->open(file_name
, O_RDONLY
);
1777 /* Init mac_text value used in processing buffer */
1783 /* When a file is UTF-8 file with BOM, if prefs.encoding is UTF-8,
1784 * then file size decreases only BOM_SIZE.
1786 static void get_filesize(void)
1788 file_size
= rb
->filesize(fd
);
1789 if (file_size
== -1)
1792 if (prefs
.encoding
== UTF_8
&& is_bom
)
1793 file_size
-= BOM_SIZE
;
1796 static int bm_comp(const void *a
, const void *b
)
1798 struct bookmark_info
*pa
;
1799 struct bookmark_info
*pb
;
1801 pa
= (struct bookmark_info
*)a
;
1802 pb
= (struct bookmark_info
*)b
;
1804 if (pa
->page
!= pb
->page
)
1805 return pa
->page
- pb
->page
;
1807 return pa
->line
- pb
->line
;
1810 static void viewer_add_bookmark(void)
1812 if (bookmark_count
>= MAX_BOOKMARKS
-1)
1815 bookmarks
[bookmark_count
].file_position
1816 = file_pos
+ screen_top_ptr
- buffer
;
1817 bookmarks
[bookmark_count
].page
= cpage
;
1818 bookmarks
[bookmark_count
].line
= cline
;
1819 bookmarks
[bookmark_count
].flag
= BOOKMARK_USER
;
1823 static int viewer_add_last_read_bookmark(void)
1827 i
= viewer_find_bookmark(cpage
, cline
);
1829 bookmarks
[i
].flag
|= BOOKMARK_LAST
;
1832 viewer_add_bookmark();
1833 i
= bookmark_count
-1;
1834 bookmarks
[i
].flag
= BOOKMARK_LAST
;
1839 static void viewer_remove_bookmark(int i
)
1843 if (i
< 0 || i
>= bookmark_count
)
1846 for (j
= i
+1; j
< bookmark_count
; j
++)
1847 rb
->memcpy(&bookmarks
[j
-1], &bookmarks
[j
],
1848 sizeof(struct bookmark_info
));
1853 static void viewer_remove_last_read_bookmark(void)
1857 for (i
= 0; i
< bookmark_count
; i
++)
1859 if (bookmarks
[i
].flag
& BOOKMARK_LAST
)
1861 if (bookmarks
[i
].flag
== BOOKMARK_LAST
)
1863 for (j
= i
+1; j
< bookmark_count
; j
++)
1864 rb
->memcpy(&bookmarks
[j
-1], &bookmarks
[j
],
1865 sizeof(struct bookmark_info
));
1870 bookmarks
[i
].flag
= BOOKMARK_USER
;
1876 static int viewer_get_last_read_bookmark(void)
1880 for (i
= 0; i
< bookmark_count
; i
++)
1882 if (bookmarks
[i
].flag
& BOOKMARK_LAST
)
1888 static void viewer_select_bookmark(int initval
)
1897 struct opt_items items
[bookmark_count
];
1898 unsigned char names
[bookmark_count
][38];
1900 if (initval
>= 0 && initval
< bookmark_count
)
1902 ipage
= bookmarks
[initval
].page
;
1903 iline
= bookmarks
[initval
].line
;
1906 rb
->qsort(bookmarks
, bookmark_count
, sizeof(struct bookmark_info
),
1909 for (i
= 0; i
< bookmark_count
; i
++)
1911 rb
->snprintf(names
[i
], sizeof(names
[0]),
1912 #if CONFIG_KEYPAD != PLAYER_PAD
1913 "%sPage: %d Line: %d",
1917 (bookmarks
[i
].flag
&BOOKMARK_LAST
)? "*":" ",
1920 items
[i
].string
= names
[i
];
1921 items
[i
].voice_id
= -1;
1922 if (selected
< 0 && bookmarks
[i
].page
== ipage
&& bookmarks
[i
].line
== iline
)
1926 rb
->set_option("Select bookmark", &selected
, INT
, items
,
1927 sizeof(items
) / sizeof(items
[0]), NULL
);
1929 if (selected
< 0 || selected
>= bookmark_count
)
1931 if (initval
< 0 || (selected
= viewer_get_last_read_bookmark()) < 0)
1934 rb
->splash(HZ
, "Start the first page.");
1936 screen_top_ptr
= buffer
;
1939 buffer_end
= BUFFER_END();
1944 screen_pos
= bookmarks
[selected
].file_position
;
1945 screen_top
= screen_pos
% buffer_size
;
1946 file_pos
= screen_pos
- screen_top
;
1947 screen_top_ptr
= buffer
+ screen_top
;
1948 cpage
= bookmarks
[selected
].page
;
1949 cline
= bookmarks
[selected
].line
;
1950 buffer_end
= BUFFER_END();
1953 static void viewer_default_preferences(void)
1955 prefs
.word_mode
= WRAP
;
1956 prefs
.line_mode
= NORMAL
;
1957 prefs
.view_mode
= NARROW
;
1958 prefs
.alignment
= LEFT
;
1959 prefs
.scroll_mode
= PAGE
;
1960 prefs
.page_mode
= NO_OVERLAP
;
1961 prefs
.scrollbar_mode
= SB_OFF
;
1962 rb
->memset(prefs
.font
, 0, MAX_PATH
);
1963 #ifdef HAVE_LCD_BITMAP
1964 prefs
.header_mode
= HD_BOTH
;
1965 prefs
.footer_mode
= FT_BOTH
;
1966 rb
->snprintf(prefs
.font
, MAX_PATH
, "%s", rb
->global_settings
->font_file
);
1968 prefs
.header_mode
= HD_NONE
;
1969 prefs
.footer_mode
= FT_NONE
;
1971 prefs
.autoscroll_speed
= 1;
1972 /* Set codepage to system default */
1973 prefs
.encoding
= rb
->global_settings
->default_codepage
;
1976 static bool viewer_read_preferences(int pfd
, int version
, struct preferences
*prf
)
1978 unsigned char buf
[PREFERENCES_SIZE
];
1979 unsigned char *p
= buf
;
1980 int read_size
= PREFERENCES_SIZE
;
1985 if (rb
->read(pfd
, buf
, read_size
) != read_size
)
1988 prf
->word_mode
= *p
++;
1989 prf
->line_mode
= *p
++;
1990 prf
->view_mode
= *p
++;
1992 prf
->alignment
= *p
++;
1994 prf
->alignment
= LEFT
;
1995 prf
->encoding
= *p
++;
1996 prf
->scrollbar_mode
= *p
++;
1997 prf
->need_scrollbar
= *p
++;
1998 prf
->page_mode
= *p
++;
1999 prf
->header_mode
= *p
++;
2000 prf
->footer_mode
= *p
++;
2001 prf
->scroll_mode
= *p
++;
2002 prf
->autoscroll_speed
= *p
++;
2003 rb
->memcpy(prf
->font
, p
, MAX_PATH
);
2007 static bool viewer_write_preferences(int pfd
, const struct preferences
*prf
)
2009 unsigned char buf
[PREFERENCES_SIZE
];
2010 unsigned char *p
= buf
;
2012 *p
++ = prf
->word_mode
;
2013 *p
++ = prf
->line_mode
;
2014 *p
++ = prf
->view_mode
;
2015 *p
++ = prf
->alignment
;
2016 *p
++ = prf
->encoding
;
2017 *p
++ = prf
->scrollbar_mode
;
2018 *p
++ = prf
->need_scrollbar
;
2019 *p
++ = prf
->page_mode
;
2020 *p
++ = prf
->header_mode
;
2021 *p
++ = prf
->footer_mode
;
2022 *p
++ = prf
->scroll_mode
;
2023 *p
++ = prf
->autoscroll_speed
;
2024 rb
->memcpy(p
, prf
->font
, MAX_PATH
);
2026 return (rb
->write(pfd
, buf
, sizeof(buf
)) == sizeof(buf
));
2029 static bool viewer_read_bookmark_info(int bfd
, struct bookmark_info
*b
)
2031 unsigned char buf
[BOOKMARK_SIZE
];
2033 if (rb
->read(bfd
, buf
, sizeof(buf
)) != sizeof(buf
))
2036 b
->file_position
= (buf
[0] << 24)|(buf
[1] << 16)|(buf
[2] << 8)|buf
[3];
2037 b
->page
= (buf
[4] << 8)|buf
[5];
2044 static bool viewer_read_bookmark_infos(int bfd
)
2049 if (rb
->read(bfd
, &c
, 1) != 1)
2056 if (bookmark_count
> MAX_BOOKMARKS
)
2057 bookmark_count
= MAX_BOOKMARKS
;
2059 for (i
= 0; i
< bookmark_count
; i
++)
2061 if (!viewer_read_bookmark_info(bfd
, &bookmarks
[i
]))
2070 static bool viewer_write_bookmark_info(int bfd
, struct bookmark_info
*b
)
2072 unsigned char buf
[BOOKMARK_SIZE
];
2073 unsigned char *p
= buf
;
2076 ul
= b
->file_position
;
2089 return (rb
->write(bfd
, buf
, sizeof(buf
)) == sizeof(buf
));
2092 static bool viewer_write_bookmark_infos(int bfd
)
2094 unsigned char c
= bookmark_count
;
2097 if (rb
->write(bfd
, &c
, 1) != 1)
2100 for (i
= 0; i
< bookmark_count
; i
++)
2102 if (!viewer_write_bookmark_info(bfd
, &bookmarks
[i
]))
2109 static bool viewer_load_global_settings(void)
2111 unsigned buf
[GLOBAL_SETTINGS_H_SIZE
];
2112 int sfd
= rb
->open(GLOBAL_SETTINGS_FILE
, O_RDONLY
);
2119 if ((rb
->read(sfd
, buf
, GLOBAL_SETTINGS_H_SIZE
) == GLOBAL_SETTINGS_H_SIZE
) ||
2120 (rb
->memcmp(buf
, GLOBAL_SETTINGS_HEADER
, GLOBAL_SETTINGS_H_SIZE
- 1) == 0))
2122 version
= buf
[GLOBAL_SETTINGS_H_SIZE
- 1] - GLOBAL_SETTINGS_FIRST_VERSION
;
2123 res
= viewer_read_preferences(sfd
, version
, &prefs
);
2129 static bool viewer_save_global_settings(void)
2131 int sfd
= rb
->open(GLOBAL_SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
);
2132 unsigned char buf
[GLOBAL_SETTINGS_H_SIZE
];
2137 rb
->memcpy(buf
, GLOBAL_SETTINGS_HEADER
, GLOBAL_SETTINGS_H_SIZE
- 1);
2138 buf
[GLOBAL_SETTINGS_H_SIZE
- 1] = GLOBAL_SETTINGS_VERSION
;
2140 if (rb
->write(sfd
, buf
, GLOBAL_SETTINGS_H_SIZE
) != GLOBAL_SETTINGS_H_SIZE
||
2141 !viewer_write_preferences(sfd
, &prefs
))
2144 rb
->remove(GLOBAL_SETTINGS_TMP_FILE
);
2148 rb
->remove(GLOBAL_SETTINGS_FILE
);
2149 rb
->rename(GLOBAL_SETTINGS_TMP_FILE
, GLOBAL_SETTINGS_FILE
);
2153 static bool viewer_convert_settings(int sfd
, int dfd
, int old_ver
)
2155 struct preferences new_prefs
;
2158 unsigned char buf
[MAX_PATH
+ 2];
2161 rb
->read(sfd
, buf
, MAX_PATH
+ 2);
2162 rb
->write(dfd
, buf
, MAX_PATH
+ 2);
2164 settings_size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+ 1];
2166 old_pos
= rb
->lseek(sfd
, 0, SEEK_CUR
);
2167 new_pos
= rb
->lseek(dfd
, 0, SEEK_CUR
);
2170 * when the settings size != preferences size + bookmarks size,
2171 * settings data are considered to be old version.
2173 if (old_ver
> 0 && ((settings_size
- PREFERENCES_SIZE
) % 8) == 0)
2176 if (!viewer_read_preferences(sfd
, old_ver
, &new_prefs
))
2179 if (!viewer_write_preferences(dfd
, &new_prefs
))
2182 settings_size
-= (rb
->lseek(sfd
, 0, SEEK_CUR
) - old_pos
);
2184 if (settings_size
> 0)
2186 rb
->read(sfd
, buf
, settings_size
);
2187 rb
->write(dfd
, buf
, settings_size
);
2190 settings_size
= rb
->lseek(dfd
, 0, SEEK_CUR
) - new_pos
;
2191 buf
[0] = settings_size
>> 8;
2192 buf
[1] = settings_size
;
2193 rb
->lseek(dfd
, new_pos
- 2, SEEK_SET
);
2194 rb
->write(dfd
, buf
, 2);
2195 rb
->lseek(dfd
, settings_size
, SEEK_CUR
);
2199 static bool viewer_convert_settings_file(void)
2201 unsigned char buf
[SETTINGS_H_SIZE
+2];
2209 if ((sfd
= rb
->open(SETTINGS_FILE
, O_RDONLY
)) < 0)
2212 if ((tfd
= rb
->open(SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
)) < 0)
2218 rb
->read(sfd
, buf
, SETTINGS_H_SIZE
+ 2);
2220 version
= buf
[SETTINGS_H_SIZE
- 1] - SETTINGS_FIRST_VERSION
;
2221 fcount
= (buf
[SETTINGS_H_SIZE
] << 8) | buf
[SETTINGS_H_SIZE
+ 1];
2222 buf
[SETTINGS_H_SIZE
- 1] = SETTINGS_VERSION
;
2224 rb
->write(tfd
, buf
, SETTINGS_H_SIZE
+ 2);
2226 for (i
= 0; i
< fcount
; i
++)
2228 if (!viewer_convert_settings(sfd
, tfd
, version
))
2239 rb
->remove(SETTINGS_TMP_FILE
);
2242 rb
->remove(SETTINGS_FILE
);
2243 rb
->rename(SETTINGS_TMP_FILE
, SETTINGS_FILE
);
2248 static bool viewer_load_settings(void)
2250 unsigned char buf
[MAX_PATH
+2];
2251 unsigned int fcount
;
2258 sfd
= rb
->open(SETTINGS_FILE
, O_RDONLY
);
2262 if ((rb
->read(sfd
, buf
, SETTINGS_H_SIZE
+2) != SETTINGS_H_SIZE
+2) ||
2263 rb
->memcmp(buf
, SETTINGS_HEADER
, SETTINGS_H_SIZE
- 1))
2265 /* illegal setting file */
2268 if (rb
->file_exists(SETTINGS_FILE
))
2269 rb
->remove(SETTINGS_FILE
);
2274 if (buf
[SETTINGS_H_SIZE
- 1] != SETTINGS_VERSION
)
2277 if (!viewer_convert_settings_file())
2280 return viewer_load_settings();
2283 version
= buf
[SETTINGS_H_SIZE
- 1] - SETTINGS_FIRST_VERSION
;
2284 fcount
= (buf
[SETTINGS_H_SIZE
] << 8) | buf
[SETTINGS_H_SIZE
+1];
2285 for (i
= 0; i
< fcount
; i
++)
2287 if (rb
->read(sfd
, buf
, MAX_PATH
+2) != MAX_PATH
+2)
2290 size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+1];
2293 * when the settings size != preferences size + bookmarks size,
2294 * the settings file converts to the newer.
2296 if (version
> 0 && ((size
- PREFERENCES_SIZE
) % 8) == 0)
2299 if (!viewer_convert_settings_file())
2302 return viewer_load_settings();
2305 if (rb
->strcmp(buf
, file_name
))
2307 if (rb
->lseek(sfd
, size
, SEEK_CUR
) < 0)
2311 if (!viewer_read_preferences(sfd
, version
, &prefs
))
2314 res
= viewer_read_bookmark_infos(sfd
);
2323 /* load global settings */
2324 if (!viewer_load_global_settings())
2325 viewer_default_preferences();
2328 screen_top_ptr
= buffer
;
2334 rb
->memcpy(&old_prefs
, &prefs
, sizeof(struct preferences
));
2337 if (bookmark_count
> 1)
2338 viewer_select_bookmark(-1);
2339 else if (bookmark_count
== 1)
2344 screen_pos
= bookmarks
[0].file_position
;
2345 screen_top
= screen_pos
% buffer_size
;
2346 file_pos
= screen_pos
- screen_top
;
2347 screen_top_ptr
= buffer
+ screen_top
;
2348 cpage
= bookmarks
[0].page
;
2349 cline
= bookmarks
[0].line
;
2352 viewer_remove_last_read_bookmark();
2357 buffer_end
= BUFFER_END(); /* Update whenever file_pos changes */
2359 if (BUFFER_OOB(screen_top_ptr
))
2360 screen_top_ptr
= buffer
;
2362 fill_buffer(file_pos
, buffer
, buffer_size
);
2363 if (prefs
.scroll_mode
== PAGE
&& cline
> 1)
2364 viewer_scroll_to_top_line();
2366 /* remember the current position */
2367 start_position
= file_pos
+ screen_top_ptr
- buffer
;
2369 #ifdef HAVE_LCD_BITMAP
2370 /* load prefs font if it is different than the global settings font */
2371 if (rb
->strcmp(prefs
.font
, rb
->global_settings
->font_file
)) {
2372 if (!change_font(prefs
.font
)) {
2373 /* fallback by resetting prefs font to the global settings font */
2374 rb
->memset(prefs
.font
, 0, MAX_PATH
);
2375 rb
->snprintf(prefs
.font
, MAX_PATH
, "%s",
2376 rb
->global_settings
->font_file
);
2378 if (!change_font(prefs
.font
))
2383 init_need_scrollbar();
2384 init_header_and_footer();
2390 static bool copy_bookmark_file(int sfd
, int dfd
, off_t start
, off_t size
)
2394 if (rb
->lseek(sfd
, start
, SEEK_SET
) < 0)
2399 if (size
> buffer_size
)
2400 rsize
= buffer_size
;
2405 if (rb
->read(sfd
, buffer
, rsize
) != rsize
||
2406 rb
->write(dfd
, buffer
, rsize
) != rsize
)
2412 static bool viewer_save_settings(void)
2414 unsigned char buf
[MAX_PATH
+2];
2415 unsigned int fcount
= 0;
2420 off_t first_copy_size
= 0;
2421 off_t second_copy_start_pos
= 0;
2424 /* add reading page to bookmarks */
2425 idx
= viewer_find_bookmark(cpage
, cline
);
2427 bookmarks
[idx
].flag
|= BOOKMARK_LAST
;
2430 viewer_add_bookmark();
2431 bookmarks
[bookmark_count
-1].flag
= BOOKMARK_LAST
;
2434 tfd
= rb
->open(SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
);
2438 ofd
= rb
->open(SETTINGS_FILE
, O_RDWR
);
2441 if ((rb
->read(ofd
, buf
, SETTINGS_H_SIZE
+2) != SETTINGS_H_SIZE
+2) ||
2442 rb
->memcmp(buf
, SETTINGS_HEADER
, SETTINGS_H_SIZE
- 1))
2448 if (buf
[SETTINGS_H_SIZE
- 1] != SETTINGS_VERSION
)
2451 if (!viewer_convert_settings_file())
2454 viewer_save_settings();
2457 fcount
= (buf
[SETTINGS_H_SIZE
] << 8) | buf
[SETTINGS_H_SIZE
+1];
2459 for (i
= 0; i
< fcount
; i
++)
2461 if (rb
->read(ofd
, buf
, MAX_PATH
+2) != MAX_PATH
+2)
2466 size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+1];
2467 if (rb
->strcmp(buf
, file_name
))
2469 if (rb
->lseek(ofd
, size
, SEEK_CUR
) < 0)
2477 first_copy_size
= rb
->lseek(ofd
, 0, SEEK_CUR
);
2478 if (first_copy_size
< 0)
2483 second_copy_start_pos
= first_copy_size
+ size
;
2484 first_copy_size
-= MAX_PATH
+2;
2489 if (first_copy_size
== 0)
2490 first_copy_size
= rb
->filesize(ofd
);
2492 if (!copy_bookmark_file(ofd
, tfd
, 0, first_copy_size
))
2497 if (second_copy_start_pos
> 0)
2499 if (!copy_bookmark_file(ofd
, tfd
, second_copy_start_pos
,
2500 rb
->filesize(ofd
) - second_copy_start_pos
))
2510 rb
->memcpy(buf
, SETTINGS_HEADER
, SETTINGS_H_SIZE
- 1);
2511 buf
[SETTINGS_H_SIZE
-1] = SETTINGS_VERSION
;
2512 buf
[SETTINGS_H_SIZE
] = 0;
2513 buf
[SETTINGS_H_SIZE
+1] = 0;
2514 if (rb
->write(tfd
, buf
, SETTINGS_H_SIZE
+2) != SETTINGS_H_SIZE
+2)
2518 /* copy to current read file's bookmarks */
2519 rb
->memset(buf
, 0, MAX_PATH
);
2520 rb
->snprintf(buf
, MAX_PATH
, "%s", file_name
);
2522 size
= PREFERENCES_SIZE
+ bookmark_count
* BOOKMARK_SIZE
+ 1;
2523 buf
[MAX_PATH
] = size
>> 8;
2524 buf
[MAX_PATH
+1] = size
;
2526 if (rb
->write(tfd
, buf
, MAX_PATH
+2) != MAX_PATH
+2)
2529 if (!viewer_write_preferences(tfd
, &prefs
))
2532 if (!viewer_write_bookmark_infos(tfd
))
2535 if (rb
->lseek(tfd
, SETTINGS_H_SIZE
, SEEK_SET
) < 0)
2539 buf
[0] = fcount
>> 8;
2542 if (rb
->write(tfd
, buf
, 2) != 2)
2547 rb
->remove(SETTINGS_FILE
);
2548 rb
->rename(SETTINGS_TMP_FILE
, SETTINGS_FILE
);
2554 rb
->remove(SETTINGS_TMP_FILE
);
2558 static void viewer_exit(void *parameter
)
2562 /* save preference and bookmarks */
2563 if (!viewer_save_settings())
2564 rb
->splash(HZ
, "Can't save preference and bookmarks.");
2567 #ifdef HAVE_LCD_BITMAP
2568 if (rb
->strcmp(prefs
.font
, rb
->global_settings
->font_file
))
2569 change_font(rb
->global_settings
->font_file
);
2573 static void calc_page(void)
2576 unsigned char *line_begin
;
2577 unsigned char *line_end
;
2579 unsigned char *sstp
;
2581 rb
->splash(0, "Calculating page/line number...");
2583 /* add reading page to bookmarks */
2584 viewer_add_last_read_bookmark();
2586 rb
->qsort(bookmarks
, bookmark_count
, sizeof(struct bookmark_info
),
2592 screen_top_ptr
= buffer
;
2593 buffer_end
= BUFFER_END();
2595 fill_buffer(file_pos
, buffer
, buffer_size
);
2596 line_end
= line_begin
= buffer
;
2598 /* update page and line of all bookmark */
2599 for (i
= 0; i
< bookmark_count
; i
++)
2601 sfp
= bookmarks
[i
].file_position
;
2604 while ((line_begin
> sstp
|| sstp
>= line_end
) ||
2605 (file_pos
> sfp
|| sfp
>= file_pos
+ BUFFER_END() - buffer
))
2607 get_next_line_position(&line_begin
, &line_end
, NULL
);
2608 if (line_end
== NULL
)
2611 next_line_ptr
= line_end
;
2613 if (sstp
== buffer
&&
2614 file_pos
<= sfp
&& sfp
< file_pos
+ BUFFER_END() - buffer
)
2615 sstp
= sfp
- file_pos
+ buffer
;
2617 increment_current_line();
2620 decrement_current_line();
2621 bookmarks
[i
].page
= cpage
;
2622 bookmarks
[i
].line
= cline
;
2623 bookmarks
[i
].file_position
= file_pos
+ (line_begin
- buffer
);
2624 increment_current_line();
2627 /* remove reading page's bookmark */
2628 for (i
= 0; i
< bookmark_count
; i
++)
2630 if (bookmarks
[i
].flag
& BOOKMARK_LAST
)
2635 screen_pos
= bookmarks
[i
].file_position
;
2636 screen_top
= screen_pos
% buffer_size
;
2637 file_pos
= screen_pos
- screen_top
;
2638 screen_top_ptr
= buffer
+ screen_top
;
2640 cpage
= bookmarks
[i
].page
;
2641 cline
= bookmarks
[i
].line
;
2642 bookmarks
[i
].flag
^= BOOKMARK_LAST
;
2643 buffer_end
= BUFFER_END();
2645 fill_buffer(file_pos
, buffer
, buffer_size
);
2647 if (bookmarks
[i
].flag
== 0)
2648 viewer_remove_bookmark(i
);
2650 if (prefs
.scroll_mode
== PAGE
&& cline
> 1)
2651 viewer_scroll_to_top_line();
2657 static int col_limit(int col
)
2662 if (col
>= max_width
- draw_columns
)
2663 col
= max_width
- draw_columns
;
2668 /* settings helper functions */
2670 static bool encoding_setting(void)
2672 static struct opt_items names
[NUM_CODEPAGES
];
2675 enum codepages oldenc
= prefs
.encoding
;
2677 for (idx
= 0; idx
< NUM_CODEPAGES
; idx
++)
2679 names
[idx
].string
= rb
->get_codepage_name(idx
);
2680 names
[idx
].voice_id
= -1;
2683 res
= rb
->set_option("Encoding", &prefs
.encoding
, INT
, names
,
2684 sizeof(names
) / sizeof(names
[0]), NULL
);
2686 /* When prefs.encoding changes into UTF-8 or changes from UTF-8,
2687 * filesize (file_size) might change.
2688 * In addition, if prefs.encoding is UTF-8, then BOM does not read.
2690 if (oldenc
!= prefs
.encoding
&& (oldenc
== UTF_8
|| prefs
.encoding
== UTF_8
))
2694 fill_buffer(file_pos
, buffer
, buffer_size
);
2700 static bool word_wrap_setting(void)
2702 static const struct opt_items names
[] = {
2704 {"Off (Chop Words)", -1},
2707 return rb
->set_option("Word Wrap", &prefs
.word_mode
, INT
,
2711 static bool line_mode_setting(void)
2713 static const struct opt_items names
[] = {
2716 {"Expand Lines", -1},
2717 #ifdef HAVE_LCD_BITMAP
2718 {"Reflow Lines", -1},
2722 return rb
->set_option("Line Mode", &prefs
.line_mode
, INT
, names
,
2723 sizeof(names
) / sizeof(names
[0]), NULL
);
2726 static bool view_mode_setting(void)
2728 static const struct opt_items names
[] = {
2729 {"No (Narrow)", -1},
2733 ret
= rb
->set_option("Wide View", &prefs
.view_mode
, INT
,
2735 if (prefs
.view_mode
== NARROW
)
2741 static bool scroll_mode_setting(void)
2743 static const struct opt_items names
[] = {
2744 {"Scroll by Page", -1},
2745 {"Scroll by Line", -1},
2748 return rb
->set_option("Scroll Mode", &prefs
.scroll_mode
, INT
,
2752 #ifdef HAVE_LCD_BITMAP
2753 static bool page_mode_setting(void)
2755 static const struct opt_items names
[] = {
2760 return rb
->set_option("Overlap Pages", &prefs
.page_mode
, INT
,
2764 static bool scrollbar_setting(void)
2766 static const struct opt_items names
[] = {
2771 return rb
->set_option("Show Scrollbar", &prefs
.scrollbar_mode
, INT
,
2775 static bool header_setting(void)
2777 int len
= (rb
->global_settings
->statusbar
== STATUSBAR_TOP
)? 4 : 2;
2778 struct opt_items names
[len
];
2780 names
[0].string
= "None";
2781 names
[0].voice_id
= -1;
2782 names
[1].string
= "File path";
2783 names
[1].voice_id
= -1;
2785 if (rb
->global_settings
->statusbar
== STATUSBAR_TOP
)
2787 names
[2].string
= "Status bar";
2788 names
[2].voice_id
= -1;
2789 names
[3].string
= "Both";
2790 names
[3].voice_id
= -1;
2793 return rb
->set_option("Show Header", &prefs
.header_mode
, INT
,
2797 static bool footer_setting(void)
2799 int len
= (rb
->global_settings
->statusbar
== STATUSBAR_BOTTOM
)? 4 : 2;
2800 struct opt_items names
[len
];
2802 names
[0].string
= "None";
2803 names
[0].voice_id
= -1;
2804 names
[1].string
= "Page Num";
2805 names
[1].voice_id
= -1;
2807 if (rb
->global_settings
->statusbar
== STATUSBAR_BOTTOM
)
2809 names
[2].string
= "Status bar";
2810 names
[2].voice_id
= -1;
2811 names
[3].string
= "Both";
2812 names
[3].voice_id
= -1;
2815 return rb
->set_option("Show Footer", &prefs
.footer_mode
, INT
,
2819 static int font_comp(const void *a
, const void *b
)
2821 struct opt_items
*pa
;
2822 struct opt_items
*pb
;
2824 pa
= (struct opt_items
*)a
;
2825 pb
= (struct opt_items
*)b
;
2827 return rb
->strcmp(pa
->string
, pb
->string
);
2830 static bool font_setting(void)
2834 struct dirent
*entry
;
2842 dir
= rb
->opendir(FONT_DIR
);
2845 rb
->splash(HZ
/2, "Font dir is not accessible");
2851 entry
= rb
->readdir(dir
);
2856 len
= rb
->strlen(entry
->d_name
);
2857 if (len
< 4 || rb
->strcmp(entry
->d_name
+ len
-4, ".fnt"))
2864 struct opt_items names
[count
];
2865 unsigned char font_names
[size
];
2866 unsigned char *p
= font_names
;
2868 dir
= rb
->opendir(FONT_DIR
);
2871 rb
->splash(HZ
/2, "Font dir is not accessible");
2877 entry
= rb
->readdir(dir
);
2882 len
= rb
->strlen(entry
->d_name
);
2883 if (len
< 4 || rb
->strcmp(entry
->d_name
+ len
-4, ".fnt"))
2886 rb
->snprintf(p
, len
-3, "%s", entry
->d_name
);
2887 names
[i
].string
= p
;
2888 names
[i
].voice_id
= -1;
2896 rb
->qsort(names
, count
, sizeof(struct opt_items
), font_comp
);
2898 for (i
= 0; i
< count
; i
++)
2900 if (!rb
->strcmp(names
[i
].string
, prefs
.font
))
2906 old_font
= new_font
;
2908 res
= rb
->set_option("Select Font", &new_font
, INT
,
2909 names
, count
, NULL
);
2911 if (new_font
!= old_font
)
2913 /* load selected font */
2914 if (!change_font((unsigned char *)names
[new_font
].string
)) {
2915 /* revert by re-loading the preferences font */
2916 change_font(prefs
.font
);
2919 rb
->memset(prefs
.font
, 0, MAX_PATH
);
2920 rb
->snprintf(prefs
.font
, MAX_PATH
, "%s", names
[new_font
].string
);
2926 static bool alignment_setting(void)
2928 static const struct opt_items names
[] = {
2933 return rb
->set_option("Alignment", &prefs
.alignment
, INT
,
2938 static bool autoscroll_speed_setting(void)
2940 return rb
->set_int("Auto-scroll Speed", "", UNIT_INT
,
2941 &prefs
.autoscroll_speed
, NULL
, 1, 1, 10, NULL
);
2944 MENUITEM_FUNCTION(encoding_item
, 0, "Encoding", encoding_setting
,
2945 NULL
, NULL
, Icon_NOICON
);
2946 MENUITEM_FUNCTION(word_wrap_item
, 0, "Word Wrap", word_wrap_setting
,
2947 NULL
, NULL
, Icon_NOICON
);
2948 MENUITEM_FUNCTION(line_mode_item
, 0, "Line Mode", line_mode_setting
,
2949 NULL
, NULL
, Icon_NOICON
);
2950 MENUITEM_FUNCTION(view_mode_item
, 0, "Wide View", view_mode_setting
,
2951 NULL
, NULL
, Icon_NOICON
);
2952 #ifdef HAVE_LCD_BITMAP
2953 MENUITEM_FUNCTION(alignment_item
, 0, "Alignment", alignment_setting
,
2954 NULL
, NULL
, Icon_NOICON
);
2955 MENUITEM_FUNCTION(scrollbar_item
, 0, "Show Scrollbar", scrollbar_setting
,
2956 NULL
, NULL
, Icon_NOICON
);
2957 MENUITEM_FUNCTION(page_mode_item
, 0, "Overlap Pages", page_mode_setting
,
2958 NULL
, NULL
, Icon_NOICON
);
2959 MENUITEM_FUNCTION(header_item
, 0, "Show Header", header_setting
,
2960 NULL
, NULL
, Icon_NOICON
);
2961 MENUITEM_FUNCTION(footer_item
, 0, "Show Footer", footer_setting
,
2962 NULL
, NULL
, Icon_NOICON
);
2963 MENUITEM_FUNCTION(font_item
, 0, "Font", font_setting
,
2964 NULL
, NULL
, Icon_NOICON
);
2966 MENUITEM_FUNCTION(scroll_mode_item
, 0, "Scroll Mode", scroll_mode_setting
,
2967 NULL
, NULL
, Icon_NOICON
);
2968 MENUITEM_FUNCTION(autoscroll_speed_item
, 0, "Auto-Scroll Speed",
2969 autoscroll_speed_setting
, NULL
, NULL
, Icon_NOICON
);
2970 MAKE_MENU(option_menu
, "Viewer Options", NULL
, Icon_NOICON
,
2971 &encoding_item
, &word_wrap_item
, &line_mode_item
, &view_mode_item
,
2972 #ifdef HAVE_LCD_BITMAP
2973 &alignment_item
, &scrollbar_item
, &page_mode_item
, &header_item
,
2974 &footer_item
, &font_item
,
2976 &scroll_mode_item
, &autoscroll_speed_item
);
2978 static bool viewer_options_menu(bool is_global
)
2981 struct preferences tmp_prefs
;
2983 rb
->memcpy(&tmp_prefs
, &prefs
, sizeof(struct preferences
));
2985 result
= (rb
->do_menu(&option_menu
, NULL
, NULL
, false) == MENU_ATTACHED_USB
);
2987 if (!is_global
&& rb
->memcmp(&tmp_prefs
, &prefs
, sizeof(struct preferences
)))
2989 /* Show-scrollbar mode for current view-width mode */
2990 #ifdef HAVE_LCD_BITMAP
2991 init_need_scrollbar();
2992 init_header_and_footer();
2999 static void viewer_menu(void)
3003 MENUITEM_STRINGLIST(menu
, "Viewer Menu", NULL
,
3004 "Return", "Viewer Options",
3005 "Show Playback Menu", "Select Bookmark",
3006 "Global Settings", "Quit");
3008 result
= rb
->do_menu(&menu
, NULL
, NULL
, false);
3011 case 0: /* return */
3013 case 1: /* change settings */
3014 done
= viewer_options_menu(false);
3016 case 2: /* playback control */
3017 playback_control(NULL
);
3019 case 3: /* select bookmark */
3020 viewer_select_bookmark(viewer_add_last_read_bookmark());
3021 viewer_remove_last_read_bookmark();
3022 fill_buffer(file_pos
, buffer
, buffer_size
);
3023 if (prefs
.scroll_mode
== PAGE
&& cline
> 1)
3024 viewer_scroll_to_top_line();
3026 case 4: /* change global settings */
3028 struct preferences orig_prefs
;
3030 rb
->memcpy(&orig_prefs
, &prefs
, sizeof(struct preferences
));
3031 if (!viewer_load_global_settings())
3032 viewer_default_preferences();
3033 done
= viewer_options_menu(true);
3034 viewer_save_global_settings();
3035 rb
->memcpy(&prefs
, &orig_prefs
, sizeof(struct preferences
));
3046 enum plugin_status
plugin_start(const void* file
)
3049 int lastbutton
= BUTTON_NONE
;
3050 bool autoscroll
= false;
3053 old_tick
= *rb
->current_tick
;
3055 /* get the plugin buffer */
3056 buffer
= rb
->plugin_get_buffer((size_t *)&buffer_size
);
3057 if (buffer_size
== 0)
3059 rb
->splash(HZ
, "buffer does not allocate !!");
3060 return PLUGIN_ERROR
;
3062 block_size
= buffer_size
/ 3;
3063 buffer_size
= 3 * block_size
;
3066 return PLUGIN_ERROR
;
3071 rb
->splash(HZ
, "Error opening file.");
3072 return PLUGIN_ERROR
;
3075 if (!viewer_load_settings()) /* load the preferences and bookmark */
3076 return PLUGIN_ERROR
;
3079 rb
->lcd_set_backdrop(NULL
);
3088 if(old_tick
<= *rb
->current_tick
- (110-prefs
.autoscroll_speed
*10))
3090 viewer_scroll_down(true);
3092 old_tick
= *rb
->current_tick
;
3096 button
= rb
->button_get_w_tmo(HZ
/10);
3098 if (prefs
.view_mode
!= WIDE
) {
3099 /* when not in wide view mode, the SCREEN_LEFT and SCREEN_RIGHT
3100 buttons jump to the beginning and end of the file. To stop
3101 users doing this by accident, replace non-held occurrences
3102 with page up/down instead. */
3103 if (button
== VIEWER_SCREEN_LEFT
)
3104 button
= VIEWER_PAGE_UP
;
3105 else if (button
== VIEWER_SCREEN_RIGHT
)
3106 button
= VIEWER_PAGE_DOWN
;
3117 case VIEWER_AUTOSCROLL
:
3118 #ifdef VIEWER_AUTOSCROLL_PRE
3119 if (lastbutton
!= VIEWER_AUTOSCROLL_PRE
)
3122 autoscroll
= !autoscroll
;
3125 case VIEWER_PAGE_UP
:
3126 case VIEWER_PAGE_UP
| BUTTON_REPEAT
:
3127 #ifdef VIEWER_PAGE_UP2
3128 case VIEWER_PAGE_UP2
:
3129 case VIEWER_PAGE_UP2
| BUTTON_REPEAT
:
3131 if (prefs
.scroll_mode
== PAGE
)
3134 #ifdef HAVE_LCD_BITMAP
3135 for (i
= prefs
.page_mode
==OVERLAP
? 1:0; i
< display_lines
; i
++)
3137 for (i
= 0; i
< display_lines
; i
++)
3143 old_tick
= *rb
->current_tick
;
3147 case VIEWER_PAGE_DOWN
:
3148 case VIEWER_PAGE_DOWN
| BUTTON_REPEAT
:
3149 #ifdef VIEWER_PAGE_DOWN2
3150 case VIEWER_PAGE_DOWN2
:
3151 case VIEWER_PAGE_DOWN2
| BUTTON_REPEAT
:
3153 if (prefs
.scroll_mode
== PAGE
)
3156 if (next_screen_ptr
!= NULL
)
3158 screen_top_ptr
= next_screen_to_draw_ptr
;
3159 if (cpage
< MAX_PAGE
)
3164 viewer_scroll_down(autoscroll
);
3165 old_tick
= *rb
->current_tick
;
3169 case VIEWER_SCREEN_LEFT
:
3170 case VIEWER_SCREEN_LEFT
| BUTTON_REPEAT
:
3171 if (prefs
.view_mode
== WIDE
) {
3173 col
= col_limit(col
- draw_columns
);
3175 else { /* prefs.view_mode == NARROW */
3183 case VIEWER_SCREEN_RIGHT
:
3184 case VIEWER_SCREEN_RIGHT
| BUTTON_REPEAT
:
3185 if (prefs
.view_mode
== WIDE
) {
3187 col
= col_limit(col
+ draw_columns
);
3189 else { /* prefs.view_mode == NARROW */
3190 /* Bottom of file */
3197 #ifdef VIEWER_LINE_UP
3198 case VIEWER_LINE_UP
:
3199 case VIEWER_LINE_UP
| BUTTON_REPEAT
:
3200 /* Scroll up one line */
3202 old_tick
= *rb
->current_tick
;
3206 case VIEWER_LINE_DOWN
:
3207 case VIEWER_LINE_DOWN
| BUTTON_REPEAT
:
3208 /* Scroll down one line */
3209 viewer_scroll_down(autoscroll
);
3210 increment_current_line();
3211 old_tick
= *rb
->current_tick
;
3215 #ifdef VIEWER_COLUMN_LEFT
3216 case VIEWER_COLUMN_LEFT
:
3217 case VIEWER_COLUMN_LEFT
| BUTTON_REPEAT
:
3218 if (prefs
.view_mode
== WIDE
) {
3219 /* Scroll left one column */
3220 col
= col_limit(col
- glyph_width('o'));
3225 case VIEWER_COLUMN_RIGHT
:
3226 case VIEWER_COLUMN_RIGHT
| BUTTON_REPEAT
:
3227 if (prefs
.view_mode
== WIDE
) {
3228 /* Scroll right one column */
3229 col
= col_limit(col
+ glyph_width('o'));
3235 #ifdef VIEWER_RC_QUIT
3236 case VIEWER_RC_QUIT
:
3246 case VIEWER_BOOKMARK
:
3248 int idx
= viewer_find_bookmark(cpage
, cline
);
3252 if (bookmark_count
>= MAX_BOOKMARKS
-1)
3253 rb
->splash(HZ
/2, "No more bookmarks");
3256 viewer_add_bookmark();
3257 rb
->splash(HZ
/2, "Bookmark added");
3262 viewer_remove_bookmark(idx
);
3263 rb
->splash(HZ
/2, "Bookmark removed");
3270 if (rb
->default_event_handler_ex(button
, viewer_exit
, NULL
)
3271 == SYS_USB_CONNECTED
)
3272 return PLUGIN_USB_CONNECTED
;
3275 if (button
!= BUTTON_NONE
)
3277 lastbutton
= button
;