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
This commit is contained in:
Yoshihisa Uchida 2010-06-05 10:30:08 +00:00
parent 991e92fd3d
commit fdba840450
30 changed files with 4798 additions and 2 deletions

View file

@ -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

View file

@ -1,5 +1,6 @@
/* For all targets */
shortcuts
text_viewer
/* For various targets... */

View file

@ -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

View file

@ -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.

View file

@ -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;
}

View file

@ -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)

View file

@ -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();
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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];
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -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

View file

@ -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