diff options
author | Yoshihisa Uchida <uchida@rockbox.org> | 2010-06-05 10:30:08 +0000 |
---|---|---|
committer | Yoshihisa Uchida <uchida@rockbox.org> | 2010-06-05 10:30:08 +0000 |
commit | fdba8404503af0448586615330a7b27f2ced531c (patch) | |
tree | bb15677a7a720675ac2666f11e62042f3b2639ad /apps/plugins | |
parent | 991e92fd3dc15f1e365761264c26305559ddb0a4 (diff) | |
download | rockbox-fdba8404503af0448586615330a7b27f2ced531c.tar.gz rockbox-fdba8404503af0448586615330a7b27f2ced531c.zip |
reworks text viewer plugin. (FS#11209)
new text viewer plugin: text_viewer.rock.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26571 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
30 files changed, 4798 insertions, 2 deletions
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES index f797c4038d..437988bd22 100644 --- a/apps/plugins/CATEGORIES +++ b/apps/plugins/CATEGORIES @@ -111,6 +111,7 @@ test_touchscreen,apps test_viewports,apps test_greylib_bitmap_scale,viewers text_editor,apps +text_viewer,viewers theme_remove,viewers vbrfix,viewers video,viewers diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS index a6b5cda363..cf1e9d2b80 100644 --- a/apps/plugins/SUBDIRS +++ b/apps/plugins/SUBDIRS @@ -1,5 +1,6 @@ /* For all targets */ shortcuts +text_viewer /* For various targets... */ diff --git a/apps/plugins/text_viewer/SOURCES b/apps/plugins/text_viewer/SOURCES new file mode 100644 index 0000000000..7e45d1fb68 --- /dev/null +++ b/apps/plugins/text_viewer/SOURCES @@ -0,0 +1,12 @@ +text_viewer.c +tv_action.c +tv_bookmark.c +tv_menu.c +tv_pager.c +tv_preferences.c +tv_reader.c +tv_screen_pos.c +tv_settings.c +tv_text_processor.c +tv_text_reader.c +tv_window.c diff --git a/apps/plugins/text_viewer/readme.txt b/apps/plugins/text_viewer/readme.txt new file mode 100644 index 0000000000..f124370bdc --- /dev/null +++ b/apps/plugins/text_viewer/readme.txt @@ -0,0 +1,62 @@ +about the text viewer plugin. + +Limitation + for the target which PLUGIN_BUFFER_SIZE < 0x13000 (i.e., archos series), + can only be read up to 999 pages. + + +Difference between viewer.rock + [settings file] + - the global setting, 'tv_global.dat' is stored. + - Settings and bookmarks for each file, 'tv_file.dat' is stored. + + Note: when viewer.dat(viewer_file.dat) exists, tv_global.dat(tv_file.dat) is created by + using viewer.dat(viewer_file.dat). + + [wod wrap] + - add the following characters which can be split the line. + '!', ',', '.', ':', ';', '?', + U+00b7, U+2010, U+3000, U+3001, U+3002, U+30fb, U+30fc, + U+ff01, U+ff0c, U+ff0d, U+ff0e, U+ff1a, U+ff1b, U+ff1f. + + - when the line split, if the line length is short ( < 0.75 * display width), + split the line in display width. (thus, maybe split a word) + + [line mode] + [join] + - break line condition has changed. + - If the next line is a blank line or spaces only line, this line breaks. + + [reflow] + - indent changes two spaces. + - supports the player which does not define HAVE_LCD_BITMAP. + + [alignment] + - the right alignment supports the player which does not define HAVE_LCD_BITMAP. + + [bookmark] + - increased to 16 the number of bookmarks that can be registered. + + +TODO list + - for the target which PLUGIN_BUFFER_SIZE < 0x13000 (i.e., archos series), + supports more than 999 pages of text. + + - add History feature. + + - when the WIDE screen, allow to specify the number of screens. + + - when the line_mode is reflow, allow to specify indent spaces. + + - for the horizontal scroll, allow the select scroll by screen/scroll by column for the settings menu. + + - can display the horizontal scroll bar. + + - draw images that are linked to the text. (<img src="...">) + + - play audios that are linked to the text. (<audio src="...">) + + - more treatments of line breaking, word wrappings. + (for example, period does not appear the top of line.) + + - whether scroll to prev/next page or scroll to top page/bottom page can be select the settings menu. diff --git a/apps/plugins/text_viewer/text_viewer.c b/apps/plugins/text_viewer/text_viewer.c new file mode 100644 index 0000000000..7150498b56 --- /dev/null +++ b/apps/plugins/text_viewer/text_viewer.c @@ -0,0 +1,210 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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_action.h" +#include "tv_button.h" +#include "tv_preferences.h" + +PLUGIN_HEADER + +enum plugin_status plugin_start(const void* file) +{ + int button; + int lastbutton = BUTTON_NONE; + bool autoscroll = false; + long old_tick; + bool done = false; + bool display_update = true; + const struct tv_preferences *prefs = tv_get_preferences(); + + old_tick = *rb->current_tick; + + if (!file) + return PLUGIN_ERROR; + + if (!tv_init(file)) { + rb->splash(HZ, "Error opening file"); + return PLUGIN_ERROR; + } + +#if LCD_DEPTH > 1 + rb->lcd_set_backdrop(NULL); +#endif + + while (!done) { + + if (display_update) + tv_draw(); + + display_update = true; + + button = rb->button_get_w_tmo(HZ/10); + + switch (button) { + case TV_MENU: +#ifdef TV_MENU2 + case TV_MENU2: +#endif + { + enum tv_menu_result res = tv_menu(); + + if (res != TV_MENU_RESULT_EXIT_MENU) + { + tv_exit(NULL); + done = true; + if (res == TV_MENU_RESULT_ATTACHED_USB) + return PLUGIN_USB_CONNECTED; + } + } + break; + + case TV_AUTOSCROLL: +#ifdef TV_AUTOSCROLL_PRE + if (lastbutton != TV_AUTOSCROLL_PRE) + break; +#endif + autoscroll = !autoscroll; + break; + + case TV_SCROLL_UP: + case TV_SCROLL_UP | BUTTON_REPEAT: +#ifdef TV_SCROLL_UP2 + case TV_SCROLL_UP2: + case TV_SCROLL_UP2 | BUTTON_REPEAT: +#endif + tv_scroll_up(TV_VERTICAL_SCROLL_PREFS); + old_tick = *rb->current_tick; + break; + + case TV_SCROLL_DOWN: + case TV_SCROLL_DOWN | BUTTON_REPEAT: +#ifdef TV_PAGE_DOWN2 + case TV_SCROLL_DOWN2: + case TV_SCROLL_DOWN2 | BUTTON_REPEAT: +#endif + tv_scroll_down(TV_VERTICAL_SCROLL_PREFS); + old_tick = *rb->current_tick; + break; + + case TV_SCREEN_LEFT: + case TV_SCREEN_LEFT | BUTTON_REPEAT: + if (prefs->view_mode == WIDE) + { + /* Screen left */ + tv_scroll_left(TV_HORIZONTAL_SCROLL_WINDOW); + } + else { /* prefs->view_mode == NARROW */ + /* scroll to previous page */ + tv_scroll_up(TV_VERTICAL_SCROLL_PAGE); +#if 0 + /* Top of file */ + tv_top(); +#endif + } + break; + + case TV_SCREEN_RIGHT: + case TV_SCREEN_RIGHT | BUTTON_REPEAT: + if (prefs->view_mode == WIDE) + { + /* Screen right */ + tv_scroll_right(TV_HORIZONTAL_SCROLL_WINDOW); + } + else { /* prefs->view_mode == NARROW */ + /* scroll to next page */ + tv_scroll_down(TV_VERTICAL_SCROLL_PAGE); +#if 0 + /* Bottom of file */ + tv_bottom(); +#endif + } + break; + +#ifdef TV_LINE_UP + case TV_LINE_UP: + case TV_LINE_UP | BUTTON_REPEAT: + /* Scroll up one line */ + tv_scroll_up(TV_VERTICAL_SCROLL_LINE); + old_tick = *rb->current_tick; + break; + + case TV_LINE_DOWN: + case TV_LINE_DOWN | BUTTON_REPEAT: + /* Scroll down one line */ + tv_scroll_down(TV_VERTICAL_SCROLL_LINE); + old_tick = *rb->current_tick; + break; +#endif +#ifdef TV_COLUMN_LEFT + case TV_COLUMN_LEFT: + case TV_COLUMN_LEFT | BUTTON_REPEAT: + /* Scroll left one column */ + tv_scroll_left(TV_HORIZONTAL_SCROLL_COLUMN); + break; + + case TV_COLUMN_RIGHT: + case TV_COLUMN_RIGHT | BUTTON_REPEAT: + /* Scroll right one column */ + tv_scroll_right(TV_HORIZONTAL_SCROLL_COLUMN); + break; +#endif + +#ifdef TV_RC_QUIT + case TV_RC_QUIT: +#endif + case TV_QUIT: +#ifdef TV_QUIT2 + case TV_QUIT2: +#endif + tv_exit(NULL); + done = true; + break; + + case TV_BOOKMARK: + tv_add_or_remove_bookmark(); + break; + + default: + if (rb->default_event_handler_ex(button, tv_exit, NULL) + == SYS_USB_CONNECTED) + return PLUGIN_USB_CONNECTED; + display_update = false; + break; + } + if (button != BUTTON_NONE) + { + lastbutton = button; + rb->yield(); + } + if (autoscroll) + { + if(old_tick <= *rb->current_tick - (110 - prefs->autoscroll_speed * 10)) + { + tv_scroll_down(TV_VERTICAL_SCROLL_PREFS); + old_tick = *rb->current_tick; + display_update = true; + } + } + } + return PLUGIN_OK; +} diff --git a/apps/plugins/text_viewer/text_viewer.make b/apps/plugins/text_viewer/text_viewer.make new file mode 100644 index 0000000000..8cb2963faf --- /dev/null +++ b/apps/plugins/text_viewer/text_viewer.make @@ -0,0 +1,20 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +TEXT_VIEWER_SRCDIR := $(APPSDIR)/plugins/text_viewer +TEXT_VIEWER_BUILDDIR := $(BUILDDIR)/apps/plugins/text_viewer + +TEXT_VIEWER_SRC := $(call preprocess, $(TEXT_VIEWER_SRCDIR)/SOURCES) +TEXT_VIEWER_OBJ := $(call c2obj, $(TEXT_VIEWER_SRC)) + +OTHER_SRC += $(TEXT_VIEWER_SRC) + +ROCKS += $(TEXT_VIEWER_BUILDDIR)/text_viewer.rock + +$(TEXT_VIEWER_BUILDDIR)/text_viewer.rock: $(TEXT_VIEWER_OBJ) diff --git a/apps/plugins/text_viewer/tv_action.c b/apps/plugins/text_viewer/tv_action.c new file mode 100644 index 0000000000..fb7fdb40e6 --- /dev/null +++ b/apps/plugins/text_viewer/tv_action.c @@ -0,0 +1,186 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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_action.h" +#include "tv_bookmark.h" +#include "tv_pager.h" +#include "tv_screen_pos.h" +#include "tv_settings.h" +#include "tv_window.h" + +static const struct tv_preferences *prefs; + +bool tv_init(const unsigned char *file) +{ + size_t req_size = 0; + size_t size; + size_t used_size; + unsigned char *buffer; + + /* get the plugin buffer */ + buffer = rb->plugin_get_buffer(&req_size); + size = req_size; + if (buffer == NULL || size == 0) + return false; + + prefs = tv_get_preferences(); + + tv_init_bookmark(); + + /* initialize modules */ + if (!tv_init_window(buffer, size, &used_size)) + return false; + + /* load the preferences and bookmark */ + tv_load_settings(file); + + /* select to read the page */ + tv_select_bookmark(); + return true; +} + +void tv_exit(void *parameter) +{ + (void)parameter; + + /* save preference and bookmarks */ + if (!tv_save_settings()) + rb->splash(HZ, "Can't save preferences and bookmarks"); + + /* finalize modules */ + tv_finalize_window(); +} + +void tv_draw(void) +{ + struct tv_screen_pos pos; + + tv_copy_screen_pos(&pos); + tv_draw_window(); + if (pos.line == 0) + tv_new_page(); + + tv_move_screen(pos.page, pos.line, SEEK_SET); +} + +void tv_scroll_up(enum tv_vertical_scroll_mode mode) +{ + int offset_page = 0; + int offset_line = -1; + + if ((mode == TV_VERTICAL_SCROLL_PAGE) || + (mode == TV_VERTICAL_SCROLL_PREFS && prefs->scroll_mode == PAGE)) + { + offset_page--; +#ifdef HAVE_LCD_BITMAP + offset_line = (prefs->page_mode == OVERLAP)? 1:0; +#endif + } + tv_move_screen(offset_page, offset_line, SEEK_CUR); +} + +void tv_scroll_down(enum tv_vertical_scroll_mode mode) +{ + int offset_page = 0; + int offset_line = 1; + + if ((mode == TV_VERTICAL_SCROLL_PAGE) || + (mode == TV_VERTICAL_SCROLL_PREFS && prefs->scroll_mode == PAGE)) + { + offset_page++; +#ifdef HAVE_LCD_BITMAP + offset_line = (prefs->page_mode == OVERLAP)? -1:0; +#endif + } + tv_move_screen(offset_page, offset_line, SEEK_CUR); +} + +void tv_scroll_left(enum tv_horizontal_scroll_mode mode) +{ + int offset_window = 0; + int offset_column = 0; + + if (mode == TV_HORIZONTAL_SCROLL_COLUMN) + { + /* Scroll left one column */ + offset_column--; + } + else + { + /* Scroll left one window */ + offset_window--; + } + tv_move_window(offset_window, offset_column); +} + +void tv_scroll_right(enum tv_horizontal_scroll_mode mode) +{ + int offset_window = 0; + int offset_column = 0; + + if (mode == TV_HORIZONTAL_SCROLL_COLUMN) + { + /* Scroll right one column */ + offset_column++; + } + else + { + /* Scroll right one window */ + offset_window++; + } + tv_move_window(offset_window, offset_column); +} + +void tv_top(void) +{ + tv_move_screen(0, 0, SEEK_SET); +} + +void tv_bottom(void) +{ + tv_move_screen(0, 0, SEEK_END); + if (prefs->scroll_mode == PAGE) + tv_move_screen(0, -tv_get_screen_pos()->line, SEEK_CUR); +} + +enum tv_menu_result tv_menu(void) +{ + enum tv_menu_result res; + struct tv_screen_pos cur_pos; + off_t cur_file_pos = tv_get_screen_pos()->file_pos; + + res = tv_display_menu(); + + tv_convert_fpos(cur_file_pos, &cur_pos); + if (prefs->scroll_mode == PAGE) + cur_pos.line = 0; + + tv_move_screen(cur_pos.page, cur_pos.line, SEEK_SET); + + return res; +} + +void tv_add_or_remove_bookmark(void) +{ + tv_toggle_bookmark(); +} diff --git a/apps/plugins/text_viewer/tv_action.h b/apps/plugins/text_viewer/tv_action.h new file mode 100644 index 0000000000..c5f7bd0e2f --- /dev/null +++ b/apps/plugins/text_viewer/tv_action.h @@ -0,0 +1,119 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_ACTION_H +#define PLUGIN_TEXT_VIEWER_ACTION_H + +#include "tv_menu.h" + +/* horizontal scroll mode */ +enum tv_horizontal_scroll_mode +{ + TV_HORIZONTAL_SCROLL_COLUMN, /* left/right one column */ + TV_HORIZONTAL_SCROLL_WINDOW, /* left/right one window */ + TV_HORIZONTAL_SCROLL_PREFS, /* left/right follows the settings */ +}; + +/*vertical scroll mode */ +enum tv_vertical_scroll_mode +{ + TV_VERTICAL_SCROLL_LINE, /* up/down one line */ + TV_VERTICAL_SCROLL_PAGE, /* up/down one page */ + TV_VERTICAL_SCROLL_PREFS, /* up/down follows the settings */ +}; + +/* + * initialize modules + * + * [In] file + * read file name + * + * return + * true initialize success + * false initialize failure + */ +bool tv_init(const unsigned char *file); + +/* + * finalize modules + * + * [In] parameter + * this argument does not use + */ +void tv_exit(void *parameter); + +/* draw the current page */ +void tv_draw(void); + +/* + * scroll up + * + * [In] mode + * scroll mode + */ +void tv_scroll_up(enum tv_vertical_scroll_mode mode); + +/* + * scroll down + * + * [In] mode + * scroll mode + */ +void tv_scroll_down(enum tv_vertical_scroll_mode mode); + +/* + * scroll left + * + * [In] mode + * scroll mode + */ +void tv_scroll_left(enum tv_horizontal_scroll_mode mode); + +/* + * scroll right + * + * [In] mode + * scroll mode + */ +void tv_scroll_right(enum tv_horizontal_scroll_mode mode); + +/* jump to the top */ +void tv_top(void); + +/* jump to the bottom */ +void tv_bottom(void); + +/* + * display menu + * + * return + * the following value returns + * TV_MENU_RESULT_EXIT_MENU menu exit and continue this plugin + * TV_MENU_RESULT_EXIT_PLUGIN request to exit this plugin + * TV_MENU_RESULT_ATTACHED_USB connect USB cable + */ +enum tv_menu_result tv_menu(void); + +/* add or remove the bookmark to the current position */ +void tv_add_or_remove_bookmark(void); + +#endif diff --git a/apps/plugins/text_viewer/tv_bookmark.c b/apps/plugins/text_viewer/tv_bookmark.c new file mode 100644 index 0000000000..61df02705e --- /dev/null +++ b/apps/plugins/text_viewer/tv_bookmark.c @@ -0,0 +1,302 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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_bookmark.h" +#include "tv_pager.h" +#include "tv_preferences.h" + +/* text viewer bookmark functions */ + +enum { + TV_BOOKMARK_SYSTEM = 1, + TV_BOOKMARK_USER = 2, +}; + +#define SERIALIZE_BOOKMARK_SIZE 8 + +struct tv_bookmark_info { + struct tv_screen_pos pos; + unsigned char flag; +}; + +/* bookmark stored array */ +struct tv_bookmark_info bookmarks[TV_MAX_BOOKMARKS + 1]; +static unsigned char bookmark_count; + +static int tv_compare_screen_pos(const struct tv_screen_pos *p1, const struct tv_screen_pos *p2) +{ + if (p1->page != p2->page) + return p1->page - p2->page; + + return p1->line - p2->line; +} + +static int bm_comp(const void *a, const void *b) +{ + struct tv_bookmark_info *pa; + struct tv_bookmark_info *pb; + + pa = (struct tv_bookmark_info*)a; + pb = (struct tv_bookmark_info*)b; + + return tv_compare_screen_pos(&pa->pos, &pb->pos); +} + +static int tv_add_bookmark(const struct tv_screen_pos *pos) +{ + if (bookmark_count >= TV_MAX_BOOKMARKS) + return -1; + + bookmarks[bookmark_count].pos = *pos; + bookmarks[bookmark_count].flag = TV_BOOKMARK_USER; + + return bookmark_count++; +} + +static void tv_remove_bookmark(int idx) +{ + int k; + + if (idx >= 0 && idx < bookmark_count) + { + for (k = idx + 1; k < bookmark_count; k++) + bookmarks[k-1] = bookmarks[k]; + + bookmark_count--; + } +} + +static int tv_find_bookmark(const struct tv_screen_pos *pos) +{ + int i; + + for (i = 0; i < bookmark_count; i++) + { + if (tv_compare_screen_pos(&bookmarks[i].pos, pos) == 0) + return i; + } + return -1; +} + +static void tv_change_preferences(const struct tv_preferences *oldp) +{ + int i; + + if (oldp == NULL) + return; + + for (i = 0; i < bookmark_count; i++) + tv_convert_fpos(bookmarks[i].pos.file_pos, &bookmarks[i].pos); +} + +void tv_init_bookmark(void) +{ + tv_add_preferences_change_listner(tv_change_preferences); +} + +int tv_get_bookmark_positions(struct tv_screen_pos *pos_array) +{ + int i; + + for(i = 0; i < bookmark_count; i++) + *pos_array++ = bookmarks[i].pos; + + return bookmark_count; +} + +void tv_toggle_bookmark(void) +{ + const struct tv_screen_pos *pos = tv_get_screen_pos(); + int idx = tv_find_bookmark(pos); + + if (idx < 0) + { + if (tv_add_bookmark(pos) >= 0) + rb->splash(HZ/2, "Bookmark add"); + else + rb->splash(HZ/2, "No more add bookmark"); + return; + } + tv_remove_bookmark(idx); + rb->splash(HZ/2, "Bookmark remove"); +} + +void tv_create_system_bookmark(void) +{ + const struct tv_screen_pos *pos = tv_get_screen_pos(); + int idx = tv_find_bookmark(pos); + + if (idx >= 0) + bookmarks[idx].flag |= TV_BOOKMARK_SYSTEM; + else + { + bookmarks[bookmark_count].pos = *pos; + bookmarks[bookmark_count].flag = TV_BOOKMARK_SYSTEM; + bookmark_count++; + } +} + +void tv_select_bookmark(void) +{ + int i; + struct tv_screen_pos select_pos; + + for (i = 0; i < bookmark_count; i++) + { + if (bookmarks[i].flag & TV_BOOKMARK_SYSTEM) + break; + } + + /* if does not find the system bookmark, add the system bookmark. */ + if (i >= bookmark_count) + tv_create_system_bookmark(); + + if (bookmark_count == 1) + select_pos = bookmarks[0].pos; + else + { + int selected = -1; + struct opt_items items[bookmark_count]; + unsigned char names[bookmark_count][24]; + + rb->qsort(bookmarks, bookmark_count, sizeof(struct tv_bookmark_info), bm_comp); + + for (i = 0; i < bookmark_count; i++) + { + rb->snprintf(names[i], sizeof(names[0]), +#if CONFIG_KEYPAD != PLAYER_PAD + "%cPage: %d Line: %d", +#else + "%cP:%d L:%d", +#endif + (bookmarks[i].flag & TV_BOOKMARK_SYSTEM)? '*' : ' ', + bookmarks[i].pos.page + 1, + bookmarks[i].pos.line + 1); + items[i].string = names[i]; + items[i].voice_id = -1; + } + + rb->set_option("Select bookmark", &selected, INT, items, + bookmark_count, NULL); + + if (selected >= 0 && selected < bookmark_count) + select_pos = bookmarks[selected].pos; + else + { + /* when does not select any bookmarks, move to the current page */ + tv_copy_screen_pos(&select_pos); + + if (select_pos.file_pos == 0) + rb->splash(HZ, "Start the first page"); + else + rb->splash(HZ, "Return to the current page"); + } + } + + /* deletes the system bookmark */ + for (i = 0; i < bookmark_count; i++) + { + if ((bookmarks[i].flag &= TV_BOOKMARK_USER) == 0) + { + tv_remove_bookmark(i); + break; + } + } + + /* move to the select position */ + if (tv_get_preferences()->scroll_mode == PAGE) + select_pos.line = 0; + + tv_move_screen(select_pos.page, select_pos.line, SEEK_SET); +} + +/* serialize or deserialize of the bookmark array */ +static bool tv_read_bookmark_info(int fd, struct tv_bookmark_info *b) +{ + unsigned char buf[SERIALIZE_BOOKMARK_SIZE]; + + if (rb->read(fd, buf, sizeof(buf)) < 0) + return false; + + b->pos.file_pos = (buf[0] << 24)|(buf[1] << 16)|(buf[2] << 8)|buf[3]; + b->pos.page = (buf[4] << 8)|buf[5]; + b->pos.line = buf[6]; + b->flag = buf[7]; + + return true; +} + +bool tv_deserialize_bookmarks(int fd) +{ + int i; + bool res = true; + + if (rb->read(fd, &bookmark_count, 1) < 0) + return false; + + for (i = 0; i < bookmark_count; i++) + { + if (!tv_read_bookmark_info(fd, &bookmarks[i])) + { + res = false; + break; + } + } + + bookmark_count = i; + return res; +} + +static bool tv_write_bookmark_info(int fd, const struct tv_bookmark_info *b) +{ + unsigned char buf[SERIALIZE_BOOKMARK_SIZE]; + unsigned char *p = buf; + + *p++ = b->pos.file_pos >> 24; + *p++ = b->pos.file_pos >> 16; + *p++ = b->pos.file_pos >> 8; + *p++ = b->pos.file_pos; + + *p++ = b->pos.page >> 8; + *p++ = b->pos.page; + + *p++ = b->pos.line; + *p = b->flag; + + return (rb->write(fd, buf, SERIALIZE_BOOKMARK_SIZE) >= 0); +} + +int tv_serialize_bookmarks(int fd) +{ + int i; + + if (rb->write(fd, &bookmark_count, 1) < 0) + return 0; + + for (i = 0; i < bookmark_count; i++) + { + if (!tv_write_bookmark_info(fd, &bookmarks[i])) + break; + } + return i * SERIALIZE_BOOKMARK_SIZE + 1; +} diff --git a/apps/plugins/text_viewer/tv_bookmark.h b/apps/plugins/text_viewer/tv_bookmark.h new file mode 100644 index 0000000000..d61af41620 --- /dev/null +++ b/apps/plugins/text_viewer/tv_bookmark.h @@ -0,0 +1,85 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_BOOKMARK_H +#define PLUGIN_TEXT_VIEWER_BOOKMARK_H + +#include "tv_screen_pos.h" + +/* stuff for the bookmarking */ + +/* Maximum amount of register possible bookmarks */ +#define TV_MAX_BOOKMARKS 16 + +/* initialize the bookmark module */ +void tv_init_bookmark(void); + +/* + * get the positions which registered bookmarks + * + * [Out] pos_array + * the array which store positions of all bookmarks + * + * return + * bookmark count + */ +int tv_get_bookmark_positions(struct tv_screen_pos *pos_array); + +/* + * the function that a bookmark add when there is not a bookmark in the given position + * or the bookmark remove when there exist a bookmark in the given position. + */ +void tv_toggle_bookmark(void); + +/* + * The menu that can select registered bookmarks is displayed, one is selected from + * among them, and moves to the page which selected bookmarks. + */ +void tv_select_bookmark(void); + +/* creates system bookmark */ +void tv_create_system_bookmark(void); + +/* + * serialize the bookmark array + * + * [In] fd + * the file descripter which is stored the result. + * + * Return + * the size of the result + */ +int tv_serialize_bookmarks(int fd); + +/* + * deserialize the bookmark array + * + * [In] fd + * the file descripter which is stored the serialization of the bookmark array. + * + * Return + * true success + * false failure + */ +bool tv_deserialize_bookmarks(int fd); + +#endif diff --git a/apps/plugins/text_viewer/tv_button.h b/apps/plugins/text_viewer/tv_button.h new file mode 100644 index 0000000000..53114c6169 --- /dev/null +++ b/apps/plugins/text_viewer/tv_button.h @@ -0,0 +1,424 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_BUTTON_H +#define PLUGIN_TEXT_VIEWER_BUTTON_H + +/* variable button definitions */ + +/* + * [required] + * TV_QUIT exit txit viewer + * TV_SCROLL_UP scroll up + * TV_SCROLL_DOWN scroll down + * TV_SCREEN_LEFT scroll left (when wide mode)/scroll previous page (when narrow mode) + * TV_SCREEN_RIGHT scroll right (when wide mode)/scroll next page (when narrow mode) + * TV_MENU enter menu + * TV_AUTOSCROLL toggle autoscroll + * TV_BOOKMARK set/reset bookmark + * + * [optional] + * TV_RC_QUIT exit text plugin (remote key only) + * TV_LINE_UP one line up + * TV_LINE_DOWN one line down + * TV_COLUMN_LEFT one column left + * TV_COLUMN_RIGHT one column right + */ + +/* Recorder keys */ +#if CONFIG_KEYPAD == RECORDER_PAD +#define TV_QUIT BUTTON_OFF +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_F1 +#define TV_AUTOSCROLL BUTTON_PLAY +#define TV_LINE_UP (BUTTON_ON | BUTTON_UP) +#define TV_LINE_DOWN (BUTTON_ON | BUTTON_DOWN) +#define TV_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT) +#define TV_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT) +#define TV_BOOKMARK BUTTON_F2 + +/* Archos AV300 keys */ +#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD +#define TV_QUIT BUTTON_OFF +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_F1 +#define TV_AUTOSCROLL BUTTON_SELECT +#define TV_LINE_UP (BUTTON_ON | BUTTON_UP) +#define TV_LINE_DOWN (BUTTON_ON | BUTTON_DOWN) +#define TV_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT) +#define TV_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT) +#define TV_BOOKMARK BUTTON_F2 + +/* Ondio keys */ +#elif CONFIG_KEYPAD == ONDIO_PAD +#define TV_QUIT BUTTON_OFF +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU (BUTTON_MENU|BUTTON_REPEAT) +#define TV_AUTOSCROLL_PRE BUTTON_MENU +#define TV_AUTOSCROLL (BUTTON_MENU|BUTTON_REL) +#define TV_BOOKMARK (BUTTON_MENU|BUTTON_OFF) + +/* Player keys */ +#elif CONFIG_KEYPAD == PLAYER_PAD +#define TV_QUIT BUTTON_STOP +#define TV_SCROLL_UP BUTTON_LEFT +#define TV_SCROLL_DOWN BUTTON_RIGHT +#define TV_SCREEN_LEFT (BUTTON_ON|BUTTON_LEFT) +#define TV_SCREEN_RIGHT (BUTTON_ON|BUTTON_RIGHT) +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL BUTTON_PLAY +#define TV_BOOKMARK BUTTON_ON + +/* iRiver H1x0 && H3x0 keys */ +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H300_PAD) +#define TV_QUIT BUTTON_OFF +#define TV_RC_QUIT BUTTON_RC_STOP +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_MODE +#define TV_AUTOSCROLL BUTTON_SELECT +#define TV_LINE_UP (BUTTON_ON | BUTTON_UP) +#define TV_LINE_DOWN (BUTTON_ON | BUTTON_DOWN) +#define TV_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT) +#define TV_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT) +#define TV_BOOKMARK (BUTTON_ON | BUTTON_SELECT) + +/* iPods */ +#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ + (CONFIG_KEYPAD == IPOD_3G_PAD) || \ + (CONFIG_KEYPAD == IPOD_1G2G_PAD) +#define TV_QUIT_PRE BUTTON_SELECT +#define TV_QUIT (BUTTON_SELECT | BUTTON_MENU) +#define TV_SCROLL_UP BUTTON_SCROLL_BACK +#define TV_SCROLL_DOWN BUTTON_SCROLL_FWD +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL BUTTON_PLAY +#define TV_BOOKMARK BUTTON_SELECT + +/* iFP7xx keys */ +#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD +#define TV_QUIT BUTTON_PLAY +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_MODE +#define TV_AUTOSCROLL BUTTON_SELECT +#define TV_BOOKMARK (BUTTON_LEFT|BUTTON_SELECT) + +/* iAudio X5 keys */ +#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_SELECT +#define TV_AUTOSCROLL BUTTON_PLAY +#define TV_BOOKMARK BUTTON_REC + +/* GIGABEAT keys */ +#elif CONFIG_KEYPAD == GIGABEAT_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL BUTTON_A +#define TV_BOOKMARK BUTTON_SELECT + +/* Sansa E200 keys */ +#elif CONFIG_KEYPAD == SANSA_E200_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_SELECT +#define TV_AUTOSCROLL BUTTON_REC +#define TV_LINE_UP BUTTON_SCROLL_BACK +#define TV_LINE_DOWN BUTTON_SCROLL_FWD +#define TV_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT) + +/* Sansa Fuze keys */ +#elif CONFIG_KEYPAD == SANSA_FUZE_PAD +#define TV_QUIT (BUTTON_HOME|BUTTON_REPEAT) +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_SELECT|BUTTON_REPEAT +#define TV_AUTOSCROLL BUTTON_SELECT|BUTTON_DOWN +#define TV_LINE_UP BUTTON_SCROLL_BACK +#define TV_LINE_DOWN BUTTON_SCROLL_FWD +#define TV_BOOKMARK BUTTON_SELECT + +/* Sansa C200 keys */ +#elif CONFIG_KEYPAD == SANSA_C200_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_VOL_UP +#define TV_SCROLL_DOWN BUTTON_VOL_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_SELECT +#define TV_AUTOSCROLL BUTTON_REC +#define TV_LINE_UP BUTTON_UP +#define TV_LINE_DOWN BUTTON_DOWN +#define TV_BOOKMARK (BUTTON_DOWN | BUTTON_SELECT) + +/* Sansa Clip keys */ +#elif CONFIG_KEYPAD == SANSA_CLIP_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_VOL_UP +#define TV_SCROLL_DOWN BUTTON_VOL_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_SELECT +#define TV_AUTOSCROLL BUTTON_HOME +#define TV_LINE_UP BUTTON_UP +#define TV_LINE_DOWN BUTTON_DOWN +#define TV_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT) + +/* Sansa M200 keys */ +#elif CONFIG_KEYPAD == SANSA_M200_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_VOL_UP +#define TV_SCROLL_DOWN BUTTON_VOL_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU (BUTTON_SELECT | BUTTON_UP) +#define TV_AUTOSCROLL (BUTTON_SELECT | BUTTON_REL) +#define TV_LINE_UP BUTTON_UP +#define TV_LINE_DOWN BUTTON_DOWN +#define TV_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT) + +/* iriver H10 keys */ +#elif CONFIG_KEYPAD == IRIVER_H10_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_SCROLL_UP +#define TV_SCROLL_DOWN BUTTON_SCROLL_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_REW +#define TV_AUTOSCROLL BUTTON_PLAY +#define TV_BOOKMARK BUTTON_FF + +/*M-Robe 500 keys */ +#elif CONFIG_KEYPAD == MROBE500_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_RC_PLAY +#define TV_SCROLL_DOWN BUTTON_RC_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_RC_HEART +#define TV_AUTOSCROLL BUTTON_RC_MODE +#define TV_BOOKMARK BUTTON_CENTER + +/*Gigabeat S keys */ +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#define TV_QUIT BUTTON_BACK +#define TV_SCROLL_UP BUTTON_PREV +#define TV_SCROLL_DOWN BUTTON_NEXT +#define TV_SCREEN_LEFT (BUTTON_PLAY | BUTTON_LEFT) +#define TV_SCREEN_RIGHT (BUTTON_PLAY | BUTTON_RIGHT) +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL_PRE BUTTON_PLAY +#define TV_AUTOSCROLL (BUTTON_PLAY|BUTTON_REL) +#define TV_LINE_UP BUTTON_UP +#define TV_LINE_DOWN BUTTON_DOWN +#define TV_COLUMN_LEFT BUTTON_LEFT +#define TV_COLUMN_RIGHT BUTTON_RIGHT +#define TV_BOOKMARK BUTTON_SELECT + +/*M-Robe 100 keys */ +#elif CONFIG_KEYPAD == MROBE100_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL BUTTON_DISPLAY +#define TV_BOOKMARK BUTTON_SELECT + +/* iAUdio M3 keys */ +#elif CONFIG_KEYPAD == IAUDIO_M3_PAD +#define TV_QUIT BUTTON_REC +#define TV_RC_QUIT BUTTON_RC_REC +#define TV_SCROLL_UP BUTTON_RC_VOL_UP +#define TV_SCROLL_DOWN BUTTON_RC_VOL_DOWN +#define TV_SCREEN_LEFT BUTTON_RC_REW +#define TV_SCREEN_RIGHT BUTTON_RC_FF +#define TV_MENU BUTTON_RC_MENU +#define TV_AUTOSCROLL BUTTON_RC_MODE +#define TV_BOOKMARK BUTTON_RC_PLAY + +/* Cowon D2 keys */ +#elif CONFIG_KEYPAD == COWON_D2_PAD +#define TV_QUIT BUTTON_POWER +#define TV_MENU BUTTON_MENU +#define TV_SCROLL_UP BUTTON_MINUS +#define TV_SCROLL_DOWN BUTTON_PLUS +#define TV_BOOKMARK (BUTTON_MENU|BUTTON_PLUS) + +#elif CONFIG_KEYPAD == IAUDIO67_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_VOLUP +#define TV_SCROLL_DOWN BUTTON_VOLDOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL BUTTON_PLAY +#define TV_RC_QUIT BUTTON_STOP +#define TV_BOOKMARK (BUTTON_LEFT|BUTTON_PLAY) + +/* Creative Zen Vision:M keys */ +#elif CONFIG_KEYPAD == CREATIVEZVM_PAD +#define TV_QUIT BUTTON_BACK +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL BUTTON_SELECT +#define TV_BOOKMARK BUTTON_PLAY + +/* Philips HDD1630 keys */ +#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL BUTTON_VIEW +#define TV_BOOKMARK BUTTON_SELECT + +/* Philips SA9200 keys */ +#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD +#define TV_QUIT BUTTON_POWER +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_PREV +#define TV_SCREEN_RIGHT BUTTON_NEXT +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL BUTTON_PLAY +#define TV_BOOKMARK BUTTON_RIGHT + +/* Onda VX747 keys */ +#elif CONFIG_KEYPAD == ONDAVX747_PAD +#define TV_QUIT BUTTON_POWER +#define TV_MENU BUTTON_MENU +#define TV_BOOKMARK (BUTTON_RIGHT|BUTTON_POWER) + +/* Onda VX777 keys */ +#elif CONFIG_KEYPAD == ONDAVX777_PAD +#define TV_QUIT BUTTON_POWER +#define TV_BOOKMARK (BUTTON_RIGHT|BUTTON_POWER) + +/* SAMSUNG YH-820 / YH-920 / YH-925 keys */ +#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD +#define TV_QUIT BUTTON_REC +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_PLAY +#define TV_AUTOSCROLL BUTTON_REW +#define TV_BOOKMARK BUTTON_FFWD + +/* Packard Bell Vibe 500 keys */ +#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD +#define TV_QUIT BUTTON_REC +#define TV_SCROLL_UP BUTTON_OK +#define TV_SCROLL_DOWN BUTTON_CANCEL +#define TV_LINE_UP BUTTON_UP +#define TV_LINE_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_PREV +#define TV_SCREEN_RIGHT BUTTON_NEXT +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL BUTTON_PLAY +#define TV_BOOKMARK BUTTON_POWER + +/* MPIO HD200 keys */ +#elif CONFIG_KEYPAD == MPIO_HD200_PAD +#define TV_QUIT (BUTTON_REC | BUTTON_PLAY) +#define TV_SCROLL_UP BUTTON_PREV +#define TV_SCROLL_DOWN BUTTON_NEXT +#define TV_SCREEN_LEFT BUTTON_VOL_DOWN +#define TV_SCREEN_RIGHT BUTTON_VOL_UP +#define TV_MENU BUTTON_SELECT +#define TV_AUTOSCROLL BUTTON_PLAY +#define TV_BOOKMARK BUTTON_REC + +#else +#error No keymap defined! +#endif + +#ifdef HAVE_TOUCHSCREEN +#ifdef TV_QUIT +#define TV_QUIT2 BUTTON_TOPLEFT +#else +#define TV_QUIT BUTTON_TOPLEFT +#endif +#ifdef TV_SCROLL_UP +#define TV_SCROLL_UP2 BUTTON_TOPMIDDLE +#else +#define TV_SCROLL_UP BUTTON_TOPMIDDLE +#endif +#ifdef TV_SCROLL_DOWN +#define TV_SCROLL_DOWN2 BUTTON_BOTTOMMIDDLE +#else +#define TV_SCROLL_DOWN BUTTON_BOTTOMMIDDLE +#endif +#ifndef TV_SCREEN_LEFT +#define TV_SCREEN_LEFT BUTTON_MIDLEFT +#endif +#ifndef TV_SCREEN_RIGHT +#define TV_SCREEN_RIGHT BUTTON_MIDRIGHT +#endif +#ifdef TV_MENU +#define TV_MENU2 BUTTON_TOPRIGHT +#else +#define TV_MENU BUTTON_TOPRIGHT +#endif +#ifndef TV_AUTOSCROLL +#define TV_AUTOSCROLL BUTTON_CENTER +#endif +#endif + +#endif diff --git a/apps/plugins/text_viewer/tv_menu.c b/apps/plugins/text_viewer/tv_menu.c new file mode 100644 index 0000000000..f40afb8848 --- /dev/null +++ b/apps/plugins/text_viewer/tv_menu.c @@ -0,0 +1,349 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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 "lib/playback_control.h" +#include "tv_bookmark.h" +#include "tv_menu.h" +#include "tv_settings.h" + +/* settings helper functions */ + +static struct tv_preferences new_prefs; + +static bool tv_encoding_setting(void) +{ + static struct opt_items names[NUM_CODEPAGES]; + int idx; + + for (idx = 0; idx < NUM_CODEPAGES; idx++) + { + names[idx].string = rb->get_codepage_name(idx); + names[idx].voice_id = -1; + } + + return rb->set_option("Encoding", &new_prefs.encoding, INT, names, + sizeof(names) / sizeof(names[0]), NULL); +} + +static bool tv_word_wrap_setting(void) +{ + static const struct opt_items names[] = { + {"On", -1}, + {"Off (Chop Words)", -1}, + }; + + return rb->set_option("Word Wrap", &new_prefs.word_mode, INT, + names, 2, NULL); +} + +static bool tv_line_mode_setting(void) +{ + static const struct opt_items names[] = { + {"Normal", -1}, + {"Join Lines", -1}, + {"Expand Lines", -1}, + {"Reflow Lines", -1}, + }; + + return rb->set_option("Line Mode", &new_prefs.line_mode, INT, names, + sizeof(names) / sizeof(names[0]), NULL); +} + +static bool tv_view_mode_setting(void) +{ + static const struct opt_items names[] = { + {"No (Narrow)", -1}, + {"Yes", -1}, + }; + + return rb->set_option("Wide View", &new_prefs.view_mode, INT, + names , 2, NULL); +} + +static bool tv_scroll_mode_setting(void) +{ + static const struct opt_items names[] = { + {"Scroll by Page", -1}, + {"Scroll by Line", -1}, + }; + + return rb->set_option("Scroll Mode", &new_prefs.scroll_mode, INT, + names, 2, NULL); +} + +static bool tv_alignment_setting(void) +{ + static const struct opt_items names[] = { + {"Left", -1}, + {"Right", -1}, + }; + + return rb->set_option("Alignment", &new_prefs.alignment, INT, + names , 2, NULL); +} + +#ifdef HAVE_LCD_BITMAP +static bool tv_page_mode_setting(void) +{ + static const struct opt_items names[] = { + {"No", -1}, + {"Yes", -1}, + }; + + return rb->set_option("Overlap Pages", &new_prefs.page_mode, INT, + names, 2, NULL); +} + +static bool tv_scrollbar_setting(void) +{ + static const struct opt_items names[] = { + {"Off", -1}, + {"On", -1} + }; + + return rb->set_option("Show Scrollbar", &new_prefs.scrollbar_mode, INT, + names, 2, NULL); +} + +static bool tv_header_setting(void) +{ + int len = (rb->global_settings->statusbar == STATUSBAR_TOP)? 4 : 2; + struct opt_items names[len]; + + names[0].string = "None"; + names[0].voice_id = -1; + names[1].string = "File path"; + names[1].voice_id = -1; + + if (rb->global_settings->statusbar == STATUSBAR_TOP) + { + names[2].string = "Status bar"; + names[2].voice_id = -1; + names[3].string = "Both"; + names[3].voice_id = -1; + } + + return rb->set_option("Show Header", &new_prefs.header_mode, INT, + names, len, NULL); +} + +static bool tv_footer_setting(void) +{ + int len = (rb->global_settings->statusbar == STATUSBAR_BOTTOM)? 4 : 2; + struct opt_items names[len]; + + names[0].string = "None"; + names[0].voice_id = -1; + names[1].string = "Page Num"; + names[1].voice_id = -1; + + if (rb->global_settings->statusbar == STATUSBAR_BOTTOM) + { + names[2].string = "Status bar"; + names[2].voice_id = -1; + names[3].string = "Both"; + names[3].voice_id = -1; + } + + return rb->set_option("Show Footer", &new_prefs.footer_mode, INT, + names, len, NULL); +} + +static int tv_font_comp(const void *a, const void *b) +{ + struct opt_items *pa; + struct opt_items *pb; + + pa = (struct opt_items *)a; + pb = (struct opt_items *)b; + + return rb->strcmp(pa->string, pb->string); +} + +static bool tv_font_setting(void) +{ + int count = 0; + DIR *dir; + struct dirent *entry; + int i = 0; + int len; + int new_font = 0; + int old_font; + bool res; + int size = 0; + + dir = rb->opendir(FONT_DIR); + if (!dir) + { + rb->splash(HZ/2, "font dir does not access"); + return false; + } + + while ((entry = rb->readdir(dir)) != NULL) + { + len = rb->strlen(entry->d_name); + if (len < 4 || rb->strcmp(entry->d_name + len - 4, ".fnt")) + continue; + size += len - 3; + count++; + } + rb->closedir(dir); + + struct opt_items names[count]; + unsigned char font_names[size]; + unsigned char *p = font_names; + + dir = rb->opendir(FONT_DIR); + if (!dir) + { + rb->splash(HZ/2, "font dir does not access"); + return false; + } + + while ((entry = rb->readdir(dir)) != NULL) + { + len = rb->strlen(entry->d_name); + if (len < 4 || rb->strcmp(entry->d_name + len - 4, ".fnt")) + continue; + + rb->strlcpy(p, entry->d_name, len - 3); + names[i].string = p; + names[i].voice_id = -1; + p += len - 3; + if (++i >= count) + break; + } + rb->closedir(dir); + + rb->qsort(names, count, sizeof(struct opt_items), tv_font_comp); + + for (i = 0; i < count; i++) + { + if (!rb->strcmp(names[i].string, new_prefs.font_name)) + { + new_font = i; + break; + } + } + old_font = new_font; + + res = rb->set_option("Select Font", &new_font, INT, + names, count, NULL); + + if (new_font != old_font) + { + rb->memset(new_prefs.font_name, 0, MAX_PATH); + rb->strlcpy(new_prefs.font_name, names[new_font].string, MAX_PATH); + } + + return res; +} +#endif + +static bool tv_autoscroll_speed_setting(void) +{ + return rb->set_int("Auto-scroll Speed", "", UNIT_INT, + &new_prefs.autoscroll_speed, NULL, 1, 1, 10, NULL); +} + +MENUITEM_FUNCTION(encoding_item, 0, "Encoding", tv_encoding_setting, + NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(word_wrap_item, 0, "Word Wrap", tv_word_wrap_setting, + NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(line_mode_item, 0, "Line Mode", tv_line_mode_setting, + NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(view_mode_item, 0, "Wide View", tv_view_mode_setting, + NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(alignment_item, 0, "Alignment", tv_alignment_setting, + NULL, NULL, Icon_NOICON); +#ifdef HAVE_LCD_BITMAP +MENUITEM_FUNCTION(scrollbar_item, 0, "Show Scrollbar", tv_scrollbar_setting, + NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(page_mode_item, 0, "Overlap Pages", tv_page_mode_setting, + NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(header_item, 0, "Show Header", tv_header_setting, + NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(footer_item, 0, "Show Footer", tv_footer_setting, + NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(font_item, 0, "Font", tv_font_setting, + NULL, NULL, Icon_NOICON); +#endif +MENUITEM_FUNCTION(scroll_mode_item, 0, "Scroll Mode", tv_scroll_mode_setting, + NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(autoscroll_speed_item, 0, "Auto-Scroll Speed", + tv_autoscroll_speed_setting, NULL, NULL, Icon_NOICON); +MAKE_MENU(option_menu, "Viewer Options", NULL, Icon_NOICON, + &encoding_item, &word_wrap_item, &line_mode_item, &view_mode_item, + &alignment_item, +#ifdef HAVE_LCD_BITMAP + &scrollbar_item, &page_mode_item, &header_item, &footer_item, &font_item, +#endif + &scroll_mode_item, &autoscroll_speed_item); + +static enum tv_menu_result tv_options_menu(void) +{ + bool result = TV_MENU_RESULT_EXIT_MENU; + + if (rb->do_menu(&option_menu, NULL, NULL, false) == MENU_ATTACHED_USB) + result = TV_MENU_RESULT_ATTACHED_USB; + + return result; +} + +enum tv_menu_result tv_display_menu(void) +{ + int result = TV_MENU_RESULT_EXIT_MENU; + + MENUITEM_STRINGLIST(menu, "Viewer Menu", NULL, + "Return", "Viewer Options", + "Show Playback Menu", "Select Bookmark", + "Global Settings", "Quit"); + + switch (rb->do_menu(&menu, NULL, NULL, false)) + { + case 0: /* return */ + break; + case 1: /* change settings */ + tv_copy_preferences(&new_prefs); + result = tv_options_menu(); + tv_set_preferences(&new_prefs); + break; + case 2: /* playback control */ + playback_control(NULL); + break; + case 3: /* select bookmark */ + tv_select_bookmark(); + break; + case 4: /* change global settings */ + if (!tv_load_global_settings(&new_prefs)) + tv_set_default_preferences(&new_prefs); + + result = tv_options_menu(); + tv_save_global_settings(&new_prefs); + break; + case 5: /* quit */ + result = TV_MENU_RESULT_EXIT_PLUGIN; + break; + } + return result; +} diff --git a/apps/plugins/text_viewer/tv_menu.h b/apps/plugins/text_viewer/tv_menu.h new file mode 100644 index 0000000000..35886d3c10 --- /dev/null +++ b/apps/plugins/text_viewer/tv_menu.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_MENU_H +#define PLUGIN_TEXT_VIEWER_MENU_H + +enum tv_menu_result { + TV_MENU_RESULT_EXIT_MENU, + TV_MENU_RESULT_EXIT_PLUGIN, + TV_MENU_RESULT_ATTACHED_USB, +}; + +/* + * display the setting menu + * + * return + * the following value returns + * TV_MENU_RESULT_EXIT_MENU menu exit and continue this plugin + * TV_MENU_RESULT_EXIT_PLUGIN request to exit this plugin + * TV_MENU_RESULT_ATTACHED_USB connect USB cable + */ +enum tv_menu_result tv_display_menu(void); + +#endif diff --git a/apps/plugins/text_viewer/tv_pager.c b/apps/plugins/text_viewer/tv_pager.c new file mode 100644 index 0000000000..d98fe4627d --- /dev/null +++ b/apps/plugins/text_viewer/tv_pager.c @@ -0,0 +1,337 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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_pager.h" +#include "tv_preferences.h" +#include "tv_reader.h" +#include "tv_window.h" + +#if PLUGIN_BUFFER_SIZE < 0x13000 +#define TV_MAX_PAGE 999 +#else +#define TV_MAX_PAGE 9999 +#endif + +#define TV_PAGER_MEMSIZE (4 * TV_MAX_PAGE) + +static unsigned char *pager_buffer; + +static struct tv_screen_pos cur_pos; + +static int parse_page; +static int last_page; +static int max_page; + +static int lines_per_page; + +static int line_pos[LCD_HEIGHT / 2]; +static int parse_page; +static int parse_top_line; +static int parse_lines; + +static void set_uint32(unsigned char *p, unsigned int val) +{ + *p++ = val & 0xff; + *p++ = (val >> 8) & 0xff; + *p++ = (val >> 16) & 0xff; + *p = (val >> 24) & 0xff; +} + +static unsigned int get_uint32(const unsigned char *p) +{ + return (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0]; +} + +static void tv_set_fpos(int page, off_t pos) +{ + if (page >= 0 && page <= max_page) + set_uint32(pager_buffer + page * 4, pos); +} + +static off_t tv_get_fpos(int page) +{ + if (page >= 0 && page <= max_page) + return get_uint32(pager_buffer + page * 4); + return 0; +} + +static void tv_change_preferences(const struct tv_preferences *oldp) +{ + (void)oldp; + + cur_pos.page = 0; + cur_pos.line = 0; + last_page = 0; + max_page = TV_MAX_PAGE - 1; + tv_set_fpos(cur_pos.page, 0); + tv_seek(0, SEEK_SET); +} + +bool tv_init_pager(unsigned char *buf, size_t bufsize, size_t *used_size) +{ + if (bufsize < TV_PAGER_MEMSIZE) + return false; + + pager_buffer = buf; + tv_set_screen_pos(&cur_pos); + tv_add_preferences_change_listner(tv_change_preferences); + + /* valid page: 0, ..., max_page. */ + max_page = TV_MAX_PAGE - 1; + + line_pos[0] = 0; + + buf += TV_PAGER_MEMSIZE; + bufsize -= TV_PAGER_MEMSIZE; + if (!tv_init_reader(buf, bufsize, used_size)) + return false; + + *used_size += TV_PAGER_MEMSIZE; + + return true; +} + +void tv_finalize_pager(void) +{ + tv_finalize_reader(); +} + +void tv_reset_line_positions(void) +{ + parse_page = cur_pos.page; + parse_top_line = cur_pos.line; + parse_lines = 0; +} + +void tv_move_next_line(int size) +{ + if (!tv_is_eof()) + { + tv_seek(size, SEEK_CUR); + cur_pos.file_pos = tv_get_current_file_pos(); + cur_pos.line++; + parse_lines++; + line_pos[cur_pos.line] = line_pos[cur_pos.line - 1] + size; + } +} + +int tv_get_line_positions(int offset) +{ + int line = cur_pos.line + offset; + + if (line < 0) + line = 0; + else if (line > parse_lines) + line = parse_lines; + + return line_pos[parse_top_line + line] - line_pos[parse_top_line]; +} + +void tv_new_page(void) +{ + parse_page = cur_pos.page; + if (cur_pos.page == last_page && last_page < max_page) + { + if (!tv_is_eof()) + tv_set_fpos(++last_page, tv_get_current_file_pos()); + else + max_page = last_page; + } + + if (++cur_pos.page > max_page) + cur_pos.page = max_page; + + lines_per_page = cur_pos.line; + cur_pos.line = 0; +} + +static void tv_seek_page(int offset, int whence) +{ + int new_page = offset; + + switch (whence) + { + case SEEK_CUR: + new_page += cur_pos.page; + break; + case SEEK_SET: + break; + case SEEK_END: + new_page += last_page; + whence = SEEK_SET; + break; + default: + return; + break; + } + if (new_page < 0) + new_page = 0; + else if (new_page >= last_page) + new_page = last_page; + + cur_pos.page = new_page; + cur_pos.line = 0; + cur_pos.file_pos = tv_get_fpos(new_page); + tv_seek(cur_pos.file_pos, SEEK_SET); +} + +static bool tv_create_line_positions(void) +{ + bool res; + + if (tv_is_eof()) + return false; + + cur_pos.line = 0; + tv_reset_line_positions(); + res = tv_traverse_lines(); + lines_per_page = cur_pos.line; + tv_new_page(); + + return res; +} + +void tv_convert_fpos(off_t fpos, struct tv_screen_pos *pos) +{ + int i; + + for (i = 0; i < last_page; i++) + { + if (tv_get_fpos(i) <= fpos && tv_get_fpos(i + 1) > fpos) + break; + } + + pos->page = i; + pos->line = 0; + pos->file_pos = fpos; + + if (tv_get_fpos(i) == fpos) + return; + + tv_seek_page(i, SEEK_SET); + while (tv_create_line_positions() && cur_pos.file_pos < fpos) + rb->splashf(0, "converting %ld%%...", 100 * cur_pos.file_pos / fpos); + + if (cur_pos.page < max_page) + cur_pos.page--; + tv_seek_page(cur_pos.page, SEEK_SET); + for (i = 0; i < lines_per_page; i++) + { + if (cur_pos.file_pos + tv_get_line_positions(i) >= fpos) + break; + } + + pos->page = cur_pos.page; + pos->line = i; +} + +static void tv_seek_to_bottom_line(void) +{ + off_t total_size = tv_get_file_size(); + + tv_seek_page(0, SEEK_END); + while (tv_create_line_positions()) + rb->splashf(0, "loading %ld%%...", 100 * cur_pos.file_pos / total_size); + + cur_pos.line = lines_per_page - 1; +} + +void tv_move_screen(int page_offset, int line_offset, int whence) +{ + struct tv_screen_pos new_pos; + int i; + + switch (whence) + { + case SEEK_CUR: + cur_pos.page += page_offset; + cur_pos.line += line_offset; + break; + case SEEK_SET: + cur_pos.page = page_offset; + cur_pos.line = line_offset; + break; + case SEEK_END: + tv_seek_to_bottom_line(); + cur_pos.page += page_offset; + cur_pos.line += line_offset; + break; + default: + return; + break; + } + + if (cur_pos.page < 0 || (cur_pos.page == 0 && cur_pos.line < 0)) + { + tv_seek_page(0, SEEK_SET); + return; + } + else if (cur_pos.page > max_page) + { + tv_seek_page(max_page, SEEK_SET); + return; + } + + new_pos = cur_pos; + if (cur_pos.line < 0) + new_pos.page--; + + tv_seek_page(new_pos.page, SEEK_SET); + while (cur_pos.page < new_pos.page && tv_create_line_positions()) + rb->splashf(0, "loading %d%%...", 100 * cur_pos.page / new_pos.page); + + if (new_pos.line == 0) + return; + + if (parse_page == cur_pos.page) + { + if (cur_pos.page < max_page && new_pos.line == lines_per_page) + { + tv_seek(line_pos[lines_per_page], SEEK_CUR); + for (i = 0; i < parse_lines; i++) + line_pos[i] = line_pos[i + lines_per_page] - line_pos[lines_per_page]; + + cur_pos.page++; + cur_pos.line = 0; + parse_top_line = 0; + new_pos.line = 0; + } + } + else + { + tv_create_line_positions(); + tv_seek_page(new_pos.page, SEEK_SET); + } + + cur_pos.line = new_pos.line; + if (cur_pos.line >= lines_per_page) + cur_pos.line = lines_per_page - 1; + else if (cur_pos.line < 0) + { + cur_pos.line += lines_per_page; + if (cur_pos.line < 0) + cur_pos.line = 0; + } + tv_seek(line_pos[cur_pos.line], SEEK_CUR); + cur_pos.file_pos += line_pos[cur_pos.line]; +} diff --git a/apps/plugins/text_viewer/tv_pager.h b/apps/plugins/text_viewer/tv_pager.h new file mode 100644 index 0000000000..798d694ce5 --- /dev/null +++ b/apps/plugins/text_viewer/tv_pager.h @@ -0,0 +1,104 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_PAGER_H +#define PLUGIN_TEXT_VIEWER_PAGER_H + +#include "tv_screen_pos.h" + +/* stuff for the paging */ + +/* + * initialize the pager module + * + * [In] buf + * the start pointer of the buffer + * + * [In] size + * enabled buffer size + * + * [Out] used_size + * the size of the buffer which the pager uses + * + * return + * true initialize success + * false initialize failure + */ +bool tv_init_pager(unsigned char *buf, size_t bufsize, size_t *used_size); + +/* finalize the pager module */ +void tv_finalize_pager(void); + +/* reset the stored line positions */ +void tv_reset_line_positions(void); + +/* + * move to the next line + * + * [In] size + * the current line size + */ +void tv_move_next_line(int size); + +/* + * return the distance from the top of the current page + * + * [In] offset + * the difference between the current line + * + * return + * difference between the current line + offset from the top of the current page + */ +int tv_get_line_positions(int offset); + +/* change the new page */ +void tv_new_page(void); + +/* + * convert the given file position to the nearest the position (page, line) + * + * [In] fpos + * the file position which want to convert + * + * [Out] pos + * result + */ +void tv_convert_fpos(off_t fpos, struct tv_screen_pos *pos); + +/* + * move to the given page and line + * + * [In] page_offset + * page offset + * + * [In] line_offset + * line offset + * + * [In] whence + * SEEK_CUR seek to the current page + offset page, the current line + offset line. + * SEEK_SET seek to the offset page, offset line. + * SEEK_END seek to the reading last page + offset page, + * the last line of the reading last page + offset line. + */ +void tv_move_screen(int page_offset, int line_offset, int whence); + +#endif diff --git a/apps/plugins/text_viewer/tv_preferences.c b/apps/plugins/text_viewer/tv_preferences.c new file mode 100644 index 0000000000..cd3560db93 --- /dev/null +++ b/apps/plugins/text_viewer/tv_preferences.c @@ -0,0 +1,119 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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_preferences.h" + +static struct tv_preferences prefs; +static bool is_initialized = false; +static int listner_count = 0; + +#define TV_MAX_LISTNERS 4 +static void (*listners[TV_MAX_LISTNERS])(const struct tv_preferences *oldp); + +static void tv_notify_change_preferences(const struct tv_preferences *oldp, + const struct tv_preferences *newp) +{ + int i; + + /* + * the following items do not check. + * - alignment + * - scroll_mode + * - page_mode + * - font + * - autoscroll_speed + */ + if ((oldp == NULL) || + (oldp->word_mode != newp->word_mode) || + (oldp->line_mode != newp->line_mode) || + (oldp->view_mode != newp->view_mode) || + (oldp->scrollbar_mode != newp->scrollbar_mode) || + (oldp->encoding != newp->encoding) || +#ifdef HAVE_LCD_BITMAP + (oldp->header_mode != newp->header_mode) || + (oldp->footer_mode != newp->footer_mode) || + (rb->strcmp(oldp->font_name, newp->font_name)) || +#endif + (rb->strcmp(oldp->file_name, newp->file_name))) + { + for (i = listner_count - 1; i >= 0; i--) + listners[i](oldp); + } +} + +const struct tv_preferences *tv_get_preferences(void) +{ + return &prefs; +} + +void tv_set_preferences(const struct tv_preferences *new_prefs) +{ + struct tv_preferences *oldp = NULL; + struct tv_preferences old_prefs; + + if (!is_initialized) + is_initialized = true; + else + { + old_prefs = prefs; + oldp = &old_prefs; + } + rb->memcpy(&prefs, new_prefs, sizeof(struct tv_preferences)); + tv_notify_change_preferences(oldp, &prefs); +} + +void tv_copy_preferences(struct tv_preferences *copy_prefs) +{ + rb->memcpy(copy_prefs, &prefs, sizeof(struct tv_preferences)); +} + +void tv_set_default_preferences(struct tv_preferences *p) +{ + p->word_mode = WRAP; + p->line_mode = NORMAL; + p->view_mode = NARROW; + p->alignment = LEFT; + p->scroll_mode = PAGE; + p->page_mode = NO_OVERLAP; + p->scrollbar_mode = SB_OFF; + rb->memset(p->font_name, 0, MAX_PATH); +#ifdef HAVE_LCD_BITMAP + p->header_mode = HD_BOTH; + p->footer_mode = FT_BOTH; + rb->strlcpy(p->font_name, rb->global_settings->font_file, MAX_PATH); + p->font = rb->font_get(FONT_UI); +#else + p->header_mode = HD_NONE; + p->footer_mode = FT_NONE; +#endif + p->autoscroll_speed = 1; + /* Set codepage to system default */ + p->encoding = rb->global_settings->default_codepage; + p->file_name[0] = '\0'; +} + +void tv_add_preferences_change_listner(void (*listner)(const struct tv_preferences *oldp)) +{ + if (listner_count < TV_MAX_LISTNERS) + listners[listner_count++] = listner; +} diff --git a/apps/plugins/text_viewer/tv_preferences.h b/apps/plugins/text_viewer/tv_preferences.h new file mode 100644 index 0000000000..64ab0d102f --- /dev/null +++ b/apps/plugins/text_viewer/tv_preferences.h @@ -0,0 +1,129 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_PREFERENCES_H +#define PLUGIN_TEXT_VIEWER_PREFERENCES_H + +struct tv_preferences { + enum { + WRAP = 0, + CHOP, + } word_mode; + + enum { + NORMAL = 0, + JOIN, + EXPAND, + REFLOW, + } line_mode; + + enum { + NARROW = 0, + WIDE, + } view_mode; + + enum { + LEFT = 0, + RIGHT, + } alignment; + + enum codepages encoding; + + enum { + SB_OFF = 0, + SB_ON, + } scrollbar_mode; + + enum { + NO_OVERLAP = 0, + OVERLAP, + } page_mode; + + enum { + HD_NONE = 0, + HD_PATH, + HD_SBAR, + HD_BOTH, + } header_mode; + + enum { + FT_NONE = 0, + FT_PAGE, + FT_SBAR, + FT_BOTH, + } footer_mode; + + enum { + PAGE=0, + LINE, + } scroll_mode; + + int autoscroll_speed; + + unsigned char font_name[MAX_PATH]; +#ifdef HAVE_LCD_BITMAP + struct font *font; +#endif + unsigned char file_name[MAX_PATH]; +}; + +/* + * return the preferences + * + * return + * the pointer the preferences + */ +const struct tv_preferences *tv_get_preferences(void); + +/* + * change the preferences + * + * [In] new_prefs + * new preferences + */ +void tv_set_preferences(const struct tv_preferences *new_prefs); + +/* + * copy the preferences + * + * [Out] copy_prefs + * the preferences in copy destination + */ +void tv_copy_preferences(struct tv_preferences *copy_prefs); + +/* + * set the default settings + * + * [Out] p + * the preferences which store the default settings + */ +void tv_set_default_preferences(struct tv_preferences *p); + +/* + * register the function to be executed when the current preferences is changed + * + * [In] listner + * the function to be executed when the current preferences is changed + */ +void tv_add_preferences_change_listner(void (*listner)(const struct tv_preferences *oldp)); + +#endif diff --git a/apps/plugins/text_viewer/tv_reader.c b/apps/plugins/text_viewer/tv_reader.c new file mode 100644 index 0000000000..6dc66ef567 --- /dev/null +++ b/apps/plugins/text_viewer/tv_reader.c @@ -0,0 +1,191 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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_preferences.h" +#include "tv_reader.h" + +#if PLUGIN_BUFFER_SIZE < 0x10000 +#define TV_MIN_BLOCK_SIZE 0x800 +#else +#define TV_MIN_BLOCK_SIZE 0x1000 +#endif + +/* UTF-8 BOM */ +#define BOM "\xef\xbb\xbf" +#define BOM_SIZE 3 + +static int fd = -1; + +static off_t file_pos; +static off_t start_file_pos; + +static off_t file_size; + +static unsigned char *reader_buffer; +static ssize_t buffer_size; +static ssize_t block_size; + +static ssize_t buf_pos; +static ssize_t read_size; + +off_t tv_get_file_size(void) +{ + return file_size; +} + +bool tv_is_eof(void) +{ + return (file_pos + buf_pos >= file_size); +} + +off_t tv_get_current_file_pos(void) +{ + return file_pos + buf_pos; +} + +const unsigned char *tv_get_buffer(ssize_t *bufsize) +{ + *bufsize = read_size - buf_pos; + return reader_buffer + buf_pos; +} + +static ssize_t tv_read(unsigned char *buf, ssize_t reqsize) +{ + if (buf - reader_buffer + reqsize > buffer_size) + reqsize = buffer_size - (buf - reader_buffer); + + return rb->read(fd, buf, reqsize); +} + +void tv_seek(off_t offset, int whence) +{ + ssize_t size; + + switch (whence) + { + case SEEK_SET: + if (offset >= file_pos && offset < file_pos + read_size) + { + buf_pos = offset - file_pos; + return; + } + file_pos = offset; + break; + + case SEEK_CUR: + buf_pos += offset; + if (buf_pos >= 0 && buf_pos < read_size) + { + if (buf_pos > block_size) + { + buf_pos -= block_size; + file_pos += block_size; + size = read_size - block_size; + rb->memcpy(reader_buffer, reader_buffer + block_size, size); + read_size = tv_read(reader_buffer + block_size, block_size); + if (read_size < 0) + read_size = 0; + + read_size += size; + } + return; + } + file_pos += buf_pos; + whence = SEEK_SET; + break; + + default: + return; + break; + } + + if (whence == SEEK_SET) + { + if (file_pos < 0) + file_pos = 0; + else if (file_pos > file_size) + file_pos = file_size; + + rb->lseek(fd, file_pos + start_file_pos, SEEK_SET); + buf_pos = 0; + read_size = tv_read(reader_buffer, buffer_size); + } +} + +static void tv_change_preferences(const struct tv_preferences *oldp) +{ + unsigned char bom[BOM_SIZE]; + const struct tv_preferences *prefs = tv_get_preferences(); + int cur_start_file_pos = start_file_pos; + off_t cur_file_pos = file_pos + buf_pos; + + file_pos = 0; + buf_pos = 0; + read_size = 0; + start_file_pos = 0; + + /* open the new file */ + if (oldp == NULL || rb->strcmp(oldp->file_name, prefs->file_name)) + { + if (fd >= 0) + rb->close(fd); + + fd = rb->open(prefs->file_name, O_RDONLY); + if (fd < 0) + return; + } + + /* + * When a file is UTF-8 file with BOM, if prefs.encoding is UTF-8, + * then file size decreases only BOM_SIZE. + */ + if (prefs->encoding == UTF_8) + { + rb->lseek(fd, 0, SEEK_SET); + rb->read(fd, bom, BOM_SIZE); + if (rb->memcmp(bom, BOM, BOM_SIZE) == 0) + start_file_pos = BOM_SIZE; + } + + file_size = rb->filesize(fd) - start_file_pos; + tv_seek(cur_file_pos + cur_start_file_pos - start_file_pos, SEEK_SET); +} + +bool tv_init_reader(unsigned char *buf, size_t bufsize, size_t *used_size) +{ + if (bufsize < 2 * TV_MIN_BLOCK_SIZE) + return false; + + reader_buffer = buf; + block_size = bufsize / 2; + buffer_size = 2 * block_size; + *used_size = buffer_size; + tv_add_preferences_change_listner(tv_change_preferences); + return true; +} + +void tv_finalize_reader(void) +{ + if (fd >= 0) + rb->close(fd); +} diff --git a/apps/plugins/text_viewer/tv_reader.h b/apps/plugins/text_viewer/tv_reader.h new file mode 100644 index 0000000000..464af1027a --- /dev/null +++ b/apps/plugins/text_viewer/tv_reader.h @@ -0,0 +1,102 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_READER_H +#define PLUGIN_TEXT_VIEWER_READER_H + +/* stuff for the reading file */ + +/* + * initialize the reader module + * + * [In] buf + * the start pointer of the buffer + * + * [In] size + * enabled buffer size + * + * [Out] used_size + * the size of the buffer which the pager uses + * + * return + * true initialize success + * false initialize failure + */ +bool tv_init_reader(unsigned char *buf, size_t bufsize, size_t *used_size); + +/* finalize the reader module */ +void tv_finalize_reader(void); + +/* + * return the file size + * + * return + * file size + * + * Note: when the file is UTF-8 file with BOM, if the encoding of the text viewer is UTF-8, + * then file size decreases only BOM size. + */ +off_t tv_get_file_size(void); + +/* + * return the whether is the end of file or not + * + * return + * true EOF + * false not EOF + */ +bool tv_is_eof(void); + +/* + * return the current file position + * + * return + * the current file position + */ +off_t tv_get_current_file_pos(void); + +/* + * return the bufer which store text data + * + * [Out] bufsize + * buffer size + * + * return + * the pointer of the buffer + */ +const unsigned char *tv_get_buffer(ssize_t *bufsize); + +/* + * seek to the given offset + * + * [In] offset + * offset size + * + * [In] whence + * SEEK_CUR seek to the current position + offset. + * SEEK_SET seek to the offset. + * + * Note: whence supports SEEK_CUR and SEEK_SET only. + */ +void tv_seek(off_t offset, int whence); + +#endif diff --git a/apps/plugins/text_viewer/tv_screen_pos.c b/apps/plugins/text_viewer/tv_screen_pos.c new file mode 100644 index 0000000000..001bd478de --- /dev/null +++ b/apps/plugins/text_viewer/tv_screen_pos.c @@ -0,0 +1,41 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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_pos.h" + +static const struct tv_screen_pos *screen_pos; + +const struct tv_screen_pos *tv_get_screen_pos(void) +{ + return screen_pos; +} + +void tv_set_screen_pos(const struct tv_screen_pos *pos) +{ + screen_pos = pos; +} + +void tv_copy_screen_pos(struct tv_screen_pos *pos) +{ + *pos = *screen_pos; +} diff --git a/apps/plugins/text_viewer/tv_screen_pos.h b/apps/plugins/text_viewer/tv_screen_pos.h new file mode 100644 index 0000000000..3ee8c10d89 --- /dev/null +++ b/apps/plugins/text_viewer/tv_screen_pos.h @@ -0,0 +1,56 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_SCREEN_POS_H +#define PLUGIN_TEXT_VIEWER_SCREEN_POS_H + +struct tv_screen_pos { + off_t file_pos; + int page; + int line; +}; + +/* + * return the current position + * + * return + * the pointer which is stored the current position + */ +const struct tv_screen_pos *tv_get_screen_pos(void); + +/* + * set the current position + * + * [In] pos + * the pointer which is stored the current position + */ +void tv_set_screen_pos(const struct tv_screen_pos *pos); + +/* + * the current position set to the given structure + * + * [Out] pos + * the pointer in order to store the current position + */ +void tv_copy_screen_pos(struct tv_screen_pos *pos); + +#endif diff --git a/apps/plugins/text_viewer/tv_settings.c b/apps/plugins/text_viewer/tv_settings.c new file mode 100644 index 0000000000..bb4ead7b5d --- /dev/null +++ b/apps/plugins/text_viewer/tv_settings.c @@ -0,0 +1,519 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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_bookmark.h" +#include "tv_reader.h" +#include "tv_settings.h" + +/* global settings file + * binary file, so dont use .cfg + * + * setting file format + * + * part byte count + * -------------------------------- + * 'TVGS' 4 + * version 1 + * word_mode 1 + * line_mode 1 + * view_mode 1 + * alignment 1 + * encoding 1 + * scrollbar_mode 1 + * (unused) 1 (for compatibility) + * page_mode 1 + * page_number_mode 1 + * title_mode 1 + * scroll_mode 1 + * autoscroll_speed 1 + * font name MAX_PATH + */ + +#define VIEWER_GLOBAL_SETTINGS_FILE VIEWERS_DIR "/viewer.dat" +#define TV_GLOBAL_SETTINGS_FILE VIEWERS_DIR "/tv_global.dat" + +#define TV_GLOBAL_SETTINGS_HEADER "\x54\x56\x47\x53" /* "TVGS" */ +#define TV_GLOBAL_SETTINGS_VERSION 0x32 +#define TV_GLOBAL_SETTINGS_HEADER_SIZE 5 +#define TV_GLOBAL_SETTINGS_FIRST_VERSION 0x31 + +/* preferences and bookmarks at each file + * binary file, so dont use .cfg + * + * setting file format + * + * part byte count + * -------------------------------- + * 'TVS' 3 + * version 1 + * file count 2 + * [1st file] + * file path MAX_PATH + * next file pos 2 (prefences size + bookmark count * bookmark size + 1) + * [preferences] + * word_mode 1 + * line_mode 1 + * view_mode 1 + * alignment 1 + * encoding 1 + * scrollbar_mode 1 + * (unused) 1 (for compatibility) + * page_mode 1 + * header_mode 1 + * footer_mode 1 + * scroll_mode 1 + * autoscroll_speed 1 + * font name MAX_PATH + * bookmark count 1 + * [1st bookmark] + * file_position 4 + * page 2 + * line 1 + * flag 1 + * [2nd bookmark] + * ... + * [last bookmark] + * [2nd file] + * ... + * [last file] + */ +#define VIEWER_SETTINGS_FILE VIEWERS_DIR "/viewer_file.dat" +#define TV_SETTINGS_FILE VIEWERS_DIR "/tv_file.dat" + +/* temporary file */ +#define TV_SETTINGS_TMP_FILE VIEWERS_DIR "/tv_file.tmp" + +#define TV_SETTINGS_HEADER "\x54\x56\x53" /* "TVS" */ +#define TV_SETTINGS_VERSION 0x33 +#define TV_SETTINGS_HEADER_SIZE 4 +#define TV_SETTINGS_FIRST_VERSION 0x32 + +#define TV_PREFERENCES_SIZE (12 + MAX_PATH) + +/* ---------------------------------------------------------------------------- + * read/write the preferences + * ---------------------------------------------------------------------------- + */ + +static bool tv_read_preferences(int pfd, int version, struct tv_preferences *prefs) +{ + unsigned char buf[TV_PREFERENCES_SIZE]; + const unsigned char *p = buf; + int read_size = TV_PREFERENCES_SIZE; + + if (version == 0) + read_size--; + + if (rb->read(pfd, buf, read_size) < 0) + return false; + + prefs->word_mode = *p++; + prefs->line_mode = *p++; + prefs->view_mode = *p++; + if (version > 0) + prefs->alignment = *p++; + else + prefs->alignment = LEFT; + prefs->encoding = *p++; + prefs->scrollbar_mode = *p++; + /* skip need_scrollbar */ + p++; + prefs->page_mode = *p++; + prefs->header_mode = *p++; + prefs->footer_mode = *p++; + prefs->scroll_mode = *p++; + prefs->autoscroll_speed = *p++; + rb->memcpy(prefs->font_name, p, MAX_PATH); +#ifdef HAVE_LCD_BITMAP + prefs->font = rb->font_get(FONT_UI); +#endif + + return true; +} + +static bool tv_write_preferences(int pfd, const struct tv_preferences *prefs) +{ + unsigned char buf[TV_PREFERENCES_SIZE]; + unsigned char *p = buf; + + *p++ = prefs->word_mode; + *p++ = prefs->line_mode; + *p++ = prefs->view_mode; + *p++ = prefs->alignment; + *p++ = prefs->encoding; + *p++ = prefs->scrollbar_mode; + /* skip need_scrollbar */ + p++; + *p++ = prefs->page_mode; + *p++ = prefs->header_mode; + *p++ = prefs->footer_mode; + *p++ = prefs->scroll_mode; + *p++ = prefs->autoscroll_speed; + rb->memcpy(p, prefs->font_name, MAX_PATH); + + return (rb->write(pfd, buf, TV_PREFERENCES_SIZE) >= 0); +} + +/* ---------------------------------------------------------------------------- + * convert vewer.rock's settings file to text_viewer.rock's settings file + * ---------------------------------------------------------------------------- + */ + +static bool tv_convert_settings(int sfd, int dfd, int old_ver) +{ + struct tv_preferences new_prefs; + off_t old_pos; + off_t new_pos; + unsigned char buf[MAX_PATH + 2]; + int settings_size; + + rb->read(sfd, buf, MAX_PATH + 2); + rb->write(dfd, buf, MAX_PATH + 2); + + settings_size = (buf[MAX_PATH] << 8) | buf[MAX_PATH + 1]; + + old_pos = rb->lseek(sfd, 0, SEEK_CUR); + new_pos = rb->lseek(dfd, 0, SEEK_CUR); + + /* + * when the settings size != preferences size + bookmarks size, + * settings data are considered to be old version. + */ + if (old_ver > 0 && ((settings_size - TV_PREFERENCES_SIZE) % 8) == 0) + old_ver = 0; + + if (!tv_read_preferences(sfd, old_ver, &new_prefs)) + return false; + + if (!tv_write_preferences(dfd, &new_prefs)) + return false; + + settings_size -= (rb->lseek(sfd, 0, SEEK_CUR) - old_pos); + + if (settings_size > 0) + { + rb->read(sfd, buf, settings_size); + rb->write(dfd, buf, settings_size); + } + + settings_size = rb->lseek(dfd, 0, SEEK_CUR) - new_pos; + buf[0] = settings_size >> 8; + buf[1] = settings_size; + rb->lseek(dfd, new_pos - 2, SEEK_SET); + rb->write(dfd, buf, 2); + rb->lseek(dfd, settings_size, SEEK_CUR); + return true; +} + +static void tv_convert_settings_file(void) +{ + unsigned char buf[TV_SETTINGS_HEADER_SIZE + 2]; + int sfd; + int tfd; + int i; + int fcount; + int version; + bool res = false; + + if ((sfd = rb->open(VIEWER_SETTINGS_FILE, O_RDONLY)) < 0) + return; + + if ((tfd = rb->open(TV_SETTINGS_TMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) + { + rb->close(sfd); + return; + } + + if (rb->read(sfd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0) + { + version = buf[TV_SETTINGS_HEADER_SIZE - 1] - TV_SETTINGS_FIRST_VERSION; + fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE + 1]; + buf[TV_SETTINGS_HEADER_SIZE - 1] = TV_SETTINGS_VERSION; + + if (rb->write(tfd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0) + { + res = true; + for (i = 0; i < fcount; i++) + { + if (!tv_convert_settings(sfd, tfd, version)) + { + res = false; + break; + } + } + } + } + + rb->close(sfd); + rb->close(tfd); + + if (res) + rb->rename(TV_SETTINGS_TMP_FILE, TV_SETTINGS_FILE); + else + rb->remove(TV_SETTINGS_TMP_FILE); + + return; +} + +/* ---------------------------------------------------------------------------- + * load/save the global settings + * ---------------------------------------------------------------------------- + */ + +bool tv_load_global_settings(struct tv_preferences *prefs) +{ + unsigned char buf[TV_GLOBAL_SETTINGS_HEADER_SIZE]; + int fd; + int version; + bool res = false; + + /* + * the viewer.rock's setting file read when the text_viewer.rock's setting file + * does not read. + */ + if ((fd = rb->open(TV_GLOBAL_SETTINGS_FILE, O_RDONLY)) < 0) + fd = rb->open(VIEWER_GLOBAL_SETTINGS_FILE, O_RDONLY); + + if (fd >= 0) + { + if ((rb->read(fd, buf, TV_GLOBAL_SETTINGS_HEADER_SIZE) > 0) && + (rb->memcmp(buf, TV_GLOBAL_SETTINGS_HEADER, TV_GLOBAL_SETTINGS_HEADER_SIZE - 1) == 0)) + { + version = buf[TV_GLOBAL_SETTINGS_HEADER_SIZE - 1] - TV_GLOBAL_SETTINGS_FIRST_VERSION; + res = tv_read_preferences(fd, version, prefs); + } + rb->close(fd); + } + return res; +} + +bool tv_save_global_settings(const struct tv_preferences *prefs) +{ + unsigned char buf[TV_GLOBAL_SETTINGS_HEADER_SIZE]; + int fd; + bool res; + + if ((fd = rb->open(TV_SETTINGS_TMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) + return false; + + rb->memcpy(buf, TV_GLOBAL_SETTINGS_HEADER, TV_GLOBAL_SETTINGS_HEADER_SIZE - 1); + buf[TV_GLOBAL_SETTINGS_HEADER_SIZE - 1] = TV_GLOBAL_SETTINGS_VERSION; + + res = (rb->write(fd, buf, TV_GLOBAL_SETTINGS_HEADER_SIZE) >= 0) && + (tv_write_preferences(fd, prefs)); + rb->close(fd); + + if (res) + { + rb->remove(TV_GLOBAL_SETTINGS_FILE); + rb->rename(TV_SETTINGS_TMP_FILE, TV_GLOBAL_SETTINGS_FILE); + } + else + rb->remove(TV_SETTINGS_TMP_FILE); + + return res; +} + +/* ---------------------------------------------------------------------------- + * load/save the settings + * ---------------------------------------------------------------------------- + */ + +void tv_load_settings(const unsigned char *file_name) +{ + unsigned char buf[MAX_PATH+2]; + unsigned int fcount; + unsigned int i; + bool res = false; + int fd; + int version; + unsigned int size; + struct tv_preferences prefs; + + if (!rb->file_exists(TV_SETTINGS_FILE)) + tv_convert_settings_file(); + + if ((fd = rb->open(TV_SETTINGS_FILE, O_RDONLY)) >= 0) + { + if ((rb->read(fd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0) && + (rb->memcmp(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1) == 0)) + { + version = buf[TV_SETTINGS_HEADER_SIZE - 1] - TV_SETTINGS_FIRST_VERSION; + fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE+1]; + + for (i = 0; i < fcount; i++) + { + if (rb->read(fd, buf, MAX_PATH+2) >= 0) + { + size = (buf[MAX_PATH] << 8) | buf[MAX_PATH+1]; + if (rb->strcmp(buf, file_name) == 0) + { + if (tv_read_preferences(fd, version, &prefs)) + res = tv_deserialize_bookmarks(fd); + + break; + } + rb->lseek(fd, size, SEEK_CUR); + } + } + rb->close(fd); + } + else + { + /* when the settings file is illegal, removes it */ + rb->close(fd); + rb->remove(TV_SETTINGS_FILE); + } + } + if (!res) + { + /* specifications are acquired from the global settings */ + if (!tv_load_global_settings(&prefs)) + tv_set_default_preferences(&prefs); + } + rb->strlcpy(prefs.file_name, file_name, MAX_PATH); + tv_set_preferences(&prefs); +} + +static bool tv_copy_settings(int sfd, int dfd, int size) +{ + unsigned char buf[MAX_PATH]; + int i = size / MAX_PATH; + + size %= MAX_PATH; + + while (i--) + { + if ((rb->read(sfd, buf, MAX_PATH) < 0) || (rb->write(dfd, buf, MAX_PATH) < 0)) + return false; + } + + return ((rb->read(sfd, buf, size) >= 0) && (rb->write(dfd, buf, size) >= 0)); +} + +bool tv_save_settings(void) +{ + const struct tv_preferences *prefs = tv_get_preferences(); + unsigned char buf[MAX_PATH+2]; + unsigned int fcount = 0; + unsigned int i; + int ofd = -1; + int tfd; + off_t size; + bool res = true; + + /* add reading page to bookmarks */ + tv_create_system_bookmark(); + + if (!rb->file_exists(TV_SETTINGS_FILE)) + tv_convert_settings_file(); + + /* create header for the temporary file */ + rb->memcpy(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1); + buf[TV_SETTINGS_HEADER_SIZE - 1] = TV_SETTINGS_VERSION; + + if ((tfd = rb->open(TV_SETTINGS_TMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) + return false; + + if (rb->write(tfd, buf, TV_SETTINGS_HEADER_SIZE + 2) < 0) + { + rb->close(tfd); + return false; + } + + if ((ofd = rb->open(TV_SETTINGS_FILE, O_RDONLY)) >= 0) + { + res = ((rb->read(ofd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0) && + (rb->memcmp(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1) == 0)); + + if (res) + { + fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE + 1]; + for (i = 0; i < fcount; i++) + { + if (rb->read(ofd, buf, MAX_PATH + 2) < 0) + { + res = false; + break; + } + + size = (buf[MAX_PATH] << 8) | buf[MAX_PATH + 1]; + if (rb->strcmp(buf, prefs->file_name) == 0) + rb->lseek(ofd, size, SEEK_CUR); + else + { + if ((rb->write(tfd, buf, MAX_PATH + 2) < 0) || + (!tv_copy_settings(ofd, tfd, size))) + { + res = false; + break; + } + } + } + } + rb->close(ofd); + } + + if (res) + { + /* save to current read file's preferences and bookmarks */ + res = false; + rb->memset(buf, 0, MAX_PATH); + rb->strlcpy(buf, prefs->file_name, MAX_PATH); + + if (rb->write(tfd, buf, MAX_PATH + 2) >= 0) + { + if (tv_write_preferences(tfd, prefs)) + { + size = tv_serialize_bookmarks(tfd); + if (size > 0) + { + size += TV_PREFERENCES_SIZE; + rb->lseek(tfd, -size - 2, SEEK_CUR); + buf[0] = size >> 8; + buf[1] = size; + if (rb->write(tfd, buf, 2) >= 0) + { + rb->lseek(tfd, TV_SETTINGS_HEADER_SIZE, SEEK_SET); + + fcount++; + buf[0] = fcount >> 8; + buf[1] = fcount; + res = (rb->write(tfd, buf, 2) >= 0); + } + } + } + } + } + rb->close(tfd); + + if (res) + { + rb->remove(TV_SETTINGS_FILE); + rb->rename(TV_SETTINGS_TMP_FILE, TV_SETTINGS_FILE); + } + else + rb->remove(TV_SETTINGS_TMP_FILE); + + return res; +} diff --git a/apps/plugins/text_viewer/tv_settings.h b/apps/plugins/text_viewer/tv_settings.h new file mode 100644 index 0000000000..c2218e7d9f --- /dev/null +++ b/apps/plugins/text_viewer/tv_settings.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_SETTINGS_H +#define PLUGIN_TEXT_VIEWER_SETTINGS_H + +#include "tv_preferences.h" + +/* + * load from the global settings file + * + * [Out] prefs + * the structure which read settings is stored + * + * return + * true success + * false failure + */ +bool tv_load_global_settings(struct tv_preferences *prefs); + +/* + * save to the global settings file + * + * [In] prefs + * the structure with settings to save + * + * return + * true success + * false failure + */ +bool tv_save_global_settings(const struct tv_preferences *prefs); + +/* + * load the settings at each file + * + * [In] file_name + * the file name of file that wants to read settings + * + * return + * true success + * false failure + */ +void tv_load_settings(const unsigned char *file_name); + +/* + * save the settings at each file + * + * return + * true success + * false failure + */ +bool tv_save_settings(void); + +#endif diff --git a/apps/plugins/text_viewer/tv_text_processor.c b/apps/plugins/text_viewer/tv_text_processor.c new file mode 100644 index 0000000000..8cdd78df15 --- /dev/null +++ b/apps/plugins/text_viewer/tv_text_processor.c @@ -0,0 +1,576 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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 "ctype.h" +#include "tv_preferences.h" +#include "tv_text_processor.h" + +enum tv_text_type { + TV_TEXT_UNKNOWN, + TV_TEXT_MAC, + TV_TEXT_UNIX, + TV_TEXT_WIN, +}; + +/* the max characters of each blocks */ +#ifdef HAVE_LCD_BITMAP +#define TV_MAX_CHARS_PER_BLOCK (LCD_WIDTH / 2 + 1) +#else +#define TV_MAX_CHARS_PER_BLOCK (LCD_WIDTH + 1) +#endif + +#define TV_MAX_BLOCKS 2 + +/* + * number of spaces to indent first paragraph + * (this value uses the line mode is REFLOW only) + */ +#define TV_INDENT_SPACES 2 + +static const struct tv_preferences *prefs; +static enum tv_text_type text_type = TV_TEXT_UNKNOWN; + +static const unsigned char *end_ptr; + +static unsigned short *ucsbuf[TV_MAX_BLOCKS]; +static unsigned char *utf8buf; +static unsigned char *outbuf; + +static int block_count; +static int block_width; + +/* if this value is true, then tv_create_line_text returns a blank line. */ +static bool expand_extra_line = false; + +/* when a line is divided, this value sets true. */ +static bool is_break_line = false; + +static unsigned short break_chars[] = + { + 0, + /* halfwidth characters */ + '\t', '\n', 0x0b, 0x0c, ' ', '!', ',', '-', '.', ':', ';', '?', 0xb7, + /* fullwidth characters */ + 0x2010, /* hyphen */ + 0x3000, /* fullwidth space */ + 0x3001, /* ideographic comma */ + 0x3002, /* ideographic full stop */ + 0x30fb, /* katakana middle dot */ + 0x30fc, /* katakana-hiragana prolonged sound mark */ + 0xff01, /* fullwidth exclamation mark */ + 0xff0c, /* fullwidth comma */ + 0xff0d, /* fullwidth hyphen-minus */ + 0xff0e, /* fullwidth full stop */ + 0xff1a, /* fullwidth colon */ + 0xff1b, /* fullwidth semicolon */ + 0xff1f, /* fullwidth question mark */ + }; + +/* the characters which is not judged as space with isspace() */ +static unsigned short extra_spaces[] = { 0, 0x3000 }; + +static int tv_glyph_width(int ch) +{ + if (ch == '\n') + return 0; + + if (ch == 0) + ch = ' '; + +#ifdef HAVE_LCD_BITMAP + /* the width of the diacritics charcter is 0 */ + if (rb->is_diacritic(ch, NULL)) + return 0; + + return rb->font_get_width(prefs->font, ch); +#else + return 1; +#endif +} + +static unsigned char *tv_get_ucs(const unsigned char *str, unsigned short *ch) +{ + int count = 1; + unsigned char utf8_tmp[3]; + + /* distinguish the text_type */ + if (*str == '\r') + { + if (text_type == TV_TEXT_WIN || text_type == TV_TEXT_UNKNOWN) + { + if (str + 1 < end_ptr && *(str+1) == '\n') + { + if (text_type == TV_TEXT_UNKNOWN) + text_type = TV_TEXT_WIN; + + *ch = '\n'; + return (unsigned char *)str + 2; + } + + if (text_type == TV_TEXT_UNKNOWN) + text_type = TV_TEXT_MAC; + } + *ch = (text_type == TV_TEXT_MAC)? '\n' : ' '; + return (unsigned char *)str + 1; + } + else if (*str == '\n') + { + if (text_type == TV_TEXT_UNKNOWN) + text_type = TV_TEXT_UNIX; + + *ch = (text_type == TV_TEXT_UNIX)? '\n' : ' '; + return (unsigned char *)str + 1; + } + + if (prefs->encoding == UTF_8) + return (unsigned char*)rb->utf8decode(str, ch); + +#ifdef HAVE_LCD_BITMAP + if ((*str >= 0x80) && + ((prefs->encoding > SJIS) || + (prefs->encoding == SJIS && (*str <= 0xa0 || *str >= 0xe0)))) + { + if (str + 1 >= end_ptr) + { + end_ptr = str; + *ch = 0; + return (unsigned char *)str; + } + count = 2; + } +#endif + rb->iso_decode(str, utf8_tmp, prefs->encoding, count); + rb->utf8decode(utf8_tmp, ch); + return (unsigned char *)str + count; +} + +static void tv_decode2utf8(const unsigned short *ucs, int count) +{ + int i; + + for (i = 0; i < count; i++) + outbuf = rb->utf8encode(ucs[i], outbuf); + + *outbuf = '\0'; +} + +static bool tv_is_line_break_char(unsigned short ch) +{ + size_t i; + + /* when the word mode is CHOP, all characters does not break line. */ + if (prefs->word_mode == CHOP) + return false; + + for (i = 0; i < sizeof(break_chars); i++) + { + if (break_chars[i] == ch) + return true; + } + return false; +} + +static bool tv_isspace(unsigned short ch) +{ + size_t i; + + if (ch < 128 && isspace(ch)) + return true; + + for (i = 0; i < sizeof(extra_spaces); i++) + { + if (extra_spaces[i] == ch) + return true; + } + return false; +} + +static bool tv_is_break_line_join_mode(const unsigned char *next_str) +{ + unsigned short ch; + + tv_get_ucs(next_str, &ch); + return tv_isspace(ch); +} + +static int tv_form_reflow_line(unsigned short *ucs, int chars) +{ + unsigned short new_ucs[TV_MAX_CHARS_PER_BLOCK]; + unsigned short *p = new_ucs; + unsigned short ch; + int i; + int k; + int expand_spaces; + int indent_chars = 0; + int nonspace_chars = 0; + int nonspace_width = 0; + int remain_spaces; + int spaces = 0; + int words_spaces; + + if (prefs->alignment == LEFT) + { + while (chars > 0 && ucs[chars-1] == ' ') + chars--; + } + + if (chars == 0) + return 0; + + while (ucs[indent_chars] == ' ') + indent_chars++; + + for (i = indent_chars; i < chars; i++) + { + ch = ucs[i]; + if (ch == ' ') + spaces++; + else + { + nonspace_chars++; + nonspace_width += tv_glyph_width(ch); + } + } + + if (spaces == 0) + return chars; + + expand_spaces = (block_width - nonspace_width) / tv_glyph_width(' ') - indent_chars; + if (indent_chars + nonspace_chars + expand_spaces > TV_MAX_CHARS_PER_BLOCK) + expand_spaces = TV_MAX_CHARS_PER_BLOCK - indent_chars - nonspace_chars; + + words_spaces = expand_spaces / spaces; + remain_spaces = expand_spaces - words_spaces * spaces; + + for (i = 0; i < indent_chars; i++) + *p++ = ' '; + + for ( ; i < chars; i++) + { + ch = ucs[i]; + *p++ = ch; + if (ch == ' ') + { + for (k = ((remain_spaces > 0)? 0 : 1); k < words_spaces; k++) + *p++ = ch; + + remain_spaces--; + } + } + + rb->memcpy(ucs, new_ucs, sizeof(unsigned short) * TV_MAX_CHARS_PER_BLOCK); + return indent_chars + nonspace_chars + expand_spaces; +} + +static void tv_align_right(int *block_chars) +{ + unsigned short *cur_text; + unsigned short *prev_text; + unsigned short ch; + int cur_block = block_count - 1; + int prev_block; + int cur_chars; + int prev_chars; + int idx; + int break_pos; + int break_width = 0; + int append_width; + int width; + + while (cur_block > 0) + { + cur_text = ucsbuf[cur_block]; + cur_chars = block_chars[cur_block]; + idx = cur_chars; + width = 0; + while(--idx >= 0) + width += tv_glyph_width(cur_text[idx]); + + width = block_width - width; + prev_block = cur_block - 1; + + do { + prev_text = ucsbuf[prev_block]; + prev_chars = block_chars[prev_block]; + + idx = prev_chars; + append_width = 0; + break_pos = prev_chars; + while (append_width < width && idx > 0) + { + ch = prev_text[--idx]; + if (tv_is_line_break_char(ch)) + { + break_pos = idx + 1; + break_width = append_width; + } + append_width += tv_glyph_width(ch); + } + if (append_width > width) + idx++; + + if (idx == 0) + { + break_pos = 0; + break_width = append_width; + } + + if (break_pos < prev_chars) + append_width = break_width; + /* the case of + * (1) when the first character of the cur_text concatenates + * the last character of the prev_text. + * (2) the length of ucsbuf[block] is short (< 0.75 * block width) + */ + else if (((!tv_isspace(*cur_text) && !tv_isspace(prev_text[prev_chars - 1])) || + (4 * width >= 3 * block_width))) + { + break_pos = idx; + } + + if (break_pos < prev_chars) + { + rb->memmove(cur_text + prev_chars - break_pos, + cur_text, block_chars[cur_block] * sizeof(unsigned short)); + rb->memcpy(cur_text, prev_text + break_pos, + (prev_chars - break_pos) * sizeof(unsigned short)); + + block_chars[prev_block] = break_pos; + block_chars[cur_block ] += prev_chars - break_pos; + } + } while ((width -= append_width) > 0 && --prev_block >= 0); + cur_block--; + } +} + +static int tv_parse_text(const unsigned char *src, unsigned short *ucs, + int *ucs_chars, bool is_indent) +{ + const unsigned char *cur = src; + const unsigned char *next = src; + const unsigned char *line_break_ptr = NULL; + const unsigned char *line_end_ptr = NULL; + unsigned short ch = 0; + unsigned short prev_ch; + int chars = 0; + int gw; + int i; + int line_break_width = 0; + int line_end_chars = 0; + int width = 0; + bool is_space = false; + + while (true) { + cur = next; + if (cur >= end_ptr) + { + line_end_ptr = cur; + line_end_chars = chars; + is_break_line = true; + break; + } + + prev_ch = ch; + next = tv_get_ucs(cur, &ch); + if (ch == '\n') + { + if (prefs->line_mode != JOIN || tv_is_break_line_join_mode(next)) + { + line_end_ptr = next; + line_end_chars = chars; + is_break_line = false; + break; + } + + if (prefs->word_mode == CHOP || tv_isspace(prev_ch)) + continue; + + /* + * when the line mode is JOIN and the word mode is WRAP, + * the next character does not concatenate with the + * previous character. + */ + ch = ' '; + } + else if ((is_space = tv_isspace(ch)) == true) + { + /* + * when the line mode is REFLOW: + * (1) spacelike character convert to ' ' + * (2) plural spaces are collected to one + */ + if (prefs->line_mode == REFLOW) + { + ch = ' '; + if (prev_ch == ch) + continue; + } + + /* when the alignment is RIGHT, ignores indent spaces. */ + if (prefs->alignment == RIGHT && is_indent) + continue; + } + else + is_indent = false; + + if (prefs->line_mode == REFLOW && is_indent) + gw = tv_glyph_width(ch) * TV_INDENT_SPACES; + else + gw = tv_glyph_width(ch); + + width += gw; + if (width > block_width) + { + width -= gw; + if (is_space) + { + line_end_ptr = cur; + line_end_chars = chars; + } + is_break_line = true; + break; + } + + if (prefs->line_mode == REFLOW && is_indent) + { + for (i = 1; i < TV_INDENT_SPACES; i++) + ucs[chars++] = ch; + } + ucs[chars++] = ch; + + if (tv_is_line_break_char(ch)) + { + line_break_ptr = next; + line_break_width = width; + line_end_chars = chars; + } + if (chars >= TV_MAX_CHARS_PER_BLOCK) + { + is_break_line = true; + break; + } + } + + /* set the end position and character count */ + if (line_end_ptr == NULL) + { + /* + * when the last line break position is too short (line length < 0.75 * block width), + * the line is cut off at the position where it is closest to the displayed width. + */ + if ((prefs->line_mode == REFLOW && line_break_ptr == NULL) || + (4 * line_break_width < 3 * block_width)) + { + line_end_ptr = cur; + line_end_chars = chars; + } + else + line_end_ptr = line_break_ptr; + } + + *ucs_chars = line_end_chars; + return line_end_ptr - src; +} + +int tv_create_formed_text(const unsigned char *src, ssize_t bufsize, + int block, bool is_multi, const unsigned char **dst) +{ + unsigned short ch; + int chars[block_count]; + int i; + int size = 0; + bool is_indent; + + outbuf = utf8buf; + *outbuf = '\0'; + + for (i = 0; i < block_count; i++) + chars[i] = 0; + + if (dst != NULL) + *dst = utf8buf; + + if (prefs->line_mode == EXPAND && (expand_extra_line = !expand_extra_line) == true) + return 0; + + end_ptr = src + bufsize; + + tv_get_ucs(src, &ch); + is_indent = (tv_isspace(ch) && !is_break_line); + + for (i = 0; i < block_count; i++) + { + size += tv_parse_text(src + size, ucsbuf[i], &chars[i], is_indent); + if (!is_break_line) + break; + + is_indent = false; + } + + if (dst != NULL) + { + if (prefs->alignment == RIGHT) + tv_align_right(chars); + + for (i = 0; i < block_count; i++) + { + if (i == block || (is_multi && i == block + 1)) + { + if (is_break_line && prefs->line_mode == REFLOW) + chars[i] = tv_form_reflow_line(ucsbuf[i], chars[i]); + + tv_decode2utf8(ucsbuf[i], chars[i]); + } + } + } + + return size; +} + +bool tv_init_text_processor(unsigned char *buf, size_t bufsize, size_t *used_size) +{ + int i; + + *used_size = TV_MAX_CHARS_PER_BLOCK * (2 * 3 + TV_MAX_BLOCKS * sizeof(unsigned short)); + if (bufsize < *used_size) + return false; + + prefs = tv_get_preferences(); + text_type = TV_TEXT_UNKNOWN; + expand_extra_line = false; + is_break_line = false; + + ucsbuf[0] = (unsigned short*)buf; + for (i = 1; i < TV_MAX_BLOCKS; i++) + ucsbuf[i] = ucsbuf[i - 1] + TV_MAX_CHARS_PER_BLOCK; + + utf8buf = buf + TV_MAX_CHARS_PER_BLOCK * TV_MAX_BLOCKS * sizeof(unsigned short); + + return true; +} + +void tv_set_creation_conditions(int blocks, int width) +{ + block_count = blocks; + block_width = width; +} diff --git a/apps/plugins/text_viewer/tv_text_processor.h b/apps/plugins/text_viewer/tv_text_processor.h new file mode 100644 index 0000000000..3cb2a96448 --- /dev/null +++ b/apps/plugins/text_viewer/tv_text_processor.h @@ -0,0 +1,80 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_TEXT_PROCESSOR_H +#define PLUGIN_TEXT_VIEWER_TEXT_PROCESSOR_H + +/* + * initialize the text processor module + * + * [In] buf + * the start pointer of the buffer + * + * [In] size + * enabled buffer size + * + * [Out] used_size + * the size of the buffer which the pager uses + * + * return + * true initialize success + * false initialize failure + */ +bool tv_init_text_processor(unsigned char *buf, size_t bufsize, size_t *used_size); + +/* + * set the processing conditions + * + * [In] blocks + * total block count + * + * [In] width + * the block width + */ +void tv_set_creation_conditions(int blocks, int width); + +/* + * create the displayed text + * + * [In] src + * the start pointer of the buffer + * + * [In] bufsize + * buffer size + * + * [In] block + * the index of block to read text + * + * [In] is_multi + * true read 2 blocks + * false read 1 block + * + * [Out] dst + * the pointer of the pointer which store the text + * + * return + * the size of the text + */ +int tv_create_formed_text(const unsigned char *src, ssize_t bufsize, + int block, bool is_multi, const unsigned char **dst); + +#endif diff --git a/apps/plugins/text_viewer/tv_text_reader.c b/apps/plugins/text_viewer/tv_text_reader.c new file mode 100644 index 0000000000..28cfa565c3 --- /dev/null +++ b/apps/plugins/text_viewer/tv_text_reader.c @@ -0,0 +1,91 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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_pager.h" +#include "tv_reader.h" +#include "tv_text_processor.h" +#include "tv_text_reader.h" + +static int get_block; +static bool get_double_blocks; + +bool tv_init_text_reader(unsigned char *buf, size_t bufsize, size_t *used_size) +{ + size_t size; + + if (!tv_init_text_processor(buf, bufsize, used_size)) + return false; + + size = *used_size; + if (!tv_init_pager(buf + size, bufsize - size, used_size)) + return false; + + *used_size += size; + return true; +} + +void tv_finalize_text_reader(void) +{ + tv_finalize_pager(); +} + +void tv_set_read_conditions(int blocks, int width) +{ + tv_set_creation_conditions(blocks, width); +} + +off_t tv_get_total_text_size(void) +{ + return tv_get_file_size(); +} + +bool tv_get_next_line(const unsigned char **buf) +{ + ssize_t bufsize; + const unsigned char *buffer = tv_get_buffer(&bufsize); + + if (bufsize > 0) + { + tv_move_next_line( + tv_create_formed_text(buffer, bufsize, get_block, get_double_blocks, buf)); + return true; + } + return false; +} + +void tv_read_start(int block, bool is_multi) +{ + get_block = block; + get_double_blocks = is_multi; + tv_reset_line_positions(); +} + +int tv_read_end(void) +{ + return tv_get_line_positions(0); +} + +void tv_seek_top(void) +{ + tv_move_screen(0, 0, SEEK_SET); +} diff --git a/apps/plugins/text_viewer/tv_text_reader.h b/apps/plugins/text_viewer/tv_text_reader.h new file mode 100644 index 0000000000..e8c712c76f --- /dev/null +++ b/apps/plugins/text_viewer/tv_text_reader.h @@ -0,0 +1,101 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_TEXT_READER_H +#define PLUGIN_TEXT_VIEWER_TEXT_READER_H + +/* + * initialize the text reader module + * + * [In] buf + * the start pointer of the buffer + * + * [In] size + * enabled buffer size + * + * [Out] used_size + * the size of the buffer which the pager uses + * + * return + * true initialize success + * false initialize failure + */ +bool tv_init_text_reader(unsigned char *buf, size_t bufsize, size_t *used_size); + +/* finalize the text reader module */ +void tv_finalize_text_reader(void); + +/* + * set the read conditions + * + * [In] blocks + * block count + * + * [In] width + * block width + */ +void tv_set_read_conditions(int blocks, int width); + +/* + * return the total text size + * + * return + * the total text size + */ +off_t tv_get_total_text_size(void); + +/* + * get the text of the next line + * + * [Out] buf + * the pointer of the pointer which store the text + * + * return + * true next line exists + * false next line does not exist + */ +bool tv_get_next_line(const unsigned char **buf); + +/* + * start to read lines + * + * [In] block + * the index of block to read text + * + * [In] is_multi + * true read 2 blocks + * false read 1 block + */ +void tv_read_start(int block, bool is_multi); + +/* + * end to read lines + * + * return + * read text size + */ +int tv_read_end(void); + +/* seek to the head of the file */ +void tv_seek_top(void); + +#endif diff --git a/apps/plugins/text_viewer/tv_window.c b/apps/plugins/text_viewer/tv_window.c new file mode 100644 index 0000000000..43a24ca4bc --- /dev/null +++ b/apps/plugins/text_viewer/tv_window.c @@ -0,0 +1,394 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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_bookmark.h" +#include "tv_preferences.h" +#include "tv_screen_pos.h" +#include "tv_text_reader.h" +#include "tv_window.h" + +#define TV_WINDOWS_PER_SCREEN 2 + +#define TV_SCROLLBAR_WIDTH rb->global_settings->scrollbar_width + +#ifndef HAVE_LCD_BITMAP +#define TV_BOOKMARK_ICON 0xe101 +#endif + +#ifdef HAVE_LCD_BITMAP +static int header_height; +static int footer_height; +static bool need_scrollbar = false; +#endif + +static int start_width; +static int display_lines; + +static int window_width; +static int window_columns; +static int col_width; + +static int max_windows; + +static int cur_window; +static int cur_column; + +static const struct tv_preferences *prefs = NULL; + +#ifdef HAVE_LCD_BITMAP +static bool tv_set_font(const unsigned char *font) +{ + unsigned char path[MAX_PATH]; + + if (font != NULL && *font != '\0') + { + rb->snprintf(path, MAX_PATH, "%s/%s.fnt", FONT_DIR, font); + if (rb->font_load(NULL, path) < 0) + { + rb->splash(HZ/2, "font load failed"); + return false; + } + } + return true; +} + +static void tv_check_header_and_footer(void) +{ + struct tv_preferences new_prefs; + + tv_copy_preferences(&new_prefs); + + if (rb->global_settings->statusbar != STATUSBAR_TOP) + { + if (new_prefs.header_mode == HD_SBAR) + new_prefs.header_mode = HD_NONE; + else if (new_prefs.header_mode == HD_BOTH) + new_prefs.header_mode = HD_PATH; + } + if (rb->global_settings->statusbar != STATUSBAR_BOTTOM) + { + if (new_prefs.footer_mode == FT_SBAR) + new_prefs.footer_mode = FT_NONE; + else if (new_prefs.footer_mode == FT_BOTH) + new_prefs.footer_mode = FT_PAGE; + } + tv_set_preferences(&new_prefs); +} + +static void tv_show_header(void) +{ + 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 - prefs->font->height, prefs->file_name); +} + +static void tv_show_footer(const struct tv_screen_pos *pos) +{ + unsigned char buf[12]; + + 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) + { + if (pos->line == 0) + rb->snprintf(buf, sizeof(buf), "%d", pos->page + 1); + else + rb->snprintf(buf, sizeof(buf), "%d - %d", pos->page + 1, pos->page + 2); + + rb->lcd_putsxy(0, LCD_HEIGHT - footer_height, buf); + } +} + +static void tv_show_scrollbar(off_t cur_pos, int size) +{ + int items; + int min_shown; + int max_shown; + int sb_begin_y; + int sb_height; + + if (!need_scrollbar) + return; + + items = (int) tv_get_total_text_size(); + min_shown = (int) cur_pos; + + max_shown = min_shown + size; + + 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, + TV_SCROLLBAR_WIDTH-1, sb_height, + items, min_shown, max_shown, VERTICAL); +} + +static int tv_calc_display_lines(void) +{ + header_height = (prefs->header_mode == HD_SBAR || prefs->header_mode == HD_BOTH)? + STATUSBAR_HEIGHT : 0; + + footer_height = (prefs->footer_mode == FT_SBAR || prefs->footer_mode == FT_BOTH)? + STATUSBAR_HEIGHT : 0; + + 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 += prefs->font->height; + + if (prefs->footer_mode == FT_PAGE || prefs->footer_mode == FT_BOTH) + footer_height += prefs->font->height; + + return (LCD_HEIGHT - header_height - footer_height) / prefs->font->height; +} +#endif + +static void tv_show_bookmarks(const struct tv_screen_pos *top_pos) +{ + struct tv_screen_pos bookmarks[TV_MAX_BOOKMARKS]; + int count = tv_get_bookmark_positions(bookmarks); + int line; + +#ifdef HAVE_LCD_BITMAP + rb->lcd_set_drawmode(DRMODE_COMPLEMENT); +#endif + while (count--) + { + line = (bookmarks[count].page - top_pos->page) * display_lines + + (bookmarks[count].line - top_pos->line); + if (line >= 0 && line < display_lines) + { +#ifdef HAVE_LCD_BITMAP + rb->lcd_fillrect(start_width, header_height + line * prefs->font->height, + window_width, prefs->font->height); +#else + rb->lcd_putc(start_width - 1, line, TV_BOOKMARK_ICON); +#endif + } + } +#ifdef HAVE_LCD_BITMAP + rb->lcd_set_drawmode(DRMODE_SOLID); +#endif +} + +void tv_draw_window(void) +{ + struct tv_screen_pos pos; + const unsigned char *line_buf; + int line; + int offset = cur_column * col_width; + int size = 0; + int line_width; + int draw_width = (max_windows - cur_window) * LCD_WIDTH - offset; + int dx = start_width - offset; + + tv_copy_screen_pos(&pos); + rb->lcd_clear_display(); + + if (prefs->alignment == LEFT) + tv_read_start(cur_window, (cur_column > 0)); + else + tv_read_start(0, prefs->view_mode == WIDE); + + for (line = 0; line < display_lines; line++) + { + if (!tv_get_next_line(&line_buf)) + break; + + if (prefs->alignment == RIGHT) + { + rb->lcd_getstringsize(line_buf, &line_width, NULL); + dx = draw_width - line_width; + } + +#ifdef HAVE_LCD_BITMAP + rb->lcd_putsxy(dx, header_height + line * prefs->font->height, line_buf); +#else + rb->lcd_puts(dx, line, line_buf); +#endif + } + + size = tv_read_end(); + + tv_show_bookmarks(&pos); + +#ifdef HAVE_LCD_BITMAP + tv_show_scrollbar(pos.file_pos, size); + tv_show_header(); + tv_show_footer(&pos); +#endif + + rb->lcd_update(); +} + +bool tv_traverse_lines(void) +{ + int i; + bool res = true; + + tv_read_start(0, false); + for (i = 0; i < display_lines; i++) + { + if (!tv_get_next_line(NULL)) + { + res = false; + break; + } + } + tv_read_end(); + return res; +} + +static void tv_change_preferences(const struct tv_preferences *oldp) +{ +#ifdef HAVE_LCD_BITMAP + static bool is_executing = false; + + is_executing = true; + + /* change font */ + if (oldp == NULL || rb->strcmp(oldp->font_name, prefs->font_name)) + { + if (!tv_set_font(prefs->font_name)) + { + struct tv_preferences new_prefs = *prefs; + const unsigned char *font_str; + + font_str = (oldp == NULL)? rb->global_settings->font_file : oldp->font_name; + + if (!tv_set_font(font_str) && oldp != NULL) + { + font_str = rb->global_settings->font_file; + tv_set_font(new_prefs.font_name); + } + + rb->strlcpy(new_prefs.font_name, font_str, MAX_PATH); + tv_set_preferences(&new_prefs); + } + } + + /* calculates display lines */ + tv_check_header_and_footer(); + display_lines = tv_calc_display_lines(); + + if (!is_executing) + return; + + is_executing = false; +#else + (void)oldp; + + /* REAL fixed pitch :) all chars use up 1 cell */ + display_lines = 2; +#endif + +#ifdef HAVE_LCD_BITMAP + col_width = 2 * rb->font_get_width(prefs->font, ' '); +#else + col_width = 1; +#endif + + max_windows = (prefs->view_mode == NARROW)? 1: TV_WINDOWS_PER_SCREEN; + if (cur_window >= max_windows) + cur_window = 0; + + window_width = LCD_WIDTH; +#ifdef HAVE_LCD_BITMAP + need_scrollbar = false; + start_width = 0; + tv_seek_top(); + tv_set_read_conditions(max_windows, window_width); + if (tv_traverse_lines() && prefs->scrollbar_mode) + { + need_scrollbar = true; + start_width = TV_SCROLLBAR_WIDTH; + } + tv_seek_top(); +#else + start_width = 1; +#endif + window_width -= start_width; + window_columns = window_width / col_width; + + cur_column = 0; + + tv_set_read_conditions(max_windows, window_width); +} + +bool tv_init_window(unsigned char *buf, size_t bufsize, size_t *used_size) +{ + tv_add_preferences_change_listner(tv_change_preferences); + if (!tv_init_text_reader(buf, bufsize, used_size)) + return false; + + prefs = tv_get_preferences(); + return true; +} + +void tv_finalize_window(void) +{ + tv_finalize_text_reader(); +} + +void tv_move_window(int window_delta, int column_delta) +{ + cur_window += window_delta; + cur_column += column_delta; + + if (cur_window < 0) + { + cur_window = 0; + cur_column = 0; + } + else if (cur_window >= max_windows) + { + cur_window = max_windows - 1; + cur_column = 0; + } + + if (cur_column < 0) + { + if (cur_window == 0) + cur_column = 0; + else + { + cur_window--; + cur_column = window_columns - 1; + } + } + else + { + if (cur_window == max_windows - 1) + cur_column = 0; + else if (cur_column >= window_columns) + { + cur_window++; + cur_column = 0; + } + } +} diff --git a/apps/plugins/text_viewer/tv_window.h b/apps/plugins/text_viewer/tv_window.h new file mode 100644 index 0000000000..fe87ec6569 --- /dev/null +++ b/apps/plugins/text_viewer/tv_window.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * 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. + * + ****************************************************************************/ +#ifndef PLUGIN_TEXT_VIEWER_WINDOW_H +#define PLUGIN_TEXT_VIEWER_WINDOW_H + +/* + * initialize the window module + * + * [In] buf + * the start pointer of the buffer + * + * [In] size + * enabled buffer size + * + * [Out] used_size + * the size of the buffer which the pager uses + * + * return + * true initialize success + * false initialize failure + */ +bool tv_init_window(unsigned char *buf, size_t bufsize, size_t *used_size); + +/* finalize the window module */ +void tv_finalize_window(void); + +/* draw the display */ +void tv_draw_window(void); + +/* traverse all lines of the current page */ +bool tv_traverse_lines(void); + +/* + * move to the window + * + * new position + * new window: the current window + window_delta + * new column: the current column + column_delta + * + * [In] window_delta + * variation of the window + * + * [In] column_delta + * variation of the column + * + */ +void tv_move_window(int window_delta, int column_delta); + +#endif diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config index 1c70c2957f..2a98bb6ed7 100644 --- a/apps/plugins/viewers.config +++ b/apps/plugins/viewers.config @@ -1,6 +1,6 @@ ch8,viewers/chip8,0 -txt,viewers/viewer,1 -nfo,viewers/viewer,1 +txt,viewers/text_viewer,1 +nfo,viewers/text_viewer,1 txt,apps/text_editor,2 bmp,viewers/bmp,2 jpg,viewers/jpeg,2 |