diff options
author | Daniel Stenberg <daniel@haxx.se> | 2003-07-24 09:47:46 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2003-07-24 09:47:46 +0000 |
commit | df9b04c6eadb08187802eb460e6719dc7157a98b (patch) | |
tree | b95721352d336d6eab2e92854cf9ff71cdce3f53 /apps | |
parent | 9b1b610bd012d2fc8b38b70953c273bed7ec221f (diff) | |
download | rockbox-df9b04c6eadb08187802eb460e6719dc7157a98b.tar.gz rockbox-df9b04c6eadb08187802eb460e6719dc7157a98b.zip |
Garrett Derner's word wrap fix for the text viewer
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3873 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/viewer.c | 970 |
1 files changed, 744 insertions, 226 deletions
diff --git a/apps/plugins/viewer.c b/apps/plugins/viewer.c index f8dc309a6e..61469fb7ff 100644 --- a/apps/plugins/viewer.c +++ b/apps/plugins/viewer.c | |||
@@ -6,9 +6,9 @@ | |||
6 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | 6 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
7 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | 7 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
8 | * \/ \/ \/ \/ \/ | 8 | * \/ \/ \/ \/ \/ |
9 | * $Id$ | ||
10 | * | 9 | * |
11 | * Copyright (C) 2002 Gilles Roux | 10 | * |
11 | * Copyright (C) 2002 Gilles Roux, 2003 Garrett Derner | ||
12 | * | 12 | * |
13 | * All files in this archive are subject to the GNU General Public License. | 13 | * All files in this archive are subject to the GNU General Public License. |
14 | * See the file COPYING in the source tree root for full license agreement. | 14 | * See the file COPYING in the source tree root for full license agreement. |
@@ -19,175 +19,614 @@ | |||
19 | ****************************************************************************/ | 19 | ****************************************************************************/ |
20 | #include "plugin.h" | 20 | #include "plugin.h" |
21 | 21 | ||
22 | #define BUFFER_SIZE 1024 | 22 | #ifdef HAVE_LCD_BITMAP |
23 | #define OUTSIDE_BUFFER -10 | 23 | #include "recorder/widgets.h" |
24 | #define OUTSIDE_FILE -11 | 24 | #endif |
25 | |||
26 | static int fd; | ||
27 | static int file_size; | ||
28 | 25 | ||
29 | static char buffer[BUFFER_SIZE+1]; | 26 | #include <ctype.h> |
30 | static int buffer_pos; /* Position of the buffer in the file */ | 27 | #include <ctype.c> |
31 | 28 | ||
32 | static char display_lines; /* number of lines on the display */ | 29 | #if PLUGIN_API_VERSION < 3 |
33 | static char display_columns; /* number of columns on the display */ | 30 | #error Scrollbar function requires PLUGIN_API_VERSION 3 at least |
34 | static int begin_line; /* Index of the first line displayed on the lcd */ | 31 | #endif |
35 | static int end_line; /* Index of the last line displayed on the lcd */ | ||
36 | static int begin_line_pos; /* Position of the first_line in the bufffer */ | ||
37 | static int end_line_pos; /* Position of the last_line in the buffer */ | ||
38 | static struct plugin_api* rb; | ||
39 | 32 | ||
40 | /* | 33 | #define WRAP_TRIM 44 /* Max number of spaces to trim (arbitrary) */ |
41 | * Known issue: The caching algorithm will fail (display incoherent data) if | 34 | #define MAX_COLUMNS 64 /* Max displayable string len (over-estimate) */ |
42 | * the total space of the lines that are displayed on the screen exceeds the | 35 | #define MAX_WIDTH 910 /* Max line length in WIDE mode */ |
43 | * buffer size (only happens with very long lines). | 36 | #define READ_PREV_ZONE 910 /* Arbitrary number less than SMALL_BLOCK_SIZE */ |
44 | */ | 37 | #define SMALL_BLOCK_SIZE 0x1000 /* 4k: Smallest file chunk we will read */ |
38 | #define LARGE_BLOCK_SIZE 0x2000 /* 8k: Preferable size of file chunk to read */ | ||
39 | #define BUFFER_SIZE 0x3000 /* 12k: Mem reserved for buffered file data */ | ||
40 | #define TOP_SECTOR buffer | ||
41 | #define MID_SECTOR (buffer + SMALL_BLOCK_SIZE) | ||
42 | #define BOTTOM_SECTOR (buffer + 2*(SMALL_BLOCK_SIZE)) | ||
43 | |||
44 | /* Out-Of-Bounds test for any pointer to data in the buffer */ | ||
45 | #define BUFFER_OOB(p) ((p) < buffer || (p) >= buffer_end) | ||
46 | |||
47 | /* Does the buffer contain the beginning of the file? */ | ||
48 | #define BUFFER_BOF() (file_pos==0) | ||
49 | |||
50 | /* Does the buffer contain the end of the file? */ | ||
51 | #define BUFFER_EOF() (file_size-file_pos <= BUFFER_SIZE) | ||
52 | |||
53 | /* Formula for the endpoint address outside of buffer data */ | ||
54 | #define BUFFER_END() \ | ||
55 | ((BUFFER_EOF()) ? (file_size-file_pos+buffer) : (buffer+BUFFER_SIZE)) | ||
56 | |||
57 | /* Is the entire file being shown in one screen? */ | ||
58 | #define ONE_SCREEN_FITS_ALL() \ | ||
59 | (next_screen_ptr==NULL && screen_top_ptr==buffer && BUFFER_BOF()) | ||
60 | |||
61 | /* Is a scrollbar called for on the current screen? */ | ||
62 | #define NEED_SCROLLBAR() ((!(ONE_SCREEN_FITS_ALL())) && \ | ||
63 | (view_mode==WIDE? scrollbar_mode[WIDE]==SB_ON: scrollbar_mode[NARROW]==SB_ON)) | ||
64 | |||
65 | enum { | ||
66 | WRAP=0, | ||
67 | CHOP, | ||
68 | WORD_MODES | ||
69 | } word_mode = 0; | ||
70 | static unsigned char *word_mode_str[] = {"wrap", "chop", "words"}; | ||
71 | |||
72 | enum { | ||
73 | NORMAL=0, | ||
74 | JOIN, | ||
75 | EXPAND, | ||
76 | LINE_MODES | ||
77 | } line_mode = 0; | ||
78 | static unsigned char *line_mode_str[] = {"normal", "join", "expand", "lines"}; | ||
79 | |||
80 | enum { | ||
81 | NARROW=0, | ||
82 | WIDE, | ||
83 | VIEW_MODES | ||
84 | } view_mode = 0; | ||
85 | static unsigned char *view_mode_str[] = {"narrow", "wide", "view"}; | ||
45 | 86 | ||
46 | static void display_line_count(void) | ||
47 | { | ||
48 | #ifdef HAVE_LCD_BITMAP | 87 | #ifdef HAVE_LCD_BITMAP |
49 | int w,h; | 88 | enum { |
50 | rb->lcd_getstringsize("M", &w, &h); | 89 | SB_OFF=0, |
51 | display_lines = LCD_HEIGHT / h; | 90 | SB_ON, |
52 | display_columns = LCD_WIDTH / w; | 91 | SCROLLBAR_MODES |
53 | #else | 92 | } scrollbar_mode[VIEW_MODES] = {SB_OFF, SB_ON}; |
54 | display_lines = 2; | 93 | static unsigned char *scrollbar_mode_str[] = {"off", "on", "scrollbar"}; |
55 | display_columns = 11; | 94 | static bool need_scrollbar; |
95 | enum { | ||
96 | NO_OVERLAP=0, | ||
97 | OVERLAP, | ||
98 | PAGE_MODES | ||
99 | } page_mode = 0; | ||
100 | static unsigned char *page_mode_str[] = {"don't overlap", "overlap", "pages"}; | ||
56 | #endif | 101 | #endif |
57 | } | ||
58 | 102 | ||
59 | static int find_next_line(int pos) | 103 | static unsigned char buffer[BUFFER_SIZE + 1]; |
104 | static unsigned char line_break[] = {0,0x20,'-',9,0xB,0xC}; | ||
105 | static int display_columns; /* number of columns on the display */ | ||
106 | static int display_lines; /* number of lines on the display */ | ||
107 | static int fd; | ||
108 | static long file_size; | ||
109 | static bool mac_text; | ||
110 | static long file_pos; /* Position of the top of the buffer in the file */ | ||
111 | static unsigned char *buffer_end; /*Set to BUFFER_END() when file_pos changes*/ | ||
112 | static int max_line_len; | ||
113 | static unsigned char *screen_top_ptr; | ||
114 | static unsigned char *next_screen_ptr; | ||
115 | static unsigned char *next_screen_to_draw_ptr; | ||
116 | static unsigned char *next_line_ptr; | ||
117 | static struct plugin_api* rb; | ||
118 | |||
119 | static unsigned char* find_first_feed(const unsigned char* p, int size) | ||
60 | { | 120 | { |
61 | int i; | 121 | int i; |
62 | 122 | ||
63 | if (pos==OUTSIDE_BUFFER || pos==OUTSIDE_FILE) | 123 | for (i=0; i < size; i++) |
64 | return pos; | 124 | if (p[i] == 0) |
125 | return (unsigned char*) p+i; | ||
65 | 126 | ||
66 | i = pos; | 127 | return NULL; |
67 | if (buffer_pos+i>=file_size) { | ||
68 | return OUTSIDE_FILE; | ||
69 | } | ||
70 | while (1) { | ||
71 | i++; | ||
72 | if (buffer_pos+i==file_size) { | ||
73 | return i; | ||
74 | } | ||
75 | if (i>=BUFFER_SIZE) { | ||
76 | return OUTSIDE_BUFFER; | ||
77 | } | ||
78 | if (buffer[i]==0) { | ||
79 | return i; | ||
80 | } | ||
81 | } | ||
82 | } | 128 | } |
83 | 129 | ||
84 | static int find_prev_line(int pos) | 130 | static unsigned char* find_last_feed(const unsigned char* p, int size) |
85 | { | 131 | { |
86 | int i; | 132 | int i; |
87 | 133 | ||
88 | if (pos==OUTSIDE_BUFFER || pos==OUTSIDE_FILE) | 134 | for (i=size-1; i>=0; i--) |
89 | return pos; | 135 | if (p[i] == 0) |
136 | return (unsigned char*) p+i; | ||
137 | |||
138 | return NULL; | ||
139 | } | ||
140 | |||
141 | static unsigned char* find_last_space(const unsigned char* p, int size) | ||
142 | { | ||
143 | int i, j, k; | ||
144 | |||
145 | k = line_mode==JOIN? 0:1; | ||
146 | |||
147 | for (i=size-1; i>=0; i--) | ||
148 | for (j=k; j < (int) sizeof(line_break); j++) | ||
149 | if (p[i] == line_break[j]) | ||
150 | return (unsigned char*) p+i; | ||
151 | |||
152 | return NULL; | ||
153 | } | ||
90 | 154 | ||
91 | i = pos; | 155 | static unsigned char* find_next_line(const unsigned char* cur_line) |
92 | if (buffer_pos+i<0) { | 156 | { |
93 | return OUTSIDE_FILE; | 157 | const unsigned char *next_line = NULL; |
158 | int size, i, j, k, chop_len, search_len, spaces, newlines, draw_columns; | ||
159 | unsigned char c; | ||
160 | |||
161 | if BUFFER_OOB(cur_line) | ||
162 | return NULL; | ||
163 | |||
164 | #ifdef HAVE_LCD_BITMAP | ||
165 | draw_columns = need_scrollbar? display_columns-1: display_columns; | ||
166 | #else | ||
167 | draw_columns = display_columns; | ||
168 | #endif | ||
169 | |||
170 | if (view_mode == WIDE) { | ||
171 | search_len = chop_len = MAX_WIDTH; | ||
94 | } | 172 | } |
95 | while (1) { | 173 | else { /* view_mode == NARROW */ |
96 | i--; | 174 | chop_len = draw_columns; |
97 | if (buffer_pos+i<0) { | 175 | search_len = chop_len + 1; |
98 | return i; | 176 | } |
99 | } | 177 | |
100 | if (i<0) { | 178 | size = BUFFER_OOB(cur_line+search_len) ? buffer_end-cur_line : search_len; |
101 | return OUTSIDE_BUFFER; | 179 | |
102 | } | 180 | if (line_mode == JOIN) { |
103 | if (buffer[i]==0) { | 181 | /* Need to scan ahead and possibly increase search_len and size, |
104 | return i; | 182 | or possibly set next_line at second hard return in a row. */ |
183 | next_line = NULL; | ||
184 | for (j=k=spaces=newlines=0; j < size; j++) { | ||
185 | if (k == MAX_COLUMNS) | ||
186 | break; | ||
187 | |||
188 | c = cur_line[j]; | ||
189 | switch (c) { | ||
190 | case ' ': | ||
191 | spaces++; | ||
192 | break; | ||
193 | |||
194 | case 0: | ||
195 | if (newlines > 0) { | ||
196 | size = j; | ||
197 | next_line = cur_line + size - spaces - 1; | ||
198 | if (next_line != cur_line) | ||
199 | return (unsigned char*) next_line; | ||
200 | break; | ||
201 | } | ||
202 | newlines++; | ||
203 | size += spaces; | ||
204 | if (BUFFER_OOB(cur_line+size) || size > 2*search_len) | ||
205 | return NULL; | ||
206 | |||
207 | search_len = size; | ||
208 | spaces = 0; | ||
209 | k++; | ||
210 | break; | ||
211 | |||
212 | default: | ||
213 | newlines = 0; | ||
214 | while (spaces) { | ||
215 | spaces--; | ||
216 | k++; | ||
217 | if (k == MAX_COLUMNS - 1) | ||
218 | break; | ||
219 | } | ||
220 | k++; | ||
221 | break; | ||
222 | } | ||
105 | } | 223 | } |
106 | } | 224 | } |
225 | else { | ||
226 | /* find first hard return */ | ||
227 | next_line = find_first_feed(cur_line, size); | ||
228 | } | ||
229 | |||
230 | if (next_line == NULL) | ||
231 | if (size == search_len) { | ||
232 | if (word_mode == WRAP) /* Find last space */ | ||
233 | next_line = find_last_space(cur_line, size); | ||
234 | |||
235 | if (next_line == NULL) | ||
236 | next_line = cur_line + chop_len; | ||
237 | else | ||
238 | if (word_mode == WRAP) | ||
239 | for (i=0; | ||
240 | i<WRAP_TRIM && isspace(next_line[0]) && !BUFFER_OOB(next_line); | ||
241 | i++) | ||
242 | next_line++; | ||
243 | } | ||
244 | |||
245 | if (line_mode == EXPAND) | ||
246 | if (!BUFFER_OOB(next_line)) /* Not Null & not out of bounds */ | ||
247 | if (next_line[0] == 0) | ||
248 | if (next_line != cur_line) | ||
249 | return (unsigned char*) next_line; | ||
250 | |||
251 | /* If next_line is pointing to a zero, increment it; i.e., | ||
252 | leave the terminator at the end of cur_line. If pointing | ||
253 | to a hyphen, increment only if there is room to display | ||
254 | the hyphen on current line (won't apply in WIDE mode, | ||
255 | since it's guarenteed there won't be room). */ | ||
256 | if (!BUFFER_OOB(next_line)) /* Not Null & not out of bounds */ | ||
257 | if (next_line[0] == 0 || | ||
258 | (next_line[0] == '-' && next_line-cur_line < draw_columns)) | ||
259 | next_line++; | ||
260 | |||
261 | if (BUFFER_OOB(next_line)) | ||
262 | return NULL; | ||
263 | |||
264 | return (unsigned char*) next_line; | ||
107 | } | 265 | } |
108 | 266 | ||
109 | static void viewer_draw(int col) | 267 | static unsigned char* find_prev_line(const unsigned char* cur_line) |
110 | { | 268 | { |
111 | int i, j; | 269 | const unsigned char *prev_line = NULL; |
112 | char* str; | 270 | const unsigned char *p; |
113 | int line_pos; | 271 | |
114 | 272 | if BUFFER_OOB(cur_line) | |
115 | rb->lcd_clear_display(); | 273 | return NULL; |
116 | 274 | ||
117 | line_pos = begin_line_pos; | 275 | /* To wrap consistently at the same places, we must |
118 | 276 | start with a known hard return, then work downwards. | |
119 | for (i=0; i <= end_line - begin_line; i++) { | 277 | We can either search backwards for a hard return, |
120 | if (line_pos == OUTSIDE_BUFFER || | 278 | or simply start wrapping downwards from top of buffer. |
121 | line_pos == OUTSIDE_FILE) | 279 | If current line is not near top of buffer, this is |
122 | break; | 280 | a file with long lines (paragraphs). We would need to |
123 | str = buffer + line_pos + 1; | 281 | read earlier sectors before we could decide how to |
124 | for (j=0; j<col && *str!=0; ++j) | 282 | properly wrap the lines above the current line, but |
125 | str++; | 283 | it probably is not worth the disk access. Instead, |
126 | rb->lcd_puts(0, i, str); | 284 | start with top of buffer and wrap down from there. |
127 | line_pos = find_next_line(line_pos); | 285 | This may result in some lines wrapping at different |
286 | points from where they wrap when scrolling down. | ||
287 | If buffer is at top of file, start at top of buffer. */ | ||
288 | |||
289 | if (line_mode == JOIN) | ||
290 | prev_line = p = NULL; | ||
291 | else | ||
292 | prev_line = p = find_last_feed(buffer, cur_line-buffer-1); | ||
293 | /* Null means no line feeds in buffer above current line. */ | ||
294 | |||
295 | if (prev_line == NULL) | ||
296 | if (BUFFER_BOF() || cur_line - buffer > READ_PREV_ZONE) | ||
297 | prev_line = p = buffer; | ||
298 | /* (else return NULL and read previous block) */ | ||
299 | |||
300 | /* Wrap downwards until too far, then use the one before. */ | ||
301 | while (p < cur_line && p != NULL) { | ||
302 | prev_line = p; | ||
303 | p = find_next_line(prev_line); | ||
128 | } | 304 | } |
129 | #ifdef HAVE_LCD_BITMAP | 305 | |
130 | rb->lcd_update(); | 306 | if (BUFFER_OOB(prev_line)) |
131 | #endif | 307 | return NULL; |
308 | |||
309 | return (unsigned char*) prev_line; | ||
132 | } | 310 | } |
133 | 311 | ||
134 | static void fill_buffer(int pos) | 312 | static void fill_buffer(long pos, unsigned char* buf, unsigned size) |
135 | { | 313 | { |
136 | int i; | 314 | /* Read from file and preprocess the data */ |
137 | int numread; | 315 | /* To minimize disk access, always read on sector boundaries */ |
138 | 316 | unsigned numread, i; | |
139 | if (pos>=file_size-BUFFER_SIZE) | 317 | bool found_CR = false; |
140 | pos = file_size-BUFFER_SIZE; | ||
141 | if (pos<0) | ||
142 | pos = 0; | ||
143 | 318 | ||
144 | rb->lseek(fd, pos, SEEK_SET); | 319 | rb->lseek(fd, pos, SEEK_SET); |
145 | numread = rb->read(fd, buffer, BUFFER_SIZE); | 320 | numread = rb->read(fd, buf, size); |
321 | while (rb->button_get(false)); /* clear button queue */ | ||
146 | 322 | ||
147 | begin_line_pos -= pos - buffer_pos; | 323 | for(i = 0; i < numread; i++) { |
148 | end_line_pos -= pos - buffer_pos; | 324 | switch(buf[i]) { |
149 | buffer_pos = pos; | ||
150 | |||
151 | buffer[numread] = 0; | ||
152 | for(i=0;i<numread;i++) { | ||
153 | switch(buffer[i]) { | ||
154 | case '\r': | 325 | case '\r': |
155 | buffer[i] = ' '; | 326 | if (mac_text) { |
327 | buf[i] = 0; | ||
328 | } | ||
329 | else { | ||
330 | buf[i] = ' '; | ||
331 | found_CR = true; | ||
332 | } | ||
156 | break; | 333 | break; |
334 | |||
157 | case '\n': | 335 | case '\n': |
158 | buffer[i] = 0; | 336 | buf[i] = 0; |
337 | found_CR = false; | ||
159 | break; | 338 | break; |
339 | |||
340 | case 0: /* No break between case 0 and default, intentionally */ | ||
341 | buf[i] = ' '; | ||
160 | default: | 342 | default: |
343 | if (found_CR) { | ||
344 | buf[i - 1] = 0; | ||
345 | found_CR = false; | ||
346 | mac_text = true; | ||
347 | } | ||
161 | break; | 348 | break; |
162 | } | 349 | } |
163 | } | 350 | } |
164 | } | 351 | } |
165 | 352 | ||
353 | static int read_and_synch(int direction) | ||
354 | { | ||
355 | /* Read next (or prev) block, and reposition global pointers. */ | ||
356 | /* direction: 1 for down (i.e., further into file), -1 for up */ | ||
357 | int move_size, move_vector, offset; | ||
358 | unsigned char *fill_buf; | ||
359 | |||
360 | if (direction == -1) /* up */ { | ||
361 | move_size = SMALL_BLOCK_SIZE; | ||
362 | offset = 0; | ||
363 | fill_buf = TOP_SECTOR; | ||
364 | rb->memcpy(BOTTOM_SECTOR, MID_SECTOR, SMALL_BLOCK_SIZE); | ||
365 | rb->memcpy(MID_SECTOR, TOP_SECTOR, SMALL_BLOCK_SIZE); | ||
366 | } | ||
367 | else /* down */ { | ||
368 | if (view_mode == WIDE) { | ||
369 | /* WIDE mode needs more buffer so we have to read smaller blocks */ | ||
370 | move_size = SMALL_BLOCK_SIZE; | ||
371 | offset = LARGE_BLOCK_SIZE; | ||
372 | fill_buf = BOTTOM_SECTOR; | ||
373 | rb->memcpy(TOP_SECTOR, MID_SECTOR, SMALL_BLOCK_SIZE); | ||
374 | rb->memcpy(MID_SECTOR, BOTTOM_SECTOR, SMALL_BLOCK_SIZE); | ||
375 | } | ||
376 | else { | ||
377 | move_size = LARGE_BLOCK_SIZE; | ||
378 | offset = SMALL_BLOCK_SIZE; | ||
379 | fill_buf = MID_SECTOR; | ||
380 | rb->memcpy(TOP_SECTOR, BOTTOM_SECTOR, SMALL_BLOCK_SIZE); | ||
381 | } | ||
382 | } | ||
383 | move_vector = direction * move_size; | ||
384 | screen_top_ptr -= move_vector; | ||
385 | file_pos += move_vector; | ||
386 | buffer_end = BUFFER_END(); /* Update whenever file_pos changes */ | ||
387 | fill_buffer(file_pos + offset, fill_buf, move_size); | ||
388 | return move_vector; | ||
389 | } | ||
390 | |||
391 | static void viewer_scroll_up(void) | ||
392 | { | ||
393 | unsigned char *p; | ||
394 | |||
395 | p = find_prev_line(screen_top_ptr); | ||
396 | if (p == NULL && !BUFFER_BOF()) { | ||
397 | read_and_synch(-1); | ||
398 | p = find_prev_line(screen_top_ptr); | ||
399 | } | ||
400 | if (p != NULL) | ||
401 | screen_top_ptr = p; | ||
402 | } | ||
403 | |||
404 | #ifdef HAVE_LCD_BITMAP | ||
405 | static void viewer_scrollbar(void) { | ||
406 | int w, h, items, min_shown, max_shown; | ||
407 | |||
408 | rb->lcd_getstringsize("o", &w, &h); | ||
409 | items = (int) file_size; /* (SH1 int is same as long) */ | ||
410 | min_shown = (int) file_pos + (screen_top_ptr - buffer); | ||
411 | |||
412 | if (next_screen_ptr == NULL) | ||
413 | max_shown = items; | ||
414 | else | ||
415 | max_shown = min_shown + (next_screen_ptr - screen_top_ptr); | ||
416 | |||
417 | rb->scrollbar(0, 0, w-1, LCD_HEIGHT, items, min_shown, max_shown, VERTICAL); | ||
418 | } | ||
419 | #endif | ||
420 | |||
421 | static void viewer_draw(int col) | ||
422 | { | ||
423 | int i, j, k, line_len, resynch_move, spaces, left_col=0; | ||
424 | unsigned char *line_begin; | ||
425 | unsigned char *line_end; | ||
426 | unsigned char c; | ||
427 | unsigned char scratch_buffer[MAX_COLUMNS + 1]; | ||
428 | |||
429 | /* If col==-1 do all calculations but don't display */ | ||
430 | if (col != -1) { | ||
431 | #ifdef HAVE_LCD_BITMAP | ||
432 | left_col = need_scrollbar? 1:0; | ||
433 | #else | ||
434 | left_col = 0; | ||
435 | #endif | ||
436 | rb->lcd_clear_display(); | ||
437 | } | ||
438 | max_line_len = 0; | ||
439 | line_begin = line_end = screen_top_ptr; | ||
440 | |||
441 | for (i = 0; i < display_lines; i++) { | ||
442 | if (BUFFER_OOB(line_end)) | ||
443 | break; /* Happens after display last line at BUFFER_EOF() */ | ||
444 | |||
445 | line_begin = line_end; | ||
446 | line_end = find_next_line(line_begin); | ||
447 | |||
448 | if (line_end == NULL) { | ||
449 | if (BUFFER_EOF()) { | ||
450 | if (i < display_lines - 1 && !BUFFER_BOF()) { | ||
451 | if (col != -1) | ||
452 | rb->lcd_clear_display(); | ||
453 | |||
454 | for (; i < display_lines - 1; i++) | ||
455 | viewer_scroll_up(); | ||
456 | |||
457 | line_begin = line_end = screen_top_ptr; | ||
458 | i = -1; | ||
459 | continue; | ||
460 | } | ||
461 | else { | ||
462 | line_end = buffer_end; | ||
463 | } | ||
464 | } | ||
465 | else { | ||
466 | resynch_move = read_and_synch(1); /* Read block & move ptrs */ | ||
467 | line_begin -= resynch_move; | ||
468 | if (i > 0) | ||
469 | next_line_ptr -= resynch_move; | ||
470 | |||
471 | line_end = find_next_line(line_begin); | ||
472 | if (line_end == NULL) /* Should not really happen */ | ||
473 | break; | ||
474 | } | ||
475 | } | ||
476 | line_len = line_end - line_begin; | ||
477 | |||
478 | if (line_mode == JOIN) { | ||
479 | if (line_begin[0] == 0) { | ||
480 | line_begin++; | ||
481 | if (word_mode == CHOP) | ||
482 | line_end++; | ||
483 | } | ||
484 | for (j=k=spaces=0; j < line_len; j++) { | ||
485 | if (k == MAX_COLUMNS) | ||
486 | break; | ||
487 | |||
488 | c = line_begin[j]; | ||
489 | switch (c) { | ||
490 | case ' ': | ||
491 | spaces++; | ||
492 | break; | ||
493 | case 0: | ||
494 | spaces = 0; | ||
495 | scratch_buffer[k++] = ' '; | ||
496 | break; | ||
497 | default: | ||
498 | while (spaces) { | ||
499 | spaces--; | ||
500 | scratch_buffer[k++] = ' '; | ||
501 | if (k == MAX_COLUMNS - 1) | ||
502 | break; | ||
503 | } | ||
504 | scratch_buffer[k++] = c; | ||
505 | break; | ||
506 | } | ||
507 | } | ||
508 | if (col != -1) | ||
509 | if (k > col) { | ||
510 | scratch_buffer[k] = 0; | ||
511 | rb->lcd_puts(left_col, i, scratch_buffer + col); | ||
512 | } | ||
513 | } | ||
514 | else { | ||
515 | if (col != -1) | ||
516 | if (line_len > col) { | ||
517 | c = line_end[0]; | ||
518 | line_end[0] = 0; | ||
519 | rb->lcd_puts(left_col, i, line_begin + col); | ||
520 | line_end[0] = c; | ||
521 | } | ||
522 | } | ||
523 | if (line_len > max_line_len) | ||
524 | max_line_len = line_len; | ||
525 | |||
526 | if (i == 0) | ||
527 | next_line_ptr = line_end; | ||
528 | } | ||
529 | next_screen_ptr = line_end; | ||
530 | if (BUFFER_OOB(next_screen_ptr)) | ||
531 | next_screen_ptr = NULL; | ||
532 | |||
533 | #ifdef HAVE_LCD_BITMAP | ||
534 | next_screen_to_draw_ptr = page_mode==OVERLAP? line_begin: next_screen_ptr; | ||
535 | |||
536 | if (need_scrollbar) | ||
537 | viewer_scrollbar(); | ||
538 | |||
539 | if (col != -1) | ||
540 | rb->lcd_update(); | ||
541 | #else | ||
542 | next_screen_to_draw_ptr = next_screen_ptr; | ||
543 | #endif | ||
544 | } | ||
545 | |||
546 | static void viewer_top(void) | ||
547 | { | ||
548 | /* Read top of file into buffer | ||
549 | and point screen pointer to top */ | ||
550 | file_pos = 0; | ||
551 | buffer_end = BUFFER_END(); /* Update whenever file_pos changes */ | ||
552 | screen_top_ptr = buffer; | ||
553 | fill_buffer(0, buffer, BUFFER_SIZE); | ||
554 | } | ||
555 | |||
556 | static void viewer_bottom(void) | ||
557 | { | ||
558 | /* Read bottom of file into buffer | ||
559 | and point screen pointer to bottom */ | ||
560 | long last_sectors; | ||
561 | |||
562 | if (file_size > BUFFER_SIZE) { | ||
563 | /* Find last buffer in file, round up to next sector boundary */ | ||
564 | last_sectors = file_size - BUFFER_SIZE + SMALL_BLOCK_SIZE; | ||
565 | last_sectors /= SMALL_BLOCK_SIZE; | ||
566 | last_sectors *= SMALL_BLOCK_SIZE; | ||
567 | } | ||
568 | else { | ||
569 | last_sectors = 0; | ||
570 | } | ||
571 | file_pos = last_sectors; | ||
572 | buffer_end = BUFFER_END(); /* Update whenever file_pos changes */ | ||
573 | screen_top_ptr = buffer_end-1; | ||
574 | fill_buffer(last_sectors, buffer, BUFFER_SIZE); | ||
575 | } | ||
576 | |||
577 | #ifdef HAVE_LCD_BITMAP | ||
578 | static void init_need_scrollbar(void) { | ||
579 | /* Call viewer_draw in quiet mode to initialize next_screen_ptr, | ||
580 | and thus ONE_SCREEN_FITS_ALL(), and thus NEED_SCROLLBAR() */ | ||
581 | viewer_draw(-1); | ||
582 | need_scrollbar = NEED_SCROLLBAR(); | ||
583 | } | ||
584 | #endif | ||
585 | |||
166 | static bool viewer_init(char* file) | 586 | static bool viewer_init(char* file) |
167 | { | 587 | { |
168 | int i; | 588 | #ifdef HAVE_LCD_BITMAP |
169 | int ret; | 589 | int w,h; |
590 | |||
591 | rb->lcd_getstringsize("o", &w, &h); | ||
592 | display_lines = LCD_HEIGHT / h; | ||
593 | display_columns = LCD_WIDTH / w; | ||
594 | #else | ||
595 | display_lines = 2; | ||
596 | display_columns = 11; | ||
597 | #endif | ||
598 | /********************* | ||
599 | * (Could re-initialize settings here, if you | ||
600 | * wanted viewer to start the same way every time) | ||
601 | word_mode = WRAP; | ||
602 | line_mode = NORMAL; | ||
603 | view_mode = NARROW; | ||
604 | #ifdef HAVE_LCD_BITMAP | ||
605 | page_mode = NO_OVERLAP; | ||
606 | scrollbar_mode[NARROW] = SB_OFF; | ||
607 | scrollbar_mode[WIDE] = SB_ON; | ||
608 | #endif | ||
609 | **********************/ | ||
170 | 610 | ||
171 | fd = rb->open(file, O_RDONLY); | 611 | fd = rb->open(file, O_RDONLY); |
172 | if (fd==-1) | 612 | if (fd==-1) |
173 | return false; | 613 | return false; |
174 | 614 | ||
175 | file_size = rb->lseek(fd, 0, SEEK_END); | 615 | file_size = rb->filesize(fd); |
176 | 616 | if (file_size==-1) | |
177 | buffer_pos = 0; | 617 | return false; |
178 | begin_line = 0; | 618 | |
179 | begin_line_pos = -1; | 619 | /* Init mac_text value used in processing buffer */ |
180 | end_line = -1; | 620 | mac_text = false; |
181 | end_line_pos = -1; | 621 | |
182 | fill_buffer(0); | 622 | /* Read top of file into buffer; |
183 | display_line_count(); | 623 | init file_pos, buffer_end, screen_top_ptr */ |
184 | for (i=0; i<display_lines; ++i) { | 624 | viewer_top(); |
185 | ret = find_next_line(end_line_pos); | 625 | |
186 | if (ret!=OUTSIDE_FILE && ret!=OUTSIDE_BUFFER) { | 626 | #ifdef HAVE_LCD_BITMAP |
187 | end_line_pos = ret; | 627 | /* Init need_scrollbar value */ |
188 | end_line++; | 628 | init_need_scrollbar(); |
189 | } | 629 | #endif |
190 | } | ||
191 | 630 | ||
192 | return true; | 631 | return true; |
193 | } | 632 | } |
@@ -197,130 +636,101 @@ static void viewer_exit(void) | |||
197 | rb->close(fd); | 636 | rb->close(fd); |
198 | } | 637 | } |
199 | 638 | ||
200 | static void viewer_scroll_down(void) | 639 | static int col_limit(int col) |
201 | { | 640 | { |
202 | int ret; | 641 | if (col < 0) |
203 | 642 | col = 0; | |
204 | ret = find_next_line(end_line_pos); | 643 | else |
205 | switch ( ret ) { | 644 | if (col > max_line_len - 2) |
206 | case OUTSIDE_BUFFER: | 645 | col = max_line_len - 2; |
207 | begin_line_pos = find_next_line(begin_line_pos); | ||
208 | fill_buffer(begin_line_pos+buffer_pos); | ||
209 | end_line_pos = find_next_line(end_line_pos); | ||
210 | break; | ||
211 | |||
212 | case OUTSIDE_FILE: | ||
213 | return; | ||
214 | |||
215 | default: | ||
216 | begin_line_pos = find_next_line(begin_line_pos); | ||
217 | end_line_pos = ret; | ||
218 | break; | ||
219 | } | ||
220 | begin_line++; | ||
221 | end_line++; | ||
222 | } | ||
223 | 646 | ||
224 | static void viewer_scroll_up(void) | 647 | return col; |
225 | { | ||
226 | int ret; | ||
227 | |||
228 | ret = find_prev_line(begin_line_pos); | ||
229 | switch ( ret ) { | ||
230 | case OUTSIDE_BUFFER: | ||
231 | end_line_pos = find_prev_line(end_line_pos); | ||
232 | fill_buffer(buffer_pos+end_line_pos-BUFFER_SIZE); | ||
233 | begin_line_pos = find_prev_line(begin_line_pos); | ||
234 | break; | ||
235 | |||
236 | case OUTSIDE_FILE: | ||
237 | return; | ||
238 | |||
239 | default: | ||
240 | end_line_pos = find_prev_line(end_line_pos); | ||
241 | begin_line_pos = ret; | ||
242 | break; | ||
243 | } | ||
244 | begin_line--; | ||
245 | end_line--; | ||
246 | } | 648 | } |
247 | 649 | ||
248 | static int pagescroll(int col) | 650 | #ifdef HAVE_LCD_BITMAP |
651 | static int viewer_recorder_on_button(int col) | ||
249 | { | 652 | { |
250 | bool exit = false; | 653 | bool exit = false; |
251 | int i; | ||
252 | 654 | ||
253 | while (!exit) { | 655 | while (!exit) { |
254 | switch (rb->button_get(true)) { | 656 | switch (rb->button_get(true)) { |
255 | #ifdef HAVE_RECORDER_KEYPAD | 657 | case BUTTON_ON | BUTTON_F1: |
658 | /* Page-overlap mode */ | ||
659 | if (++page_mode == PAGE_MODES) | ||
660 | page_mode = 0; | ||
661 | |||
662 | rb->splash(HZ, 0, true, "%s %s", | ||
663 | page_mode_str[page_mode], page_mode_str[PAGE_MODES]); | ||
664 | |||
665 | viewer_draw(col); | ||
666 | break; | ||
667 | |||
668 | case BUTTON_ON | BUTTON_F3: | ||
669 | /* Show-scrollbar mode for current view-width mode */ | ||
670 | if (!(ONE_SCREEN_FITS_ALL())) { | ||
671 | if (++scrollbar_mode[view_mode] == SCROLLBAR_MODES) | ||
672 | scrollbar_mode[view_mode] = 0; | ||
673 | |||
674 | init_need_scrollbar(); | ||
675 | viewer_draw(col); | ||
676 | |||
677 | rb->splash(HZ, 0, true, "%s %s (%s %s)", | ||
678 | scrollbar_mode_str[SCROLLBAR_MODES], | ||
679 | scrollbar_mode_str[scrollbar_mode[view_mode]], | ||
680 | view_mode_str[view_mode], view_mode_str[VIEW_MODES]); | ||
681 | } | ||
682 | viewer_draw(col); | ||
683 | break; | ||
684 | |||
256 | case BUTTON_ON | BUTTON_UP: | 685 | case BUTTON_ON | BUTTON_UP: |
257 | case BUTTON_ON | BUTTON_UP | BUTTON_REPEAT: | 686 | case BUTTON_ON | BUTTON_UP | BUTTON_REPEAT: |
258 | #else | 687 | /* Scroll up one line */ |
259 | case BUTTON_ON | BUTTON_LEFT: | 688 | viewer_scroll_up(); |
260 | case BUTTON_ON | BUTTON_LEFT | BUTTON_REPEAT: | 689 | viewer_draw(col); |
261 | #endif | ||
262 | for (i=0; i<display_lines; i++) | ||
263 | viewer_scroll_up(); | ||
264 | break; | 690 | break; |
265 | 691 | ||
266 | #ifdef HAVE_RECORDER_KEYPAD | ||
267 | case BUTTON_ON | BUTTON_DOWN: | 692 | case BUTTON_ON | BUTTON_DOWN: |
268 | case BUTTON_ON | BUTTON_DOWN | BUTTON_REPEAT: | 693 | case BUTTON_ON | BUTTON_DOWN | BUTTON_REPEAT: |
269 | #else | 694 | /* Scroll down one line */ |
270 | case BUTTON_ON | BUTTON_RIGHT: | 695 | if (next_screen_ptr != NULL) |
271 | case BUTTON_ON | BUTTON_RIGHT | BUTTON_REPEAT: | 696 | screen_top_ptr = next_line_ptr; |
272 | #endif | 697 | |
273 | for (i=0; i<display_lines; i++) | 698 | viewer_draw(col); |
274 | viewer_scroll_down(); | ||
275 | break; | 699 | break; |
276 | 700 | ||
277 | #ifdef HAVE_RECORDER_KEYPAD | ||
278 | case BUTTON_ON | BUTTON_LEFT: | 701 | case BUTTON_ON | BUTTON_LEFT: |
279 | case BUTTON_ON | BUTTON_LEFT | BUTTON_REPEAT: | 702 | case BUTTON_ON | BUTTON_LEFT | BUTTON_REPEAT: |
280 | #else | 703 | /* Scroll left one column */ |
281 | case BUTTON_ON | BUTTON_MENU | BUTTON_LEFT: | 704 | col--; |
282 | case BUTTON_ON | BUTTON_MENU | BUTTON_LEFT | BUTTON_REPEAT: | 705 | col = col_limit(col); |
283 | #endif | 706 | viewer_draw(col); |
284 | col -= display_columns; | ||
285 | if (col < 0) | ||
286 | col = 0; | ||
287 | break; | 707 | break; |
288 | 708 | ||
289 | #ifdef HAVE_RECORDER_KEYPAD | ||
290 | case BUTTON_ON | BUTTON_RIGHT: | 709 | case BUTTON_ON | BUTTON_RIGHT: |
291 | case BUTTON_ON | BUTTON_RIGHT | BUTTON_REPEAT: | 710 | case BUTTON_ON | BUTTON_RIGHT | BUTTON_REPEAT: |
292 | #else | 711 | /* Scroll right one column */ |
293 | case BUTTON_ON | BUTTON_MENU | BUTTON_RIGHT: | 712 | col++; |
294 | case BUTTON_ON | BUTTON_MENU | BUTTON_RIGHT | BUTTON_REPEAT: | 713 | col = col_limit(col); |
295 | #endif | 714 | viewer_draw(col); |
296 | col += display_columns; | ||
297 | break; | 715 | break; |
298 | 716 | ||
299 | case BUTTON_ON | BUTTON_REL: | 717 | case BUTTON_ON | BUTTON_REL: |
300 | #ifdef HAVE_RECORDER_KEYPAD | ||
301 | case BUTTON_ON | BUTTON_DOWN | BUTTON_REL: | 718 | case BUTTON_ON | BUTTON_DOWN | BUTTON_REL: |
302 | case BUTTON_ON | BUTTON_UP | BUTTON_REL: | 719 | case BUTTON_ON | BUTTON_UP | BUTTON_REL: |
303 | #else | 720 | /* Drop out of this loop (when ON btn released) */ |
304 | case BUTTON_ON | BUTTON_RIGHT | BUTTON_REL: | ||
305 | case BUTTON_ON | BUTTON_LEFT | BUTTON_REL: | ||
306 | case BUTTON_ON | BUTTON_MENU | BUTTON_RIGHT | BUTTON_REL: | ||
307 | case BUTTON_ON | BUTTON_MENU | BUTTON_LEFT | BUTTON_REL: | ||
308 | #endif | ||
309 | exit = true; | 721 | exit = true; |
310 | break; | 722 | break; |
311 | } | 723 | } |
312 | if ( !exit ) | ||
313 | viewer_draw(col); | ||
314 | } | 724 | } |
315 | |||
316 | return col; | 725 | return col; |
317 | } | 726 | } |
727 | #endif | ||
318 | 728 | ||
319 | enum plugin_status plugin_start(struct plugin_api* api, void* file) | 729 | enum plugin_status plugin_start(struct plugin_api* api, void* file) |
320 | { | 730 | { |
321 | bool exit=false; | 731 | bool exit=false; |
322 | int button; | ||
323 | int col = 0; | 732 | int col = 0; |
733 | int i; | ||
324 | int ok; | 734 | int ok; |
325 | 735 | ||
326 | TEST_PLUGIN_API(api); | 736 | TEST_PLUGIN_API(api); |
@@ -337,13 +747,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file) | |||
337 | } | 747 | } |
338 | 748 | ||
339 | viewer_draw(col); | 749 | viewer_draw(col); |
340 | while (!exit) { | ||
341 | button = rb->button_get(true); | ||
342 | |||
343 | switch ( button ) { | ||
344 | 750 | ||
751 | while (!exit) { | ||
752 | switch (rb->button_get(true)) { | ||
345 | #ifdef HAVE_RECORDER_KEYPAD | 753 | #ifdef HAVE_RECORDER_KEYPAD |
346 | case BUTTON_F1: | ||
347 | case BUTTON_OFF: | 754 | case BUTTON_OFF: |
348 | #else | 755 | #else |
349 | case BUTTON_STOP: | 756 | case BUTTON_STOP: |
@@ -353,13 +760,104 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file) | |||
353 | break; | 760 | break; |
354 | 761 | ||
355 | #ifdef HAVE_RECORDER_KEYPAD | 762 | #ifdef HAVE_RECORDER_KEYPAD |
763 | case BUTTON_F1: | ||
764 | #else | ||
765 | case BUTTON_ON | BUTTON_LEFT: | ||
766 | #endif | ||
767 | /* Word-wrap mode: WRAP or CHOP */ | ||
768 | if (++word_mode == WORD_MODES) | ||
769 | word_mode = 0; | ||
770 | |||
771 | #ifdef HAVE_LCD_BITMAP | ||
772 | init_need_scrollbar(); | ||
773 | #endif | ||
774 | viewer_draw(col); | ||
775 | |||
776 | rb->splash(HZ, 0, true, "%s %s", | ||
777 | word_mode_str[word_mode], word_mode_str[WORD_MODES]); | ||
778 | |||
779 | viewer_draw(col); | ||
780 | break; | ||
781 | |||
782 | #ifdef HAVE_RECORDER_KEYPAD | ||
783 | case BUTTON_F2: | ||
784 | #else | ||
785 | case BUTTON_ON | BUTTON_MENU | BUTTON_RIGHT: | ||
786 | #endif | ||
787 | /* Line-paragraph mode: NORMAL, JOIN or EXPAND */ | ||
788 | if (++line_mode == LINE_MODES) | ||
789 | line_mode = 0; | ||
790 | |||
791 | if (view_mode == WIDE) | ||
792 | if (line_mode == JOIN) | ||
793 | if (++line_mode == LINE_MODES) | ||
794 | line_mode = 0; | ||
795 | |||
796 | #ifdef HAVE_LCD_BITMAP | ||
797 | init_need_scrollbar(); | ||
798 | #endif | ||
799 | viewer_draw(col); | ||
800 | |||
801 | rb->splash(HZ, 0, true, "%s %s", | ||
802 | line_mode_str[line_mode], line_mode_str[LINE_MODES]); | ||
803 | |||
804 | viewer_draw(col); | ||
805 | break; | ||
806 | |||
807 | #ifdef HAVE_RECORDER_KEYPAD | ||
808 | case BUTTON_F3: | ||
809 | #else | ||
810 | case BUTTON_ON | BUTTON_RIGHT: | ||
811 | #endif | ||
812 | /* View-width mode: NARROW or WIDE */ | ||
813 | if (line_mode == JOIN) | ||
814 | rb->splash(HZ, 0, true, "(no %s %s)", | ||
815 | view_mode_str[WIDE], line_mode_str[JOIN]); | ||
816 | else | ||
817 | if (++view_mode == VIEW_MODES) | ||
818 | view_mode = 0; | ||
819 | |||
820 | col = 0; | ||
821 | |||
822 | /***** Could do this after change of word-wrap mode | ||
823 | * and after change of view-width mode, to normalize | ||
824 | * view: | ||
825 | if (screen_top_ptr > buffer + BUFFER_SIZE/2) { | ||
826 | screen_top_ptr = find_prev_line(screen_top_ptr); | ||
827 | screen_top_ptr = find_next_line(screen_top_ptr); | ||
828 | } | ||
829 | else { | ||
830 | screen_top_ptr = find_next_line(screen_top_ptr); | ||
831 | screen_top_ptr = find_prev_line(screen_top_ptr); | ||
832 | } | ||
833 | ***********/ | ||
834 | |||
835 | #ifdef HAVE_LCD_BITMAP | ||
836 | init_need_scrollbar(); | ||
837 | #endif | ||
838 | viewer_draw(col); | ||
839 | |||
840 | rb->splash(HZ, 0, true, "%s %s", | ||
841 | view_mode_str[view_mode], view_mode_str[VIEW_MODES]); | ||
842 | |||
843 | viewer_draw(col); | ||
844 | break; | ||
845 | |||
846 | #ifdef HAVE_RECORDER_KEYPAD | ||
356 | case BUTTON_UP: | 847 | case BUTTON_UP: |
357 | case BUTTON_UP | BUTTON_REPEAT: | 848 | case BUTTON_UP | BUTTON_REPEAT: |
358 | #else | 849 | #else |
359 | case BUTTON_LEFT: | 850 | case BUTTON_LEFT: |
360 | case BUTTON_LEFT | BUTTON_REPEAT: | 851 | case BUTTON_LEFT | BUTTON_REPEAT: |
361 | #endif | 852 | #endif |
362 | viewer_scroll_up(); | 853 | /* Page up */ |
854 | #ifdef HAVE_LCD_BITMAP | ||
855 | for (i = page_mode==OVERLAP? 1:0; i < display_lines; i++) | ||
856 | #else | ||
857 | for (i = 0; i < display_lines; i++) | ||
858 | #endif | ||
859 | viewer_scroll_up(); | ||
860 | |||
363 | viewer_draw(col); | 861 | viewer_draw(col); |
364 | break; | 862 | break; |
365 | 863 | ||
@@ -370,7 +868,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file) | |||
370 | case BUTTON_RIGHT: | 868 | case BUTTON_RIGHT: |
371 | case BUTTON_RIGHT | BUTTON_REPEAT: | 869 | case BUTTON_RIGHT | BUTTON_REPEAT: |
372 | #endif | 870 | #endif |
373 | viewer_scroll_down(); | 871 | /* Page down */ |
872 | if (next_screen_ptr != NULL) | ||
873 | screen_top_ptr = next_screen_to_draw_ptr; | ||
874 | |||
374 | viewer_draw(col); | 875 | viewer_draw(col); |
375 | break; | 876 | break; |
376 | 877 | ||
@@ -381,9 +882,16 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file) | |||
381 | case BUTTON_MENU | BUTTON_LEFT: | 882 | case BUTTON_MENU | BUTTON_LEFT: |
382 | case BUTTON_MENU | BUTTON_LEFT | BUTTON_REPEAT: | 883 | case BUTTON_MENU | BUTTON_LEFT | BUTTON_REPEAT: |
383 | #endif | 884 | #endif |
384 | col--; | 885 | if (view_mode == WIDE) { |
385 | if (col < 0) | 886 | /* Screen left */ |
386 | col = 0; | 887 | col -= display_columns; |
888 | col = col_limit(col); | ||
889 | } | ||
890 | else { /* view_mode == NARROW */ | ||
891 | /* Top of file */ | ||
892 | viewer_top(); | ||
893 | } | ||
894 | |||
387 | viewer_draw(col); | 895 | viewer_draw(col); |
388 | break; | 896 | break; |
389 | 897 | ||
@@ -394,18 +902,28 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file) | |||
394 | case BUTTON_MENU | BUTTON_RIGHT: | 902 | case BUTTON_MENU | BUTTON_RIGHT: |
395 | case BUTTON_MENU | BUTTON_RIGHT | BUTTON_REPEAT: | 903 | case BUTTON_MENU | BUTTON_RIGHT | BUTTON_REPEAT: |
396 | #endif | 904 | #endif |
397 | col++; | 905 | if (view_mode == WIDE) { |
906 | /* Screen right */ | ||
907 | col += display_columns; | ||
908 | col = col_limit(col); | ||
909 | } | ||
910 | else { /* view_mode == NARROW */ | ||
911 | /* Bottom of file */ | ||
912 | viewer_bottom(); | ||
913 | } | ||
914 | |||
398 | viewer_draw(col); | 915 | viewer_draw(col); |
399 | break; | 916 | break; |
400 | 917 | ||
918 | #ifdef HAVE_RECORDER_KEYPAD | ||
401 | case BUTTON_ON: | 919 | case BUTTON_ON: |
402 | #ifdef HAVE_PLAYER_KEYPAD | 920 | /*Go to On-btn combinations */ |
403 | case BUTTON_ON | BUTTON_MENU: | 921 | col = viewer_recorder_on_button(col); |
404 | #endif | ||
405 | col = pagescroll(col); | ||
406 | break; | 922 | break; |
923 | #endif | ||
407 | 924 | ||
408 | case SYS_USB_CONNECTED: | 925 | case SYS_USB_CONNECTED: |
926 | /* Release control to USB functions */ | ||
409 | rb->usb_screen(); | 927 | rb->usb_screen(); |
410 | viewer_exit(); | 928 | viewer_exit(); |
411 | return PLUGIN_USB_CONNECTED; | 929 | return PLUGIN_USB_CONNECTED; |