summaryrefslogtreecommitdiff
path: root/apps/plugins/textviewer/tv_screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/textviewer/tv_screen.c')
-rw-r--r--apps/plugins/textviewer/tv_screen.c468
1 files changed, 468 insertions, 0 deletions
diff --git a/apps/plugins/textviewer/tv_screen.c b/apps/plugins/textviewer/tv_screen.c
new file mode 100644
index 0000000..ce2d82d
--- /dev/null
+++ b/apps/plugins/textviewer/tv_screen.c
@@ -0,0 +1,468 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 Gilles Roux, 2003 Garrett Derner
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+#include "tv_screen.h"
+#include "tv_settings.h"
+
+static int draw_columns; /* number of (pixel) columns available for text */
+static int par_indent_spaces; /* number of spaces to indent first paragraph */
+
+#ifdef HAVE_LCD_BITMAP
+static struct font *pf;
+static int header_height = 0;
+static int footer_height = 0;
+#endif
+
+void viewer_init_screen(void)
+{
+#ifdef HAVE_LCD_BITMAP
+ /* initialize fonts */
+ pf = rb->font_get(FONT_UI);
+ draw_columns = display_columns = LCD_WIDTH;
+#else
+ /* REAL fixed pitch :) all chars use up 1 cell */
+ display_lines = 2;
+ draw_columns = display_columns = 11;
+ par_indent_spaces = 2;
+#endif
+}
+
+void viewer_finalize_screen(void)
+{
+ change_font(rb->global_settings->font_file);
+}
+
+void viewer_draw(void)
+{
+}
+
+void viewer_top(void)
+{
+ /* Read top of file into buffer
+ and point screen pointer to top */
+ if (file_pos != 0)
+ {
+ rb->splash(0, "Loading...");
+
+ file_pos = 0;
+ buffer_end = BUFFER_END(); /* Update whenever file_pos changes */
+ fill_buffer(0, buffer, buffer_size);
+ }
+
+ screen_top_ptr = buffer;
+ cpage = 1;
+ cline = 1;
+}
+
+void viewer_bottom(void)
+{
+ unsigned char *line_begin;
+ unsigned char *line_end;
+
+ rb->splash(0, "Loading...");
+
+ if (last_screen_top_ptr)
+ {
+ cpage = lpage;
+ cline = 1;
+ screen_top_ptr = last_screen_top_ptr;
+ file_pos = last_file_pos;
+ fill_buffer(file_pos, buffer, buffer_size);
+ buffer_end = BUFFER_END();
+ return;
+ }
+
+ line_end = screen_top_ptr;
+
+ while (!BUFFER_EOF() || !BUFFER_OOB(line_end))
+ {
+ get_next_line_position(&line_begin, &line_end, NULL);
+ if (line_end == NULL)
+ break;
+
+ increment_current_line();
+ if (cline == 1)
+ screen_top_ptr = line_end;
+ }
+ lpage = cpage;
+ cline = 1;
+ last_screen_top_ptr = screen_top_ptr;
+ last_file_pos = file_pos;
+ buffer_end = BUFFER_END();
+}
+
+static void increment_current_line(void)
+{
+ if (cline < display_lines)
+ cline++;
+ else if (cpage < MAX_PAGE)
+ {
+ cpage++;
+ cline = 1;
+ }
+}
+
+static void decrement_current_line(void)
+{
+ if (cline > 1)
+ cline--;
+ else if (cpage > 1)
+ {
+ cpage--;
+ cline = display_lines;
+ }
+}
+
+static void viewer_line_scroll_up(void)
+{
+ unsigned char *p;
+
+ p = find_prev_line(screen_top_ptr);
+ if (p == NULL && !BUFFER_BOF()) {
+ read_and_synch(-1);
+ p = find_prev_line(screen_top_ptr);
+ }
+ if (p != NULL)
+ screen_top_ptr = p;
+
+ decrement_current_line();
+}
+
+static void viewer_line_scroll_down(void)
+{
+ if (cpage == lpage)
+ return;
+
+ if (next_line_ptr != NULL)
+ screen_top_ptr = next_line_ptr;
+
+ increment_current_line();
+}
+
+static void viewer_scroll_to_top_line(void)
+{
+ int line;
+
+ for (line = cline; line > 1; line--)
+ viewer_scroll_up();
+}
+
+void viewer_scroll_up(int mode)
+{
+ int i;
+ int line_count = 1;
+ struct viewer_preference *prefs = viewer_get_preference();
+
+ if ((mode == VIEWER_SCROLL_PAGE) ||
+ (mode == VIEWER_SCROLL_PREFS && prefs->scroll_mode == PAGE))
+ {
+#ifdef HAVE_LCD_BITMAP
+ line_count = display_lines - ((prefs->page_mode==OVERLAP)? 1:0);
+#else
+ line_count = display_lines;
+#endif
+ }
+
+ for (i = 0; i < line_count; i++)
+ viewer_line_scroll_up();
+}
+
+void viewer_scroll_down(int mode)
+{
+ struct viewer_preference *prefs = viewer_get_preference();
+
+ if ((mode == VIEWER_SCROLL_PAGE) ||
+ (mode == VIEWER_SCROLL_PREFS && prefs->scroll_mode == PAGE))
+ {
+ /* Page down */
+ if (next_screen_ptr != NULL)
+ {
+ screen_top_ptr = next_screen_to_draw_ptr;
+ if (cpage < MAX_PAGE)
+ cpage++;
+ }
+ }
+ else
+ viewer_line_scroll_down();
+}
+
+#ifdef HAVE_LCD_BITMAP
+static void viewer_scrollbar(void) {
+ int items, min_shown, max_shown, sb_begin_y, sb_height;
+
+ items = (int) file_size; /* (SH1 int is same as long) */
+ min_shown = (int) file_pos + (screen_top_ptr - buffer);
+
+ if (next_screen_ptr == NULL)
+ max_shown = items;
+ else
+ max_shown = min_shown + (next_screen_ptr - screen_top_ptr);
+
+ sb_begin_y = header_height;
+ sb_height = LCD_HEIGHT - header_height - footer_height;
+
+ rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, sb_begin_y,
+ SCROLLBAR_WIDTH-1, sb_height,
+ items, min_shown, max_shown, VERTICAL);
+}
+
+static void viewer_show_header(void)
+{
+ struct viewer_preference *prefs = viewer_get_preference();
+
+ if (prefs->header_mode == HD_SBAR || prefs->header_mode == HD_BOTH)
+ rb->gui_syncstatusbar_draw(rb->statusbars, true);
+
+ if (prefs->header_mode == HD_PATH || prefs->header_mode == HD_BOTH)
+ rb->lcd_putsxy(0, header_height - pf->height, file_name);
+}
+
+static void viewer_show_footer(void)
+{
+ struct viewer_preference *prefs = viewer_get_preference();
+
+ if (prefs->footer_mode == FT_SBAR || prefs->footer_mode == FT_BOTH)
+ rb->gui_syncstatusbar_draw(rb->statusbars, true);
+
+ if (prefs->footer_mode == FT_PAGE || prefs->footer_mode == FT_BOTH)
+ {
+ unsigned char buf[12];
+
+ if (cline == 1)
+ rb->snprintf(buf, sizeof(buf), "%d", cpage);
+ else
+ rb->snprintf(buf, sizeof(buf), "%d - %d", cpage, cpage+1);
+
+ rb->lcd_putsxy(0, LCD_HEIGHT - footer_height, buf);
+ }
+}
+
+static bool need_scrollbar(void)
+{
+ struct viewer_preference *prefs = viewer_get_preference();
+
+ return prefs->need_scrollbar;
+}
+
+static void init_need_scrollbar(void) {
+ draw_columns = need_scrollbar()? display_columns-SCROLLBAR_WIDTH : display_columns;
+ par_indent_spaces = draw_columns/(5*glyph_width(' '));
+ calc_max_width();
+}
+
+static void init_header_and_footer(void)
+{
+ struct viewer_preference *prefs = viewer_get_preference();
+
+ header_height = 0;
+ footer_height = 0;
+ if (rb->global_settings->statusbar == STATUSBAR_TOP)
+ {
+ if (prefs->header_mode == HD_SBAR || prefs->header_mode == HD_BOTH)
+ header_height = STATUSBAR_HEIGHT;
+
+ if (prefs->footer_mode == FT_SBAR)
+ prefs->footer_mode = FT_NONE;
+ else if (prefs->footer_mode == FT_BOTH)
+ prefs->footer_mode = FT_PAGE;
+ }
+ else if (rb->global_settings->statusbar == STATUSBAR_BOTTOM)
+ {
+ if (prefs->footer_mode == FT_SBAR || prefs->footer_mode == FT_BOTH)
+ footer_height = STATUSBAR_HEIGHT;
+
+ if (prefs->header_mode == HD_SBAR)
+ prefs->header_mode = HD_NONE;
+ else if (prefs->header_mode == HD_BOTH)
+ prefs->header_mode = HD_PATH;
+ }
+ else /* STATUSBAR_OFF || STATUSBAR_CUSTOM */
+ {
+ if (prefs->header_mode == HD_SBAR)
+ prefs->header_mode = HD_NONE;
+ else if (prefs->header_mode == HD_BOTH)
+ prefs->header_mode = HD_PATH;
+
+ if (prefs->footer_mode == FT_SBAR)
+ prefs->footer_mode = FT_NONE;
+ else if (prefs->footer_mode == FT_BOTH)
+ prefs->footer_mode = FT_PAGE;
+ }
+
+ if (prefs->header_mode == HD_NONE || prefs->header_mode == HD_PATH ||
+ prefs->footer_mode == FT_NONE || prefs->footer_mode == FT_PAGE)
+ rb->gui_syncstatusbar_draw(rb->statusbars, false);
+
+ if (prefs->header_mode == HD_PATH || prefs->header_mode == HD_BOTH)
+ header_height += pf->height;
+ if (prefs->footer_mode == FT_PAGE || prefs->footer_mode == FT_BOTH)
+ footer_height += pf->height;
+
+ display_lines = (LCD_HEIGHT - header_height - footer_height) / pf->height;
+
+ lpage = 0;
+ last_file_pos = 0;
+ last_screen_top_ptr = NULL;
+}
+
+void change_font(unsigned char *font)
+{
+ unsigned char buf[MAX_PATH];
+ struct viewer_preference *prefs = viewer_get_preference();
+
+ if (font == NULL || *font == '\0')
+ return;
+
+ if (rb->strcmp(prefs->font, rb->global_settings->font_file) == 0)
+ return;
+
+ rb->snprintf(buf, MAX_PATH, "%s/%s.fnt", FONT_DIR, font);
+ if (rb->font_load(NULL, buf) < 0)
+ rb->splash(HZ/2, "font load failed.");
+}
+#else
+#define change_font(f)
+#endif
+
+static void calc_page(void)
+{
+ int i;
+ unsigned char *line_begin;
+ unsigned char *line_end;
+ off_t sfp;
+ unsigned char *sstp;
+ struct viewer_preference *prefs = viewer_get_preference();
+
+ rb->splash(0, "Calculating page/line number...");
+
+ /* add reading page to bookmarks */
+ viewer_add_last_read_bookmark();
+
+ rb->qsort(bookmarks, bookmark_count, sizeof(struct bookmark_info),
+ bm_comp);
+
+ cpage = 1;
+ cline = 1;
+ file_pos = 0;
+ screen_top_ptr = buffer;
+ buffer_end = BUFFER_END();
+
+ fill_buffer(file_pos, buffer, buffer_size);
+ line_end = line_begin = buffer;
+
+ for (i = 0; i < bookmark_count; i++)
+ {
+ sfp = bookmarks[i].file_position;
+ sstp = buffer;
+
+ while ((line_begin > sstp || sstp >= line_end) ||
+ (file_pos > sfp || sfp >= file_pos + BUFFER_END() - buffer))
+ {
+ get_next_line_position(&line_begin, &line_end, NULL);
+ if (line_end == NULL)
+ break;
+
+ next_line_ptr = line_end;
+
+ if (sstp == buffer &&
+ file_pos <= sfp && sfp < file_pos + BUFFER_END() - buffer)
+ sstp = sfp - file_pos + buffer;
+
+ increment_current_line();
+ }
+
+ decrement_current_line();
+ bookmarks[i].page = cpage;
+ bookmarks[i].line = cline;
+ bookmarks[i].file_position = file_pos + (line_begin - buffer);
+ increment_current_line();
+ }
+
+ /* remove reading page's bookmark */
+ for (i = 0; i < bookmark_count; i++)
+ {
+ if (bookmarks[i].flag & BOOKMARK_LAST)
+ {
+ int screen_pos;
+ int screen_top;
+
+ screen_pos = bookmarks[i].file_position;
+ screen_top = screen_pos % buffer_size;
+ file_pos = screen_pos - screen_top;
+ screen_top_ptr = buffer + screen_top;
+
+ cpage = bookmarks[i].page;
+ cline = bookmarks[i].line;
+ bookmarks[i].flag ^= BOOKMARK_LAST;
+ buffer_end = BUFFER_END();
+
+ fill_buffer(file_pos, buffer, buffer_size);
+
+ if (bookmarks[i].flag == 0)
+ viewer_remove_bookmark(i);
+
+ if (prefs->scroll_mode == PAGE && cline > 1)
+ viewer_scroll_to_top_line();
+ break;
+ }
+ }
+}
+
+static int col_limit(int col)
+{
+ if (col < 0)
+ col = 0;
+ else
+ if (col >= max_width)
+ col = max_width - draw_columns;
+
+ return col;
+}
+
+void viewer_scroll_left(int mode)
+{
+ if (mode == VIEWER_SCROLL_COLUMN)
+ {
+ /* Scroll left one column */
+ col -= glyph_width('o');
+ }
+ else
+ {
+ /* Screen left */
+ col -= draw_columns;
+ }
+ col = col_limit(col);
+}
+
+void viewer_scroll_right(int mode)
+{
+ if (mode == VIEWER_SCROLL_COLUMN)
+ {
+ /* Scroll right one column */
+ col += glyph_width('o');
+ }
+ else
+ {
+ /* Screen right */
+ col += draw_columns;
+ }
+ col = col_limit(col);
+}