summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorTeruaki Kawashima <teru@rockbox.org>2010-06-08 11:07:36 +0000
committerTeruaki Kawashima <teru@rockbox.org>2010-06-08 11:07:36 +0000
commit0c7eb41da8253837a571cc037a932c77348a88c9 (patch)
tree762f30148d6c4c01d85766097c9745431489f34f /apps
parent755fef66b30633365f7401ddbeb40a0481d616d4 (diff)
downloadrockbox-0c7eb41da8253837a571cc037a932c77348a88c9.tar.gz
rockbox-0c7eb41da8253837a571cc037a932c77348a88c9.zip
add simple text viewer to pluginlib and use this for dict to show description.
now dict can scroll the description. it might not show full description if it is too long or memory is not enough. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26687 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/dict.c212
-rw-r--r--apps/plugins/lib/SOURCES1
-rw-r--r--apps/plugins/lib/simple_viewer.c260
-rw-r--r--apps/plugins/lib/simple_viewer.h28
4 files changed, 307 insertions, 194 deletions
diff --git a/apps/plugins/dict.c b/apps/plugins/dict.c
index 8c262923b7..13fe8e3cc6 100644
--- a/apps/plugins/dict.c
+++ b/apps/plugins/dict.c
@@ -20,11 +20,11 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "plugin.h" 22#include "plugin.h"
23#include "lib/simple_viewer.h"
23 24
24PLUGIN_HEADER 25PLUGIN_HEADER
25 26
26/* screen info */ 27#define MIN_DESC_BUF_SIZE 0x400 /* arbitrary minimum size for description */
27static int display_columns, display_lines;
28 28
29/* Some lenghts */ 29/* Some lenghts */
30#define WORDLEN 32 /* has to be the same in rdf2binary.c */ 30#define WORDLEN 32 /* has to be the same in rdf2binary.c */
@@ -44,50 +44,6 @@ struct stWord
44 long offset; 44 long offset;
45} STRUCT_PACKED; 45} STRUCT_PACKED;
46 46
47/* A funtion to get width and height etc (from viewer.c) */
48void init_screen(void)
49{
50#ifdef HAVE_LCD_BITMAP
51 int w,h;
52
53 rb->lcd_getstringsize("o", &w, &h);
54 display_lines = LCD_HEIGHT / h;
55 display_columns = LCD_WIDTH / w;
56#else
57
58 display_lines = 2;
59 display_columns = 11;
60#endif
61}
62
63/* global vars for pl_malloc() */
64void *bufptr;
65size_t bufleft;
66
67/* simple function to "allocate" memory in pluginbuffer. */
68void *pl_malloc(size_t size)
69{
70 void *ptr;
71 ptr = bufptr;
72
73 if (bufleft < size)
74 {
75 return NULL;
76 }
77 else
78 {
79 bufptr += size;
80 bufleft -= size;
81 return ptr;
82 }
83}
84
85/* init function for pl_malloc() */
86void pl_malloc_init(void)
87{
88 bufptr = rb->plugin_get_buffer(&bufleft);
89}
90
91/* for endian problems */ 47/* for endian problems */
92#ifdef ROCKBOX_BIG_ENDIAN 48#ifdef ROCKBOX_BIG_ENDIAN
93#define reverse(x) x 49#define reverse(x) x
@@ -102,59 +58,6 @@ long reverse (long N) {
102} 58}
103#endif 59#endif
104 60
105/* Button definitions */
106#if CONFIG_KEYPAD == PLAYER_PAD
107#define LP_QUIT BUTTON_STOP
108#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
109 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
110 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
111#define LP_QUIT BUTTON_MENU
112#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
113#define LP_QUIT BUTTON_PLAY
114#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
115#define LP_QUIT BUTTON_POWER
116#elif CONFIG_KEYPAD == GIGABEAT_PAD
117#define LP_QUIT BUTTON_POWER
118#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
119 (CONFIG_KEYPAD == SANSA_C200_PAD) || \
120 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
121 (CONFIG_KEYPAD == SANSA_M200_PAD)
122#define LP_QUIT BUTTON_POWER
123#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
124#define LP_QUIT (BUTTON_HOME|BUTTON_REPEAT)
125#elif CONFIG_KEYPAD == IRIVER_H10_PAD
126#define LP_QUIT BUTTON_POWER
127#elif CONFIG_KEYPAD == MROBE500_PAD
128#define LP_QUIT BUTTON_POWER
129#elif CONFIG_KEYPAD == MROBE100_PAD
130#define LP_QUIT BUTTON_POWER
131#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
132#define LP_QUIT BUTTON_BACK
133#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
134#define LP_QUIT BUTTON_RC_REC
135#elif CONFIG_KEYPAD == COWON_D2_PAD
136#define LP_QUIT BUTTON_POWER
137#elif CONFIG_KEYPAD == IAUDIO67_PAD
138#define LP_QUIT BUTTON_POWER
139#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
140#define LP_QUIT BUTTON_BACK
141#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
142#define LP_QUIT BUTTON_POWER
143#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
144#define LP_QUIT BUTTON_POWER
145#elif CONFIG_KEYPAD == ONDAVX747_PAD
146#define LP_QUIT BUTTON_POWER
147#elif CONFIG_KEYPAD == ONDAVX777_PAD
148#define LP_QUIT BUTTON_POWER
149#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
150#define LP_QUIT BUTTON_LEFT
151#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
152#define LP_QUIT BUTTON_CANCEL
153#elif CONFIG_KEYPAD == MPIO_HD200_PAD
154#define LP_QUIT (BUTTON_REC|BUTTON_PLAY)
155#else
156#define LP_QUIT BUTTON_OFF
157#endif
158 61
159/* data files */ 62/* data files */
160#define DICT_INDEX PLUGIN_APPS_DIR "/dict.index" 63#define DICT_INDEX PLUGIN_APPS_DIR "/dict.index"
@@ -165,42 +68,32 @@ enum plugin_status plugin_start(const void* parameter)
165{ 68{
166 char searchword[WORDLEN]; /* word to search for */ 69 char searchword[WORDLEN]; /* word to search for */
167 char *description; /* pointer to description buffer */ 70 char *description; /* pointer to description buffer */
168 char *output; /* pointer to output buffer */
169 char *ptr, *space;
170 struct stWord word; /* the struct to read into */ 71 struct stWord word; /* the struct to read into */
171 int fIndex, fData; /* files */ 72 int fIndex, fData; /* files */
172 int filesize, high, low, probe; 73 int filesize, high, low, probe;
173 int lines, len, outputted, next; 74 char *buffer;
75 size_t buffer_size;
174 76
175 /* plugin stuff */ 77 /* plugin stuff */
176 (void)parameter; 78 (void)parameter;
177 79
178 /* get screen info */ 80 /* allocate buffer. */
179 init_screen(); 81 buffer = rb->plugin_get_buffer(&buffer_size);
180 82 if (buffer == NULL || buffer_size < MIN_DESC_BUF_SIZE)
181 /* get pl_malloc() buffer ready. */
182 pl_malloc_init();
183
184 /* init description buffer (size is because we don't have scrolling)*/
185 description = (char *)pl_malloc(display_columns * display_lines);
186 if (description == NULL)
187 { 83 {
188 DEBUGF("Err: failed to allocate description buffer."); 84 DEBUGF("Err: Failed to allocate buffer.\n");
85 rb->splash(HZ*2, "Failed to allocate buffer.");
189 return PLUGIN_ERROR; 86 return PLUGIN_ERROR;
190 } 87 }
191 88
192 /* init output buffer */ 89 description = buffer;
193 output = (char *)pl_malloc(display_columns);
194 if (output == NULL)
195 {
196 DEBUGF("Err: failed to allocate output buffer.");
197 return PLUGIN_ERROR;
198 }
199 90
200 /* "clear" input buffer */ 91 /* "clear" input buffer */
201 searchword[0] = '\0'; 92 searchword[0] = '\0';
202 93
203 rb->kbd_input(searchword, sizeof(searchword)); /* get the word to search */ 94 /* get the word to search */
95 if (rb->kbd_input(searchword, sizeof(searchword)) < 0)
96 return PLUGIN_OK; /* input cancelled */
204 97
205 fIndex = rb->open(DICT_INDEX, O_RDONLY); /* index file */ 98 fIndex = rb->open(DICT_INDEX, O_RDONLY); /* index file */
206 if (fIndex < 0) 99 if (fIndex < 0)
@@ -241,13 +134,13 @@ enum plugin_status plugin_start(const void* parameter)
241 /* read in the word */ 134 /* read in the word */
242 rb->lseek(fIndex, sizeof(struct stWord) * low, SEEK_SET); 135 rb->lseek(fIndex, sizeof(struct stWord) * low, SEEK_SET);
243 rb->read(fIndex, &word, sizeof(struct stWord)); 136 rb->read(fIndex, &word, sizeof(struct stWord));
137 rb->close(fIndex);
244 138
245 /* Check if we found something */ 139 /* Check if we found something */
246 if (low == -1 || rb->strcasecmp(searchword, word.word) != 0) 140 if (low == -1 || rb->strcasecmp(searchword, word.word) != 0)
247 { 141 {
248 DEBUGF("Not found.\n"); 142 DEBUGF("Not found.\n");
249 rb->splash(HZ*2, "Not found."); 143 rb->splash(HZ*2, "Not found.");
250 rb->close(fIndex);
251 return PLUGIN_OK; 144 return PLUGIN_OK;
252 } 145 }
253 146
@@ -259,7 +152,6 @@ enum plugin_status plugin_start(const void* parameter)
259 { 152 {
260 DEBUGF("Err: Failed to open description file.\n"); 153 DEBUGF("Err: Failed to open description file.\n");
261 rb->splash(HZ*2, "Failed to open descriptions."); 154 rb->splash(HZ*2, "Failed to open descriptions.");
262 rb->close(fIndex);
263 return PLUGIN_ERROR; 155 return PLUGIN_ERROR;
264 } 156 }
265 157
@@ -267,83 +159,15 @@ enum plugin_status plugin_start(const void* parameter)
267 rb->lseek(fData, (off_t)reverse(word.offset), SEEK_SET); 159 rb->lseek(fData, (off_t)reverse(word.offset), SEEK_SET);
268 160
269 /* Read in the description */ 161 /* Read in the description */
270 rb->read_line(fData, description, display_columns * display_lines); 162 rb->read_line(fData, description, buffer_size);
271 163
272 /* And print it to debug. */ 164 /* And print it to debug. */
273 DEBUGF("Description: %s\n", description); 165 DEBUGF("Description: %s\n", description);
274 166
275 /* get pointer to first char */ 167 rb->close(fData);
276 ptr = description;
277
278 lines = 0;
279 outputted = 0;
280 len = rb->strlen(description);
281
282 /* clear screen */
283 rb->lcd_clear_display();
284
285 /* for large screens display the searched word. */
286 if(display_lines > 4)
287 {
288 rb->lcd_puts(0, lines, searchword);
289 lines++;
290 }
291
292 /* TODO: Scroll, or just stop when there are to much lines. */
293 while (1)
294 {
295 /* copy one lcd line */
296 rb->strlcpy(output, ptr, display_columns + 1);
297
298 /* typecast to kill a warning... */
299 if((int)rb->strlen(ptr) < display_columns)
300 {
301 rb->lcd_puts(0, lines, output);
302 lines++;
303 break;
304 }
305
306
307 /* get the last spacechar */
308 space = rb->strrchr(output, ' ');
309
310 if (space != NULL)
311 {
312 *space = '\0';
313 next = (space - (char*)output) + 1;
314 }
315 else
316 {
317 next = display_columns;
318 }
319
320 /* put the line on screen */
321 rb->lcd_puts(0, lines, output);
322
323 /* get output count */
324 outputted += rb->strlen(output);
325
326 if (outputted < len)
327 {
328 /* set pointer to the next part */
329 ptr += next;
330 lines++;
331 }
332 else
333 {
334 break;
335 }
336 }
337 rb->lcd_update();
338 168
339 /* wait for keypress */ 169 /* display description. */
340 while(rb->button_get(true) != LP_QUIT) 170 view_text(searchword, description);
341 {
342 /* do nothing */
343 /* maybe define some keys for navigation here someday. */
344 }
345 171
346 rb->close(fIndex);
347 rb->close(fData);
348 return PLUGIN_OK; 172 return PLUGIN_OK;
349} 173}
diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES
index 8c160e1cc4..5ed163f951 100644
--- a/apps/plugins/lib/SOURCES
+++ b/apps/plugins/lib/SOURCES
@@ -9,6 +9,7 @@ fixedpoint.c
9playback_control.c 9playback_control.c
10rgb_hsv.c 10rgb_hsv.c
11buflib.c 11buflib.c
12simple_viewer.c
12display_text.c 13display_text.c
13strncpy.c 14strncpy.c
14 15
diff --git a/apps/plugins/lib/simple_viewer.c b/apps/plugins/lib/simple_viewer.c
new file mode 100644
index 0000000000..c83f005ef4
--- /dev/null
+++ b/apps/plugins/lib/simple_viewer.c
@@ -0,0 +1,260 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2010 Teruaki Kawashima
11*
12* This program is free software; you can redistribute it and/or
13* modify it under the terms of the GNU General Public License
14* as published by the Free Software Foundation; either version 2
15* of the License, or (at your option) any later version.
16*
17* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18* KIND, either express or implied.
19*
20****************************************************************************/
21
22#include "config.h"
23#include "plugin.h"
24#include "pluginlib_actions.h"
25#include "simple_viewer.h"
26#include <ctype.h>
27
28struct view_info {
29#ifdef HAVE_LCD_BITMAP
30 struct font* pf;
31#endif
32 const char *title;
33 const char *text; /* displayed text */
34 int display_lines; /* number of lines can be displayed */
35 int line_count; /* number of lines */
36 int line; /* current fisrt line */
37 int start; /* possition of first line in text */
38};
39
40static const char* get_next_line(const char *text, struct view_info *info)
41{
42 (void) info;
43 const char *ptr = text;
44 const char *space = NULL;
45 int total, n, w;
46 total = 0;
47 while(*ptr)
48 {
49#ifdef HAVE_LCD_CHARCELLS
50 n = rb->utf8seek(ptr, 1);
51 w = 1;
52#else
53 unsigned short ch;
54 n = ((long)rb->utf8decode(ptr, &ch) - (long)ptr);
55 w = rb->font_get_width(info->pf, ch);
56#endif
57 if (isspace(*ptr))
58 space = ptr+n;
59 if (*ptr == '\n')
60 {
61 ptr += n;
62 break;
63 }
64 if (total + w > LCD_WIDTH)
65 break;
66 ptr += n;
67 total += w;
68 }
69 return *ptr && space? space: ptr;
70}
71
72static void calc_line_count(struct view_info *info)
73{
74 const char *ptr = info->text;
75 int i = 0;
76
77 while (*ptr)
78 {
79 ptr = get_next_line(ptr, info);
80 i++;
81 }
82 info->line_count = i;
83}
84
85static void calc_first_line(struct view_info *info, int line)
86{
87 const char *ptr = info->text;
88 int i = 0;
89
90 if (line > info->line_count - info->display_lines)
91 line = info->line_count - info->display_lines;
92 if (line < 0)
93 line = 0;
94
95 DEBUGF("%d -> %d\n", info->line, line);
96 if (info->line <= line)
97 {
98 ptr += info->start;
99 i = info->line;
100 }
101 while (*ptr && i < line)
102 {
103 ptr = get_next_line(ptr, info);
104 i++;
105 }
106 info->start = ptr - info->text;
107 info->line = i;
108 DEBUGF("%d: %d\n", info->line, info->start);
109}
110
111static int init_view(struct view_info *info,
112 const char *title, const char *text)
113{
114#ifdef HAVE_LCD_BITMAP
115 info->pf = rb->font_get(FONT_UI);
116 info->display_lines = LCD_HEIGHT / info->pf->height;
117#else
118
119 info->display_lines = LCD_HEIGHT;
120#endif
121
122 info->title = title;
123 info->text = text;
124 info->line_count = 0;
125 info->line = 0;
126 info->start = 0;
127
128 /* no title for small screens. */
129 if (info->display_lines < 4)
130 {
131 info->title = NULL;
132 }
133 else
134 {
135 info->display_lines--;
136 }
137
138 calc_line_count(info);
139 return 0;
140}
141
142static void draw_text(struct view_info *info)
143{
144#ifdef HAVE_LCD_BITMAP
145#define OUTPUT_SIZE LCD_WIDTH+1
146#else
147#define OUTPUT_SIZE LCD_WIDTH*3+1
148#endif
149 static char output[OUTPUT_SIZE];
150 const char *text, *ptr;
151 int i, max_show, lines = 0;
152
153 /* clear screen */
154 rb->lcd_clear_display();
155
156 /* display title. */
157 if(info->title)
158 {
159 rb->lcd_puts(0, lines, info->title);
160 lines++;
161 }
162
163 max_show = MIN(info->line_count - info->line, info->display_lines);
164 DEBUGF("draw_text: %d-%d/%d\n",
165 info->line, info->line + max_show, info->line_count);
166 text = info->text + info->start;
167
168 for (i = 0; i < max_show; i++, lines++)
169 {
170 ptr = get_next_line(text, info);
171 DEBUGF("%d>%d-%d, ", i, text-info->text, ptr-text);
172 rb->strlcpy(output, text, ptr-text+1);
173 rb->lcd_puts(0, lines, output);
174 text = ptr;
175 }
176 DEBUGF("\n");
177
178 rb->lcd_update();
179}
180
181static void scroll_up(struct view_info *info)
182{
183 if (info->line <= 0)
184 return;
185 calc_first_line(info, info->line-1);
186 draw_text(info);
187 return;
188}
189
190static void scroll_down(struct view_info *info)
191{
192 if (info->line + info->display_lines >= info->line_count)
193 return;
194
195 calc_first_line(info, info->line+1);
196 draw_text(info);
197}
198
199static void scroll_to_top(struct view_info *info)
200{
201 if (info->line <= 0)
202 return;
203
204 calc_first_line(info, 0);
205 draw_text(info);
206}
207
208static void scroll_to_bottom(struct view_info *info)
209{
210 if (info->line + info->display_lines >= info->line_count)
211 return;
212
213 calc_first_line(info, info->line_count - info->display_lines);
214 draw_text(info);
215}
216
217int view_text(const char *title, const char *text)
218{
219 struct view_info info;
220 const struct button_mapping *view_contexts[] = {
221 pla_main_ctx,
222 };
223 int button;
224
225 init_view(&info, title, text);
226 draw_text(&info);
227
228 /* wait for keypress */
229 while(1)
230 {
231 button = pluginlib_getaction(TIMEOUT_BLOCK, view_contexts,
232 ARRAYLEN(view_contexts));
233 switch (button)
234 {
235 case PLA_UP:
236 case PLA_UP_REPEAT:
237 scroll_up(&info);
238 break;
239 case PLA_DOWN:
240 case PLA_DOWN_REPEAT:
241 scroll_down(&info);
242 break;
243 case PLA_LEFT_REPEAT:
244 scroll_to_top(&info);
245 break;
246 case PLA_RIGHT_REPEAT:
247 scroll_to_bottom(&info);
248 break;
249 case PLA_EXIT:
250 case PLA_CANCEL:
251 return PLUGIN_OK;
252 default:
253 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
254 return PLUGIN_USB_CONNECTED;
255 break;
256 }
257 }
258
259 return PLUGIN_OK;
260}
diff --git a/apps/plugins/lib/simple_viewer.h b/apps/plugins/lib/simple_viewer.h
new file mode 100644
index 0000000000..ff3ef23f14
--- /dev/null
+++ b/apps/plugins/lib/simple_viewer.h
@@ -0,0 +1,28 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2010 Teruaki Kawashima
11*
12* This program is free software; you can redistribute it and/or
13* modify it under the terms of the GNU General Public License
14* as published by the Free Software Foundation; either version 2
15* of the License, or (at your option) any later version.
16*
17* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18* KIND, either express or implied.
19*
20****************************************************************************/
21
22#ifndef __PLUGINLIB_VIEWER_H__
23#define __PLUGINLIB_VIEWER_H__
24
25#include "plugin.h"
26int view_text(const char *title, const char *text);
27
28#endif /* __PLUGINLIB_VIEWER_H__ */