We have a 3.9 release, update builds.pm
[maemo-rb.git] / apps / plugins / lib / simple_viewer.c
blob16cbcb35de3ea2bc9a31323bb4c5730fa9637e75
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2010 Teruaki Kawashima
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "config.h"
23 #include "plugin.h"
24 #include "pluginlib_actions.h"
25 #include "simple_viewer.h"
26 #include <ctype.h>
28 struct view_info {
29 #ifdef HAVE_LCD_BITMAP
30 struct font* pf;
31 struct viewport scrollbar_vp; /* viewport for scrollbar */
32 #endif
33 struct viewport vp;
34 const char *title;
35 const char *text; /* displayed text */
36 int display_lines; /* number of lines can be displayed */
37 int line_count; /* number of lines */
38 int line; /* current first line */
39 int start; /* possition of first line in text */
42 static bool isbrchr(const unsigned char *str, int len)
44 const unsigned char *p = "!,-.:;? 、。!,.:;?―";
45 if (isspace(*str))
46 return true;
48 while(*p)
50 int n = rb->utf8seek(p, 1);
51 if (len == n && !rb->strncmp(p, str, len))
52 return true;
53 p += n;
55 return false;
58 static const char* get_next_line(const char *text, struct view_info *info)
60 const char *ptr = text;
61 const char *space = NULL;
62 int total, n, w;
63 total = 0;
64 while(*ptr)
66 #ifdef HAVE_LCD_CHARCELLS
67 n = rb->utf8seek(ptr, 1);
68 w = 1;
69 #else
70 unsigned short ch;
71 n = ((long)rb->utf8decode(ptr, &ch) - (long)ptr);
72 if (rb->is_diacritic(ch, NULL))
73 w = 0;
74 else
75 w = rb->font_get_width(info->pf, ch);
76 #endif
77 if (isbrchr(ptr, n))
78 space = ptr+(isspace(*ptr) || total + w <= info->vp.width? n: 0);
79 if (*ptr == '\n')
81 ptr += n;
82 break;
84 if (total + w > info->vp.width)
85 break;
86 ptr += n;
87 total += w;
89 return *ptr && space? space: ptr;
92 static void calc_line_count(struct view_info *info)
94 const char *ptr = info->text;
95 int i = 0;
96 #ifdef HAVE_LCD_BITMAP
97 bool scrollbar = false;
98 #endif
100 while (*ptr)
102 ptr = get_next_line(ptr, info);
103 i++;
104 #ifdef HAVE_LCD_BITMAP
105 if (!scrollbar && i > info->display_lines)
107 ptr = info->text;
108 i = 0;
109 info->scrollbar_vp = info->vp;
110 info->scrollbar_vp.width = rb->global_settings->scrollbar_width;
111 info->vp.width -= info->scrollbar_vp.width;
112 if (rb->global_settings->scrollbar != SCROLLBAR_RIGHT)
113 info->vp.x = info->scrollbar_vp.width;
114 else
115 info->scrollbar_vp.x = info->vp.width;
116 scrollbar = true;
118 #endif
120 info->line_count = i;
123 static void calc_first_line(struct view_info *info, int line)
125 const char *ptr = info->text;
126 int i = 0;
128 if (line > info->line_count - info->display_lines)
129 line = info->line_count - info->display_lines;
130 if (line < 0)
131 line = 0;
133 if (info->line <= line)
135 ptr += info->start;
136 i = info->line;
138 while (*ptr && i < line)
140 ptr = get_next_line(ptr, info);
141 i++;
143 info->start = ptr - info->text;
144 info->line = i;
147 static int init_view(struct view_info *info,
148 const char *title, const char *text)
150 rb->viewport_set_defaults(&info->vp, SCREEN_MAIN);
151 #ifdef HAVE_LCD_BITMAP
152 info->pf = rb->font_get(FONT_UI);
153 info->display_lines = info->vp.height / info->pf->height;
154 #else
155 info->display_lines = info->vp.height;
156 #endif
158 info->title = title;
159 info->text = text;
160 info->line_count = 0;
161 info->line = 0;
162 info->start = 0;
164 #ifdef HAVE_LCD_BITMAP
165 /* no title for small screens. */
166 if (info->display_lines < 4)
168 info->title = NULL;
170 else
172 info->display_lines--;
173 info->vp.y += info->pf->height;
174 info->vp.height -= info->pf->height;
176 #endif
178 calc_line_count(info);
179 return 0;
182 static void draw_text(struct view_info *info)
184 #ifdef HAVE_LCD_BITMAP
185 #define OUTPUT_SIZE LCD_WIDTH+1
186 #else
187 #define OUTPUT_SIZE LCD_WIDTH*3+1
188 #endif
189 static char output[OUTPUT_SIZE];
190 const char *text, *ptr;
191 int max_show, line;
192 struct screen* display = rb->screens[SCREEN_MAIN];
194 /* clear screen */
195 display->clear_display();
197 #ifdef HAVE_LCD_BITMAP
198 /* display title. */
199 if(info->title)
201 display->set_viewport(NULL);
202 display->puts(0, 0, info->title);
204 #endif
206 max_show = MIN(info->line_count - info->line, info->display_lines);
207 text = info->text + info->start;
209 display->set_viewport(&info->vp);
210 for (line = 0; line < max_show; line++)
212 int len;
213 ptr = get_next_line(text, info);
214 len = ptr-text;
215 while(len > 0 && isspace(text[len-1]))
216 len--;
217 rb->memcpy(output, text, len);
218 output[len] = 0;
219 display->puts(0, line, output);
220 text = ptr;
222 #ifdef HAVE_LCD_BITMAP
223 if (info->line_count > info->display_lines)
225 display->set_viewport(&info->scrollbar_vp);
226 rb->gui_scrollbar_draw(display, (info->scrollbar_vp.width? 0: 1), 0,
227 info->scrollbar_vp.width - 1, info->scrollbar_vp.height,
228 info->line_count, info->line, info->line + max_show,
229 VERTICAL);
231 #endif
233 display->set_viewport(NULL);
234 display->update();
237 static void scroll_up(struct view_info *info, int n)
239 if (info->line <= 0)
240 return;
242 calc_first_line(info, info->line-n);
243 draw_text(info);
246 static void scroll_down(struct view_info *info, int n)
248 if (info->line + info->display_lines >= info->line_count)
249 return;
251 calc_first_line(info, info->line+n);
252 draw_text(info);
255 static void scroll_to_top(struct view_info *info)
257 if (info->line <= 0)
258 return;
260 calc_first_line(info, 0);
261 draw_text(info);
264 static void scroll_to_bottom(struct view_info *info)
266 if (info->line + info->display_lines >= info->line_count)
267 return;
269 calc_first_line(info, info->line_count - info->display_lines);
270 draw_text(info);
273 int view_text(const char *title, const char *text)
275 struct view_info info;
276 const struct button_mapping *view_contexts[] = {
277 pla_main_ctx,
279 int button;
281 init_view(&info, title, text);
282 draw_text(&info);
284 /* wait for keypress */
285 while(1)
287 button = pluginlib_getaction(TIMEOUT_BLOCK, view_contexts,
288 ARRAYLEN(view_contexts));
289 switch (button)
291 case PLA_UP:
292 case PLA_UP_REPEAT:
293 #ifdef HAVE_SCROLLWHEEL
294 case PLA_SCROLL_BACK:
295 case PLA_SCROLL_BACK_REPEAT:
296 #endif
297 scroll_up(&info, 1);
298 break;
299 case PLA_DOWN:
300 case PLA_DOWN_REPEAT:
301 #ifdef HAVE_SCROLLWHEEL
302 case PLA_SCROLL_FWD:
303 case PLA_SCROLL_FWD_REPEAT:
304 #endif
305 scroll_down(&info, 1);
306 break;
307 case PLA_LEFT:
308 scroll_up(&info, info.display_lines);
309 break;
310 case PLA_RIGHT:
311 scroll_down(&info, info.display_lines);
312 break;
313 case PLA_LEFT_REPEAT:
314 scroll_to_top(&info);
315 break;
316 case PLA_RIGHT_REPEAT:
317 scroll_to_bottom(&info);
318 break;
319 case PLA_EXIT:
320 case PLA_CANCEL:
321 return PLUGIN_OK;
322 default:
323 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
324 return PLUGIN_USB_CONNECTED;
325 break;
329 return PLUGIN_OK;