summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorZakk Roberts <midk@rockbox.org>2006-05-01 05:45:18 +0000
committerZakk Roberts <midk@rockbox.org>2006-05-01 05:45:18 +0000
commit07fcf77cb0b734135fdc730a164f3333d6c703e5 (patch)
treeb30cffeb322adff6c09033c482ec3e0288167aef /apps
parent0d6b5557a113afab41c7ef239c9ce5ddabebea8b (diff)
downloadrockbox-07fcf77cb0b734135fdc730a164f3333d6c703e5.tar.gz
rockbox-07fcf77cb0b734135fdc730a164f3333d6c703e5.zip
Patch #5056 by Jonathan Gordon, with rework and additions by me: Updated Viewer plugin. Replaces annoying mode-toggle key-combos with a settings menu, including a new 'Scroll by Line' option. I've also added a 'hands-free' auto-scroll feature and added lcd_setmargins to the plugin API, since we need it here.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9844 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugin.c20
-rw-r--r--apps/plugin.h18
-rw-r--r--apps/plugins/viewer.c704
3 files changed, 351 insertions, 391 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index b023a6553f..0b09d07ad6 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -182,7 +182,7 @@ static const struct plugin_api rockbox_api = {
182 button_get_w_tmo, 182 button_get_w_tmo,
183 button_status, 183 button_status,
184 button_clear_queue, 184 button_clear_queue,
185#ifdef HAS_BUTTON_HOLD 185#ifdef HAS_BUTTON_HOLD
186 button_hold, 186 button_hold,
187#endif 187#endif
188 188
@@ -202,7 +202,7 @@ static const struct plugin_api rockbox_api = {
202 settings_parseline, 202 settings_parseline,
203#ifndef SIMULATOR 203#ifndef SIMULATOR
204 ata_sleep, 204 ata_sleep,
205 ata_disk_is_active, 205 ata_disk_is_active,
206#endif 206#endif
207 207
208 /* dir */ 208 /* dir */
@@ -290,7 +290,7 @@ static const struct plugin_api rockbox_api = {
290 bitswap, 290 bitswap,
291#endif 291#endif
292#if CONFIG_CODEC == SWCODEC 292#if CONFIG_CODEC == SWCODEC
293 pcm_play_data, 293 pcm_play_data,
294 pcm_play_stop, 294 pcm_play_stop,
295 pcm_set_frequency, 295 pcm_set_frequency,
296 pcm_is_playing, 296 pcm_is_playing,
@@ -357,7 +357,7 @@ static const struct plugin_api rockbox_api = {
357 battery_level_safe, 357 battery_level_safe,
358 battery_time, 358 battery_time,
359#ifndef SIMULATOR 359#ifndef SIMULATOR
360 battery_voltage, 360 battery_voltage,
361#endif 361#endif
362#ifdef HAVE_CHARGING 362#ifdef HAVE_CHARGING
363 charger_inserted, 363 charger_inserted,
@@ -434,6 +434,10 @@ static const struct plugin_api rockbox_api = {
434 gui_synclist_scroll_left, 434 gui_synclist_scroll_left,
435#endif 435#endif
436 gui_synclist_do_button, 436 gui_synclist_do_button,
437
438#ifdef HAVE_LCD_BITMAP
439 lcd_setmargins,
440#endif
437}; 441};
438 442
439int plugin_load(const char* plugin, void* parameter) 443int plugin_load(const char* plugin, void* parameter)
@@ -553,7 +557,7 @@ int plugin_load(const char* plugin, void* parameter)
553#ifdef HAVE_LCD_BITMAP 557#ifdef HAVE_LCD_BITMAP
554#if LCD_DEPTH > 1 558#if LCD_DEPTH > 1
555#ifdef HAVE_LCD_COLOR 559#ifdef HAVE_LCD_COLOR
556 lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color, 560 lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color,
557 global_settings.bg_color); 561 global_settings.bg_color);
558#else 562#else
559 lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG); 563 lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG);
@@ -607,7 +611,7 @@ void* plugin_get_buffer(int* buffer_size)
607 { 611 {
608 if (plugin_size >= PLUGIN_BUFFER_SIZE) 612 if (plugin_size >= PLUGIN_BUFFER_SIZE)
609 return NULL; 613 return NULL;
610 614
611 *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size; 615 *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size;
612 buffer_pos = plugin_size; 616 buffer_pos = plugin_size;
613 } 617 }
@@ -620,7 +624,7 @@ void* plugin_get_buffer(int* buffer_size)
620 return &pluginbuf[buffer_pos]; 624 return &pluginbuf[buffer_pos];
621} 625}
622 626
623/* Returns a pointer to the mp3 buffer. 627/* Returns a pointer to the mp3 buffer.
624 Playback gets stopped, to avoid conflicts. */ 628 Playback gets stopped, to avoid conflicts. */
625void* plugin_get_audio_buffer(int* buffer_size) 629void* plugin_get_audio_buffer(int* buffer_size)
626{ 630{
@@ -631,7 +635,7 @@ void* plugin_get_audio_buffer(int* buffer_size)
631} 635}
632 636
633/* The plugin wants to stay resident after leaving its main function, e.g. 637/* The plugin wants to stay resident after leaving its main function, e.g.
634 runs from timer or own thread. The callback is registered to later 638 runs from timer or own thread. The callback is registered to later
635 instruct it to free its resources before a new plugin gets loaded. */ 639 instruct it to free its resources before a new plugin gets loaded. */
636void plugin_tsr(void (*exit_callback)(void)) 640void plugin_tsr(void (*exit_callback)(void))
637{ 641{
diff --git a/apps/plugin.h b/apps/plugin.h
index d39e92de9c..a6807284f8 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -106,7 +106,7 @@
106#define PLUGIN_API_VERSION 18 106#define PLUGIN_API_VERSION 18
107 107
108/* update this to latest version if a change to the api struct breaks 108/* update this to latest version if a change to the api struct breaks
109 backwards compatibility (and please take the opportunity to sort in any 109 backwards compatibility (and please take the opportunity to sort in any
110 new function which are "waiting" at the end of the function table) */ 110 new function which are "waiting" at the end of the function table) */
111#define PLUGIN_MIN_API_VERSION 14 111#define PLUGIN_MIN_API_VERSION 14
112 112
@@ -233,7 +233,7 @@ struct plugin_api {
233 long (*button_get_w_tmo)(int ticks); 233 long (*button_get_w_tmo)(int ticks);
234 int (*button_status)(void); 234 int (*button_status)(void);
235 void (*button_clear_queue)(void); 235 void (*button_clear_queue)(void);
236#ifdef HAS_BUTTON_HOLD 236#ifdef HAS_BUTTON_HOLD
237 bool (*button_hold)(void); 237 bool (*button_hold)(void);
238#endif 238#endif
239 239
@@ -255,7 +255,7 @@ struct plugin_api {
255 void (*ata_sleep)(void); 255 void (*ata_sleep)(void);
256 bool (*ata_disk_is_active)(void); 256 bool (*ata_disk_is_active)(void);
257#endif 257#endif
258 258
259 /* dir */ 259 /* dir */
260 DIR* (*PREFIX(opendir))(const char* name); 260 DIR* (*PREFIX(opendir))(const char* name);
261 int (*PREFIX(closedir))(DIR* dir); 261 int (*PREFIX(closedir))(DIR* dir);
@@ -376,7 +376,7 @@ struct plugin_api {
376#endif 376#endif
377#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) || \ 377#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) || \
378 (CONFIG_CODEC == SWCODEC) 378 (CONFIG_CODEC == SWCODEC)
379 void (*sound_set_pitch)(int pitch); 379 void (*sound_set_pitch)(int pitch);
380#endif 380#endif
381 381
382 /* MAS communication */ 382 /* MAS communication */
@@ -408,8 +408,8 @@ struct plugin_api {
408 void (*menu_insert)(int menu, int position, char *desc, bool (*function) (void)); 408 void (*menu_insert)(int menu, int position, char *desc, bool (*function) (void));
409 void (*menu_set_cursor)(int menu, int position); 409 void (*menu_set_cursor)(int menu, int position);
410 410
411 bool (*set_option)(const char* string, void* variable, 411 bool (*set_option)(const char* string, void* variable,
412 enum optiontype type, const struct opt_items* options, 412 enum optiontype type, const struct opt_items* options,
413 int numoptions, void (*function)(int)); 413 int numoptions, void (*function)(int));
414 414
415 415
@@ -473,7 +473,7 @@ struct plugin_api {
473 struct tree_context* (*tree_get_context)(void); 473 struct tree_context* (*tree_get_context)(void);
474 474
475 /* new stuff at the end, sort into place next time 475 /* new stuff at the end, sort into place next time
476 the API gets incompatible */ 476 the API gets incompatible */
477 bool (*set_sound)(const unsigned char * string, 477 bool (*set_sound)(const unsigned char * string,
478 int* variable, int setting); 478 int* variable, int setting);
479#if ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)) && !defined(SIMULATOR) 479#if ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)) && !defined(SIMULATOR)
@@ -510,6 +510,10 @@ struct plugin_api {
510 void (*gui_synclist_scroll_left)(struct gui_synclist * lists); 510 void (*gui_synclist_scroll_left)(struct gui_synclist * lists);
511#endif 511#endif
512 unsigned (*gui_synclist_do_button)(struct gui_synclist * lists, unsigned button); 512 unsigned (*gui_synclist_do_button)(struct gui_synclist * lists, unsigned button);
513
514#ifdef HAVE_LCD_BITMAP
515 void (*lcd_setmargins)(int x, int y);
516#endif
513}; 517};
514 518
515/* plugin header */ 519/* plugin header */
diff --git a/apps/plugins/viewer.c b/apps/plugins/viewer.c
index 51bf03af75..947dfc980a 100644
--- a/apps/plugins/viewer.c
+++ b/apps/plugins/viewer.c
@@ -23,7 +23,7 @@
23 23
24PLUGIN_HEADER 24PLUGIN_HEADER
25 25
26#define SETTINGS_FILE "/.rockbox/viewers/viewer.dat" 26#define SETTINGS_FILE "/.rockbox/viewers/viewer.cfg"
27 27
28#define WRAP_TRIM 44 /* Max number of spaces to trim (arbitrary) */ 28#define WRAP_TRIM 44 /* Max number of spaces to trim (arbitrary) */
29#define MAX_COLUMNS 64 /* Max displayable string len (over-estimate) */ 29#define MAX_COLUMNS 64 /* Max displayable string len (over-estimate) */
@@ -55,22 +55,19 @@ PLUGIN_HEADER
55 55
56/* Is a scrollbar called for on the current screen? */ 56/* Is a scrollbar called for on the current screen? */
57#define NEED_SCROLLBAR() \ 57#define NEED_SCROLLBAR() \
58 ((!(ONE_SCREEN_FITS_ALL())) && (scrollbar_mode[view_mode]==SB_ON)) 58 ((!(ONE_SCREEN_FITS_ALL())) && (prefs.scrollbar_mode==SB_ON))
59 59
60/* variable button definitions */ 60/* variable button definitions */
61 61
62/* Recorder keys */ 62/* Recorder keys */
63#if CONFIG_KEYPAD == RECORDER_PAD 63#if CONFIG_KEYPAD == RECORDER_PAD
64#define VIEWER_MENU BUTTON_OFF 64#define VIEWER_QUIT BUTTON_OFF
65#define VIEWER_PAGE_UP BUTTON_UP 65#define VIEWER_PAGE_UP BUTTON_UP
66#define VIEWER_PAGE_DOWN BUTTON_DOWN 66#define VIEWER_PAGE_DOWN BUTTON_DOWN
67#define VIEWER_SCREEN_LEFT BUTTON_LEFT 67#define VIEWER_SCREEN_LEFT BUTTON_LEFT
68#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 68#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
69#define VIEWER_MODE_WRAP BUTTON_F1 69#define VIEWER_MENU BUTTON_F1
70#define VIEWER_MODE_LINE BUTTON_F2 70#define VIEWER_AUTOSCROLL BUTTON_PLAY
71#define VIEWER_MODE_WIDTH BUTTON_F3
72#define VIEWER_MODE_PAGE (BUTTON_ON | BUTTON_F1)
73#define VIEWER_MODE_SCROLLBAR (BUTTON_ON | BUTTON_F3)
74#define VIEWER_LINE_UP (BUTTON_ON | BUTTON_UP) 71#define VIEWER_LINE_UP (BUTTON_ON | BUTTON_UP)
75#define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN) 72#define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN)
76#define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT) 73#define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT)
@@ -78,151 +75,128 @@ PLUGIN_HEADER
78 75
79/* Ondio keys */ 76/* Ondio keys */
80#elif CONFIG_KEYPAD == ONDIO_PAD 77#elif CONFIG_KEYPAD == ONDIO_PAD
81#define VIEWER_MENU BUTTON_OFF
82#define VIEWER_PAGE_UP BUTTON_UP 78#define VIEWER_PAGE_UP BUTTON_UP
83#define VIEWER_PAGE_DOWN BUTTON_DOWN 79#define VIEWER_PAGE_DOWN BUTTON_DOWN
84#define VIEWER_SCREEN_LEFT BUTTON_LEFT 80#define VIEWER_SCREEN_LEFT BUTTON_LEFT
85#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 81#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
86#define VIEWER_MODE_WRAP (BUTTON_MENU | BUTTON_LEFT) 82#define VIEWER_MENU BUTTON_OFF
87#define VIEWER_MODE_LINE (BUTTON_MENU | BUTTON_UP) 83#define VIEWER_AUTOSCROLL BUTTON_MENU
88#define VIEWER_MODE_WIDTH (BUTTON_MENU | BUTTON_RIGHT)
89#define VIEWER_MODE_PAGE (BUTTON_MENU | BUTTON_DOWN)
90#define VIEWER_MODE_SCROLLBAR (BUTTON_MENU | BUTTON_OFF)
91 84
92/* Player keys */ 85/* Player keys */
93#elif CONFIG_KEYPAD == PLAYER_PAD 86#elif CONFIG_KEYPAD == PLAYER_PAD
94#define VIEWER_MENU BUTTON_STOP 87#define VIEWER_QUIT BUTTON_STOP
95#define VIEWER_PAGE_UP BUTTON_LEFT 88#define VIEWER_PAGE_UP BUTTON_LEFT
96#define VIEWER_PAGE_DOWN BUTTON_RIGHT 89#define VIEWER_PAGE_DOWN BUTTON_RIGHT
97#define VIEWER_SCREEN_LEFT (BUTTON_MENU | BUTTON_LEFT) 90#define VIEWER_MENU BUTTON_MENU
98#define VIEWER_SCREEN_RIGHT (BUTTON_MENU | BUTTON_RIGHT) 91#define VIEWER_AUTOSCROLL BUTTON_ON
99#define VIEWER_MODE_WRAP (BUTTON_ON | BUTTON_LEFT)
100#define VIEWER_MODE_LINE (BUTTON_ON | BUTTON_MENU | BUTTON_RIGHT)
101#define VIEWER_MODE_WIDTH (BUTTON_ON | BUTTON_RIGHT)
102 92
103/* iRiver H1x0 && H3x0 keys */ 93/* iRiver H1x0 && H3x0 keys */
104#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 94#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
105 (CONFIG_KEYPAD == IRIVER_H300_PAD) 95 (CONFIG_KEYPAD == IRIVER_H300_PAD)
106#define VIEWER_MENU BUTTON_OFF 96#define VIEWER_QUIT BUTTON_OFF
107#define VIEWER_PAGE_UP BUTTON_UP 97#define VIEWER_PAGE_UP BUTTON_UP
108#define VIEWER_PAGE_DOWN BUTTON_DOWN 98#define VIEWER_PAGE_DOWN BUTTON_DOWN
109#define VIEWER_SCREEN_LEFT BUTTON_LEFT 99#define VIEWER_SCREEN_LEFT BUTTON_LEFT
110#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 100#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
111#define VIEWER_MODE_WRAP BUTTON_REC 101#define VIEWER_MENU BUTTON_MODE
112#define VIEWER_MODE_LINE BUTTON_MODE 102#define VIEWER_AUTOSCROLL BUTTON_SELECT
113#define VIEWER_MODE_WIDTH BUTTON_SELECT
114#define VIEWER_MODE_PAGE (BUTTON_ON | BUTTON_MODE)
115#define VIEWER_MODE_SCROLLBAR (BUTTON_ON | BUTTON_REC)
116#define VIEWER_LINE_UP (BUTTON_ON | BUTTON_UP) 103#define VIEWER_LINE_UP (BUTTON_ON | BUTTON_UP)
117#define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN) 104#define VIEWER_LINE_DOWN (BUTTON_ON | BUTTON_DOWN)
118#define VIEWER_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT)
119#define VIEWER_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT)
120 105
121/* iPods with the 4G pad */ 106/* iPods with the 4G pad */
122#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ 107#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
123 (CONFIG_KEYPAD == IPOD_3G_PAD) 108 (CONFIG_KEYPAD == IPOD_3G_PAD)
109#define VIEWER_QUIT_PRE BUTTON_SELECT
110#define VIEWER_QUIT (BUTTON_SELECT | BUTTON_MENU)
124#define VIEWER_MENU BUTTON_MENU 111#define VIEWER_MENU BUTTON_MENU
112#define VIEWER_AUTOSCROLL BUTTON_PLAY
125#define VIEWER_PAGE_UP BUTTON_SCROLL_BACK 113#define VIEWER_PAGE_UP BUTTON_SCROLL_BACK
126#define VIEWER_PAGE_DOWN BUTTON_SCROLL_FWD 114#define VIEWER_PAGE_DOWN BUTTON_SCROLL_FWD
127#define VIEWER_SCREEN_LEFT BUTTON_LEFT 115#define VIEWER_SCREEN_LEFT BUTTON_LEFT
128#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 116#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
129#define VIEWER_MODE_WRAP (BUTTON_SELECT | BUTTON_LEFT)
130#define VIEWER_MODE_LINE (BUTTON_SELECT | BUTTON_PLAY)
131#define VIEWER_MODE_WIDTH (BUTTON_SELECT | BUTTON_RIGHT)
132#define VIEWER_MODE_PAGE (BUTTON_SELECT | BUTTON_LEFT | BUTTON_MENU)
133#define VIEWER_MODE_SCROLLBAR (BUTTON_SELECT | BUTTON_LEFT | BUTTON_RIGHT)
134 117
135/* iFP7xx keys */ 118/* iFP7xx keys */
136#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD 119#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
137#define VIEWER_MENU BUTTON_PLAY 120#define VIEWER_QUIT BUTTON_PLAY
138#define VIEWER_PAGE_UP BUTTON_UP 121#define VIEWER_PAGE_UP BUTTON_UP
139#define VIEWER_PAGE_DOWN BUTTON_DOWN 122#define VIEWER_PAGE_DOWN BUTTON_DOWN
140#define VIEWER_SCREEN_LEFT BUTTON_LEFT 123#define VIEWER_SCREEN_LEFT BUTTON_LEFT
141#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 124#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
142#define VIEWER_MODE_WRAP (BUTTON_EQ | BUTTON_REL) 125#define VIEWER_MENU BUTTON_MODE
143#define VIEWER_MODE_LINE (BUTTON_EQ | BUTTON_REPEAT) 126#define VIEWER_AUTOSCROLL BUTTON_SELECT
144#define VIEWER_MODE_WIDTH BUTTON_MODE
145 127
146/* iAudio X5 keys */ 128/* iAudio X5 keys */
147#elif CONFIG_KEYPAD == IAUDIO_X5_PAD 129#elif CONFIG_KEYPAD == IAUDIO_X5_PAD
148#define VIEWER_MENU BUTTON_POWER 130#define VIEWER_QUIT BUTTON_POWER
149#define VIEWER_PAGE_UP BUTTON_UP 131#define VIEWER_PAGE_UP BUTTON_UP
150#define VIEWER_PAGE_DOWN BUTTON_DOWN 132#define VIEWER_PAGE_DOWN BUTTON_DOWN
151#define VIEWER_SCREEN_LEFT BUTTON_LEFT 133#define VIEWER_SCREEN_LEFT BUTTON_LEFT
152#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 134#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
153#define VIEWER_MODE_WRAP (BUTTON_PLAY | BUTTON_REL) 135#define VIEWER_MENU BUTTON_SELECT
154#define VIEWER_MODE_LINE (BUTTON_PLAY | BUTTON_REPEAT) 136#define VIEWER_AUTOSCROLL BUTTON_PLAY
155#define VIEWER_MODE_WIDTH BUTTON_SELECT
156 137
157/* iAudio X5 keys */ 138/* GIGABEAT keys */
158#elif CONFIG_KEYPAD == GIGABEAT_PAD 139#elif CONFIG_KEYPAD == GIGABEAT_PAD
159#define VIEWER_MENU BUTTON_A 140#define VIEWER_QUIT BUTTON_POWER
160#define VIEWER_PAGE_UP BUTTON_UP 141#define VIEWER_PAGE_UP BUTTON_UP
161#define VIEWER_PAGE_DOWN BUTTON_DOWN 142#define VIEWER_PAGE_DOWN BUTTON_DOWN
162#define VIEWER_SCREEN_LEFT BUTTON_LEFT 143#define VIEWER_SCREEN_LEFT BUTTON_LEFT
163#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT 144#define VIEWER_SCREEN_RIGHT BUTTON_RIGHT
164#define VIEWER_MODE_WRAP (BUTTON_POWER | BUTTON_REL) 145#define VIEWER_MENU BUTTON_MENU
165#define VIEWER_MODE_LINE (BUTTON_POWER | BUTTON_REPEAT) 146#define VIEWER_AUTOSCROLL BUTTON_A
166#define VIEWER_MODE_WIDTH BUTTON_MENU
167 147
168#endif 148#endif
169 149
170enum { 150struct preferences {
171 WRAP=0, 151 enum {
172 CHOP, 152 WRAP=0,
173 WORD_MODES 153 CHOP,
174} word_mode = 0; 154 WORD_MODES
175static unsigned char *word_mode_str[] = {"wrap", "chop", "words"}; 155 } word_mode;
176 156
177enum { 157 enum {
178 NORMAL=0, 158 NORMAL=0,
179 JOIN, 159 JOIN,
180#ifdef HAVE_LCD_BITMAP 160#ifdef HAVE_LCD_BITMAP
181 REFLOW, /* Makes no sense for the player */ 161 REFLOW, /* Makes no sense for the player */
182#endif 162#endif
183 EXPAND, 163 EXPAND,
184 LINE_MODES, 164 LINE_MODES,
185#ifndef HAVE_LCD_BITMAP 165#ifndef HAVE_LCD_BITMAP
186 REFLOW /* Sorting it behind LINE_MODES effectively disables it. */ 166 REFLOW /* Sorting it behind LINE_MODES effectively disables it. */
187#endif 167#endif
188} line_mode = 0; 168 } line_mode;
189
190static unsigned char *line_mode_str[] = {
191 [NORMAL] = "normal", [JOIN] = "join", [REFLOW] = "reflow",
192 [EXPAND] = "expand", [LINE_MODES] = "lines"
193};
194 169
195enum { 170 enum {
196 NARROW=0, 171 NARROW=0,
197 WIDE, 172 WIDE,
198 VIEW_MODES 173 VIEW_MODES
199} view_mode = 0; 174 } view_mode;
200static unsigned char *view_mode_str[] = {"narrow", "wide", "view"};
201 175
202#ifdef HAVE_LCD_BITMAP 176#ifdef HAVE_LCD_BITMAP
203enum { 177 enum {
204 SB_OFF=0, 178 SB_OFF=0,
205 SB_ON, 179 SB_ON,
206 SCROLLBAR_MODES 180 SCROLLBAR_MODES
207} scrollbar_mode[VIEW_MODES] = {SB_OFF, SB_ON}; 181 } scrollbar_mode;
208#ifdef VIEWER_MODE_SCROLLBAR 182 bool need_scrollbar;
209static unsigned char *scrollbar_mode_str[] = {"off", "on", "scrollbar"}; 183
210#endif 184 enum {
211 185 NO_OVERLAP=0,
212static bool need_scrollbar; 186 OVERLAP,
213 187 PAGE_MODES
214 188 } page_mode;
215enum { 189
216 NO_OVERLAP=0, 190#endif /* HAVE_LCD_BITMAP */
217 OVERLAP, 191
218 PAGE_MODES 192 enum {
219} page_mode = 0; 193 PAGE=0,
220 194 LINE,
221#ifdef VIEWER_MODE_PAGE 195 SCROLL_MODES
222static unsigned char *page_mode_str[] = {"don't overlap", "overlap", "pages"}; 196 } scroll_mode;
223#endif 197
224 198 int autoscroll_speed;
225#endif 199} prefs;
226 200
227static unsigned char buffer[BUFFER_SIZE + 1]; 201static unsigned char buffer[BUFFER_SIZE + 1];
228static unsigned char line_break[] = {0,0x20,'-',9,0xB,0xC}; 202static unsigned char line_break[] = {0,0x20,'-',9,0xB,0xC};
@@ -245,6 +219,9 @@ static struct plugin_api* rb;
245 219
246static unsigned char glyph_width[256]; 220static unsigned char glyph_width[256];
247 221
222bool done = false;
223int col = 0;
224
248#define ADVANCE_COUNTERS(c) do { width += glyph_width[c]; k++; } while(0) 225#define ADVANCE_COUNTERS(c) do { width += glyph_width[c]; k++; } while(0)
249#define LINE_IS_FULL ((k>MAX_COLUMNS-1) || (width > draw_columns)) 226#define LINE_IS_FULL ((k>MAX_COLUMNS-1) || (width > draw_columns))
250static unsigned char* crop_at_width(const unsigned char* p) 227static unsigned char* crop_at_width(const unsigned char* p)
@@ -284,7 +261,7 @@ static unsigned char* find_last_space(const unsigned char* p, int size)
284{ 261{
285 int i, j, k; 262 int i, j, k;
286 263
287 k = (line_mode==JOIN) || (line_mode==REFLOW) ? 0:1; 264 k = (prefs.line_mode==JOIN) || (prefs.line_mode==REFLOW) ? 0:1;
288 265
289 for (i=size-1; i>=0; i--) 266 for (i=size-1; i>=0; i--)
290 for (j=k; j < (int) sizeof(line_break); j++) 267 for (j=k; j < (int) sizeof(line_break); j++)
@@ -307,16 +284,16 @@ static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_sho
307 if BUFFER_OOB(cur_line) 284 if BUFFER_OOB(cur_line)
308 return NULL; 285 return NULL;
309 286
310 if (view_mode == WIDE) { 287 if (prefs.view_mode == WIDE) {
311 search_len = MAX_WIDTH; 288 search_len = MAX_WIDTH;
312 } 289 }
313 else { /* view_mode == NARROW */ 290 else { /* prefs.view_mode == NARROW */
314 search_len = crop_at_width(cur_line) - cur_line; 291 search_len = crop_at_width(cur_line) - cur_line;
315 } 292 }
316 293
317 size = BUFFER_OOB(cur_line+search_len) ? buffer_end-cur_line : search_len; 294 size = BUFFER_OOB(cur_line+search_len) ? buffer_end-cur_line : search_len;
318 295
319 if ((line_mode == JOIN) || (line_mode == REFLOW)) { 296 if ((prefs.line_mode == JOIN) || (prefs.line_mode == REFLOW)) {
320 /* Need to scan ahead and possibly increase search_len and size, 297 /* Need to scan ahead and possibly increase search_len and size,
321 or possibly set next_line at second hard return in a row. */ 298 or possibly set next_line at second hard return in a row. */
322 next_line = NULL; 299 next_line = NULL;
@@ -332,7 +309,7 @@ static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_sho
332 c = cur_line[j]; 309 c = cur_line[j];
333 switch (c) { 310 switch (c) {
334 case ' ': 311 case ' ':
335 if (line_mode == REFLOW) { 312 if (prefs.line_mode == REFLOW) {
336 if (newlines > 0) { 313 if (newlines > 0) {
337 size = j; 314 size = j;
338 next_line = cur_line + size; 315 next_line = cur_line + size;
@@ -363,7 +340,7 @@ static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_sho
363 break; 340 break;
364 341
365 default: 342 default:
366 if (line_mode==JOIN || newlines>0) { 343 if (prefs.line_mode==JOIN || newlines>0) {
367 while (spaces) { 344 while (spaces) {
368 spaces--; 345 spaces--;
369 ADVANCE_COUNTERS(' '); 346 ADVANCE_COUNTERS(' ');
@@ -398,20 +375,20 @@ static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_sho
398 375
399 if (next_line == NULL) 376 if (next_line == NULL)
400 if (size == search_len) { 377 if (size == search_len) {
401 if (word_mode == WRAP) /* Find last space */ 378 if (prefs.word_mode == WRAP) /* Find last space */
402 next_line = find_last_space(cur_line, size); 379 next_line = find_last_space(cur_line, size);
403 380
404 if (next_line == NULL) 381 if (next_line == NULL)
405 next_line = crop_at_width(cur_line); 382 next_line = crop_at_width(cur_line);
406 else 383 else
407 if (word_mode == WRAP) 384 if (prefs.word_mode == WRAP)
408 for (i=0; 385 for (i=0;
409 i<WRAP_TRIM && isspace(next_line[0]) && !BUFFER_OOB(next_line); 386 i<WRAP_TRIM && isspace(next_line[0]) && !BUFFER_OOB(next_line);
410 i++) 387 i++)
411 next_line++; 388 next_line++;
412 } 389 }
413 390
414 if (line_mode == EXPAND) 391 if (prefs.line_mode == EXPAND)
415 if (!BUFFER_OOB(next_line)) /* Not Null & not out of bounds */ 392 if (!BUFFER_OOB(next_line)) /* Not Null & not out of bounds */
416 if (next_line[0] == 0) 393 if (next_line[0] == 0)
417 if (next_line != cur_line) 394 if (next_line != cur_line)
@@ -458,7 +435,7 @@ static unsigned char* find_prev_line(const unsigned char* cur_line)
458 points from where they wrap when scrolling down. 435 points from where they wrap when scrolling down.
459 If buffer is at top of file, start at top of buffer. */ 436 If buffer is at top of file, start at top of buffer. */
460 437
461 if ((line_mode == JOIN) || (line_mode == REFLOW)) 438 if ((prefs.line_mode == JOIN) || (prefs.line_mode == REFLOW))
462 prev_line = p = NULL; 439 prev_line = p = NULL;
463 else 440 else
464 prev_line = p = find_last_feed(buffer, cur_line-buffer-1); 441 prev_line = p = find_last_feed(buffer, cur_line-buffer-1);
@@ -537,7 +514,7 @@ static int read_and_synch(int direction)
537 rb->memcpy(MID_SECTOR, TOP_SECTOR, SMALL_BLOCK_SIZE); 514 rb->memcpy(MID_SECTOR, TOP_SECTOR, SMALL_BLOCK_SIZE);
538 } 515 }
539 else /* down */ { 516 else /* down */ {
540 if (view_mode == WIDE) { 517 if (prefs.view_mode == WIDE) {
541 /* WIDE mode needs more buffer so we have to read smaller blocks */ 518 /* WIDE mode needs more buffer so we have to read smaller blocks */
542 move_size = SMALL_BLOCK_SIZE; 519 move_size = SMALL_BLOCK_SIZE;
543 offset = LARGE_BLOCK_SIZE; 520 offset = LARGE_BLOCK_SIZE;
@@ -573,6 +550,12 @@ static void viewer_scroll_up(void)
573 screen_top_ptr = p; 550 screen_top_ptr = p;
574} 551}
575 552
553static void viewer_scroll_down(void)
554{
555 if (next_screen_ptr != NULL)
556 screen_top_ptr = next_line_ptr;
557}
558
576#ifdef HAVE_LCD_BITMAP 559#ifdef HAVE_LCD_BITMAP
577static void viewer_scrollbar(void) { 560static void viewer_scrollbar(void) {
578 int w, h, items, min_shown, max_shown; 561 int w, h, items, min_shown, max_shown;
@@ -586,7 +569,7 @@ static void viewer_scrollbar(void) {
586 else 569 else
587 max_shown = min_shown + (next_screen_ptr - screen_top_ptr); 570 max_shown = min_shown + (next_screen_ptr - screen_top_ptr);
588 571
589 rb->scrollbar(0, 0, w-1, LCD_HEIGHT, items, min_shown, max_shown, VERTICAL); 572 rb->scrollbar(0, 0, w-2, LCD_HEIGHT, items, min_shown, max_shown, VERTICAL);
590} 573}
591#endif 574#endif
592 575
@@ -603,11 +586,10 @@ static void viewer_draw(int col)
603 int len; 586 int len;
604 unsigned char *endptr; 587 unsigned char *endptr;
605 588
606
607 /* If col==-1 do all calculations but don't display */ 589 /* If col==-1 do all calculations but don't display */
608 if (col != -1) { 590 if (col != -1) {
609#ifdef HAVE_LCD_BITMAP 591#ifdef HAVE_LCD_BITMAP
610 left_col = need_scrollbar? 1:0; 592 left_col = prefs.need_scrollbar? 1:0;
611#else 593#else
612 left_col = 0; 594 left_col = 0;
613#endif 595#endif
@@ -653,10 +635,10 @@ static void viewer_draw(int col)
653 } 635 }
654 line_len = line_end - line_begin; 636 line_len = line_end - line_begin;
655 637
656 if (line_mode == JOIN) { 638 if (prefs.line_mode == JOIN) {
657 if (line_begin[0] == 0) { 639 if (line_begin[0] == 0) {
658 line_begin++; 640 line_begin++;
659 if (word_mode == CHOP) 641 if (prefs.word_mode == CHOP)
660 line_end++; 642 line_end++;
661 else 643 else
662 line_len--; 644 line_len--;
@@ -696,10 +678,10 @@ static void viewer_draw(int col)
696 rb->lcd_puts(left_col, i, utf8_buffer); 678 rb->lcd_puts(left_col, i, utf8_buffer);
697 } 679 }
698 } 680 }
699 else if (line_mode == REFLOW) { 681 else if (prefs.line_mode == REFLOW) {
700 if (line_begin[0] == 0) { 682 if (line_begin[0] == 0) {
701 line_begin++; 683 line_begin++;
702 if (word_mode == CHOP) 684 if (prefs.word_mode == CHOP)
703 line_end++; 685 line_end++;
704 else 686 else
705 line_len--; 687 line_len--;
@@ -713,7 +695,7 @@ static void viewer_draw(int col)
713 switch (c) { 695 switch (c) {
714 case ' ': 696 case ' ':
715 case 0: 697 case 0:
716 if ((j==0) && (word_mode==WRAP)) 698 if ((j==0) && (prefs.word_mode==WRAP))
717 /* special case: indent the paragraph, 699 /* special case: indent the paragraph,
718 * don't count spaces */ 700 * don't count spaces */
719 indent_spaces = par_indent_spaces; 701 indent_spaces = par_indent_spaces;
@@ -759,7 +741,7 @@ static void viewer_draw(int col)
759 switch (c) { 741 switch (c) {
760 case ' ': 742 case ' ':
761 case 0: 743 case 0:
762 if (j==0 && word_mode==WRAP) { /* indent paragraph */ 744 if (j==0 && prefs.word_mode==WRAP) { /* indent paragraph */
763 for (j=0; j<par_indent_spaces; j++) 745 for (j=0; j<par_indent_spaces; j++)
764 scratch_buffer[k++] = ' '; 746 scratch_buffer[k++] = ' ';
765 j=0; 747 j=0;
@@ -788,7 +770,7 @@ static void viewer_draw(int col)
788 rb->lcd_puts(left_col, i, utf8_buffer); 770 rb->lcd_puts(left_col, i, utf8_buffer);
789 } 771 }
790 } 772 }
791 else { /* line_mode != JOIN && line_mode != REFLOW */ 773 else { /* prefs.line_mode != JOIN && prefs.line_mode != REFLOW */
792 if (col != -1) 774 if (col != -1)
793 if (line_len > col) { 775 if (line_len > col) {
794 c = line_end[0]; 776 c = line_end[0];
@@ -812,9 +794,9 @@ static void viewer_draw(int col)
812 next_screen_ptr = NULL; 794 next_screen_ptr = NULL;
813 795
814#ifdef HAVE_LCD_BITMAP 796#ifdef HAVE_LCD_BITMAP
815 next_screen_to_draw_ptr = page_mode==OVERLAP? line_begin: next_screen_ptr; 797 next_screen_to_draw_ptr = prefs.page_mode==OVERLAP? line_begin: next_screen_ptr;
816 798
817 if (need_scrollbar) 799 if (prefs.need_scrollbar)
818 viewer_scrollbar(); 800 viewer_scrollbar();
819 801
820 if (col != -1) 802 if (col != -1)
@@ -834,6 +816,7 @@ static void viewer_top(void)
834 fill_buffer(0, buffer, BUFFER_SIZE); 816 fill_buffer(0, buffer, BUFFER_SIZE);
835} 817}
836 818
819#ifdef HAVE_LCD_BITMAP
837static void viewer_bottom(void) 820static void viewer_bottom(void)
838{ 821{
839 /* Read bottom of file into buffer 822 /* Read bottom of file into buffer
@@ -855,13 +838,12 @@ static void viewer_bottom(void)
855 fill_buffer(last_sectors, buffer, BUFFER_SIZE); 838 fill_buffer(last_sectors, buffer, BUFFER_SIZE);
856} 839}
857 840
858#ifdef HAVE_LCD_BITMAP
859static void init_need_scrollbar(void) { 841static void init_need_scrollbar(void) {
860 /* Call viewer_draw in quiet mode to initialize next_screen_ptr, 842 /* Call viewer_draw in quiet mode to initialize next_screen_ptr,
861 and thus ONE_SCREEN_FITS_ALL(), and thus NEED_SCROLLBAR() */ 843 and thus ONE_SCREEN_FITS_ALL(), and thus NEED_SCROLLBAR() */
862 viewer_draw(-1); 844 viewer_draw(-1);
863 need_scrollbar = NEED_SCROLLBAR(); 845 prefs.need_scrollbar = NEED_SCROLLBAR();
864 draw_columns = need_scrollbar? display_columns-glyph_width['o'] : display_columns; 846 draw_columns = prefs.need_scrollbar? display_columns-glyph_width['o'] : display_columns;
865 par_indent_spaces = draw_columns/(5*glyph_width[' ']); 847 par_indent_spaces = draw_columns/(5*glyph_width[' ']);
866} 848}
867#else 849#else
@@ -875,6 +857,7 @@ static bool viewer_init(void)
875 struct font *pf; 857 struct font *pf;
876 858
877 pf = rb->font_get(FONT_UI); 859 pf = rb->font_get(FONT_UI);
860
878 if (pf->width != NULL) 861 if (pf->width != NULL)
879 { /* variable pitch font -- fill structure from font width data */ 862 { /* variable pitch font -- fill structure from font width data */
880 ch = pf->defaultchar - pf->firstchar; 863 ch = pf->defaultchar - pf->firstchar;
@@ -896,18 +879,6 @@ static bool viewer_init(void)
896 par_indent_spaces = 2; 879 par_indent_spaces = 2;
897 rb->memset(glyph_width, 1, 256); 880 rb->memset(glyph_width, 1, 256);
898#endif 881#endif
899 /*********************
900 * (Could re-initialize settings here, if you
901 * wanted viewer to start the same way every time)
902 word_mode = WRAP;
903 line_mode = NORMAL;
904 view_mode = NARROW;
905#ifdef HAVE_LCD_BITMAP
906 page_mode = NO_OVERLAP;
907 scrollbar_mode[NARROW] = SB_OFF;
908 scrollbar_mode[WIDE] = SB_ON;
909#endif
910 **********************/
911 882
912 fd = rb->open(file_name, O_RDONLY); 883 fd = rb->open(file_name, O_RDONLY);
913 if (fd==-1) 884 if (fd==-1)
@@ -924,118 +895,63 @@ static bool viewer_init(void)
924 init file_pos, buffer_end, screen_top_ptr */ 895 init file_pos, buffer_end, screen_top_ptr */
925 viewer_top(); 896 viewer_top();
926 897
927 /* Init need_scrollbar value */ 898 /* Init prefs.need_scrollbar value */
928 init_need_scrollbar(); 899 init_need_scrollbar();
929 900
930 return true; 901 return true;
931} 902}
932 903
933/* in the viewer settings file, the line format is: 904static void viewer_reset_settings(void)
934 * - file name (variable length) 905{
935 * - settings (fixed length strings appended, EOL included) 906 prefs.word_mode = WRAP;
936 */ 907 prefs.line_mode = NORMAL;
937typedef struct { 908 prefs.view_mode = NARROW;
938 char word_mode[2], line_mode[2], view_mode[2]; 909 prefs.scroll_mode = PAGE;
939 char file_pos[11], screen_top_ptr[11];
940#ifdef HAVE_LCD_BITMAP 910#ifdef HAVE_LCD_BITMAP
941 char scrollbar_mode[VIEW_MODES][2], page_mode[2]; 911 prefs.page_mode = NO_OVERLAP;
912 prefs.scrollbar_mode = SB_OFF;
942#endif 913#endif
943 char EOL; 914}
944} viewer_settings_string;
945 915
946static void viewer_load_settings(void) 916static void viewer_load_settings(void) /* same name as global, but not the same file.. */
947{ 917{
948 int settings_fd, file_name_len, req_line_len, line_len; 918 int settings_fd;
949 char line[1024];
950 919
951 settings_fd=rb->open(SETTINGS_FILE, O_RDONLY); 920 settings_fd=rb->open(SETTINGS_FILE, O_RDONLY);
952 if (settings_fd < 0) return; 921 if (settings_fd < 0)
953 922 {
954 file_name_len = rb->strlen(file_name); 923 rb->splash(HZ*2, true, "No Settings File");
955 req_line_len = file_name_len + sizeof(viewer_settings_string); 924 return;
956 while ((line_len = rb->read_line(settings_fd, line, sizeof(line))) > 0) { 925 }
957 if ((line_len == req_line_len) && 926 if (rb->filesize(settings_fd) != sizeof(struct preferences))
958 (rb->strncasecmp(line, file_name, file_name_len) == 0)) { 927 {
959 /* found a match, load stored values */ 928 rb->splash(HZ*2, true, "Settings File Invalid");
960 viewer_settings_string *prefs = (void*) &line[file_name_len]; 929 return;
930 }
961 931
962#ifdef HAVE_LCD_BITMAP 932 rb->read(settings_fd, &prefs, sizeof(struct preferences));
963 /* view mode will be initialized later anyways */ 933 rb->close(settings_fd);
964 for (view_mode=0; view_mode<VIEW_MODES; ++view_mode)
965 scrollbar_mode[view_mode] =
966 rb->atoi(prefs->scrollbar_mode[view_mode]);
967 934
968 page_mode = rb->atoi(prefs->page_mode); 935 init_need_scrollbar();
969#endif
970 936
971 word_mode = rb->atoi(prefs->word_mode); 937 file_pos=0;
972 line_mode = rb->atoi(prefs->line_mode); 938 buffer_end = BUFFER_END(); /* Update whenever file_pos changes */
973 view_mode = rb->atoi(prefs->view_mode);
974
975 init_need_scrollbar();
976 /* the following settings are safety checked
977 * (file may have changed on disk)
978 */
979 file_pos = rb->atoi(prefs->file_pos); /* should be atol() */
980 if (file_pos > file_size) {
981 file_pos = 0;
982 break;
983 }
984 buffer_end = BUFFER_END(); /* Update whenever file_pos changes */
985 939
986 screen_top_ptr = buffer + rb->atoi(prefs->screen_top_ptr); 940 screen_top_ptr = buffer;
987 if (BUFFER_OOB(screen_top_ptr)) { 941 if (BUFFER_OOB(screen_top_ptr)) {
988 screen_top_ptr = buffer; 942 screen_top_ptr = buffer;
989 break;
990 }
991 }
992 } 943 }
993 rb->close(settings_fd);
994 944
995 fill_buffer(file_pos, buffer, BUFFER_SIZE); 945 fill_buffer(file_pos, buffer, BUFFER_SIZE);
996} 946}
997 947
998static void viewer_save_settings(void) 948static void viewer_save_settings(void)/* same name as global, but not the same file.. */
999{ 949{
1000 int settings_fd, file_name_len, req_line_len, line_len; 950 int settings_fd;
1001 char line[1024];
1002 viewer_settings_string prefs;
1003
1004 settings_fd=rb->open(SETTINGS_FILE, O_RDWR | O_CREAT);
1005 DEBUGF("SETTINGS_FILE: %d\n", settings_fd);
1006 if (settings_fd < 0) return;
1007
1008 file_name_len = rb->strlen(file_name);
1009 req_line_len = file_name_len + sizeof(viewer_settings_string);
1010 while ((line_len = rb->read_line(settings_fd, line, sizeof(line))) > 0) {
1011 if ((line_len == req_line_len) &&
1012 (rb->strncasecmp(line, file_name, file_name_len) == 0)) {
1013 /* found a match, reposition file pointer to overwrite this line */
1014 rb->lseek(settings_fd, -line_len, SEEK_CUR);
1015 break;
1016 }
1017 }
1018 951
1019 /* fill structure in order to prevent overwriting with 0s (snprintf 952 settings_fd = rb->creat(SETTINGS_FILE, O_WRONLY); /* create the settings file */
1020 * intentionally overflows so that no terminating NULLs are written
1021 * to disk). */
1022 rb->snprintf(prefs.word_mode, 3, "%2d", word_mode);
1023 rb->snprintf(prefs.line_mode, 3, "%2d", line_mode);
1024 rb->snprintf(prefs.view_mode, 3, "%2d", view_mode);
1025 rb->snprintf(prefs.file_pos, 12, "%11d", file_pos);
1026 rb->snprintf(prefs.screen_top_ptr, 12, "%11d", screen_top_ptr-buffer);
1027#ifdef HAVE_LCD_BITMAP
1028 /* view_mode is not needed anymore */
1029 for (view_mode=0; view_mode<VIEW_MODES; ++view_mode)
1030 rb->snprintf(prefs.scrollbar_mode[view_mode], 3,
1031 "%2d", scrollbar_mode[view_mode]);
1032
1033 rb->snprintf(prefs.page_mode, 3, "%2d", page_mode);
1034#endif
1035 prefs.EOL = '\n';
1036 953
1037 rb->write(settings_fd, file_name, file_name_len); 954 rb->write (settings_fd, &prefs, sizeof(struct preferences));
1038 rb->write(settings_fd, &prefs, sizeof(prefs));
1039 rb->close(settings_fd); 955 rb->close(settings_fd);
1040} 956}
1041 957
@@ -1047,6 +963,7 @@ static void viewer_exit(void *parameter)
1047 rb->close(fd); 963 rb->close(fd);
1048} 964}
1049 965
966#ifdef HAVE_LCD_BITMAP
1050static int col_limit(int col) 967static int col_limit(int col)
1051{ 968{
1052 if (col < 0) 969 if (col < 0)
@@ -1057,45 +974,155 @@ static int col_limit(int col)
1057 974
1058 return col; 975 return col;
1059} 976}
977#endif
1060 978
979static void change_options_menu(void)
980{
981 int m, result;
982 bool done = false;
983
984 static const struct menu_item items[] = {
985 {"Word Wrap", NULL },
986 {"Line Mode", NULL },
987 {"Wide View", NULL },
988 {"Overlap Pages", NULL },
989 {"Scroll Mode", NULL},
990#ifdef HAVE_LCD_BITMAP
991 {"Show Scrollbar", NULL },
992#endif
993 {"Auto-Scroll Speed", NULL },
994 };
995 static const struct opt_items opt_word_mode[2] = {
996 {"On",NULL},{"Off (Chop Words)",NULL},
997 };
998#ifdef HAVE_LCD_BITMAP
999 static const struct opt_items opt_line_mode[4] = {
1000 {"Normal",NULL},{"Join Lines",NULL},
1001 {"Reflow Lines",NULL},{"Expand Lines",NULL},
1002#else
1003 static const struct opt_items opt_line_mode[3] = {
1004 {"Normal",NULL},{"Join Lines",NULL},
1005 {"Expand Lines",NULL},
1006#endif
1007 };
1008 static const struct opt_items opt_view_mode[2] = {
1009 {"No (Narrow)",NULL},{"Yes",NULL}
1010 };
1011 static const struct opt_items opt_scroll_mode[2] = {
1012 {"Scroll by Page",NULL},{"Scroll by Line",NULL}
1013 };
1014#ifdef HAVE_LCD_BITMAP
1015 static const struct opt_items opt_scrollbar_mode[2] = {
1016 {"Off",NULL},{"On",NULL}
1017 };
1018 static const struct opt_items opt_page_mode[2] = {
1019 {"No",NULL},{"Yes",NULL}
1020 };
1021#endif
1022 static const struct opt_items opt_autoscroll_speed[10] = {
1023 { "1", NULL },{ "2", NULL },{ "3", NULL },{ "4", NULL },{ "5", NULL },
1024 { "6", NULL },{ "7", NULL },{ "8", NULL },{ "9", NULL },{ "10", NULL }
1025 };
1026 m = rb->menu_init(items, sizeof(items) / sizeof(*items),
1027 NULL, NULL, NULL, NULL);
1028
1029 while(!done)
1030 {
1031 result=rb->menu_show(m);
1032 switch (result)
1033 {
1034 case MENU_SELECTED_EXIT:
1035 done = true;
1036 break;
1061 1037
1062bool done=false; 1038 case 0: /* word mode */
1063int col = 0; 1039 rb->set_option("Word Wrap", &prefs.word_mode, INT,
1040 opt_word_mode , 2, NULL);
1041 break;
1042 case 1: /* line mode */
1043 rb->set_option("Line Mode", &prefs.line_mode, INT, opt_line_mode,
1044 sizeof(opt_line_mode) / sizeof(*opt_line_mode), NULL);
1045 break;
1046 case 2: /* view mode */
1047 rb->set_option("Wide View", &prefs.view_mode, INT,
1048 opt_view_mode , 2, NULL);
1049 break;
1050#ifdef HAVE_LCD_BITMAP
1051 case 3:
1052 rb->set_option("Overlap Pages", &prefs.page_mode, INT,
1053 opt_page_mode , 2, NULL);
1054 break;
1055#endif
1056 case 4:
1057 rb->set_option("Scroll Mode", &prefs.scroll_mode, INT,
1058 opt_scroll_mode , 2, NULL);
1059 break;
1060 #ifdef HAVE_LCD_BITMAP
1061 case 5:
1062 rb->set_option("Show Scrollbar", &prefs.scrollbar_mode, INT,
1063 opt_scrollbar_mode , 2, NULL);
1064 /* Show-scrollbar mode for current view-width mode */
1065 if (!(ONE_SCREEN_FITS_ALL())) {
1066 if (prefs.scrollbar_mode == true)
1067 init_need_scrollbar();
1068 }
1069 break;
1070 #endif
1071 case 6:
1072 rb->set_option("Auto-Scroll Speed", &prefs.autoscroll_speed, INT,
1073 opt_autoscroll_speed, sizeof(opt_autoscroll_speed) /
1074 sizeof(*opt_autoscroll_speed), NULL);
1075 break;
1076 } /* switch() */
1077 }
1078 rb->menu_exit(m);
1079#ifdef HAVE_LCD_BITMAP
1080 rb->lcd_setmargins(0,0);
1081#endif
1082}
1064 1083
1065static void show_menu(void) 1084static void show_menu(void)
1066 { 1085{
1067 int m; 1086 int m;
1068 int result; 1087 int result;
1069 static const struct menu_item items[] = { 1088 static const struct menu_item items[] = {
1070 {"Quit", NULL }, 1089 {"Quit", NULL },
1071 {"Show Playback menu", NULL }, 1090 {"Viewer Options", NULL },
1072 {"Return", NULL }, 1091 {"Show Playback Menu", NULL },
1073 }; 1092 {"Return", NULL },
1074 m = rb->menu_init(items, sizeof(items) / sizeof(*items), NULL, NULL, NULL, NULL); 1093 };
1075 result=rb->menu_show(m); 1094
1076 switch (result) 1095 m = rb->menu_init(items, sizeof(items) / sizeof(*items), NULL, NULL, NULL, NULL);
1077 { 1096 result=rb->menu_show(m);
1078 case 0: 1097 switch (result)
1079 viewer_exit(NULL); 1098 {
1080 done = true; 1099 case 0: /* quit */
1081 break; 1100 rb->splash(1, true, "Saving Settings");
1082 case 1: 1101 rb->menu_exit(m);
1083 playback_control(rb); 1102 viewer_exit(NULL);
1084 break; 1103 done = true;
1085 case 2: 1104 break;
1086 rb->menu_exit(m); 1105 case 1: /* change settings */
1087 viewer_draw(col); 1106 change_options_menu();
1088 break; 1107 break;
1089 } 1108 case 2: /* playback control */
1090 viewer_draw(col); 1109 playback_control(rb);
1091 } 1110 break;
1111 case 3: /* return */
1112 break;
1113 }
1114 rb->menu_exit(m);
1115#ifdef HAVE_LCD_BITMAP
1116 rb->lcd_setmargins(0,0);
1117#endif
1118 viewer_draw(col);
1119}
1092 1120
1093enum plugin_status plugin_start(struct plugin_api* api, void* file) 1121enum plugin_status plugin_start(struct plugin_api* api, void* file)
1094{ 1122{
1095 1123 int button, i, ok;
1096 int button; 1124 bool autoscroll = false;
1097 int i; 1125 int old_tick = *rb->current_tick;
1098 int ok;
1099 1126
1100 rb = api; 1127 rb = api;
1101 1128
@@ -1110,177 +1137,97 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file)
1110 return PLUGIN_OK; 1137 return PLUGIN_OK;
1111 } 1138 }
1112 1139
1113 viewer_load_settings(); 1140 viewer_reset_settings(); /* load defaults first */
1141 viewer_load_settings(); /* .. then try to load from disk */
1114 1142
1115 viewer_draw(col); 1143 viewer_draw(col);
1116 1144
1117 while (!done) { 1145 while (!done) {
1118 button = rb->button_get(true);
1119 switch (button) {
1120 case VIEWER_MENU:
1121 show_menu();
1122 break;
1123
1124 case VIEWER_MODE_WRAP:
1125 /* Word-wrap mode: WRAP or CHOP */
1126 if (++word_mode == WORD_MODES)
1127 word_mode = 0;
1128
1129 init_need_scrollbar();
1130 1146
1147 if(autoscroll)
1148 {
1149 if(old_tick <= *rb->current_tick - (110-prefs.autoscroll_speed*10))
1150 {
1151 viewer_scroll_down();
1131 viewer_draw(col); 1152 viewer_draw(col);
1153 old_tick = *rb->current_tick;
1154 }
1155 }
1132 1156
1133 rb->splash(HZ, true, "%s %s", 1157 button = rb->button_get_w_tmo(HZ/10);
1134 word_mode_str[word_mode], 1158 switch (button) {
1135 word_mode_str[WORD_MODES]); 1159 case VIEWER_MENU:
1136 1160 show_menu();
1137 viewer_draw(col);
1138 break; 1161 break;
1139 1162
1140 case VIEWER_MODE_LINE: 1163 case VIEWER_AUTOSCROLL:
1141 /* Line-paragraph mode: NORMAL, JOIN, REFLOW or EXPAND */ 1164 autoscroll = !autoscroll;
1142 if (++line_mode == LINE_MODES)
1143 line_mode = 0;
1144
1145 if (view_mode == WIDE) {
1146 if (line_mode == JOIN)
1147 if (++line_mode == LINE_MODES)
1148 line_mode = 0;
1149 if (line_mode == REFLOW)
1150 if (++line_mode == LINE_MODES)
1151 line_mode = 0;
1152 }
1153
1154 init_need_scrollbar();
1155
1156 viewer_draw(col);
1157
1158 rb->splash(HZ, true, "%s %s",
1159 line_mode_str[line_mode],
1160 line_mode_str[LINE_MODES]);
1161
1162 viewer_draw(col);
1163 break;
1164
1165 case VIEWER_MODE_WIDTH:
1166 /* View-width mode: NARROW or WIDE */
1167 if ((line_mode == JOIN) || (line_mode == REFLOW))
1168 rb->splash(HZ, true, "(no %s %s)",
1169 view_mode_str[WIDE],
1170 line_mode_str[line_mode]);
1171 else
1172 if (++view_mode == VIEW_MODES)
1173 view_mode = 0;
1174
1175 col = 0;
1176
1177 /***** Could do this after change of word-wrap mode
1178 * and after change of view-width mode, to normalize
1179 * view:
1180 if (screen_top_ptr > buffer + BUFFER_SIZE/2) {
1181 screen_top_ptr = find_prev_line(screen_top_ptr);
1182 screen_top_ptr = find_next_line(screen_top_ptr);
1183 }
1184 else {
1185 screen_top_ptr = find_next_line(screen_top_ptr);
1186 screen_top_ptr = find_prev_line(screen_top_ptr);
1187 }
1188 ***********/
1189
1190 init_need_scrollbar();
1191
1192 viewer_draw(col);
1193
1194 rb->splash(HZ, true, "%s %s",
1195 view_mode_str[view_mode],
1196 view_mode_str[VIEW_MODES]);
1197
1198 viewer_draw(col);
1199 break; 1165 break;
1200 1166
1201 case VIEWER_PAGE_UP: 1167 case VIEWER_PAGE_UP:
1202 case VIEWER_PAGE_UP | BUTTON_REPEAT: 1168 case VIEWER_PAGE_UP | BUTTON_REPEAT:
1203 /* Page up */ 1169 if (prefs.scroll_mode == PAGE)
1170 {
1171 /* Page up */
1204#ifdef HAVE_LCD_BITMAP 1172#ifdef HAVE_LCD_BITMAP
1205 for (i = page_mode==OVERLAP? 1:0; i < display_lines; i++) 1173 for (i = prefs.page_mode==OVERLAP? 1:0; i < display_lines; i++)
1206#else 1174#else
1207 for (i = 0; i < display_lines; i++) 1175 for (i = 0; i < display_lines; i++)
1208#endif 1176#endif
1177 viewer_scroll_up();
1178 }
1179 else
1209 viewer_scroll_up(); 1180 viewer_scroll_up();
1210 1181 old_tick = *rb->current_tick;
1211 viewer_draw(col); 1182 viewer_draw(col);
1212 break; 1183 break;
1213 1184
1214 case VIEWER_PAGE_DOWN: 1185 case VIEWER_PAGE_DOWN:
1215 case VIEWER_PAGE_DOWN | BUTTON_REPEAT: 1186 case VIEWER_PAGE_DOWN | BUTTON_REPEAT:
1216 /* Page down */ 1187 if (prefs.scroll_mode == PAGE)
1217 if (next_screen_ptr != NULL) 1188 {
1218 screen_top_ptr = next_screen_to_draw_ptr; 1189 /* Page down */
1219 1190 if (next_screen_ptr != NULL)
1191 screen_top_ptr = next_screen_to_draw_ptr;
1192 }
1193 else
1194 viewer_scroll_down();
1195 old_tick = *rb->current_tick;
1220 viewer_draw(col); 1196 viewer_draw(col);
1221 break; 1197 break;
1222 1198
1199#ifdef VIEWER_SCREEN_LEFT
1223 case VIEWER_SCREEN_LEFT: 1200 case VIEWER_SCREEN_LEFT:
1224 case VIEWER_SCREEN_LEFT | BUTTON_REPEAT: 1201 case VIEWER_SCREEN_LEFT | BUTTON_REPEAT:
1225 if (view_mode == WIDE) { 1202 if (prefs.view_mode == WIDE) {
1226 /* Screen left */ 1203 /* Screen left */
1227 col -= draw_columns/glyph_width['o']; 1204 col -= draw_columns/glyph_width['o'];
1228 col = col_limit(col); 1205 col = col_limit(col);
1229 } 1206 }
1230 else { /* view_mode == NARROW */ 1207 else { /* prefs.view_mode == NARROW */
1231 /* Top of file */ 1208 /* Top of file */
1232 viewer_top(); 1209 viewer_top();
1233 } 1210 }
1234 1211
1235 viewer_draw(col); 1212 viewer_draw(col);
1236 break; 1213 break;
1214#endif
1237 1215
1216#ifdef VIEWER_SCREEN_LEFT
1238 case VIEWER_SCREEN_RIGHT: 1217 case VIEWER_SCREEN_RIGHT:
1239 case VIEWER_SCREEN_RIGHT | BUTTON_REPEAT: 1218 case VIEWER_SCREEN_RIGHT | BUTTON_REPEAT:
1240 if (view_mode == WIDE) { 1219 if (prefs.view_mode == WIDE) {
1241 /* Screen right */ 1220 /* Screen right */
1242 col += draw_columns/glyph_width['o']; 1221 col += draw_columns/glyph_width['o'];
1243 col = col_limit(col); 1222 col = col_limit(col);
1244 } 1223 }
1245 else { /* view_mode == NARROW */ 1224 else { /* prefs.view_mode == NARROW */
1246 /* Bottom of file */ 1225 /* Bottom of file */
1247 viewer_bottom(); 1226 viewer_bottom();
1248 } 1227 }
1249 1228
1250 viewer_draw(col); 1229 viewer_draw(col);
1251 break; 1230 break;
1252
1253#ifdef VIEWER_MODE_PAGE
1254 case VIEWER_MODE_PAGE:
1255 /* Page-overlap mode */
1256 if (++page_mode == PAGE_MODES)
1257 page_mode = 0;
1258
1259 rb->splash(HZ, true, "%s %s",
1260 page_mode_str[page_mode],
1261 page_mode_str[PAGE_MODES]);
1262
1263 viewer_draw(col);
1264 break;
1265#endif
1266#ifdef VIEWER_MODE_SCROLLBAR
1267 case VIEWER_MODE_SCROLLBAR:
1268 /* Show-scrollbar mode for current view-width mode */
1269 if (!(ONE_SCREEN_FITS_ALL())) {
1270 if (++scrollbar_mode[view_mode] == SCROLLBAR_MODES)
1271 scrollbar_mode[view_mode] = 0;
1272
1273 init_need_scrollbar();
1274 viewer_draw(col);
1275
1276 rb->splash(HZ, true, "%s %s (%s %s)",
1277 scrollbar_mode_str[SCROLLBAR_MODES],
1278 scrollbar_mode_str[scrollbar_mode[view_mode]],
1279 view_mode_str[view_mode],
1280 view_mode_str[VIEW_MODES]);
1281 }
1282 viewer_draw(col);
1283 break;
1284#endif 1231#endif
1285 1232
1286#ifdef VIEWER_LINE_UP 1233#ifdef VIEWER_LINE_UP
@@ -1288,6 +1235,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file)
1288 case VIEWER_LINE_UP | BUTTON_REPEAT: 1235 case VIEWER_LINE_UP | BUTTON_REPEAT:
1289 /* Scroll up one line */ 1236 /* Scroll up one line */
1290 viewer_scroll_up(); 1237 viewer_scroll_up();
1238 old_tick = *rb->current_tick;
1291 viewer_draw(col); 1239 viewer_draw(col);
1292 break; 1240 break;
1293 1241
@@ -1296,7 +1244,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file)
1296 /* Scroll down one line */ 1244 /* Scroll down one line */
1297 if (next_screen_ptr != NULL) 1245 if (next_screen_ptr != NULL)
1298 screen_top_ptr = next_line_ptr; 1246 screen_top_ptr = next_line_ptr;
1299 1247 old_tick = *rb->current_tick;
1300 viewer_draw(col); 1248 viewer_draw(col);
1301 break; 1249 break;
1302#endif 1250#endif
@@ -1317,6 +1265,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file)
1317 viewer_draw(col); 1265 viewer_draw(col);
1318 break; 1266 break;
1319#endif 1267#endif
1268 case VIEWER_QUIT:
1269 viewer_exit(NULL);
1270 done = true;
1271 break;
1320 1272
1321 default: 1273 default:
1322 if (rb->default_event_handler_ex(button, viewer_exit, NULL) 1274 if (rb->default_event_handler_ex(button, viewer_exit, NULL)