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
489 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
490 #define VIEWER_QUIT (BUTTON_REC | BUTTON_PLAY)
491 #define VIEWER_PAGE_UP BUTTON_PREV
492 #define VIEWER_PAGE_DOWN BUTTON_NEXT
493 #define VIEWER_SCREEN_LEFT BUTTON_VOL_DOWN
494 #define VIEWER_SCREEN_RIGHT BUTTON_VOL_UP
495 #define VIEWER_MENU BUTTON_SELECT
496 #define VIEWER_AUTOSCROLL BUTTON_PLAY
497 #define VIEWER_BOOKMARK BUTTON_REC
500 #error No keymap defined!
503 #ifdef HAVE_TOUCHSCREEN
505 #define VIEWER_QUIT2 BUTTON_TOPLEFT
507 #define VIEWER_QUIT BUTTON_TOPLEFT
509 #ifdef VIEWER_PAGE_UP
510 #define VIEWER_PAGE_UP2 BUTTON_TOPMIDDLE
512 #define VIEWER_PAGE_UP BUTTON_TOPMIDDLE
514 #ifdef VIEWER_PAGE_DOWN
515 #define VIEWER_PAGE_DOWN2 BUTTON_BOTTOMMIDDLE
517 #define VIEWER_PAGE_DOWN BUTTON_BOTTOMMIDDLE
519 #ifndef VIEWER_SCREEN_LEFT
520 #define VIEWER_SCREEN_LEFT BUTTON_MIDLEFT
522 #ifndef VIEWER_SCREEN_RIGHT
523 #define VIEWER_SCREEN_RIGHT BUTTON_MIDRIGHT
526 #define VIEWER_MENU2 BUTTON_TOPRIGHT
528 #define VIEWER_MENU BUTTON_TOPRIGHT
530 #ifndef VIEWER_AUTOSCROLL
531 #define VIEWER_AUTOSCROLL BUTTON_CENTER
535 /* stuff for the bookmarking */
536 struct bookmark_info
{
553 REFLOW
, /* won't be set on charcell LCD, must be last */
566 enum codepages encoding
;
598 int autoscroll_speed
;
600 unsigned char font
[MAX_PATH
];
604 VIEWER_FONT_MENU
= 0,
608 struct preferences prefs
;
609 struct preferences old_prefs
;
611 static unsigned char *buffer
;
612 static long buffer_size
;
613 static long block_size
= 0x1000;
614 static unsigned char line_break
[] = {0,0x20,9,0xB,0xC,'-'};
615 static int display_columns
; /* number of (pixel) columns on the display */
616 static int display_lines
; /* number of lines on the display */
617 static int draw_columns
; /* number of (pixel) columns available for text */
618 static int par_indent_spaces
; /* number of spaces to indent first paragraph */
620 static const char *file_name
;
621 static long file_size
;
622 static long start_position
; /* position in the file after the viewer is started */
623 static bool mac_text
;
624 static long file_pos
; /* Position of the top of the buffer in the file */
625 static long last_file_pos
;
626 static unsigned char *buffer_end
; /*Set to BUFFER_END() when file_pos changes*/
627 static int max_width
;
628 static int max_columns
;
629 static int cline
= 1;
630 static int cpage
= 1;
631 static int lpage
= 0;
632 static unsigned char *screen_top_ptr
;
633 static unsigned char *next_screen_ptr
;
634 static unsigned char *next_screen_to_draw_ptr
;
635 static unsigned char *next_line_ptr
;
636 static unsigned char *last_screen_top_ptr
= NULL
;
637 #ifdef HAVE_LCD_BITMAP
638 static struct font
*pf
;
639 static int header_height
= 0;
640 static int footer_height
= 0;
642 struct bookmark_info bookmarks
[MAX_BOOKMARKS
];
643 static int bookmark_count
;
646 #define BOM "\xef\xbb\xbf"
649 static bool is_bom
= false;
651 /* We draw a diacritic char over a non-diacritic one. Therefore, such chars are
652 * not considered to occupy space, therefore buffers might have more than
653 * max_columns characters. The DIACRITIC_FACTOR is the max ratio between all
654 * characters and non-diacritic characters in the buffer
656 #define DIACRITIC_FACTOR 2
658 /* calculate the width of a UCS character (zero width for diacritics) */
659 static int glyph_width(unsigned short ch
)
664 #ifdef HAVE_LCD_BITMAP
665 if (rb
->is_diacritic(ch
, NULL
))
668 return rb
->font_get_width(pf
, ch
);
674 /* get UCS character from string */
675 static unsigned char* get_ucs(const unsigned char* str
, unsigned short* ch
)
677 unsigned char utf8_tmp
[6];
680 if (prefs
.encoding
== UTF_8
)
681 return (unsigned char*)rb
->utf8decode(str
, ch
);
683 rb
->iso_decode(str
, utf8_tmp
, prefs
.encoding
, count
);
684 rb
->utf8decode(utf8_tmp
, ch
);
686 /* return a pointer after the parsed section of the string */
687 #ifdef HAVE_LCD_BITMAP
688 if (prefs
.encoding
>= SJIS
&& *str
>= 0x80
689 && !(prefs
.encoding
== SJIS
&& *str
> 0xA0 && *str
< 0xE0))
690 return (unsigned char*)str
+2;
693 return (unsigned char*)str
+1;
696 /* decode iso string into UTF-8 string */
697 static unsigned char *decode2utf8(const unsigned char *src
, unsigned char *dst
,
698 int skip_width
, int disp_width
)
700 unsigned short ucs
[max_columns
* DIACRITIC_FACTOR
+ 1];
702 const unsigned char *oldstr
= src
;
703 const unsigned char *str
= src
;
704 unsigned char *utf8
= dst
;
707 int width
= max_width
;
709 if (prefs
.alignment
== LEFT
)
711 /* skip the skip_width */
714 while (skip_width
> 0 && *str
!= '\0')
717 str
= get_ucs(oldstr
, &ch
);
718 skip_width
-= glyph_width(ch
);
724 /* decode until string end or disp_width reached */
727 str
= get_ucs(str
, &ch
);
728 disp_width
-= glyph_width(ch
);
731 utf8
= rb
->utf8encode(ch
, utf8
);
736 while (width
> 0 && *str
!= '\0')
738 str
= get_ucs(str
, &ch
);
743 skip_width
= max_width
- skip_width
- disp_width
;
746 while (skip_width
> 0 && chars
-- > 0)
747 skip_width
-= glyph_width(ucs
[chars
]);
755 while (disp_width
> 0 && idx
-- > 0)
756 disp_width
-= glyph_width(ucs
[idx
]);
758 if (disp_width
< 0 || idx
< 0)
762 for ( ; idx
< chars
; idx
++)
763 utf8
= rb
->utf8encode(ucs
[idx
], utf8
);
768 /* return a pointer after the dst string ends */
772 /* set max_columns and max_width */
773 static void calc_max_width(void)
775 if (prefs
.view_mode
== NARROW
)
777 max_columns
= NARROW_MAX_COLUMNS
;
778 max_width
= draw_columns
;
782 max_columns
= WIDE_MAX_COLUMNS
;
783 max_width
= 2 * draw_columns
;
787 static bool done
= false;
790 static inline void advance_conters(unsigned short ch
, int* k
, int* width
)
792 #ifdef HAVE_LCD_BITMAP
793 /* diacritics do not count */
794 if (rb
->is_diacritic(ch
, NULL
))
798 *width
+= glyph_width(ch
);
802 static inline bool line_is_full(int k
, int width
)
804 return ((k
>= max_columns
- 1) || (width
>= max_width
));
807 static unsigned char* crop_at_width(const unsigned char* p
)
811 const unsigned char *oldp
= p
;
815 while (!line_is_full(k
, width
)) {
820 advance_conters(ch
, &k
, &width
);
823 return (unsigned char*)oldp
;
826 static unsigned char* find_first_feed(const unsigned char* p
, int size
)
830 const unsigned char *oldp
= p
;
831 const unsigned char *lbrkp
= NULL
;
838 return (unsigned char*)p
;
842 if (prefs
.word_mode
== WRAP
)
844 for (j
= 0; j
< ((int) sizeof(line_break
)); j
++)
846 if (ch
== line_break
[j
])
854 width
+= glyph_width(ch
);
855 if (width
> max_width
)
856 return (lbrkp
== NULL
)? (unsigned char*)oldp
: (unsigned char*)lbrkp
;
864 static unsigned char* find_last_feed(const unsigned char* p
, int size
)
868 for (i
=size
-1; i
>=0; i
--)
870 return (unsigned char*) p
+i
;
875 static unsigned char* find_last_space(const unsigned char* p
, int size
)
879 k
= (prefs
.line_mode
==JOIN
) || (prefs
.line_mode
==REFLOW
) ? 0:1;
882 if (!BUFFER_OOB(&p
[i
]))
883 for (j
=k
; j
< ((int) sizeof(line_break
)) - 1; j
++) {
884 if (p
[i
] == line_break
[j
])
885 return (unsigned char*) p
+i
;
888 if (prefs
.word_mode
== WRAP
) {
889 for (i
=size
-1; i
>=0; i
--) {
890 for (j
=k
; j
< (int) sizeof(line_break
) - 1; j
++) {
891 if (p
[i
] == line_break
[j
])
892 return (unsigned char*) p
+i
;
900 static unsigned char* find_next_line(const unsigned char* cur_line
, bool *is_short
)
902 const unsigned char *next_line
= NULL
;
903 int size
, i
, j
, j_next
, j_prev
, k
, width
, search_len
, spaces
, newlines
;
907 if (is_short
!= NULL
)
910 if BUFFER_OOB(cur_line
)
913 if (prefs
.view_mode
== WIDE
) {
914 search_len
= MAX_WIDTH
;
916 else { /* prefs.view_mode == NARROW */
917 search_len
= crop_at_width(cur_line
) - cur_line
;
920 size
= BUFFER_OOB(cur_line
+search_len
) ? buffer_end
-cur_line
: search_len
;
922 if ((prefs
.line_mode
== JOIN
) || (prefs
.line_mode
== REFLOW
)) {
923 /* Need to scan ahead and possibly increase search_len and size,
924 or possibly set next_line at second hard return in a row. */
927 j_next
=j
=k
=width
=spaces
=newlines
=0;
929 const unsigned char *p
, *oldp
;
934 if (BUFFER_OOB(cur_line
+j
))
936 if (line_is_full(k
, width
)) {
937 size
= search_len
= j_prev
;
941 oldp
= p
= &cur_line
[j
];
943 j_next
= j
+ (p
- oldp
);
947 if (prefs
.line_mode
== REFLOW
) {
950 next_line
= cur_line
+ size
;
951 return (unsigned char*) next_line
;
953 if (j
==0) /* i=1 is intentional */
954 for (i
=0; i
<par_indent_spaces
; i
++)
955 advance_conters(' ', &k
, &width
);
957 if (!first_chars
) spaces
++;
963 next_line
= cur_line
+ size
- spaces
;
964 if (next_line
!= cur_line
)
965 return (unsigned char*) next_line
;
971 if (BUFFER_OOB(cur_line
+size
) || size
> 2*search_len
)
974 spaces
= first_chars
? 0:1;
978 if (prefs
.line_mode
==JOIN
|| newlines
>0) {
981 advance_conters(' ', &k
, &width
);
982 if (line_is_full(k
, width
)) {
983 size
= search_len
= j
;
989 /* REFLOW, multiple spaces between words: count only
990 * one. If more are needed, they will be added
994 advance_conters(' ', &k
, &width
);
995 if (line_is_full(k
, width
)) {
996 size
= search_len
= j
;
1000 first_chars
= false;
1001 advance_conters(ch
, &k
, &width
);
1007 /* find first hard return */
1008 next_line
= find_first_feed(cur_line
, size
);
1011 if (next_line
== NULL
)
1012 if (size
== search_len
) {
1013 if (prefs
.word_mode
== WRAP
) /* Find last space */
1014 next_line
= find_last_space(cur_line
, size
);
1016 if (next_line
== NULL
) {
1017 next_line
= crop_at_width(cur_line
);
1020 if (prefs
.word_mode
== WRAP
) {
1021 for (i
=0;i
<WRAP_TRIM
;i
++) {
1022 if (!(isspace(next_line
[0]) && !BUFFER_OOB(next_line
)))
1030 if (prefs
.line_mode
== EXPAND
)
1031 if (!BUFFER_OOB(next_line
)) /* Not Null & not out of bounds */
1032 if (next_line
[0] == 0)
1033 if (next_line
!= cur_line
)
1034 return (unsigned char*) next_line
;
1036 /* If next_line is pointing to a zero, increment it; i.e.,
1037 leave the terminator at the end of cur_line. If pointing
1038 to a hyphen, increment only if there is room to display
1039 the hyphen on current line (won't apply in WIDE mode,
1040 since it's guarenteed there won't be room). */
1041 if (!BUFFER_OOB(next_line
)) /* Not Null & not out of bounds */
1042 if (next_line
[0] == 0)/* ||
1043 (next_line[0] == '-' && next_line-cur_line < draw_columns)) */
1046 if (BUFFER_OOB(next_line
))
1048 if (BUFFER_EOF() && next_line
!= cur_line
)
1049 return (unsigned char*) next_line
;
1056 return (unsigned char*) next_line
;
1059 static unsigned char* find_prev_line(const unsigned char* cur_line
)
1061 const unsigned char *prev_line
= NULL
;
1062 const unsigned char *p
;
1064 if BUFFER_OOB(cur_line
)
1067 /* To wrap consistently at the same places, we must
1068 start with a known hard return, then work downwards.
1069 We can either search backwards for a hard return,
1070 or simply start wrapping downwards from top of buffer.
1071 If current line is not near top of buffer, this is
1072 a file with long lines (paragraphs). We would need to
1073 read earlier sectors before we could decide how to
1074 properly wrap the lines above the current line, but
1075 it probably is not worth the disk access. Instead,
1076 start with top of buffer and wrap down from there.
1077 This may result in some lines wrapping at different
1078 points from where they wrap when scrolling down.
1079 If buffer is at top of file, start at top of buffer. */
1081 if ((prefs
.line_mode
== JOIN
) || (prefs
.line_mode
== REFLOW
))
1082 prev_line
= p
= NULL
;
1084 prev_line
= p
= find_last_feed(buffer
, cur_line
-buffer
-1);
1085 /* Null means no line feeds in buffer above current line. */
1087 if (prev_line
== NULL
)
1088 if (BUFFER_BOF() || cur_line
- buffer
> READ_PREV_ZONE
)
1089 prev_line
= p
= buffer
;
1090 /* (else return NULL and read previous block) */
1092 /* Wrap downwards until too far, then use the one before. */
1093 while (p
!= NULL
&& p
< cur_line
) {
1095 p
= find_next_line(prev_line
, NULL
);
1098 if (BUFFER_OOB(prev_line
))
1101 return (unsigned char*) prev_line
;
1104 static void check_bom(void)
1106 unsigned char bom
[BOM_SIZE
];
1107 off_t orig
= rb
->lseek(fd
, 0, SEEK_CUR
);
1111 rb
->lseek(fd
, 0, SEEK_SET
);
1113 if (rb
->read(fd
, bom
, BOM_SIZE
) == BOM_SIZE
)
1114 is_bom
= !memcmp(bom
, BOM
, BOM_SIZE
);
1116 rb
->lseek(fd
, orig
, SEEK_SET
);
1119 static void fill_buffer(long pos
, unsigned char* buf
, unsigned size
)
1121 /* Read from file and preprocess the data */
1122 /* To minimize disk access, always read on sector boundaries */
1123 unsigned numread
, i
;
1124 bool found_CR
= false;
1125 off_t offset
= rb
->lseek(fd
, pos
, SEEK_SET
);
1127 if (offset
== 0 && prefs
.encoding
== UTF_8
&& is_bom
)
1128 rb
->lseek(fd
, BOM_SIZE
, SEEK_SET
);
1130 numread
= rb
->read(fd
, buf
, size
- 1);
1132 rb
->button_clear_queue(); /* clear button queue */
1134 for(i
= 0; i
< numread
; i
++) {
1151 case 0: /* No break between case 0 and default, intentionally */
1164 static int viewer_find_bookmark(int page
, int line
)
1168 for (i
= 0; i
< bookmark_count
; i
++)
1170 if (bookmarks
[i
].page
== page
&& bookmarks
[i
].line
== line
)
1176 static int read_and_synch(int direction
)
1178 /* Read next (or prev) block, and reposition global pointers. */
1179 /* direction: 1 for down (i.e., further into file), -1 for up */
1180 int move_size
, move_vector
, offset
;
1181 unsigned char *fill_buf
;
1183 if (direction
== -1) /* up */ {
1184 move_size
= SMALL_BLOCK_SIZE
;
1186 fill_buf
= TOP_SECTOR
;
1187 rb
->memcpy(BOTTOM_SECTOR
, MID_SECTOR
, SMALL_BLOCK_SIZE
);
1188 rb
->memcpy(MID_SECTOR
, TOP_SECTOR
, SMALL_BLOCK_SIZE
);
1191 if (prefs
.view_mode
== WIDE
) {
1192 /* WIDE mode needs more buffer so we have to read smaller blocks */
1193 move_size
= SMALL_BLOCK_SIZE
;
1194 offset
= LARGE_BLOCK_SIZE
;
1195 fill_buf
= BOTTOM_SECTOR
;
1196 rb
->memcpy(TOP_SECTOR
, MID_SECTOR
, SMALL_BLOCK_SIZE
);
1197 rb
->memcpy(MID_SECTOR
, BOTTOM_SECTOR
, SMALL_BLOCK_SIZE
);
1200 move_size
= LARGE_BLOCK_SIZE
;
1201 offset
= SMALL_BLOCK_SIZE
;
1202 fill_buf
= MID_SECTOR
;
1203 rb
->memcpy(TOP_SECTOR
, BOTTOM_SECTOR
, SMALL_BLOCK_SIZE
);
1206 move_vector
= direction
* move_size
;
1207 screen_top_ptr
-= move_vector
;
1208 file_pos
+= move_vector
;
1209 buffer_end
= BUFFER_END(); /* Update whenever file_pos changes */
1210 fill_buffer(file_pos
+ offset
, fill_buf
, move_size
);
1214 static void get_next_line_position(unsigned char **line_begin
,
1215 unsigned char **line_end
,
1220 *line_begin
= *line_end
;
1221 *line_end
= find_next_line(*line_begin
, is_short
);
1223 if (*line_end
== NULL
&& !BUFFER_EOF())
1225 resynch_move
= read_and_synch(1); /* Read block & move ptrs */
1226 *line_begin
-= resynch_move
;
1227 if (next_line_ptr
> buffer
)
1228 next_line_ptr
-= resynch_move
;
1230 *line_end
= find_next_line(*line_begin
, is_short
);
1234 static void increment_current_line(void)
1236 if (cline
< display_lines
)
1238 else if (cpage
< MAX_PAGE
)
1245 static void decrement_current_line(void)
1252 cline
= display_lines
;
1256 static void viewer_scroll_up(void)
1260 p
= find_prev_line(screen_top_ptr
);
1261 if (p
== NULL
&& !BUFFER_BOF()) {
1263 p
= find_prev_line(screen_top_ptr
);
1268 decrement_current_line();
1271 static void viewer_scroll_down(bool autoscroll
)
1276 if (next_line_ptr
!= NULL
)
1277 screen_top_ptr
= next_line_ptr
;
1279 if (prefs
.scroll_mode
== LINE
|| autoscroll
)
1280 increment_current_line();
1282 if (cline
> display_lines
) {
1288 static void viewer_scroll_to_top_line(void)
1292 for (line
= cline
; line
> 1; line
--)
1296 #ifdef HAVE_LCD_BITMAP
1297 static void viewer_scrollbar(void) {
1298 int items
, min_shown
, max_shown
, sb_begin_y
, sb_height
;
1300 items
= (int) file_size
; /* (SH1 int is same as long) */
1301 min_shown
= (int) file_pos
+ (screen_top_ptr
- buffer
);
1303 if (next_screen_ptr
== NULL
)
1306 max_shown
= min_shown
+ (next_screen_ptr
- screen_top_ptr
);
1308 sb_begin_y
= header_height
;
1309 sb_height
= LCD_HEIGHT
- header_height
- footer_height
;
1311 rb
->gui_scrollbar_draw(rb
->screens
[SCREEN_MAIN
],0, sb_begin_y
,
1312 SCROLLBAR_WIDTH
-1, sb_height
,
1313 items
, min_shown
, max_shown
, VERTICAL
);
1317 #ifdef HAVE_LCD_BITMAP
1318 static void viewer_show_header(void)
1320 if (prefs
.header_mode
== HD_SBAR
|| prefs
.header_mode
== HD_BOTH
)
1321 rb
->gui_syncstatusbar_draw(rb
->statusbars
, true);
1323 if (prefs
.header_mode
== HD_PATH
|| prefs
.header_mode
== HD_BOTH
)
1324 rb
->lcd_putsxy(0, header_height
- pf
->height
, file_name
);
1327 static void viewer_show_footer(void)
1329 if (prefs
.footer_mode
== FT_SBAR
|| prefs
.footer_mode
== FT_BOTH
)
1330 rb
->gui_syncstatusbar_draw(rb
->statusbars
, true);
1332 if (prefs
.footer_mode
== FT_PAGE
|| prefs
.footer_mode
== FT_BOTH
)
1334 unsigned char buf
[12];
1337 rb
->snprintf(buf
, sizeof(buf
), "%d", cpage
);
1339 rb
->snprintf(buf
, sizeof(buf
), "%d - %d", cpage
, cpage
+1);
1341 rb
->lcd_putsxy(0, LCD_HEIGHT
- footer_height
, buf
);
1346 static void viewer_draw(int col
)
1348 int i
, j
, k
, line_len
, line_width
, spaces
, left_col
=0;
1349 int width
, extra_spaces
, indent_spaces
, spaces_per_word
, spaces_width
, disp_width
= 0;
1350 bool multiple_spacing
, line_is_short
;
1352 unsigned char *str
, *oldstr
;
1353 unsigned char *line_begin
;
1354 unsigned char *line_end
;
1356 int max_chars
= max_columns
* DIACRITIC_FACTOR
;
1357 unsigned char scratch_buffer
[max_chars
* 4 + 1];
1358 unsigned char utf8_buffer
[max_chars
* 4 + 1];
1360 /* If col==-1 do all calculations but don't display */
1362 #ifdef HAVE_LCD_BITMAP
1363 left_col
= prefs
.need_scrollbar
? SCROLLBAR_WIDTH
:0;
1367 rb
->lcd_clear_display();
1369 line_begin
= line_end
= screen_top_ptr
;
1371 for (i
= 0; i
< display_lines
; i
++) {
1372 if (BUFFER_OOB(line_end
))
1375 break; /* Happens after display last line at BUFFER_EOF() */
1377 if (lpage
== 0 && cline
== 1)
1380 last_screen_top_ptr
= screen_top_ptr
;
1381 last_file_pos
= file_pos
;
1385 get_next_line_position(&line_begin
, &line_end
, &line_is_short
);
1386 if (line_end
== NULL
)
1388 if (BUFFER_OOB(line_begin
))
1390 line_end
= buffer_end
+ 1;
1393 line_len
= line_end
- line_begin
;
1395 /* calculate line_len */
1396 str
= oldstr
= line_begin
;
1398 while (str
< line_end
) {
1400 str
= crop_at_width(str
);
1408 /* width of un-displayed part of the line */
1409 line_width
= j
*draw_columns
;
1411 while (oldstr
< line_end
) {
1412 oldstr
= get_ucs(oldstr
, &ch
);
1413 /* add width of displayed part of the line */
1416 int dw
= glyph_width(ch
);
1418 /* avoid counting spaces at the end of the line */
1425 line_width
+= dw
+ spaces_width
;
1431 if (prefs
.line_mode
== JOIN
) {
1432 if (line_begin
[0] == 0) {
1434 if (prefs
.word_mode
== CHOP
)
1439 for (j
=k
=spaces
=0; j
< line_len
; j
++) {
1450 scratch_buffer
[k
++] = ' ';
1455 scratch_buffer
[k
++] = ' ';
1456 if (k
== max_chars
- 1)
1459 scratch_buffer
[k
++] = c
;
1463 scratch_buffer
[k
] = 0;
1465 else if (prefs
.line_mode
== REFLOW
) {
1466 if (line_begin
[0] == 0) {
1468 if (prefs
.word_mode
== CHOP
)
1475 if (!line_is_short
) {
1476 multiple_spacing
= false;
1478 for (str
= line_begin
; str
< line_end
; ) {
1479 str
= get_ucs(str
, &ch
);
1483 if (str
== line_begin
)
1485 if (prefs
.word_mode
== WRAP
&& prefs
.alignment
== LEFT
)
1487 /* special case: indent the paragraph,
1488 * don't count spaces */
1489 indent_spaces
= par_indent_spaces
;
1492 else if (!multiple_spacing
)
1494 multiple_spacing
= true;
1497 multiple_spacing
= false;
1498 width
+= glyph_width(ch
);
1502 if (multiple_spacing
) spaces
--;
1505 /* total number of spaces to insert between words */
1506 extra_spaces
= (max_width
-width
)/glyph_width(' ')
1508 /* number of spaces between each word*/
1509 spaces_per_word
= extra_spaces
/ spaces
;
1510 /* number of words with n+1 spaces (to fill up) */
1511 extra_spaces
= extra_spaces
% spaces
;
1512 if (spaces_per_word
> 2) { /* too much spacing is awful */
1513 spaces_per_word
= 3;
1516 } else { /* this doesn't matter much... no spaces anyway */
1517 spaces_per_word
= extra_spaces
= 0;
1519 } else { /* end of a paragraph: don't fill line */
1520 spaces_per_word
= 1;
1523 multiple_spacing
= false;
1524 for (j
=k
=spaces
=0; j
< line_len
; j
++) {
1531 if (j
== line_len
- 1)
1535 /* indent paragraph */
1536 if (prefs
.word_mode
== WRAP
&& prefs
.alignment
== LEFT
)
1538 for (j
=0; j
<par_indent_spaces
; j
++)
1539 scratch_buffer
[k
++] = ' ';
1543 else if (!multiple_spacing
) {
1544 for (width
= spaces
<extra_spaces
? -1:0; width
< spaces_per_word
; width
++)
1545 scratch_buffer
[k
++] = ' ';
1548 multiple_spacing
= true;
1551 scratch_buffer
[k
++] = c
;
1552 multiple_spacing
= false;
1556 while (scratch_buffer
[k
-1] == ' ')
1558 scratch_buffer
[k
] = 0;
1560 else { /* prefs.line_mode != JOIN && prefs.line_mode != REFLOW */
1563 rb
->memcpy(scratch_buffer
, line_begin
, line_len
);
1564 scratch_buffer
[line_len
] = '\0';
1568 /* create displayed line */
1571 decode2utf8(scratch_buffer
, utf8_buffer
, col
, draw_columns
);
1572 rb
->lcd_getstringsize(utf8_buffer
, &disp_width
, NULL
);
1575 /* display on screen the displayed part of the line */
1578 bool in_page
= (cline
+i
<= display_lines
);
1579 int dpage
= cpage
+ (in_page
? 0 : 1);
1580 int dline
= cline
+ i
- (in_page
? 0 : display_lines
);
1581 bool bflag
= (viewer_find_bookmark(dpage
, dline
) >= 0);
1582 #ifdef HAVE_LCD_BITMAP
1583 int dy
= i
* pf
->height
+ header_height
;
1584 int dx
= (prefs
.alignment
== LEFT
)? left_col
: LCD_WIDTH
- disp_width
;
1587 #ifdef HAVE_LCD_BITMAP
1589 rb
->lcd_set_drawmode(DRMODE_BG
|DRMODE_FG
);
1590 rb
->lcd_fillrect(left_col
, dy
, LCD_WIDTH
- left_col
, pf
->height
);
1591 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
1593 rb
->lcd_putsxy(dx
, dy
, utf8_buffer
);
1594 rb
->lcd_set_drawmode(DRMODE_SOLID
);
1597 rb
->lcd_puts(left_col
, i
, BOOKMARK_ICON
);
1599 rb
->lcd_puts(left_col
+1, i
, utf8_buffer
);
1604 next_line_ptr
= line_end
;
1606 next_screen_ptr
= line_end
;
1607 if (BUFFER_OOB(next_screen_ptr
))
1608 next_screen_ptr
= NULL
;
1610 #ifdef HAVE_LCD_BITMAP
1611 next_screen_to_draw_ptr
= prefs
.page_mode
==OVERLAP
? line_begin
: next_screen_ptr
;
1613 if (prefs
.need_scrollbar
)
1616 next_screen_to_draw_ptr
= next_screen_ptr
;
1619 #ifdef HAVE_LCD_BITMAP
1621 viewer_show_header();
1624 viewer_show_footer();
1631 static void viewer_top(void)
1633 /* Read top of file into buffer
1634 and point screen pointer to top */
1637 rb
->splash(0, "Loading...");
1640 buffer_end
= BUFFER_END(); /* Update whenever file_pos changes */
1641 fill_buffer(0, buffer
, buffer_size
);
1644 screen_top_ptr
= buffer
;
1649 static void viewer_bottom(void)
1651 unsigned char *line_begin
;
1652 unsigned char *line_end
;
1654 rb
->splash(0, "Loading...");
1656 if (last_screen_top_ptr
)
1660 screen_top_ptr
= last_screen_top_ptr
;
1661 file_pos
= last_file_pos
;
1662 fill_buffer(file_pos
, buffer
, buffer_size
);
1663 buffer_end
= BUFFER_END();
1667 line_end
= screen_top_ptr
;
1669 while (!BUFFER_EOF() || !BUFFER_OOB(line_end
))
1671 get_next_line_position(&line_begin
, &line_end
, NULL
);
1672 if (line_end
== NULL
)
1675 increment_current_line();
1677 screen_top_ptr
= line_end
;
1681 last_screen_top_ptr
= screen_top_ptr
;
1682 last_file_pos
= file_pos
;
1683 buffer_end
= BUFFER_END();
1686 #ifdef HAVE_LCD_BITMAP
1687 static void init_need_scrollbar(void) {
1688 /* Call viewer_draw in quiet mode to initialize next_screen_ptr,
1689 and thus ONE_SCREEN_FITS_ALL(), and thus NEED_SCROLLBAR() */
1691 prefs
.need_scrollbar
= NEED_SCROLLBAR();
1692 draw_columns
= prefs
.need_scrollbar
? display_columns
-SCROLLBAR_WIDTH
: display_columns
;
1693 par_indent_spaces
= draw_columns
/(5*glyph_width(' '));
1697 static void init_header_and_footer(void)
1701 if (rb
->global_settings
->statusbar
== STATUSBAR_TOP
)
1703 if (prefs
.header_mode
== HD_SBAR
|| prefs
.header_mode
== HD_BOTH
)
1704 header_height
= STATUSBAR_HEIGHT
;
1706 if (prefs
.footer_mode
== FT_SBAR
)
1707 prefs
.footer_mode
= FT_NONE
;
1708 else if (prefs
.footer_mode
== FT_BOTH
)
1709 prefs
.footer_mode
= FT_PAGE
;
1711 else if (rb
->global_settings
->statusbar
== STATUSBAR_BOTTOM
)
1713 if (prefs
.footer_mode
== FT_SBAR
|| prefs
.footer_mode
== FT_BOTH
)
1714 footer_height
= STATUSBAR_HEIGHT
;
1716 if (prefs
.header_mode
== HD_SBAR
)
1717 prefs
.header_mode
= HD_NONE
;
1718 else if (prefs
.header_mode
== HD_BOTH
)
1719 prefs
.header_mode
= HD_PATH
;
1721 else /* STATUSBAR_OFF || STATUSBAR_CUSTOM */
1723 if (prefs
.header_mode
== HD_SBAR
)
1724 prefs
.header_mode
= HD_NONE
;
1725 else if (prefs
.header_mode
== HD_BOTH
)
1726 prefs
.header_mode
= HD_PATH
;
1728 if (prefs
.footer_mode
== FT_SBAR
)
1729 prefs
.footer_mode
= FT_NONE
;
1730 else if (prefs
.footer_mode
== FT_BOTH
)
1731 prefs
.footer_mode
= FT_PAGE
;
1734 if (prefs
.header_mode
== HD_NONE
|| prefs
.header_mode
== HD_PATH
||
1735 prefs
.footer_mode
== FT_NONE
|| prefs
.footer_mode
== FT_PAGE
)
1736 rb
->gui_syncstatusbar_draw(rb
->statusbars
, false);
1738 if (prefs
.header_mode
== HD_PATH
|| prefs
.header_mode
== HD_BOTH
)
1739 header_height
+= pf
->height
;
1740 if (prefs
.footer_mode
== FT_PAGE
|| prefs
.footer_mode
== FT_BOTH
)
1741 footer_height
+= pf
->height
;
1743 display_lines
= (LCD_HEIGHT
- header_height
- footer_height
) / pf
->height
;
1747 last_screen_top_ptr
= NULL
;
1750 static bool change_font(unsigned char *font
)
1752 unsigned char buf
[MAX_PATH
];
1754 if (font
== NULL
|| *font
== '\0')
1757 rb
->snprintf(buf
, MAX_PATH
, "%s/%s.fnt", FONT_DIR
, font
);
1758 if (rb
->font_load(NULL
, buf
) < 0) {
1759 rb
->splash(HZ
/2, "Font load failed.");
1767 static bool viewer_init(void)
1769 #ifdef HAVE_LCD_BITMAP
1770 /* initialize fonts */
1771 pf
= rb
->font_get(FONT_UI
);
1775 draw_columns
= display_columns
= LCD_WIDTH
;
1777 /* REAL fixed pitch :) all chars use up 1 cell */
1779 draw_columns
= display_columns
= 11;
1780 par_indent_spaces
= 2;
1783 fd
= rb
->open(file_name
, O_RDONLY
);
1787 /* Init mac_text value used in processing buffer */
1793 /* When a file is UTF-8 file with BOM, if prefs.encoding is UTF-8,
1794 * then file size decreases only BOM_SIZE.
1796 static void get_filesize(void)
1798 file_size
= rb
->filesize(fd
);
1799 if (file_size
== -1)
1802 if (prefs
.encoding
== UTF_8
&& is_bom
)
1803 file_size
-= BOM_SIZE
;
1806 static int bm_comp(const void *a
, const void *b
)
1808 struct bookmark_info
*pa
;
1809 struct bookmark_info
*pb
;
1811 pa
= (struct bookmark_info
*)a
;
1812 pb
= (struct bookmark_info
*)b
;
1814 if (pa
->page
!= pb
->page
)
1815 return pa
->page
- pb
->page
;
1817 return pa
->line
- pb
->line
;
1820 static void viewer_add_bookmark(void)
1822 if (bookmark_count
>= MAX_BOOKMARKS
-1)
1825 bookmarks
[bookmark_count
].file_position
1826 = file_pos
+ screen_top_ptr
- buffer
;
1827 bookmarks
[bookmark_count
].page
= cpage
;
1828 bookmarks
[bookmark_count
].line
= cline
;
1829 bookmarks
[bookmark_count
].flag
= BOOKMARK_USER
;
1833 static int viewer_add_last_read_bookmark(void)
1837 i
= viewer_find_bookmark(cpage
, cline
);
1839 bookmarks
[i
].flag
|= BOOKMARK_LAST
;
1842 viewer_add_bookmark();
1843 i
= bookmark_count
-1;
1844 bookmarks
[i
].flag
= BOOKMARK_LAST
;
1849 static void viewer_remove_bookmark(int i
)
1853 if (i
< 0 || i
>= bookmark_count
)
1856 for (j
= i
+1; j
< bookmark_count
; j
++)
1857 rb
->memcpy(&bookmarks
[j
-1], &bookmarks
[j
],
1858 sizeof(struct bookmark_info
));
1863 static void viewer_remove_last_read_bookmark(void)
1867 for (i
= 0; i
< bookmark_count
; i
++)
1869 if (bookmarks
[i
].flag
& BOOKMARK_LAST
)
1871 if (bookmarks
[i
].flag
== BOOKMARK_LAST
)
1873 for (j
= i
+1; j
< bookmark_count
; j
++)
1874 rb
->memcpy(&bookmarks
[j
-1], &bookmarks
[j
],
1875 sizeof(struct bookmark_info
));
1880 bookmarks
[i
].flag
= BOOKMARK_USER
;
1886 static int viewer_get_last_read_bookmark(void)
1890 for (i
= 0; i
< bookmark_count
; i
++)
1892 if (bookmarks
[i
].flag
& BOOKMARK_LAST
)
1898 static void viewer_select_bookmark(int initval
)
1907 struct opt_items items
[bookmark_count
];
1908 unsigned char names
[bookmark_count
][38];
1910 if (initval
>= 0 && initval
< bookmark_count
)
1912 ipage
= bookmarks
[initval
].page
;
1913 iline
= bookmarks
[initval
].line
;
1916 rb
->qsort(bookmarks
, bookmark_count
, sizeof(struct bookmark_info
),
1919 for (i
= 0; i
< bookmark_count
; i
++)
1921 rb
->snprintf(names
[i
], sizeof(names
[0]),
1922 #if CONFIG_KEYPAD != PLAYER_PAD
1923 "%sPage: %d Line: %d",
1927 (bookmarks
[i
].flag
&BOOKMARK_LAST
)? "*":" ",
1930 items
[i
].string
= names
[i
];
1931 items
[i
].voice_id
= -1;
1932 if (selected
< 0 && bookmarks
[i
].page
== ipage
&& bookmarks
[i
].line
== iline
)
1936 rb
->set_option("Select bookmark", &selected
, INT
, items
,
1937 sizeof(items
) / sizeof(items
[0]), NULL
);
1939 if (selected
< 0 || selected
>= bookmark_count
)
1941 if (initval
< 0 || (selected
= viewer_get_last_read_bookmark()) < 0)
1944 rb
->splash(HZ
, "Start the first page.");
1946 screen_top_ptr
= buffer
;
1949 buffer_end
= BUFFER_END();
1954 screen_pos
= bookmarks
[selected
].file_position
;
1955 screen_top
= screen_pos
% buffer_size
;
1956 file_pos
= screen_pos
- screen_top
;
1957 screen_top_ptr
= buffer
+ screen_top
;
1958 cpage
= bookmarks
[selected
].page
;
1959 cline
= bookmarks
[selected
].line
;
1960 buffer_end
= BUFFER_END();
1963 static void viewer_default_preferences(void)
1965 prefs
.word_mode
= WRAP
;
1966 prefs
.line_mode
= NORMAL
;
1967 prefs
.view_mode
= NARROW
;
1968 prefs
.alignment
= LEFT
;
1969 prefs
.scroll_mode
= PAGE
;
1970 prefs
.page_mode
= NO_OVERLAP
;
1971 prefs
.scrollbar_mode
= SB_OFF
;
1972 rb
->memset(prefs
.font
, 0, MAX_PATH
);
1973 #ifdef HAVE_LCD_BITMAP
1974 prefs
.header_mode
= HD_BOTH
;
1975 prefs
.footer_mode
= FT_BOTH
;
1976 rb
->snprintf(prefs
.font
, MAX_PATH
, "%s", rb
->global_settings
->font_file
);
1978 prefs
.header_mode
= HD_NONE
;
1979 prefs
.footer_mode
= FT_NONE
;
1981 prefs
.autoscroll_speed
= 1;
1982 /* Set codepage to system default */
1983 prefs
.encoding
= rb
->global_settings
->default_codepage
;
1986 static bool viewer_read_preferences(int pfd
, int version
, struct preferences
*prf
)
1988 unsigned char buf
[PREFERENCES_SIZE
];
1989 unsigned char *p
= buf
;
1990 int read_size
= PREFERENCES_SIZE
;
1995 if (rb
->read(pfd
, buf
, read_size
) != read_size
)
1998 prf
->word_mode
= *p
++;
1999 prf
->line_mode
= *p
++;
2000 prf
->view_mode
= *p
++;
2002 prf
->alignment
= *p
++;
2004 prf
->alignment
= LEFT
;
2005 prf
->encoding
= *p
++;
2006 prf
->scrollbar_mode
= *p
++;
2007 prf
->need_scrollbar
= *p
++;
2008 prf
->page_mode
= *p
++;
2009 prf
->header_mode
= *p
++;
2010 prf
->footer_mode
= *p
++;
2011 prf
->scroll_mode
= *p
++;
2012 prf
->autoscroll_speed
= *p
++;
2013 rb
->memcpy(prf
->font
, p
, MAX_PATH
);
2017 static bool viewer_write_preferences(int pfd
, const struct preferences
*prf
)
2019 unsigned char buf
[PREFERENCES_SIZE
];
2020 unsigned char *p
= buf
;
2022 *p
++ = prf
->word_mode
;
2023 *p
++ = prf
->line_mode
;
2024 *p
++ = prf
->view_mode
;
2025 *p
++ = prf
->alignment
;
2026 *p
++ = prf
->encoding
;
2027 *p
++ = prf
->scrollbar_mode
;
2028 *p
++ = prf
->need_scrollbar
;
2029 *p
++ = prf
->page_mode
;
2030 *p
++ = prf
->header_mode
;
2031 *p
++ = prf
->footer_mode
;
2032 *p
++ = prf
->scroll_mode
;
2033 *p
++ = prf
->autoscroll_speed
;
2034 rb
->memcpy(p
, prf
->font
, MAX_PATH
);
2036 return (rb
->write(pfd
, buf
, sizeof(buf
)) == sizeof(buf
));
2039 static bool viewer_read_bookmark_info(int bfd
, struct bookmark_info
*b
)
2041 unsigned char buf
[BOOKMARK_SIZE
];
2043 if (rb
->read(bfd
, buf
, sizeof(buf
)) != sizeof(buf
))
2046 b
->file_position
= (buf
[0] << 24)|(buf
[1] << 16)|(buf
[2] << 8)|buf
[3];
2047 b
->page
= (buf
[4] << 8)|buf
[5];
2054 static bool viewer_read_bookmark_infos(int bfd
)
2059 if (rb
->read(bfd
, &c
, 1) != 1)
2066 if (bookmark_count
> MAX_BOOKMARKS
)
2067 bookmark_count
= MAX_BOOKMARKS
;
2069 for (i
= 0; i
< bookmark_count
; i
++)
2071 if (!viewer_read_bookmark_info(bfd
, &bookmarks
[i
]))
2080 static bool viewer_write_bookmark_info(int bfd
, struct bookmark_info
*b
)
2082 unsigned char buf
[BOOKMARK_SIZE
];
2083 unsigned char *p
= buf
;
2086 ul
= b
->file_position
;
2099 return (rb
->write(bfd
, buf
, sizeof(buf
)) == sizeof(buf
));
2102 static bool viewer_write_bookmark_infos(int bfd
)
2104 unsigned char c
= bookmark_count
;
2107 if (rb
->write(bfd
, &c
, 1) != 1)
2110 for (i
= 0; i
< bookmark_count
; i
++)
2112 if (!viewer_write_bookmark_info(bfd
, &bookmarks
[i
]))
2119 static bool viewer_load_global_settings(void)
2121 unsigned buf
[GLOBAL_SETTINGS_H_SIZE
];
2122 int sfd
= rb
->open(GLOBAL_SETTINGS_FILE
, O_RDONLY
);
2129 if ((rb
->read(sfd
, buf
, GLOBAL_SETTINGS_H_SIZE
) == GLOBAL_SETTINGS_H_SIZE
) ||
2130 (rb
->memcmp(buf
, GLOBAL_SETTINGS_HEADER
, GLOBAL_SETTINGS_H_SIZE
- 1) == 0))
2132 version
= buf
[GLOBAL_SETTINGS_H_SIZE
- 1] - GLOBAL_SETTINGS_FIRST_VERSION
;
2133 res
= viewer_read_preferences(sfd
, version
, &prefs
);
2139 static bool viewer_save_global_settings(void)
2141 int sfd
= rb
->open(GLOBAL_SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666);
2142 unsigned char buf
[GLOBAL_SETTINGS_H_SIZE
];
2147 rb
->memcpy(buf
, GLOBAL_SETTINGS_HEADER
, GLOBAL_SETTINGS_H_SIZE
- 1);
2148 buf
[GLOBAL_SETTINGS_H_SIZE
- 1] = GLOBAL_SETTINGS_VERSION
;
2150 if (rb
->write(sfd
, buf
, GLOBAL_SETTINGS_H_SIZE
) != GLOBAL_SETTINGS_H_SIZE
||
2151 !viewer_write_preferences(sfd
, &prefs
))
2154 rb
->remove(GLOBAL_SETTINGS_TMP_FILE
);
2158 rb
->remove(GLOBAL_SETTINGS_FILE
);
2159 rb
->rename(GLOBAL_SETTINGS_TMP_FILE
, GLOBAL_SETTINGS_FILE
);
2163 static bool viewer_convert_settings(int sfd
, int dfd
, int old_ver
)
2165 struct preferences new_prefs
;
2168 unsigned char buf
[MAX_PATH
+ 2];
2171 rb
->read(sfd
, buf
, MAX_PATH
+ 2);
2172 rb
->write(dfd
, buf
, MAX_PATH
+ 2);
2174 settings_size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+ 1];
2176 old_pos
= rb
->lseek(sfd
, 0, SEEK_CUR
);
2177 new_pos
= rb
->lseek(dfd
, 0, SEEK_CUR
);
2180 * when the settings size != preferences size + bookmarks size,
2181 * settings data are considered to be old version.
2183 if (old_ver
> 0 && ((settings_size
- PREFERENCES_SIZE
) % 8) == 0)
2186 if (!viewer_read_preferences(sfd
, old_ver
, &new_prefs
))
2189 if (!viewer_write_preferences(dfd
, &new_prefs
))
2192 settings_size
-= (rb
->lseek(sfd
, 0, SEEK_CUR
) - old_pos
);
2194 if (settings_size
> 0)
2196 rb
->read(sfd
, buf
, settings_size
);
2197 rb
->write(dfd
, buf
, settings_size
);
2200 settings_size
= rb
->lseek(dfd
, 0, SEEK_CUR
) - new_pos
;
2201 buf
[0] = settings_size
>> 8;
2202 buf
[1] = settings_size
;
2203 rb
->lseek(dfd
, new_pos
- 2, SEEK_SET
);
2204 rb
->write(dfd
, buf
, 2);
2205 rb
->lseek(dfd
, settings_size
, SEEK_CUR
);
2209 static bool viewer_convert_settings_file(void)
2211 unsigned char buf
[SETTINGS_H_SIZE
+2];
2219 if ((sfd
= rb
->open(SETTINGS_FILE
, O_RDONLY
)) < 0)
2222 if ((tfd
= rb
->open(SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666)) < 0)
2228 rb
->read(sfd
, buf
, SETTINGS_H_SIZE
+ 2);
2230 version
= buf
[SETTINGS_H_SIZE
- 1] - SETTINGS_FIRST_VERSION
;
2231 fcount
= (buf
[SETTINGS_H_SIZE
] << 8) | buf
[SETTINGS_H_SIZE
+ 1];
2232 buf
[SETTINGS_H_SIZE
- 1] = SETTINGS_VERSION
;
2234 rb
->write(tfd
, buf
, SETTINGS_H_SIZE
+ 2);
2236 for (i
= 0; i
< fcount
; i
++)
2238 if (!viewer_convert_settings(sfd
, tfd
, version
))
2249 rb
->remove(SETTINGS_TMP_FILE
);
2252 rb
->remove(SETTINGS_FILE
);
2253 rb
->rename(SETTINGS_TMP_FILE
, SETTINGS_FILE
);
2258 static bool viewer_load_settings(void)
2260 unsigned char buf
[MAX_PATH
+2];
2261 unsigned int fcount
;
2268 sfd
= rb
->open(SETTINGS_FILE
, O_RDONLY
);
2272 if ((rb
->read(sfd
, buf
, SETTINGS_H_SIZE
+2) != SETTINGS_H_SIZE
+2) ||
2273 rb
->memcmp(buf
, SETTINGS_HEADER
, SETTINGS_H_SIZE
- 1))
2275 /* illegal setting file */
2278 if (rb
->file_exists(SETTINGS_FILE
))
2279 rb
->remove(SETTINGS_FILE
);
2284 if (buf
[SETTINGS_H_SIZE
- 1] != SETTINGS_VERSION
)
2287 if (!viewer_convert_settings_file())
2290 return viewer_load_settings();
2293 version
= buf
[SETTINGS_H_SIZE
- 1] - SETTINGS_FIRST_VERSION
;
2294 fcount
= (buf
[SETTINGS_H_SIZE
] << 8) | buf
[SETTINGS_H_SIZE
+1];
2295 for (i
= 0; i
< fcount
; i
++)
2297 if (rb
->read(sfd
, buf
, MAX_PATH
+2) != MAX_PATH
+2)
2300 size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+1];
2303 * when the settings size != preferences size + bookmarks size,
2304 * the settings file converts to the newer.
2306 if (version
> 0 && ((size
- PREFERENCES_SIZE
) % 8) == 0)
2309 if (!viewer_convert_settings_file())
2312 return viewer_load_settings();
2315 if (rb
->strcmp(buf
, file_name
))
2317 if (rb
->lseek(sfd
, size
, SEEK_CUR
) < 0)
2321 if (!viewer_read_preferences(sfd
, version
, &prefs
))
2324 res
= viewer_read_bookmark_infos(sfd
);
2333 /* load global settings */
2334 if (!viewer_load_global_settings())
2335 viewer_default_preferences();
2338 screen_top_ptr
= buffer
;
2344 rb
->memcpy(&old_prefs
, &prefs
, sizeof(struct preferences
));
2347 if (bookmark_count
> 1)
2348 viewer_select_bookmark(-1);
2349 else if (bookmark_count
== 1)
2354 screen_pos
= bookmarks
[0].file_position
;
2355 screen_top
= screen_pos
% buffer_size
;
2356 file_pos
= screen_pos
- screen_top
;
2357 screen_top_ptr
= buffer
+ screen_top
;
2358 cpage
= bookmarks
[0].page
;
2359 cline
= bookmarks
[0].line
;
2362 viewer_remove_last_read_bookmark();
2367 buffer_end
= BUFFER_END(); /* Update whenever file_pos changes */
2369 if (BUFFER_OOB(screen_top_ptr
))
2370 screen_top_ptr
= buffer
;
2372 fill_buffer(file_pos
, buffer
, buffer_size
);
2373 if (prefs
.scroll_mode
== PAGE
&& cline
> 1)
2374 viewer_scroll_to_top_line();
2376 /* remember the current position */
2377 start_position
= file_pos
+ screen_top_ptr
- buffer
;
2379 #ifdef HAVE_LCD_BITMAP
2380 /* load prefs font if it is different than the global settings font */
2381 if (rb
->strcmp(prefs
.font
, rb
->global_settings
->font_file
)) {
2382 if (!change_font(prefs
.font
)) {
2383 /* fallback by resetting prefs font to the global settings font */
2384 rb
->memset(prefs
.font
, 0, MAX_PATH
);
2385 rb
->snprintf(prefs
.font
, MAX_PATH
, "%s",
2386 rb
->global_settings
->font_file
);
2388 if (!change_font(prefs
.font
))
2393 init_need_scrollbar();
2394 init_header_and_footer();
2400 static bool copy_bookmark_file(int sfd
, int dfd
, off_t start
, off_t size
)
2404 if (rb
->lseek(sfd
, start
, SEEK_SET
) < 0)
2409 if (size
> buffer_size
)
2410 rsize
= buffer_size
;
2415 if (rb
->read(sfd
, buffer
, rsize
) != rsize
||
2416 rb
->write(dfd
, buffer
, rsize
) != rsize
)
2422 static bool viewer_save_settings(void)
2424 unsigned char buf
[MAX_PATH
+2];
2425 unsigned int fcount
= 0;
2430 off_t first_copy_size
= 0;
2431 off_t second_copy_start_pos
= 0;
2434 /* add reading page to bookmarks */
2435 idx
= viewer_find_bookmark(cpage
, cline
);
2437 bookmarks
[idx
].flag
|= BOOKMARK_LAST
;
2440 viewer_add_bookmark();
2441 bookmarks
[bookmark_count
-1].flag
= BOOKMARK_LAST
;
2444 tfd
= rb
->open(SETTINGS_TMP_FILE
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666);
2448 ofd
= rb
->open(SETTINGS_FILE
, O_RDWR
);
2451 if ((rb
->read(ofd
, buf
, SETTINGS_H_SIZE
+2) != SETTINGS_H_SIZE
+2) ||
2452 rb
->memcmp(buf
, SETTINGS_HEADER
, SETTINGS_H_SIZE
- 1))
2458 if (buf
[SETTINGS_H_SIZE
- 1] != SETTINGS_VERSION
)
2461 if (!viewer_convert_settings_file())
2464 viewer_save_settings();
2467 fcount
= (buf
[SETTINGS_H_SIZE
] << 8) | buf
[SETTINGS_H_SIZE
+1];
2469 for (i
= 0; i
< fcount
; i
++)
2471 if (rb
->read(ofd
, buf
, MAX_PATH
+2) != MAX_PATH
+2)
2476 size
= (buf
[MAX_PATH
] << 8) | buf
[MAX_PATH
+1];
2477 if (rb
->strcmp(buf
, file_name
))
2479 if (rb
->lseek(ofd
, size
, SEEK_CUR
) < 0)
2487 first_copy_size
= rb
->lseek(ofd
, 0, SEEK_CUR
);
2488 if (first_copy_size
< 0)
2493 second_copy_start_pos
= first_copy_size
+ size
;
2494 first_copy_size
-= MAX_PATH
+2;
2499 if (first_copy_size
== 0)
2500 first_copy_size
= rb
->filesize(ofd
);
2502 if (!copy_bookmark_file(ofd
, tfd
, 0, first_copy_size
))
2507 if (second_copy_start_pos
> 0)
2509 if (!copy_bookmark_file(ofd
, tfd
, second_copy_start_pos
,
2510 rb
->filesize(ofd
) - second_copy_start_pos
))
2520 rb
->memcpy(buf
, SETTINGS_HEADER
, SETTINGS_H_SIZE
- 1);
2521 buf
[SETTINGS_H_SIZE
-1] = SETTINGS_VERSION
;
2522 buf
[SETTINGS_H_SIZE
] = 0;
2523 buf
[SETTINGS_H_SIZE
+1] = 0;
2524 if (rb
->write(tfd
, buf
, SETTINGS_H_SIZE
+2) != SETTINGS_H_SIZE
+2)
2528 /* copy to current read file's bookmarks */
2529 rb
->memset(buf
, 0, MAX_PATH
);
2530 rb
->snprintf(buf
, MAX_PATH
, "%s", file_name
);
2532 size
= PREFERENCES_SIZE
+ bookmark_count
* BOOKMARK_SIZE
+ 1;
2533 buf
[MAX_PATH
] = size
>> 8;
2534 buf
[MAX_PATH
+1] = size
;
2536 if (rb
->write(tfd
, buf
, MAX_PATH
+2) != MAX_PATH
+2)
2539 if (!viewer_write_preferences(tfd
, &prefs
))
2542 if (!viewer_write_bookmark_infos(tfd
))
2545 if (rb
->lseek(tfd
, SETTINGS_H_SIZE
, SEEK_SET
) < 0)
2549 buf
[0] = fcount
>> 8;
2552 if (rb
->write(tfd
, buf
, 2) != 2)
2557 rb
->remove(SETTINGS_FILE
);
2558 rb
->rename(SETTINGS_TMP_FILE
, SETTINGS_FILE
);
2564 rb
->remove(SETTINGS_TMP_FILE
);
2568 static void viewer_exit(void *parameter
)
2572 /* save preference and bookmarks */
2573 if (!viewer_save_settings())
2574 rb
->splash(HZ
, "Can't save preference and bookmarks.");
2577 #ifdef HAVE_LCD_BITMAP
2578 if (rb
->strcmp(prefs
.font
, rb
->global_settings
->font_file
))
2579 change_font(rb
->global_settings
->font_file
);
2583 static void calc_page(void)
2586 unsigned char *line_begin
;
2587 unsigned char *line_end
;
2589 unsigned char *sstp
;
2591 rb
->splash(0, "Calculating page/line number...");
2593 /* add reading page to bookmarks */
2594 viewer_add_last_read_bookmark();
2596 rb
->qsort(bookmarks
, bookmark_count
, sizeof(struct bookmark_info
),
2602 screen_top_ptr
= buffer
;
2603 buffer_end
= BUFFER_END();
2605 fill_buffer(file_pos
, buffer
, buffer_size
);
2606 line_end
= line_begin
= buffer
;
2608 /* update page and line of all bookmark */
2609 for (i
= 0; i
< bookmark_count
; i
++)
2611 sfp
= bookmarks
[i
].file_position
;
2614 while ((line_begin
> sstp
|| sstp
>= line_end
) ||
2615 (file_pos
> sfp
|| sfp
>= file_pos
+ BUFFER_END() - buffer
))
2617 get_next_line_position(&line_begin
, &line_end
, NULL
);
2618 if (line_end
== NULL
)
2621 next_line_ptr
= line_end
;
2623 if (sstp
== buffer
&&
2624 file_pos
<= sfp
&& sfp
< file_pos
+ BUFFER_END() - buffer
)
2625 sstp
= sfp
- file_pos
+ buffer
;
2627 increment_current_line();
2630 decrement_current_line();
2631 bookmarks
[i
].page
= cpage
;
2632 bookmarks
[i
].line
= cline
;
2633 bookmarks
[i
].file_position
= file_pos
+ (line_begin
- buffer
);
2634 increment_current_line();
2637 /* remove reading page's bookmark */
2638 for (i
= 0; i
< bookmark_count
; i
++)
2640 if (bookmarks
[i
].flag
& BOOKMARK_LAST
)
2645 screen_pos
= bookmarks
[i
].file_position
;
2646 screen_top
= screen_pos
% buffer_size
;
2647 file_pos
= screen_pos
- screen_top
;
2648 screen_top_ptr
= buffer
+ screen_top
;
2650 cpage
= bookmarks
[i
].page
;
2651 cline
= bookmarks
[i
].line
;
2652 bookmarks
[i
].flag
^= BOOKMARK_LAST
;
2653 buffer_end
= BUFFER_END();
2655 fill_buffer(file_pos
, buffer
, buffer_size
);
2657 if (bookmarks
[i
].flag
== 0)
2658 viewer_remove_bookmark(i
);
2660 if (prefs
.scroll_mode
== PAGE
&& cline
> 1)
2661 viewer_scroll_to_top_line();
2667 static int col_limit(int col
)
2672 if (col
>= max_width
- draw_columns
)
2673 col
= max_width
- draw_columns
;
2678 /* settings helper functions */
2680 static bool encoding_setting(void)
2682 static struct opt_items names
[NUM_CODEPAGES
];
2685 enum codepages oldenc
= prefs
.encoding
;
2687 for (idx
= 0; idx
< NUM_CODEPAGES
; idx
++)
2689 names
[idx
].string
= rb
->get_codepage_name(idx
);
2690 names
[idx
].voice_id
= -1;
2693 res
= rb
->set_option("Encoding", &prefs
.encoding
, INT
, names
,
2694 sizeof(names
) / sizeof(names
[0]), NULL
);
2696 /* When prefs.encoding changes into UTF-8 or changes from UTF-8,
2697 * filesize (file_size) might change.
2698 * In addition, if prefs.encoding is UTF-8, then BOM does not read.
2700 if (oldenc
!= prefs
.encoding
&& (oldenc
== UTF_8
|| prefs
.encoding
== UTF_8
))
2704 fill_buffer(file_pos
, buffer
, buffer_size
);
2710 static bool word_wrap_setting(void)
2712 static const struct opt_items names
[] = {
2714 {"Off (Chop Words)", -1},
2717 return rb
->set_option("Word Wrap", &prefs
.word_mode
, INT
,
2721 static bool line_mode_setting(void)
2723 static const struct opt_items names
[] = {
2726 {"Expand Lines", -1},
2727 #ifdef HAVE_LCD_BITMAP
2728 {"Reflow Lines", -1},
2732 return rb
->set_option("Line Mode", &prefs
.line_mode
, INT
, names
,
2733 sizeof(names
) / sizeof(names
[0]), NULL
);
2736 static bool view_mode_setting(void)
2738 static const struct opt_items names
[] = {
2739 {"No (Narrow)", -1},
2743 ret
= rb
->set_option("Wide View", &prefs
.view_mode
, INT
,
2745 if (prefs
.view_mode
== NARROW
)
2751 static bool scroll_mode_setting(void)
2753 static const struct opt_items names
[] = {
2754 {"Scroll by Page", -1},
2755 {"Scroll by Line", -1},
2758 return rb
->set_option("Scroll Mode", &prefs
.scroll_mode
, INT
,
2762 #ifdef HAVE_LCD_BITMAP
2763 static bool page_mode_setting(void)
2765 static const struct opt_items names
[] = {
2770 return rb
->set_option("Overlap Pages", &prefs
.page_mode
, INT
,
2774 static bool scrollbar_setting(void)
2776 static const struct opt_items names
[] = {
2781 return rb
->set_option("Show Scrollbar", &prefs
.scrollbar_mode
, INT
,
2785 static bool header_setting(void)
2787 int len
= (rb
->global_settings
->statusbar
== STATUSBAR_TOP
)? 4 : 2;
2788 struct opt_items names
[len
];
2790 names
[0].string
= "None";
2791 names
[0].voice_id
= -1;
2792 names
[1].string
= "File path";
2793 names
[1].voice_id
= -1;
2795 if (rb
->global_settings
->statusbar
== STATUSBAR_TOP
)
2797 names
[2].string
= "Status bar";
2798 names
[2].voice_id
= -1;
2799 names
[3].string
= "Both";
2800 names
[3].voice_id
= -1;
2803 return rb
->set_option("Show Header", &prefs
.header_mode
, INT
,
2807 static bool footer_setting(void)
2809 int len
= (rb
->global_settings
->statusbar
== STATUSBAR_BOTTOM
)? 4 : 2;
2810 struct opt_items names
[len
];
2812 names
[0].string
= "None";
2813 names
[0].voice_id
= -1;
2814 names
[1].string
= "Page Num";
2815 names
[1].voice_id
= -1;
2817 if (rb
->global_settings
->statusbar
== STATUSBAR_BOTTOM
)
2819 names
[2].string
= "Status bar";
2820 names
[2].voice_id
= -1;
2821 names
[3].string
= "Both";
2822 names
[3].voice_id
= -1;
2825 return rb
->set_option("Show Footer", &prefs
.footer_mode
, INT
,
2829 static int font_comp(const void *a
, const void *b
)
2831 struct opt_items
*pa
;
2832 struct opt_items
*pb
;
2834 pa
= (struct opt_items
*)a
;
2835 pb
= (struct opt_items
*)b
;
2837 return rb
->strcmp(pa
->string
, pb
->string
);
2840 static bool font_setting(void)
2844 struct dirent
*entry
;
2852 dir
= rb
->opendir(FONT_DIR
);
2855 rb
->splash(HZ
/2, "Font dir is not accessible");
2861 entry
= rb
->readdir(dir
);
2866 len
= rb
->strlen(entry
->d_name
);
2867 if (len
< 4 || rb
->strcmp(entry
->d_name
+ len
-4, ".fnt"))
2874 struct opt_items names
[count
];
2875 unsigned char font_names
[size
];
2876 unsigned char *p
= font_names
;
2878 dir
= rb
->opendir(FONT_DIR
);
2881 rb
->splash(HZ
/2, "Font dir is not accessible");
2887 entry
= rb
->readdir(dir
);
2892 len
= rb
->strlen(entry
->d_name
);
2893 if (len
< 4 || rb
->strcmp(entry
->d_name
+ len
-4, ".fnt"))
2896 rb
->snprintf(p
, len
-3, "%s", entry
->d_name
);
2897 names
[i
].string
= p
;
2898 names
[i
].voice_id
= -1;
2906 rb
->qsort(names
, count
, sizeof(struct opt_items
), font_comp
);
2908 for (i
= 0; i
< count
; i
++)
2910 if (!rb
->strcmp(names
[i
].string
, prefs
.font
))
2916 old_font
= new_font
;
2918 res
= rb
->set_option("Select Font", &new_font
, INT
,
2919 names
, count
, NULL
);
2921 if (new_font
!= old_font
)
2923 /* load selected font */
2924 if (!change_font((unsigned char *)names
[new_font
].string
)) {
2925 /* revert by re-loading the preferences font */
2926 change_font(prefs
.font
);
2929 rb
->memset(prefs
.font
, 0, MAX_PATH
);
2930 rb
->snprintf(prefs
.font
, MAX_PATH
, "%s", names
[new_font
].string
);
2936 static bool alignment_setting(void)
2938 static const struct opt_items names
[] = {
2943 return rb
->set_option("Alignment", &prefs
.alignment
, INT
,
2948 static bool autoscroll_speed_setting(void)
2950 return rb
->set_int("Auto-scroll Speed", "", UNIT_INT
,
2951 &prefs
.autoscroll_speed
, NULL
, 1, 1, 10, NULL
);
2954 MENUITEM_FUNCTION(encoding_item
, 0, "Encoding", encoding_setting
,
2955 NULL
, NULL
, Icon_NOICON
);
2956 MENUITEM_FUNCTION(word_wrap_item
, 0, "Word Wrap", word_wrap_setting
,
2957 NULL
, NULL
, Icon_NOICON
);
2958 MENUITEM_FUNCTION(line_mode_item
, 0, "Line Mode", line_mode_setting
,
2959 NULL
, NULL
, Icon_NOICON
);
2960 MENUITEM_FUNCTION(view_mode_item
, 0, "Wide View", view_mode_setting
,
2961 NULL
, NULL
, Icon_NOICON
);
2962 #ifdef HAVE_LCD_BITMAP
2963 MENUITEM_FUNCTION(alignment_item
, 0, "Alignment", alignment_setting
,
2964 NULL
, NULL
, Icon_NOICON
);
2965 MENUITEM_FUNCTION(scrollbar_item
, 0, "Show Scrollbar", scrollbar_setting
,
2966 NULL
, NULL
, Icon_NOICON
);
2967 MENUITEM_FUNCTION(page_mode_item
, 0, "Overlap Pages", page_mode_setting
,
2968 NULL
, NULL
, Icon_NOICON
);
2969 MENUITEM_FUNCTION(header_item
, 0, "Show Header", header_setting
,
2970 NULL
, NULL
, Icon_NOICON
);
2971 MENUITEM_FUNCTION(footer_item
, 0, "Show Footer", footer_setting
,
2972 NULL
, NULL
, Icon_NOICON
);
2973 MENUITEM_FUNCTION(font_item
, 0, "Font", font_setting
,
2974 NULL
, NULL
, Icon_NOICON
);
2976 MENUITEM_FUNCTION(scroll_mode_item
, 0, "Scroll Mode", scroll_mode_setting
,
2977 NULL
, NULL
, Icon_NOICON
);
2978 MENUITEM_FUNCTION(autoscroll_speed_item
, 0, "Auto-Scroll Speed",
2979 autoscroll_speed_setting
, NULL
, NULL
, Icon_NOICON
);
2980 MAKE_MENU(option_menu
, "Viewer Options", NULL
, Icon_NOICON
,
2981 &encoding_item
, &word_wrap_item
, &line_mode_item
, &view_mode_item
,
2982 #ifdef HAVE_LCD_BITMAP
2983 &alignment_item
, &scrollbar_item
, &page_mode_item
, &header_item
,
2984 &footer_item
, &font_item
,
2986 &scroll_mode_item
, &autoscroll_speed_item
);
2988 static bool viewer_options_menu(bool is_global
)
2991 struct preferences tmp_prefs
;
2993 rb
->memcpy(&tmp_prefs
, &prefs
, sizeof(struct preferences
));
2995 result
= (rb
->do_menu(&option_menu
, NULL
, NULL
, false) == MENU_ATTACHED_USB
);
2997 if (!is_global
&& rb
->memcmp(&tmp_prefs
, &prefs
, sizeof(struct preferences
)))
2999 /* Show-scrollbar mode for current view-width mode */
3000 #ifdef HAVE_LCD_BITMAP
3001 init_need_scrollbar();
3002 init_header_and_footer();
3009 static void viewer_menu(void)
3013 MENUITEM_STRINGLIST(menu
, "Viewer Menu", NULL
,
3014 "Return", "Viewer Options",
3015 "Show Playback Menu", "Select Bookmark",
3016 "Global Settings", "Quit");
3018 result
= rb
->do_menu(&menu
, NULL
, NULL
, false);
3021 case 0: /* return */
3023 case 1: /* change settings */
3024 done
= viewer_options_menu(false);
3026 case 2: /* playback control */
3027 playback_control(NULL
);
3029 case 3: /* select bookmark */
3030 viewer_select_bookmark(viewer_add_last_read_bookmark());
3031 viewer_remove_last_read_bookmark();
3032 fill_buffer(file_pos
, buffer
, buffer_size
);
3033 if (prefs
.scroll_mode
== PAGE
&& cline
> 1)
3034 viewer_scroll_to_top_line();
3036 case 4: /* change global settings */
3038 struct preferences orig_prefs
;
3040 rb
->memcpy(&orig_prefs
, &prefs
, sizeof(struct preferences
));
3041 if (!viewer_load_global_settings())
3042 viewer_default_preferences();
3043 done
= viewer_options_menu(true);
3044 viewer_save_global_settings();
3045 rb
->memcpy(&prefs
, &orig_prefs
, sizeof(struct preferences
));
3056 enum plugin_status
plugin_start(const void* file
)
3059 int lastbutton
= BUTTON_NONE
;
3060 bool autoscroll
= false;
3064 old_tick
= *rb
->current_tick
;
3066 /* get the plugin buffer */
3067 buffer
= rb
->plugin_get_buffer(&buf_size
);
3068 buffer_size
= buf_size
;
3069 if (buffer_size
== 0)
3071 rb
->splash(HZ
, "buffer does not allocate !!");
3072 return PLUGIN_ERROR
;
3074 block_size
= buffer_size
/ 3;
3075 buffer_size
= 3 * block_size
;
3078 return PLUGIN_ERROR
;
3083 rb
->splash(HZ
, "Error opening file.");
3084 return PLUGIN_ERROR
;
3087 if (!viewer_load_settings()) /* load the preferences and bookmark */
3088 return PLUGIN_ERROR
;
3091 rb
->lcd_set_backdrop(NULL
);
3100 if(old_tick
<= *rb
->current_tick
- (110-prefs
.autoscroll_speed
*10))
3102 viewer_scroll_down(true);
3104 old_tick
= *rb
->current_tick
;
3108 button
= rb
->button_get_w_tmo(HZ
/10);
3110 if (prefs
.view_mode
!= WIDE
) {
3111 /* when not in wide view mode, the SCREEN_LEFT and SCREEN_RIGHT
3112 buttons jump to the beginning and end of the file. To stop
3113 users doing this by accident, replace non-held occurrences
3114 with page up/down instead. */
3115 if (button
== VIEWER_SCREEN_LEFT
)
3116 button
= VIEWER_PAGE_UP
;
3117 else if (button
== VIEWER_SCREEN_RIGHT
)
3118 button
= VIEWER_PAGE_DOWN
;
3129 case VIEWER_AUTOSCROLL
:
3130 #ifdef VIEWER_AUTOSCROLL_PRE
3131 if (lastbutton
!= VIEWER_AUTOSCROLL_PRE
)
3134 autoscroll
= !autoscroll
;
3137 case VIEWER_PAGE_UP
:
3138 case VIEWER_PAGE_UP
| BUTTON_REPEAT
:
3139 #ifdef VIEWER_PAGE_UP2
3140 case VIEWER_PAGE_UP2
:
3141 case VIEWER_PAGE_UP2
| BUTTON_REPEAT
:
3143 if (prefs
.scroll_mode
== PAGE
)
3146 #ifdef HAVE_LCD_BITMAP
3147 for (i
= prefs
.page_mode
==OVERLAP
? 1:0; i
< display_lines
; i
++)
3149 for (i
= 0; i
< display_lines
; i
++)
3155 old_tick
= *rb
->current_tick
;
3159 case VIEWER_PAGE_DOWN
:
3160 case VIEWER_PAGE_DOWN
| BUTTON_REPEAT
:
3161 #ifdef VIEWER_PAGE_DOWN2
3162 case VIEWER_PAGE_DOWN2
:
3163 case VIEWER_PAGE_DOWN2
| BUTTON_REPEAT
:
3165 if (prefs
.scroll_mode
== PAGE
)
3168 if (next_screen_ptr
!= NULL
)
3170 screen_top_ptr
= next_screen_to_draw_ptr
;
3171 if (cpage
< MAX_PAGE
)
3176 viewer_scroll_down(autoscroll
);
3177 old_tick
= *rb
->current_tick
;
3181 case VIEWER_SCREEN_LEFT
:
3182 case VIEWER_SCREEN_LEFT
| BUTTON_REPEAT
:
3183 if (prefs
.view_mode
== WIDE
) {
3185 col
= col_limit(col
- draw_columns
);
3187 else { /* prefs.view_mode == NARROW */
3195 case VIEWER_SCREEN_RIGHT
:
3196 case VIEWER_SCREEN_RIGHT
| BUTTON_REPEAT
:
3197 if (prefs
.view_mode
== WIDE
) {
3199 col
= col_limit(col
+ draw_columns
);
3201 else { /* prefs.view_mode == NARROW */
3202 /* Bottom of file */
3209 #ifdef VIEWER_LINE_UP
3210 case VIEWER_LINE_UP
:
3211 case VIEWER_LINE_UP
| BUTTON_REPEAT
:
3212 /* Scroll up one line */
3214 old_tick
= *rb
->current_tick
;
3218 case VIEWER_LINE_DOWN
:
3219 case VIEWER_LINE_DOWN
| BUTTON_REPEAT
:
3220 /* Scroll down one line */
3221 viewer_scroll_down(autoscroll
);
3222 increment_current_line();
3223 old_tick
= *rb
->current_tick
;
3227 #ifdef VIEWER_COLUMN_LEFT
3228 case VIEWER_COLUMN_LEFT
:
3229 case VIEWER_COLUMN_LEFT
| BUTTON_REPEAT
:
3230 if (prefs
.view_mode
== WIDE
) {
3231 /* Scroll left one column */
3232 col
= col_limit(col
- glyph_width('o'));
3237 case VIEWER_COLUMN_RIGHT
:
3238 case VIEWER_COLUMN_RIGHT
| BUTTON_REPEAT
:
3239 if (prefs
.view_mode
== WIDE
) {
3240 /* Scroll right one column */
3241 col
= col_limit(col
+ glyph_width('o'));
3247 #ifdef VIEWER_RC_QUIT
3248 case VIEWER_RC_QUIT
:
3258 case VIEWER_BOOKMARK
:
3260 int idx
= viewer_find_bookmark(cpage
, cline
);
3264 if (bookmark_count
>= MAX_BOOKMARKS
-1)
3265 rb
->splash(HZ
/2, "No more bookmarks");
3268 viewer_add_bookmark();
3269 rb
->splash(HZ
/2, "Bookmark added");
3274 viewer_remove_bookmark(idx
);
3275 rb
->splash(HZ
/2, "Bookmark removed");
3282 if (rb
->default_event_handler_ex(button
, viewer_exit
, NULL
)
3283 == SYS_USB_CONNECTED
)
3284 return PLUGIN_USB_CONNECTED
;
3287 if (button
!= BUTTON_NONE
)
3289 lastbutton
= button
;