summaryrefslogtreecommitdiff
path: root/apps/plugins/lib/simple_viewer.c
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/plugins/lib/simple_viewer.c
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/plugins/lib/simple_viewer.c')
-rw-r--r--apps/plugins/lib/simple_viewer.c260
1 files changed, 260 insertions, 0 deletions
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}