c733d5a0882894d19659f3cf77dfbd6d94d9e930
[kugel-rb.git] / apps / plugins / text_viewer / tv_window.c
blobc733d5a0882894d19659f3cf77dfbd6d94d9e930
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
23 #include "plugin.h"
24 #include "tv_bookmark.h"
25 #include "tv_preferences.h"
26 #include "tv_screen_pos.h"
27 #include "tv_text_reader.h"
28 #include "tv_window.h"
30 #define TV_SCROLLBAR_WIDTH rb->global_settings->scrollbar_width
31 #define TV_SCROLLBAR_HEIGHT 4
33 #ifndef HAVE_LCD_BITMAP
34 #define TV_BOOKMARK_ICON 0xe101
35 #endif
37 #ifdef HAVE_LCD_BITMAP
38 static int header_height;
39 static int footer_height;
40 static bool need_vertical_scrollbar = false;
41 #endif
43 static int start_width;
44 static int display_lines;
46 static int window_width;
47 static int window_columns;
48 static int col_width;
50 static int cur_window;
51 static int cur_column;
53 #ifdef HAVE_LCD_BITMAP
54 static bool tv_set_font(const unsigned char *font)
56 unsigned char path[MAX_PATH];
58 if (font != NULL && *font != '\0')
60 rb->snprintf(path, MAX_PATH, "%s/%s.fnt", FONT_DIR, font);
61 if (rb->font_load(NULL, path) < 0)
63 rb->splash(HZ/2, "font load failed");
64 return false;
67 return true;
70 static void tv_show_header(void)
72 unsigned header_mode = header_mode;
73 if (header_mode == HD_SBAR || header_mode == HD_BOTH)
74 rb->gui_syncstatusbar_draw(rb->statusbars, true);
76 if (header_mode == HD_PATH || header_mode == HD_BOTH)
77 rb->lcd_putsxy(0, header_height - preferences->font->height, preferences->file_name);
80 static void tv_show_footer(const struct tv_screen_pos *pos)
82 unsigned char buf[12];
83 unsigned footer_mode = preferences->footer_mode;
85 if (footer_mode == FT_SBAR || footer_mode == FT_BOTH)
86 rb->gui_syncstatusbar_draw(rb->statusbars, true);
88 if (footer_mode == FT_PAGE || footer_mode == FT_BOTH)
90 if (pos->line == 0)
91 rb->snprintf(buf, sizeof(buf), "%d", pos->page + 1);
92 else
93 rb->snprintf(buf, sizeof(buf), "%d - %d", pos->page + 1, pos->page + 2);
95 rb->lcd_putsxy(0, LCD_HEIGHT - footer_height, buf);
99 static void tv_show_scrollbar(off_t cur_pos, int size)
101 int items;
102 int min_shown;
103 int max_shown;
104 int sb_width;
105 int sb_height;
107 sb_height = LCD_HEIGHT - header_height - footer_height;
108 if (preferences->horizontal_scrollbar)
110 items = preferences->windows * window_columns;
111 min_shown = cur_window * window_columns + cur_column;
112 max_shown = min_shown + window_columns;
113 sb_width = (need_vertical_scrollbar)? TV_SCROLLBAR_WIDTH : 0;
114 sb_height -= TV_SCROLLBAR_HEIGHT;
116 rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],
117 sb_width,
118 LCD_HEIGHT - footer_height - TV_SCROLLBAR_HEIGHT,
119 LCD_WIDTH - sb_width, TV_SCROLLBAR_HEIGHT,
120 items, min_shown, max_shown, HORIZONTAL);
123 if (need_vertical_scrollbar)
125 items = (int) tv_get_total_text_size();
126 min_shown = (int) cur_pos;
127 max_shown = min_shown + size;
129 rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN], 0, header_height,
130 TV_SCROLLBAR_WIDTH-1, sb_height,
131 items, min_shown, max_shown, VERTICAL);
135 static int tv_calc_display_lines(void)
137 int scrollbar_height = preferences->horizontal_scrollbar ? TV_SCROLLBAR_HEIGHT : 0;
138 unsigned header_mode = preferences->header_mode;
139 unsigned footer_mode = preferences->footer_mode;
141 header_height = (header_mode == HD_SBAR || header_mode == HD_BOTH)?
142 STATUSBAR_HEIGHT : 0;
144 footer_height = (footer_mode == FT_SBAR || footer_mode == FT_BOTH)?
145 STATUSBAR_HEIGHT : 0;
147 if (header_mode == HD_NONE || header_mode == HD_PATH ||
148 footer_mode == FT_NONE || footer_mode == FT_PAGE)
149 rb->gui_syncstatusbar_draw(rb->statusbars, false);
151 if (header_mode == HD_PATH || header_mode == HD_BOTH)
152 header_height += preferences->font->height;
154 if (footer_mode == FT_PAGE || footer_mode == FT_BOTH)
155 footer_height += preferences->font->height;
157 return (LCD_HEIGHT - header_height - footer_height - scrollbar_height) / preferences->font->height;
159 #endif
161 static void tv_show_bookmarks(const struct tv_screen_pos *top_pos)
163 struct tv_screen_pos bookmarks[TV_MAX_BOOKMARKS];
164 int count = tv_get_bookmark_positions(bookmarks);
165 int line;
167 #ifdef HAVE_LCD_BITMAP
168 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
169 #endif
170 while (count--)
172 line = (bookmarks[count].page - top_pos->page) * display_lines
173 + (bookmarks[count].line - top_pos->line);
174 if (line >= 0 && line < display_lines)
176 #ifdef HAVE_LCD_BITMAP
177 rb->lcd_fillrect(start_width, header_height + line * preferences->font->height,
178 window_width, preferences->font->height);
179 #else
180 rb->lcd_putc(start_width - 1, line, TV_BOOKMARK_ICON);
181 #endif
184 #ifdef HAVE_LCD_BITMAP
185 rb->lcd_set_drawmode(DRMODE_SOLID);
186 #endif
189 void tv_draw_window(void)
191 struct tv_screen_pos pos;
192 const unsigned char *line_buf;
193 int line;
194 int offset = cur_column * col_width;
195 int size = 0;
196 int line_width;
197 int draw_width = (preferences->windows - cur_window) * LCD_WIDTH - offset;
198 int dx = start_width - offset;
200 tv_copy_screen_pos(&pos);
201 rb->lcd_clear_display();
203 if (preferences->alignment == LEFT)
204 tv_read_start(cur_window, (cur_column > 0));
205 else
206 tv_read_start(0, preferences->windows > 1);
208 for (line = 0; line < display_lines; line++)
210 if (!tv_get_next_line(&line_buf))
211 break;
213 if (preferences->alignment == RIGHT)
215 rb->lcd_getstringsize(line_buf, &line_width, NULL);
216 dx = draw_width - line_width;
219 #ifdef HAVE_LCD_BITMAP
220 rb->lcd_putsxy(dx, header_height + line * preferences->font->height, line_buf);
221 #else
222 rb->lcd_puts(dx, line, line_buf);
223 #endif
226 size = tv_read_end();
228 tv_show_bookmarks(&pos);
230 #ifdef HAVE_LCD_BITMAP
231 tv_show_scrollbar(pos.file_pos, size);
232 tv_show_header();
233 tv_show_footer(&pos);
234 #endif
236 rb->lcd_update();
239 bool tv_traverse_lines(void)
241 int i;
242 bool res = true;
244 tv_read_start(0, false);
245 for (i = 0; i < display_lines; i++)
247 if (!tv_get_next_line(NULL))
249 res = false;
250 break;
253 tv_read_end();
254 return res;
257 static void tv_change_preferences(const struct tv_preferences *oldp)
259 #ifdef HAVE_LCD_BITMAP
260 static bool font_changing = false;
261 const unsigned char *font_str;
263 font_str = (oldp && !font_changing)? oldp->font_name : rb->global_settings->font_file;
265 /* change font */
266 if (font_changing || rb->strcmp(font_str, preferences->font_name))
268 font_changing = true;
269 if (!tv_set_font(preferences->font_name))
271 struct tv_preferences new_prefs;
272 tv_copy_preferences(&new_prefs);
274 rb->strlcpy(new_prefs.font_name, font_str, MAX_PATH);
275 tv_set_preferences(&new_prefs);
276 return;
279 font_changing = false;
281 /* calculates display lines */
282 display_lines = tv_calc_display_lines();
283 #else
284 (void)oldp;
286 /* REAL fixed pitch :) all chars use up 1 cell */
287 display_lines = 2;
288 #endif
290 #ifdef HAVE_LCD_BITMAP
291 col_width = 2 * rb->font_get_width(preferences->font, ' ');
292 #else
293 col_width = 1;
294 #endif
296 if (cur_window >= preferences->windows)
297 cur_window = 0;
299 window_width = LCD_WIDTH;
300 #ifdef HAVE_LCD_BITMAP
301 need_vertical_scrollbar = false;
302 start_width = 0;
303 tv_seek_top();
304 tv_set_read_conditions(preferences->windows, window_width);
305 if (tv_traverse_lines() && preferences->vertical_scrollbar)
307 need_vertical_scrollbar = true;
308 start_width = TV_SCROLLBAR_WIDTH;
310 tv_seek_top();
311 #else
312 start_width = 1;
313 #endif
314 window_width -= start_width;
315 window_columns = window_width / col_width;
317 cur_column = 0;
319 tv_set_read_conditions(preferences->windows, window_width);
322 bool tv_init_window(void)
324 tv_add_preferences_change_listner(tv_change_preferences);
325 return tv_init_text_reader();
328 void tv_finalize_window(void)
330 tv_finalize_text_reader();
332 #ifdef HAVE_LCD_BITMAP
333 /* restore font */
334 if (rb->strcmp(rb->global_settings->font_file, preferences->font_name))
336 tv_set_font(rb->global_settings->font_file);
338 #endif
341 void tv_move_window(int window_delta, int column_delta)
343 cur_window += window_delta;
344 cur_column += column_delta;
346 if (cur_window < 0)
348 cur_window = 0;
349 cur_column = 0;
351 else if (cur_window >= preferences->windows)
353 cur_window = preferences->windows - 1;
354 cur_column = 0;
357 if (cur_column < 0)
359 if (cur_window == 0)
360 cur_column = 0;
361 else
363 cur_window--;
364 cur_column = window_columns - 1;
367 else
369 if (cur_window == preferences->windows - 1)
370 cur_column = 0;
371 else if (cur_column >= window_columns)
373 cur_window++;
374 cur_column = 0;