Prepare new maemo release
[maemo-rb.git] / apps / plugins / lib / simple_viewer.c
blob06cc9c1a71cf7fa45761075eb108a145d8002b54
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>
29 struct view_info {
30 #ifdef HAVE_LCD_BITMAP
31 struct font* pf;
32 struct viewport scrollbar_vp; /* viewport for scrollbar */
33 #endif
34 struct viewport vp;
35 const char *title;
36 const char *text; /* displayed text */
37 int display_lines; /* number of lines can be displayed */
38 int line_count; /* number of lines */
39 int line; /* current first line */
40 int start; /* possition of first line in text */
43 static bool isbrchr(const unsigned char *str, int len)
45 const unsigned char *p = "!,-.:;? 、。!,.:;?―";
46 if (isspace(*str))
47 return true;
49 while(*p)
51 int n = rb->utf8seek(p, 1);
52 if (len == n && !rb->strncmp(p, str, len))
53 return true;
54 p += n;
56 return false;
59 static const char* get_next_line(const char *text, struct view_info *info)
61 const char *ptr = text;
62 const char *space = NULL;
63 int total, n, w;
64 total = 0;
65 while(*ptr)
67 #ifdef HAVE_LCD_CHARCELLS
68 n = rb->utf8seek(ptr, 1);
69 w = 1;
70 #else
71 unsigned short ch;
72 n = ((long)rb->utf8decode(ptr, &ch) - (long)ptr);
73 if (rb->is_diacritic(ch, NULL))
74 w = 0;
75 else
76 w = rb->font_get_width(info->pf, ch);
77 #endif
78 if (isbrchr(ptr, n))
79 space = ptr+(isspace(*ptr) || total + w <= info->vp.width? n: 0);
80 if (*ptr == '\n')
82 ptr += n;
83 break;
85 if (total + w > info->vp.width)
86 break;
87 ptr += n;
88 total += w;
90 return *ptr && space? space: ptr;
93 static void calc_line_count(struct view_info *info)
95 const char *ptr = info->text;
96 int i = 0;
97 #ifdef HAVE_LCD_BITMAP
98 bool scrollbar = false;
99 #endif
101 while (*ptr)
103 ptr = get_next_line(ptr, info);
104 i++;
105 #ifdef HAVE_LCD_BITMAP
106 if (!scrollbar && i > info->display_lines)
108 ptr = info->text;
109 i = 0;
110 info->scrollbar_vp = info->vp;
111 info->scrollbar_vp.width = rb->global_settings->scrollbar_width;
112 info->vp.width -= info->scrollbar_vp.width;
113 if (rb->global_settings->scrollbar != SCROLLBAR_RIGHT)
114 info->vp.x = info->scrollbar_vp.width;
115 else
116 info->scrollbar_vp.x = info->vp.width;
117 scrollbar = true;
119 #endif
121 info->line_count = i;
124 static void calc_first_line(struct view_info *info, int line)
126 const char *ptr = info->text;
127 int i = 0;
129 if (line > info->line_count - info->display_lines)
130 line = info->line_count - info->display_lines;
131 if (line < 0)
132 line = 0;
134 if (info->line <= line)
136 ptr += info->start;
137 i = info->line;
139 while (*ptr && i < line)
141 ptr = get_next_line(ptr, info);
142 i++;
144 info->start = ptr - info->text;
145 info->line = i;
148 static int init_view(struct view_info *info,
149 const char *title, const char *text)
151 rb->viewport_set_defaults(&info->vp, SCREEN_MAIN);
152 #ifdef HAVE_LCD_BITMAP
153 info->pf = rb->font_get(FONT_UI);
154 info->display_lines = info->vp.height / info->pf->height;
155 #else
156 info->display_lines = info->vp.height;
157 #endif
159 info->title = title;
160 info->text = text;
161 info->line_count = 0;
162 info->line = 0;
163 info->start = 0;
165 #ifdef HAVE_LCD_BITMAP
166 /* no title for small screens. */
167 if (info->display_lines < 4)
169 info->title = NULL;
171 else
173 info->display_lines--;
174 info->vp.y += info->pf->height;
175 info->vp.height -= info->pf->height;
177 #endif
179 calc_line_count(info);
180 return 0;
183 static void draw_text(struct view_info *info)
185 #ifdef HAVE_LCD_BITMAP
186 #define OUTPUT_SIZE LCD_WIDTH+1
187 #else
188 #define OUTPUT_SIZE LCD_WIDTH*3+1
189 #endif
190 static char output[OUTPUT_SIZE];
191 const char *text, *ptr;
192 int max_show, line;
193 struct screen* display = rb->screens[SCREEN_MAIN];
195 /* clear screen */
196 display->clear_display();
198 #ifdef HAVE_LCD_BITMAP
199 /* display title. */
200 if(info->title)
202 display->set_viewport(NULL);
203 display->puts(0, 0, info->title);
205 #endif
207 max_show = MIN(info->line_count - info->line, info->display_lines);
208 text = info->text + info->start;
210 display->set_viewport(&info->vp);
211 for (line = 0; line < max_show; line++)
213 int len;
214 ptr = get_next_line(text, info);
215 len = ptr-text;
216 while(len > 0 && isspace(text[len-1]))
217 len--;
218 rb->memcpy(output, text, len);
219 output[len] = 0;
220 display->puts(0, line, output);
221 text = ptr;
223 #ifdef HAVE_LCD_BITMAP
224 if (info->line_count > info->display_lines)
226 display->set_viewport(&info->scrollbar_vp);
227 rb->gui_scrollbar_draw(display, (info->scrollbar_vp.width? 0: 1), 0,
228 info->scrollbar_vp.width - 1, info->scrollbar_vp.height,
229 info->line_count, info->line, info->line + max_show,
230 VERTICAL);
232 #endif
234 display->set_viewport(NULL);
235 display->update();
238 static void scroll_up(struct view_info *info, int n)
240 if (info->line <= 0)
241 return;
243 calc_first_line(info, info->line-n);
244 draw_text(info);
247 static void scroll_down(struct view_info *info, int n)
249 if (info->line + info->display_lines >= info->line_count)
250 return;
252 calc_first_line(info, info->line+n);
253 draw_text(info);
256 static void scroll_to_top(struct view_info *info)
258 if (info->line <= 0)
259 return;
261 calc_first_line(info, 0);
262 draw_text(info);
265 static void scroll_to_bottom(struct view_info *info)
267 if (info->line + info->display_lines >= info->line_count)
268 return;
270 calc_first_line(info, info->line_count - info->display_lines);
271 draw_text(info);
274 int view_text(const char *title, const char *text)
276 struct view_info info;
277 const struct button_mapping *view_contexts[] = {
278 pla_main_ctx,
280 int button;
282 init_view(&info, title, text);
283 draw_text(&info);
285 /* wait for keypress */
286 while(1)
288 button = pluginlib_getaction(TIMEOUT_BLOCK, view_contexts,
289 ARRAYLEN(view_contexts));
290 switch (button)
292 case PLA_UP:
293 case PLA_UP_REPEAT:
294 #ifdef HAVE_SCROLLWHEEL
295 case PLA_SCROLL_BACK:
296 case PLA_SCROLL_BACK_REPEAT:
297 #endif
298 scroll_up(&info, 1);
299 break;
300 case PLA_DOWN:
301 case PLA_DOWN_REPEAT:
302 #ifdef HAVE_SCROLLWHEEL
303 case PLA_SCROLL_FWD:
304 case PLA_SCROLL_FWD_REPEAT:
305 #endif
306 scroll_down(&info, 1);
307 break;
308 case PLA_LEFT:
309 scroll_up(&info, info.display_lines);
310 break;
311 case PLA_RIGHT:
312 scroll_down(&info, info.display_lines);
313 break;
314 case PLA_LEFT_REPEAT:
315 scroll_to_top(&info);
316 break;
317 case PLA_RIGHT_REPEAT:
318 scroll_to_bottom(&info);
319 break;
320 case PLA_EXIT:
321 case PLA_CANCEL:
322 return PLUGIN_OK;
323 default:
324 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
325 return PLUGIN_USB_CONNECTED;
326 break;
330 return PLUGIN_OK;