diff options
author | Daniel Stenberg <daniel@haxx.se> | 2002-09-30 19:05:03 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2002-09-30 19:05:03 +0000 |
commit | 773e7a70cc94fc6b6a0f9406ab99b828bea5bd42 (patch) | |
tree | a8d5789ab3544147d726d04b2a5a9399dd0eed2d /apps/viewer.c | |
parent | ad911c0ac82f409251230b39b39fc3e8c2b83ff9 (diff) | |
download | rockbox-773e7a70cc94fc6b6a0f9406ab99b828bea5bd42.tar.gz rockbox-773e7a70cc94fc6b6a0f9406ab99b828bea5bd42.zip |
Gilles Roux's text viewer
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2452 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/viewer.c')
-rw-r--r-- | apps/viewer.c | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/apps/viewer.c b/apps/viewer.c new file mode 100644 index 0000000000..d986ce2dcf --- /dev/null +++ b/apps/viewer.c | |||
@@ -0,0 +1,342 @@ | |||
1 | /*************************************************************************** | ||
2 | * | ||
3 | * __________ __ ___. | ||
4 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
5 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
6 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
7 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
8 | * \/ \/ \/ \/ \/ | ||
9 | * $Id$ | ||
10 | * | ||
11 | * Copyright (C) 2002 Gilles Roux | ||
12 | * | ||
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. | ||
15 | * | ||
16 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
17 | * KIND, either express or implied. | ||
18 | * | ||
19 | ****************************************************************************/ | ||
20 | #include <stdio.h> | ||
21 | #include <string.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <stdbool.h> | ||
24 | |||
25 | #include "file.h" | ||
26 | #include "lcd.h" | ||
27 | #include "button.h" | ||
28 | #include "kernel.h" | ||
29 | #include "font.h" | ||
30 | #include "settings.h" | ||
31 | #include "icons.h" | ||
32 | #include "screens.h" | ||
33 | |||
34 | #define BUFFER_SIZE 1024 | ||
35 | |||
36 | #define OUTSIDE_BUFFER -10 | ||
37 | #define OUTSIDE_FILE -11 | ||
38 | |||
39 | static int fd; | ||
40 | static int file_size; | ||
41 | |||
42 | static char buffer[BUFFER_SIZE+1]; | ||
43 | static int buffer_pos; /* Position of the buffer in the file */ | ||
44 | |||
45 | static int begin_line; /* Index of the first line displayed on the lcd */ | ||
46 | static int end_line; /* Index of the last line displayed on the lcd */ | ||
47 | static int begin_line_pos; /* Position of the first_line in the bufffer */ | ||
48 | static int end_line_pos; /* Position of the last_line in the buffer */ | ||
49 | |||
50 | /* | ||
51 | * Known issue: The caching algorithm will fail (display incoherent data) if | ||
52 | * the total space of the lines that are displayed on the screen exceeds the | ||
53 | * buffer size (only happens with very long lines). | ||
54 | */ | ||
55 | |||
56 | static int display_line_count(void) | ||
57 | { | ||
58 | #ifdef HAVE_LCD_BITMAP | ||
59 | int fh; | ||
60 | fh = font_get(FONT_UI)->height; | ||
61 | if (global_settings.statusbar) | ||
62 | return (LCD_HEIGHT - STATUSBAR_HEIGHT) / fh; | ||
63 | else | ||
64 | return LCD_HEIGHT/fh; | ||
65 | #else | ||
66 | return 2; | ||
67 | #endif | ||
68 | } | ||
69 | |||
70 | static int find_next_line(int pos) | ||
71 | { | ||
72 | int i; | ||
73 | |||
74 | if (pos==OUTSIDE_BUFFER || pos==OUTSIDE_FILE) | ||
75 | return pos; | ||
76 | |||
77 | i = pos; | ||
78 | if (buffer_pos+i>=file_size) { | ||
79 | return OUTSIDE_FILE; | ||
80 | } | ||
81 | while (1) { | ||
82 | i++; | ||
83 | if (buffer_pos+i==file_size) { | ||
84 | return i; | ||
85 | } | ||
86 | if (i>=BUFFER_SIZE) { | ||
87 | return OUTSIDE_BUFFER; | ||
88 | } | ||
89 | if (buffer[i]==0) { | ||
90 | return i; | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | static int find_prev_line(int pos) | ||
96 | { | ||
97 | int i; | ||
98 | |||
99 | if (pos==OUTSIDE_BUFFER || pos==OUTSIDE_FILE) | ||
100 | return pos; | ||
101 | |||
102 | i = pos; | ||
103 | if (buffer_pos+i<0) { | ||
104 | return OUTSIDE_FILE; | ||
105 | } | ||
106 | while (1) { | ||
107 | i--; | ||
108 | if (buffer_pos+i<0) { | ||
109 | return i; | ||
110 | } | ||
111 | if (i<0) { | ||
112 | return OUTSIDE_BUFFER; | ||
113 | } | ||
114 | if (buffer[i]==0) { | ||
115 | return i; | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | |||
120 | static void viewer_draw(int col) | ||
121 | { | ||
122 | int i, j; | ||
123 | char* str; | ||
124 | int line_pos; | ||
125 | |||
126 | lcd_clear_display(); | ||
127 | |||
128 | line_pos = begin_line_pos; | ||
129 | |||
130 | for (i=0; | ||
131 | i<=end_line-begin_line && | ||
132 | line_pos!=OUTSIDE_BUFFER && | ||
133 | line_pos!=OUTSIDE_FILE; | ||
134 | i++) { | ||
135 | str = buffer + line_pos + 1; | ||
136 | for (j=0; j<col && *str!=0; ++j) | ||
137 | str++; | ||
138 | lcd_puts(0, i, str); | ||
139 | line_pos = find_next_line(line_pos); | ||
140 | } | ||
141 | |||
142 | lcd_update(); | ||
143 | } | ||
144 | |||
145 | static void fill_buffer(int pos) | ||
146 | { | ||
147 | int i; | ||
148 | int numread; | ||
149 | |||
150 | if (pos>=file_size-BUFFER_SIZE) | ||
151 | pos = file_size-BUFFER_SIZE; | ||
152 | if (pos<0) | ||
153 | pos = 0; | ||
154 | |||
155 | lseek(fd, pos, SEEK_SET); | ||
156 | numread = read(fd, buffer, BUFFER_SIZE); | ||
157 | |||
158 | begin_line_pos -= pos - buffer_pos; | ||
159 | end_line_pos -= pos - buffer_pos; | ||
160 | buffer_pos = pos; | ||
161 | |||
162 | buffer[numread] = 0; | ||
163 | for(i=0;i<numread;i++) { | ||
164 | switch(buffer[i]) { | ||
165 | case '\r': | ||
166 | buffer[i] = ' '; | ||
167 | break; | ||
168 | case '\n': | ||
169 | buffer[i] = 0; | ||
170 | break; | ||
171 | default: | ||
172 | break; | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | |||
177 | static bool viewer_init(char* file) | ||
178 | { | ||
179 | int i; | ||
180 | int ret; | ||
181 | int disp_lines; | ||
182 | |||
183 | fd = open(file, O_RDONLY); | ||
184 | if (fd==-1) | ||
185 | return false; | ||
186 | |||
187 | file_size = lseek(fd, 0, SEEK_END); | ||
188 | |||
189 | buffer_pos = 0; | ||
190 | begin_line = 0; | ||
191 | begin_line_pos = -1; | ||
192 | end_line = -1; | ||
193 | end_line_pos = -1; | ||
194 | fill_buffer(0); | ||
195 | disp_lines = display_line_count(); | ||
196 | for (i=0; i<disp_lines; ++i) { | ||
197 | ret = find_next_line(end_line_pos); | ||
198 | if (ret!=OUTSIDE_FILE && ret!=OUTSIDE_BUFFER) { | ||
199 | end_line_pos = ret; | ||
200 | end_line++; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | return true; | ||
205 | } | ||
206 | |||
207 | static void viewer_exit(void) | ||
208 | { | ||
209 | close(fd); | ||
210 | } | ||
211 | |||
212 | static void viewer_scroll_down(void) | ||
213 | { | ||
214 | int ret; | ||
215 | |||
216 | ret = find_next_line(end_line_pos); | ||
217 | if (ret==OUTSIDE_BUFFER) { | ||
218 | begin_line_pos = find_next_line(begin_line_pos); | ||
219 | fill_buffer(begin_line_pos+buffer_pos); | ||
220 | end_line_pos = find_next_line(end_line_pos); | ||
221 | } else if (ret==OUTSIDE_FILE) { | ||
222 | return; | ||
223 | } else { | ||
224 | begin_line_pos = find_next_line(begin_line_pos); | ||
225 | end_line_pos = ret; | ||
226 | } | ||
227 | begin_line++; | ||
228 | end_line++; | ||
229 | } | ||
230 | |||
231 | static void viewer_scroll_up(void) | ||
232 | { | ||
233 | int ret; | ||
234 | |||
235 | ret = find_prev_line(begin_line_pos); | ||
236 | if (ret==OUTSIDE_BUFFER) { | ||
237 | end_line_pos = find_prev_line(end_line_pos); | ||
238 | fill_buffer(buffer_pos+end_line_pos-BUFFER_SIZE); | ||
239 | begin_line_pos = find_prev_line(begin_line_pos); | ||
240 | } else if (ret==OUTSIDE_FILE) { | ||
241 | return; | ||
242 | } else { | ||
243 | end_line_pos = find_prev_line(end_line_pos); | ||
244 | begin_line_pos = ret; | ||
245 | } | ||
246 | begin_line--; | ||
247 | end_line--; | ||
248 | } | ||
249 | |||
250 | bool viewer_run(char* file) | ||
251 | { | ||
252 | int button; | ||
253 | int col = 0; | ||
254 | int ok; | ||
255 | |||
256 | #ifdef HAVE_LCD_BITMAP | ||
257 | /* no margins */ | ||
258 | lcd_setmargins(0, 0); | ||
259 | #endif | ||
260 | |||
261 | ok = viewer_init(file); | ||
262 | if (!ok) { | ||
263 | lcd_clear_display(); | ||
264 | lcd_puts(0, 0, "Error"); | ||
265 | lcd_update(); | ||
266 | sleep(HZ); | ||
267 | viewer_exit(); | ||
268 | return false; | ||
269 | } | ||
270 | |||
271 | viewer_draw(col); | ||
272 | while(1) { | ||
273 | button = button_get(true); | ||
274 | |||
275 | switch ( button ) { | ||
276 | |||
277 | #ifdef HAVE_RECORDER_KEYPAD | ||
278 | case BUTTON_F1: | ||
279 | case BUTTON_ON: | ||
280 | #else | ||
281 | case BUTTON_STOP: | ||
282 | case BUTTON_ON: | ||
283 | #endif | ||
284 | viewer_exit(); | ||
285 | return true; | ||
286 | break; | ||
287 | |||
288 | #ifdef HAVE_RECORDER_KEYPAD | ||
289 | case BUTTON_UP: | ||
290 | case BUTTON_UP | BUTTON_REPEAT: | ||
291 | #else | ||
292 | case BUTTON_LEFT: | ||
293 | case BUTTON_LEFT | BUTTON_REPEAT: | ||
294 | #endif | ||
295 | viewer_scroll_up(); | ||
296 | viewer_draw(col); | ||
297 | break; | ||
298 | |||
299 | #ifdef HAVE_RECORDER_KEYPAD | ||
300 | case BUTTON_DOWN: | ||
301 | case BUTTON_DOWN | BUTTON_REPEAT: | ||
302 | #else | ||
303 | case BUTTON_RIGHT: | ||
304 | case BUTTON_RIGHT | BUTTON_REPEAT: | ||
305 | #endif | ||
306 | viewer_scroll_down(); | ||
307 | viewer_draw(col); | ||
308 | break; | ||
309 | |||
310 | #ifdef HAVE_RECORDER_KEYPAD | ||
311 | case BUTTON_LEFT: | ||
312 | case BUTTON_LEFT | BUTTON_REPEAT: | ||
313 | #else | ||
314 | case BUTTON_MENU | BUTTON_LEFT: | ||
315 | case BUTTON_MENU | BUTTON_LEFT | BUTTON_REPEAT: | ||
316 | #endif | ||
317 | col--; | ||
318 | viewer_draw(col); | ||
319 | break; | ||
320 | |||
321 | #ifdef HAVE_RECORDER_KEYPAD | ||
322 | case BUTTON_RIGHT: | ||
323 | case BUTTON_RIGHT | BUTTON_REPEAT: | ||
324 | #else | ||
325 | case BUTTON_MENU | BUTTON_RIGHT: | ||
326 | case BUTTON_MENU | BUTTON_RIGHT | BUTTON_REPEAT: | ||
327 | #endif | ||
328 | col++; | ||
329 | viewer_draw(col); | ||
330 | break; | ||
331 | |||
332 | case SYS_USB_CONNECTED: | ||
333 | usb_screen(); | ||
334 | #ifdef HAVE_LCD_CHARCELLS | ||
335 | lcd_icon(ICON_PARAM, false); | ||
336 | #endif | ||
337 | viewer_exit(); | ||
338 | return true; | ||
339 | } | ||
340 | } | ||
341 | } | ||
342 | |||