diff options
Diffstat (limited to 'apps/plugins/textviewer/tv_screen.c')
| -rw-r--r-- | apps/plugins/textviewer/tv_screen.c | 468 |
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); +} |