diff --git a/apps/plugins/viewer.c b/apps/plugins/viewer.c old mode 100644 new mode 100755 index f01afbb..87f081b --- a/apps/plugins/viewer.c +++ b/apps/plugins/viewer.c @@ -39,6 +39,7 @@ PLUGIN_HEADER #define MID_SECTOR (buffer + SMALL_BLOCK_SIZE) #define BOTTOM_SECTOR (buffer + 2*(SMALL_BLOCK_SIZE)) #define SCROLLBAR_WIDTH 6 +#define MAX_PAGE 9999 #define MAX_BOOKMARKED_FILES ((buffer_size/(signed)sizeof(struct bookmarked_file_info))-1) @@ -356,6 +357,8 @@ PLUGIN_HEADER struct bookmarked_file_info { long file_position; int top_ptr_pos; + int bookmark_page; + int bookmark_line; char filename[MAX_PATH]; }; @@ -395,6 +398,16 @@ struct preferences { NO_OVERLAP=0, OVERLAP, } page_mode; + + enum { + PN_OFF = 0, + PN_ON + } page_number_mode; + + enum { + T_OFF = 0, + T_ON + } title_mode; #endif /* HAVE_LCD_BITMAP */ enum { @@ -422,18 +435,23 @@ static long file_size; static long start_position; /* position in the file after the viewer is started */ static bool mac_text; static long file_pos; /* Position of the top of the buffer in the file */ +static long last_file_pos; static unsigned char *buffer_end; /*Set to BUFFER_END() when file_pos changes*/ static int max_line_len; +static int cline = 1; +static int cpage = 1; +static int lpage = 0; static unsigned char *screen_top_ptr; static unsigned char *next_screen_ptr; static unsigned char *next_screen_to_draw_ptr; static unsigned char *next_line_ptr; +static unsigned char *last_screen_top_ptr = NULL; #ifdef HAVE_LCD_BITMAP static struct font *pf; #endif -int glyph_width(int ch) +static int glyph_width(int ch) { if (ch == 0) ch = ' '; @@ -445,7 +463,7 @@ int glyph_width(int ch) #endif } -unsigned char* get_ucs(const unsigned char* str, unsigned short* ch) +static unsigned char* get_ucs(const unsigned char* str, unsigned short* ch) { unsigned char utf8_tmp[6]; int count; @@ -809,17 +827,43 @@ static void viewer_scroll_up(void) } if (p != NULL) screen_top_ptr = p; + + if (prefs.scroll_mode == LINE) + { + if (cline > 1) + cline--; + else if (cpage > 1) + { + cpage--; + cline = display_lines; + } + } } -static void viewer_scroll_down(void) +static void viewer_scroll_down(bool autoscroll) { - if (next_screen_ptr != NULL) + if (cpage == lpage) + return; + + if (next_line_ptr != NULL) screen_top_ptr = next_line_ptr; + + if (prefs.scroll_mode == LINE || autoscroll) + { + if (cline < display_lines) + cline++; + else + { + if (cpage < MAX_PAGE) + cpage++; + cline = 1; + } + } } #ifdef HAVE_LCD_BITMAP static void viewer_scrollbar(void) { - int items, min_shown, max_shown; + 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); @@ -829,8 +873,28 @@ static void viewer_scrollbar(void) { else max_shown = min_shown + (next_screen_ptr - screen_top_ptr); - rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, 0, SCROLLBAR_WIDTH-1, - LCD_HEIGHT, items, min_shown, max_shown, VERTICAL); + sb_begin_y = (prefs.title_mode)?pf->height:0; + sb_height = LCD_HEIGHT - sb_begin_y + - ((prefs.page_number_mode)?pf->height:0); + + rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, sb_begin_y, + SCROLLBAR_WIDTH-1, sb_height, + items, min_shown, max_shown, VERTICAL); +} +#endif + +#ifdef HAVE_LCD_BITMAP +static void viewer_show_title(void) +{ + rb->lcd_putsxy(0, 0, file_name); +} + +static void viewer_show_page(void) +{ + unsigned char buf[6]; + + rb->snprintf(buf, sizeof(buf), "%d", cpage); + rb->lcd_putsxy(0, LCD_HEIGHT - pf->height, buf); } #endif @@ -862,7 +926,12 @@ static void viewer_draw(int col) for (i = 0; i < display_lines; i++) { if (BUFFER_OOB(line_end)) - break; /* Happens after display last line at BUFFER_EOF() */ + { + if (lpage == 0) + lpage = (cline == 1)?cpage:cpage+1; + if (lpage == cpage) + break; /* Happens after display last line at BUFFER_EOF() */ + } line_begin = line_end; line_end = find_next_line(line_begin, &line_is_short); @@ -1067,7 +1136,7 @@ static void viewer_draw(int col) } if (col != -1 && line_width > col) #ifdef HAVE_LCD_BITMAP - rb->lcd_putsxy(left_col, i*pf->height, utf8_buffer); + rb->lcd_putsxy(left_col, (i+((prefs.title_mode)?1:0))*pf->height, utf8_buffer); #else rb->lcd_puts(left_col, i, utf8_buffer); #endif @@ -1090,6 +1159,16 @@ static void viewer_draw(int col) next_screen_to_draw_ptr = next_screen_ptr; #endif +#ifdef HAVE_LCD_BITMAP + /* show title */ + if (prefs.title_mode) + viewer_show_title(); + + /* show page number */ + if (prefs.page_number_mode) + viewer_show_page(); +#endif + if (col != -1) rb->lcd_update(); } @@ -1106,32 +1185,62 @@ static void viewer_top(void) } screen_top_ptr = buffer; + cline = 1; + cpage = 1; } static void viewer_bottom(void) { - /* Read bottom of file into buffer - and point screen pointer to bottom */ - long last_sectors; - - if (file_size > buffer_size) { - /* Find last buffer in file, round up to next sector boundary */ - last_sectors = file_size - buffer_size + SMALL_BLOCK_SIZE; - last_sectors /= SMALL_BLOCK_SIZE; - last_sectors *= SMALL_BLOCK_SIZE; - } - else { - last_sectors = 0; - } + int resynch_move; + unsigned char *line_begin; + unsigned char *line_end; + + rb->splash(0, "Loading..."); - if (file_pos != last_sectors) + if (last_screen_top_ptr) { - file_pos = last_sectors; - buffer_end = BUFFER_END(); /* Update whenever file_pos changes */ - fill_buffer(last_sectors, buffer, buffer_size); + cline = 1; + cpage = lpage; + screen_top_ptr = last_screen_top_ptr; + file_pos = last_file_pos; + fill_buffer(file_pos, buffer, buffer_size); + buffer_end = BUFFER_END(); + return; } - screen_top_ptr = buffer_end-1; + line_end = screen_top_ptr; + + while (!BUFFER_EOF() || !BUFFER_OOB(line_end)) + { + line_begin = line_end; + line_end = find_next_line(line_begin, NULL); + + if (line_end == NULL && !BUFFER_EOF()) + { + resynch_move = read_and_synch(1); /* Read block & move ptrs */ + line_begin -= resynch_move; + if (next_line_ptr > buffer) + next_line_ptr -= resynch_move; + + line_end = find_next_line(line_begin, NULL); + if (line_end == NULL) /* Should not really happen */ + break; + } + + if (cline < display_lines) + cline++; + else + { + screen_top_ptr = line_end; + cline = 1; + if (cpage < MAX_PAGE) + cpage++; + } + } + cline = 1; + lpage = cpage; + last_screen_top_ptr = screen_top_ptr; + last_file_pos = file_pos; } #ifdef HAVE_LCD_BITMAP @@ -1143,8 +1252,19 @@ static void init_need_scrollbar(void) { draw_columns = prefs.need_scrollbar? display_columns-SCROLLBAR_WIDTH : display_columns; par_indent_spaces = draw_columns/(5*glyph_width(' ')); } + +static void init_header_footer(void) +{ + display_lines = LCD_HEIGHT / pf->height + - ((prefs.page_number_mode)?1:0) + - ((prefs.title_mode)?1:0); + + last_screen_top_ptr = NULL; +} + #else #define init_need_scrollbar() +#define init_header_footer() #endif static bool viewer_init(void) @@ -1153,7 +1273,6 @@ static bool viewer_init(void) pf = rb->font_get(FONT_UI); - display_lines = LCD_HEIGHT / pf->height; draw_columns = display_columns = LCD_WIDTH; #else /* REAL fixed pitch :) all chars use up 1 cell */ @@ -1185,6 +1304,8 @@ static void viewer_default_settings(void) #ifdef HAVE_LCD_BITMAP prefs.page_mode = NO_OVERLAP; prefs.scrollbar_mode = SB_OFF; + prefs.page_number_mode = PN_ON; + prefs.title_mode = T_ON; #endif prefs.autoscroll_speed = 1; /* Set codepage to system default */ @@ -1223,13 +1344,25 @@ static void viewer_load_settings(void) /* same name as global, but not the same rb->read(settings_fd, &data->bookmarked_files_count, sizeof(signed int)); if (data->bookmarked_files_count > MAX_BOOKMARKED_FILES) data->bookmarked_files_count = MAX_BOOKMARKED_FILES; - rb->read(settings_fd, data->bookmarks, - sizeof(struct bookmarked_file_info) * data->bookmarked_files_count); + + long size = sizeof(struct bookmarked_file_info) * + data->bookmarked_files_count; + + long rsize = rb->read(settings_fd, data->bookmarks, size); + rb->close(settings_fd); + + if (rsize != size) + { + data->bookmarked_files_count = 0; + rb->remove(BOOKMARKS_FILE); + } } file_pos = 0; screen_top_ptr = buffer; + cpage = 1; + cline = 1; /* check if current file is in list */ for (i=0; i < data->bookmarked_files_count; i++) @@ -1240,12 +1373,16 @@ static void viewer_load_settings(void) /* same name as global, but not the same int screen_top = screen_pos % buffer_size; file_pos = screen_pos - screen_top; screen_top_ptr = buffer + screen_top; + cpage = data->bookmarks[i].bookmark_page; + cline = data->bookmarks[i].bookmark_line; break; } } this_bookmark.file_position = file_pos; this_bookmark.top_ptr_pos = screen_top_ptr - buffer; + this_bookmark.bookmark_page = cpage; + this_bookmark.bookmark_line = cline; rb->memset(&this_bookmark.filename[0],0,MAX_PATH); rb->strcpy(this_bookmark.filename,file_name); @@ -1289,6 +1426,7 @@ static void viewer_load_settings(void) /* same name as global, but not the same start_position = file_pos + screen_top_ptr - buffer; init_need_scrollbar(); + init_header_footer(); } static void viewer_save_settings(void)/* same name as global, but not the same file.. */ @@ -1317,6 +1455,8 @@ static void viewer_save_settings(void)/* same name as global, but not the same f struct bookmarked_file_info b; b.file_position = file_pos + screen_top_ptr - buffer; b.top_ptr_pos = 0; /* this is only kept for legassy reasons */ + b.bookmark_page = cpage; + b.bookmark_line = cline; rb->memset(&b.filename[0],0,MAX_PATH); rb->strcpy(b.filename,file_name); rb->lseek(settings_fd,sizeof(signed int),SEEK_SET); @@ -1435,6 +1575,28 @@ static bool scrollbar_setting(void) return rb->set_option("Show Scrollbar", &prefs.scrollbar_mode, INT, names, 2, NULL); } + +static bool page_number_setting(void) +{ + static const struct opt_items names[] = { + {"No", -1}, + {"Yes", -1} + }; + + return rb->set_option("Show Page number", &prefs.page_number_mode, INT, + names, 2, NULL); +} + +static bool title_setting(void) +{ + static const struct opt_items names[] = { + {"No", -1}, + {"Yes", -1} + }; + + return rb->set_option("Show Title", &prefs.title_mode, INT, + names, 2, NULL); +} #endif static bool autoscroll_speed_setting(void) @@ -1456,6 +1618,8 @@ static bool viewer_options_menu(void) #ifdef HAVE_LCD_BITMAP {"Show Scrollbar", scrollbar_setting }, {"Overlap Pages", page_mode_setting }, + {"Show Page number", page_number_setting }, + {"Show Title", title_setting }, #endif {"Scroll Mode", scroll_mode_setting}, {"Auto-Scroll Speed", autoscroll_speed_setting }, @@ -1465,11 +1629,12 @@ static bool viewer_options_menu(void) result = menu_run(m); menu_exit(m); -#ifdef HAVE_LCD_BITMAP /* Show-scrollbar mode for current view-width mode */ init_need_scrollbar(); -#endif + + init_header_footer(); + return result; } @@ -1542,7 +1707,7 @@ enum plugin_status plugin_start(const void* file) { if(old_tick <= *rb->current_tick - (110-prefs.autoscroll_speed*10)) { - viewer_scroll_down(); + viewer_scroll_down(true); viewer_draw(col); old_tick = *rb->current_tick; } @@ -1573,6 +1738,9 @@ enum plugin_status plugin_start(const void* file) for (i = 0; i < display_lines; i++) #endif viewer_scroll_up(); + + if (cpage > 1) + cpage--; } else viewer_scroll_up(); @@ -1586,10 +1754,14 @@ enum plugin_status plugin_start(const void* file) { /* Page down */ if (next_screen_ptr != NULL) + { screen_top_ptr = next_screen_to_draw_ptr; + if (cpage < MAX_PAGE) + cpage++; + } } else - viewer_scroll_down(); + viewer_scroll_down(autoscroll); old_tick = *rb->current_tick; viewer_draw(col); break;