summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoshihisa Uchida <uchida@rockbox.org>2010-06-05 10:30:08 +0000
committerYoshihisa Uchida <uchida@rockbox.org>2010-06-05 10:30:08 +0000
commitfdba8404503af0448586615330a7b27f2ced531c (patch)
treebb15677a7a720675ac2666f11e62042f3b2639ad
parent991e92fd3dc15f1e365761264c26305559ddb0a4 (diff)
downloadrockbox-fdba8404503af0448586615330a7b27f2ced531c.tar.gz
rockbox-fdba8404503af0448586615330a7b27f2ced531c.zip
reworks text viewer plugin. (FS#11209)
new text viewer plugin: text_viewer.rock. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26571 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/CATEGORIES1
-rw-r--r--apps/plugins/SUBDIRS1
-rw-r--r--apps/plugins/text_viewer/SOURCES12
-rw-r--r--apps/plugins/text_viewer/readme.txt62
-rw-r--r--apps/plugins/text_viewer/text_viewer.c210
-rw-r--r--apps/plugins/text_viewer/text_viewer.make20
-rw-r--r--apps/plugins/text_viewer/tv_action.c186
-rw-r--r--apps/plugins/text_viewer/tv_action.h119
-rw-r--r--apps/plugins/text_viewer/tv_bookmark.c302
-rw-r--r--apps/plugins/text_viewer/tv_bookmark.h85
-rw-r--r--apps/plugins/text_viewer/tv_button.h424
-rw-r--r--apps/plugins/text_viewer/tv_menu.c349
-rw-r--r--apps/plugins/text_viewer/tv_menu.h43
-rw-r--r--apps/plugins/text_viewer/tv_pager.c337
-rw-r--r--apps/plugins/text_viewer/tv_pager.h104
-rw-r--r--apps/plugins/text_viewer/tv_preferences.c119
-rw-r--r--apps/plugins/text_viewer/tv_preferences.h129
-rw-r--r--apps/plugins/text_viewer/tv_reader.c191
-rw-r--r--apps/plugins/text_viewer/tv_reader.h102
-rw-r--r--apps/plugins/text_viewer/tv_screen_pos.c41
-rw-r--r--apps/plugins/text_viewer/tv_screen_pos.h56
-rw-r--r--apps/plugins/text_viewer/tv_settings.c519
-rw-r--r--apps/plugins/text_viewer/tv_settings.h73
-rw-r--r--apps/plugins/text_viewer/tv_text_processor.c576
-rw-r--r--apps/plugins/text_viewer/tv_text_processor.h80
-rw-r--r--apps/plugins/text_viewer/tv_text_reader.c91
-rw-r--r--apps/plugins/text_viewer/tv_text_reader.h101
-rw-r--r--apps/plugins/text_viewer/tv_window.c394
-rw-r--r--apps/plugins/text_viewer/tv_window.h69
-rw-r--r--apps/plugins/viewers.config4
30 files changed, 4798 insertions, 2 deletions
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index f797c4038d..437988bd22 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -111,6 +111,7 @@ test_touchscreen,apps
111test_viewports,apps 111test_viewports,apps
112test_greylib_bitmap_scale,viewers 112test_greylib_bitmap_scale,viewers
113text_editor,apps 113text_editor,apps
114text_viewer,viewers
114theme_remove,viewers 115theme_remove,viewers
115vbrfix,viewers 116vbrfix,viewers
116video,viewers 117video,viewers
diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS
index a6b5cda363..cf1e9d2b80 100644
--- a/apps/plugins/SUBDIRS
+++ b/apps/plugins/SUBDIRS
@@ -1,5 +1,6 @@
1/* For all targets */ 1/* For all targets */
2shortcuts 2shortcuts
3text_viewer
3 4
4/* For various targets... */ 5/* For various targets... */
5 6
diff --git a/apps/plugins/text_viewer/SOURCES b/apps/plugins/text_viewer/SOURCES
new file mode 100644
index 0000000000..7e45d1fb68
--- /dev/null
+++ b/apps/plugins/text_viewer/SOURCES
@@ -0,0 +1,12 @@
1text_viewer.c
2tv_action.c
3tv_bookmark.c
4tv_menu.c
5tv_pager.c
6tv_preferences.c
7tv_reader.c
8tv_screen_pos.c
9tv_settings.c
10tv_text_processor.c
11tv_text_reader.c
12tv_window.c
diff --git a/apps/plugins/text_viewer/readme.txt b/apps/plugins/text_viewer/readme.txt
new file mode 100644
index 0000000000..f124370bdc
--- /dev/null
+++ b/apps/plugins/text_viewer/readme.txt
@@ -0,0 +1,62 @@
1about the text viewer plugin.
2
3Limitation
4 for the target which PLUGIN_BUFFER_SIZE < 0x13000 (i.e., archos series),
5 can only be read up to 999 pages.
6
7
8Difference between viewer.rock
9 [settings file]
10 - the global setting, 'tv_global.dat' is stored.
11 - Settings and bookmarks for each file, 'tv_file.dat' is stored.
12
13 Note: when viewer.dat(viewer_file.dat) exists, tv_global.dat(tv_file.dat) is created by
14 using viewer.dat(viewer_file.dat).
15
16 [wod wrap]
17 - add the following characters which can be split the line.
18 '!', ',', '.', ':', ';', '?',
19 U+00b7, U+2010, U+3000, U+3001, U+3002, U+30fb, U+30fc,
20 U+ff01, U+ff0c, U+ff0d, U+ff0e, U+ff1a, U+ff1b, U+ff1f.
21
22 - when the line split, if the line length is short ( < 0.75 * display width),
23 split the line in display width. (thus, maybe split a word)
24
25 [line mode]
26 [join]
27 - break line condition has changed.
28 - If the next line is a blank line or spaces only line, this line breaks.
29
30 [reflow]
31 - indent changes two spaces.
32 - supports the player which does not define HAVE_LCD_BITMAP.
33
34 [alignment]
35 - the right alignment supports the player which does not define HAVE_LCD_BITMAP.
36
37 [bookmark]
38 - increased to 16 the number of bookmarks that can be registered.
39
40
41TODO list
42 - for the target which PLUGIN_BUFFER_SIZE < 0x13000 (i.e., archos series),
43 supports more than 999 pages of text.
44
45 - add History feature.
46
47 - when the WIDE screen, allow to specify the number of screens.
48
49 - when the line_mode is reflow, allow to specify indent spaces.
50
51 - for the horizontal scroll, allow the select scroll by screen/scroll by column for the settings menu.
52
53 - can display the horizontal scroll bar.
54
55 - draw images that are linked to the text. (<img src="...">)
56
57 - play audios that are linked to the text. (<audio src="...">)
58
59 - more treatments of line breaking, word wrappings.
60 (for example, period does not appear the top of line.)
61
62 - whether scroll to prev/next page or scroll to top page/bottom page can be select the settings menu.
diff --git a/apps/plugins/text_viewer/text_viewer.c b/apps/plugins/text_viewer/text_viewer.c
new file mode 100644
index 0000000000..7150498b56
--- /dev/null
+++ b/apps/plugins/text_viewer/text_viewer.c
@@ -0,0 +1,210 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "tv_action.h"
25#include "tv_button.h"
26#include "tv_preferences.h"
27
28PLUGIN_HEADER
29
30enum plugin_status plugin_start(const void* file)
31{
32 int button;
33 int lastbutton = BUTTON_NONE;
34 bool autoscroll = false;
35 long old_tick;
36 bool done = false;
37 bool display_update = true;
38 const struct tv_preferences *prefs = tv_get_preferences();
39
40 old_tick = *rb->current_tick;
41
42 if (!file)
43 return PLUGIN_ERROR;
44
45 if (!tv_init(file)) {
46 rb->splash(HZ, "Error opening file");
47 return PLUGIN_ERROR;
48 }
49
50#if LCD_DEPTH > 1
51 rb->lcd_set_backdrop(NULL);
52#endif
53
54 while (!done) {
55
56 if (display_update)
57 tv_draw();
58
59 display_update = true;
60
61 button = rb->button_get_w_tmo(HZ/10);
62
63 switch (button) {
64 case TV_MENU:
65#ifdef TV_MENU2
66 case TV_MENU2:
67#endif
68 {
69 enum tv_menu_result res = tv_menu();
70
71 if (res != TV_MENU_RESULT_EXIT_MENU)
72 {
73 tv_exit(NULL);
74 done = true;
75 if (res == TV_MENU_RESULT_ATTACHED_USB)
76 return PLUGIN_USB_CONNECTED;
77 }
78 }
79 break;
80
81 case TV_AUTOSCROLL:
82#ifdef TV_AUTOSCROLL_PRE
83 if (lastbutton != TV_AUTOSCROLL_PRE)
84 break;
85#endif
86 autoscroll = !autoscroll;
87 break;
88
89 case TV_SCROLL_UP:
90 case TV_SCROLL_UP | BUTTON_REPEAT:
91#ifdef TV_SCROLL_UP2
92 case TV_SCROLL_UP2:
93 case TV_SCROLL_UP2 | BUTTON_REPEAT:
94#endif
95 tv_scroll_up(TV_VERTICAL_SCROLL_PREFS);
96 old_tick = *rb->current_tick;
97 break;
98
99 case TV_SCROLL_DOWN:
100 case TV_SCROLL_DOWN | BUTTON_REPEAT:
101#ifdef TV_PAGE_DOWN2
102 case TV_SCROLL_DOWN2:
103 case TV_SCROLL_DOWN2 | BUTTON_REPEAT:
104#endif
105 tv_scroll_down(TV_VERTICAL_SCROLL_PREFS);
106 old_tick = *rb->current_tick;
107 break;
108
109 case TV_SCREEN_LEFT:
110 case TV_SCREEN_LEFT | BUTTON_REPEAT:
111 if (prefs->view_mode == WIDE)
112 {
113 /* Screen left */
114 tv_scroll_left(TV_HORIZONTAL_SCROLL_WINDOW);
115 }
116 else { /* prefs->view_mode == NARROW */
117 /* scroll to previous page */
118 tv_scroll_up(TV_VERTICAL_SCROLL_PAGE);
119#if 0
120 /* Top of file */
121 tv_top();
122#endif
123 }
124 break;
125
126 case TV_SCREEN_RIGHT:
127 case TV_SCREEN_RIGHT | BUTTON_REPEAT:
128 if (prefs->view_mode == WIDE)
129 {
130 /* Screen right */
131 tv_scroll_right(TV_HORIZONTAL_SCROLL_WINDOW);
132 }
133 else { /* prefs->view_mode == NARROW */
134 /* scroll to next page */
135 tv_scroll_down(TV_VERTICAL_SCROLL_PAGE);
136#if 0
137 /* Bottom of file */
138 tv_bottom();
139#endif
140 }
141 break;
142
143#ifdef TV_LINE_UP
144 case TV_LINE_UP:
145 case TV_LINE_UP | BUTTON_REPEAT:
146 /* Scroll up one line */
147 tv_scroll_up(TV_VERTICAL_SCROLL_LINE);
148 old_tick = *rb->current_tick;
149 break;
150
151 case TV_LINE_DOWN:
152 case TV_LINE_DOWN | BUTTON_REPEAT:
153 /* Scroll down one line */
154 tv_scroll_down(TV_VERTICAL_SCROLL_LINE);
155 old_tick = *rb->current_tick;
156 break;
157#endif
158#ifdef TV_COLUMN_LEFT
159 case TV_COLUMN_LEFT:
160 case TV_COLUMN_LEFT | BUTTON_REPEAT:
161 /* Scroll left one column */
162 tv_scroll_left(TV_HORIZONTAL_SCROLL_COLUMN);
163 break;
164
165 case TV_COLUMN_RIGHT:
166 case TV_COLUMN_RIGHT | BUTTON_REPEAT:
167 /* Scroll right one column */
168 tv_scroll_right(TV_HORIZONTAL_SCROLL_COLUMN);
169 break;
170#endif
171
172#ifdef TV_RC_QUIT
173 case TV_RC_QUIT:
174#endif
175 case TV_QUIT:
176#ifdef TV_QUIT2
177 case TV_QUIT2:
178#endif
179 tv_exit(NULL);
180 done = true;
181 break;
182
183 case TV_BOOKMARK:
184 tv_add_or_remove_bookmark();
185 break;
186
187 default:
188 if (rb->default_event_handler_ex(button, tv_exit, NULL)
189 == SYS_USB_CONNECTED)
190 return PLUGIN_USB_CONNECTED;
191 display_update = false;
192 break;
193 }
194 if (button != BUTTON_NONE)
195 {
196 lastbutton = button;
197 rb->yield();
198 }
199 if (autoscroll)
200 {
201 if(old_tick <= *rb->current_tick - (110 - prefs->autoscroll_speed * 10))
202 {
203 tv_scroll_down(TV_VERTICAL_SCROLL_PREFS);
204 old_tick = *rb->current_tick;
205 display_update = true;
206 }
207 }
208 }
209 return PLUGIN_OK;
210}
diff --git a/apps/plugins/text_viewer/text_viewer.make b/apps/plugins/text_viewer/text_viewer.make
new file mode 100644
index 0000000000..8cb2963faf
--- /dev/null
+++ b/apps/plugins/text_viewer/text_viewer.make
@@ -0,0 +1,20 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id$
8#
9
10TEXT_VIEWER_SRCDIR := $(APPSDIR)/plugins/text_viewer
11TEXT_VIEWER_BUILDDIR := $(BUILDDIR)/apps/plugins/text_viewer
12
13TEXT_VIEWER_SRC := $(call preprocess, $(TEXT_VIEWER_SRCDIR)/SOURCES)
14TEXT_VIEWER_OBJ := $(call c2obj, $(TEXT_VIEWER_SRC))
15
16OTHER_SRC += $(TEXT_VIEWER_SRC)
17
18ROCKS += $(TEXT_VIEWER_BUILDDIR)/text_viewer.rock
19
20$(TEXT_VIEWER_BUILDDIR)/text_viewer.rock: $(TEXT_VIEWER_OBJ)
diff --git a/apps/plugins/text_viewer/tv_action.c b/apps/plugins/text_viewer/tv_action.c
new file mode 100644
index 0000000000..fb7fdb40e6
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_action.c
@@ -0,0 +1,186 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "tv_action.h"
25#include "tv_bookmark.h"
26#include "tv_pager.h"
27#include "tv_screen_pos.h"
28#include "tv_settings.h"
29#include "tv_window.h"
30
31static const struct tv_preferences *prefs;
32
33bool tv_init(const unsigned char *file)
34{
35 size_t req_size = 0;
36 size_t size;
37 size_t used_size;
38 unsigned char *buffer;
39
40 /* get the plugin buffer */
41 buffer = rb->plugin_get_buffer(&req_size);
42 size = req_size;
43 if (buffer == NULL || size == 0)
44 return false;
45
46 prefs = tv_get_preferences();
47
48 tv_init_bookmark();
49
50 /* initialize modules */
51 if (!tv_init_window(buffer, size, &used_size))
52 return false;
53
54 /* load the preferences and bookmark */
55 tv_load_settings(file);
56
57 /* select to read the page */
58 tv_select_bookmark();
59 return true;
60}
61
62void tv_exit(void *parameter)
63{
64 (void)parameter;
65
66 /* save preference and bookmarks */
67 if (!tv_save_settings())
68 rb->splash(HZ, "Can't save preferences and bookmarks");
69
70 /* finalize modules */
71 tv_finalize_window();
72}
73
74void tv_draw(void)
75{
76 struct tv_screen_pos pos;
77
78 tv_copy_screen_pos(&pos);
79 tv_draw_window();
80 if (pos.line == 0)
81 tv_new_page();
82
83 tv_move_screen(pos.page, pos.line, SEEK_SET);
84}
85
86void tv_scroll_up(enum tv_vertical_scroll_mode mode)
87{
88 int offset_page = 0;
89 int offset_line = -1;
90
91 if ((mode == TV_VERTICAL_SCROLL_PAGE) ||
92 (mode == TV_VERTICAL_SCROLL_PREFS && prefs->scroll_mode == PAGE))
93 {
94 offset_page--;
95#ifdef HAVE_LCD_BITMAP
96 offset_line = (prefs->page_mode == OVERLAP)? 1:0;
97#endif
98 }
99 tv_move_screen(offset_page, offset_line, SEEK_CUR);
100}
101
102void tv_scroll_down(enum tv_vertical_scroll_mode mode)
103{
104 int offset_page = 0;
105 int offset_line = 1;
106
107 if ((mode == TV_VERTICAL_SCROLL_PAGE) ||
108 (mode == TV_VERTICAL_SCROLL_PREFS && prefs->scroll_mode == PAGE))
109 {
110 offset_page++;
111#ifdef HAVE_LCD_BITMAP
112 offset_line = (prefs->page_mode == OVERLAP)? -1:0;
113#endif
114 }
115 tv_move_screen(offset_page, offset_line, SEEK_CUR);
116}
117
118void tv_scroll_left(enum tv_horizontal_scroll_mode mode)
119{
120 int offset_window = 0;
121 int offset_column = 0;
122
123 if (mode == TV_HORIZONTAL_SCROLL_COLUMN)
124 {
125 /* Scroll left one column */
126 offset_column--;
127 }
128 else
129 {
130 /* Scroll left one window */
131 offset_window--;
132 }
133 tv_move_window(offset_window, offset_column);
134}
135
136void tv_scroll_right(enum tv_horizontal_scroll_mode mode)
137{
138 int offset_window = 0;
139 int offset_column = 0;
140
141 if (mode == TV_HORIZONTAL_SCROLL_COLUMN)
142 {
143 /* Scroll right one column */
144 offset_column++;
145 }
146 else
147 {
148 /* Scroll right one window */
149 offset_window++;
150 }
151 tv_move_window(offset_window, offset_column);
152}
153
154void tv_top(void)
155{
156 tv_move_screen(0, 0, SEEK_SET);
157}
158
159void tv_bottom(void)
160{
161 tv_move_screen(0, 0, SEEK_END);
162 if (prefs->scroll_mode == PAGE)
163 tv_move_screen(0, -tv_get_screen_pos()->line, SEEK_CUR);
164}
165
166enum tv_menu_result tv_menu(void)
167{
168 enum tv_menu_result res;
169 struct tv_screen_pos cur_pos;
170 off_t cur_file_pos = tv_get_screen_pos()->file_pos;
171
172 res = tv_display_menu();
173
174 tv_convert_fpos(cur_file_pos, &cur_pos);
175 if (prefs->scroll_mode == PAGE)
176 cur_pos.line = 0;
177
178 tv_move_screen(cur_pos.page, cur_pos.line, SEEK_SET);
179
180 return res;
181}
182
183void tv_add_or_remove_bookmark(void)
184{
185 tv_toggle_bookmark();
186}
diff --git a/apps/plugins/text_viewer/tv_action.h b/apps/plugins/text_viewer/tv_action.h
new file mode 100644
index 0000000000..c5f7bd0e2f
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_action.h
@@ -0,0 +1,119 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_ACTION_H
24#define PLUGIN_TEXT_VIEWER_ACTION_H
25
26#include "tv_menu.h"
27
28/* horizontal scroll mode */
29enum tv_horizontal_scroll_mode
30{
31 TV_HORIZONTAL_SCROLL_COLUMN, /* left/right one column */
32 TV_HORIZONTAL_SCROLL_WINDOW, /* left/right one window */
33 TV_HORIZONTAL_SCROLL_PREFS, /* left/right follows the settings */
34};
35
36/*vertical scroll mode */
37enum tv_vertical_scroll_mode
38{
39 TV_VERTICAL_SCROLL_LINE, /* up/down one line */
40 TV_VERTICAL_SCROLL_PAGE, /* up/down one page */
41 TV_VERTICAL_SCROLL_PREFS, /* up/down follows the settings */
42};
43
44/*
45 * initialize modules
46 *
47 * [In] file
48 * read file name
49 *
50 * return
51 * true initialize success
52 * false initialize failure
53 */
54bool tv_init(const unsigned char *file);
55
56/*
57 * finalize modules
58 *
59 * [In] parameter
60 * this argument does not use
61 */
62void tv_exit(void *parameter);
63
64/* draw the current page */
65void tv_draw(void);
66
67/*
68 * scroll up
69 *
70 * [In] mode
71 * scroll mode
72 */
73void tv_scroll_up(enum tv_vertical_scroll_mode mode);
74
75/*
76 * scroll down
77 *
78 * [In] mode
79 * scroll mode
80 */
81void tv_scroll_down(enum tv_vertical_scroll_mode mode);
82
83/*
84 * scroll left
85 *
86 * [In] mode
87 * scroll mode
88 */
89void tv_scroll_left(enum tv_horizontal_scroll_mode mode);
90
91/*
92 * scroll right
93 *
94 * [In] mode
95 * scroll mode
96 */
97void tv_scroll_right(enum tv_horizontal_scroll_mode mode);
98
99/* jump to the top */
100void tv_top(void);
101
102/* jump to the bottom */
103void tv_bottom(void);
104
105/*
106 * display menu
107 *
108 * return
109 * the following value returns
110 * TV_MENU_RESULT_EXIT_MENU menu exit and continue this plugin
111 * TV_MENU_RESULT_EXIT_PLUGIN request to exit this plugin
112 * TV_MENU_RESULT_ATTACHED_USB connect USB cable
113 */
114enum tv_menu_result tv_menu(void);
115
116/* add or remove the bookmark to the current position */
117void tv_add_or_remove_bookmark(void);
118
119#endif
diff --git a/apps/plugins/text_viewer/tv_bookmark.c b/apps/plugins/text_viewer/tv_bookmark.c
new file mode 100644
index 0000000000..61df02705e
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_bookmark.c
@@ -0,0 +1,302 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "tv_bookmark.h"
25#include "tv_pager.h"
26#include "tv_preferences.h"
27
28/* text viewer bookmark functions */
29
30enum {
31 TV_BOOKMARK_SYSTEM = 1,
32 TV_BOOKMARK_USER = 2,
33};
34
35#define SERIALIZE_BOOKMARK_SIZE 8
36
37struct tv_bookmark_info {
38 struct tv_screen_pos pos;
39 unsigned char flag;
40};
41
42/* bookmark stored array */
43struct tv_bookmark_info bookmarks[TV_MAX_BOOKMARKS + 1];
44static unsigned char bookmark_count;
45
46static int tv_compare_screen_pos(const struct tv_screen_pos *p1, const struct tv_screen_pos *p2)
47{
48 if (p1->page != p2->page)
49 return p1->page - p2->page;
50
51 return p1->line - p2->line;
52}
53
54static int bm_comp(const void *a, const void *b)
55{
56 struct tv_bookmark_info *pa;
57 struct tv_bookmark_info *pb;
58
59 pa = (struct tv_bookmark_info*)a;
60 pb = (struct tv_bookmark_info*)b;
61
62 return tv_compare_screen_pos(&pa->pos, &pb->pos);
63}
64
65static int tv_add_bookmark(const struct tv_screen_pos *pos)
66{
67 if (bookmark_count >= TV_MAX_BOOKMARKS)
68 return -1;
69
70 bookmarks[bookmark_count].pos = *pos;
71 bookmarks[bookmark_count].flag = TV_BOOKMARK_USER;
72
73 return bookmark_count++;
74}
75
76static void tv_remove_bookmark(int idx)
77{
78 int k;
79
80 if (idx >= 0 && idx < bookmark_count)
81 {
82 for (k = idx + 1; k < bookmark_count; k++)
83 bookmarks[k-1] = bookmarks[k];
84
85 bookmark_count--;
86 }
87}
88
89static int tv_find_bookmark(const struct tv_screen_pos *pos)
90{
91 int i;
92
93 for (i = 0; i < bookmark_count; i++)
94 {
95 if (tv_compare_screen_pos(&bookmarks[i].pos, pos) == 0)
96 return i;
97 }
98 return -1;
99}
100
101static void tv_change_preferences(const struct tv_preferences *oldp)
102{
103 int i;
104
105 if (oldp == NULL)
106 return;
107
108 for (i = 0; i < bookmark_count; i++)
109 tv_convert_fpos(bookmarks[i].pos.file_pos, &bookmarks[i].pos);
110}
111
112void tv_init_bookmark(void)
113{
114 tv_add_preferences_change_listner(tv_change_preferences);
115}
116
117int tv_get_bookmark_positions(struct tv_screen_pos *pos_array)
118{
119 int i;
120
121 for(i = 0; i < bookmark_count; i++)
122 *pos_array++ = bookmarks[i].pos;
123
124 return bookmark_count;
125}
126
127void tv_toggle_bookmark(void)
128{
129 const struct tv_screen_pos *pos = tv_get_screen_pos();
130 int idx = tv_find_bookmark(pos);
131
132 if (idx < 0)
133 {
134 if (tv_add_bookmark(pos) >= 0)
135 rb->splash(HZ/2, "Bookmark add");
136 else
137 rb->splash(HZ/2, "No more add bookmark");
138 return;
139 }
140 tv_remove_bookmark(idx);
141 rb->splash(HZ/2, "Bookmark remove");
142}
143
144void tv_create_system_bookmark(void)
145{
146 const struct tv_screen_pos *pos = tv_get_screen_pos();
147 int idx = tv_find_bookmark(pos);
148
149 if (idx >= 0)
150 bookmarks[idx].flag |= TV_BOOKMARK_SYSTEM;
151 else
152 {
153 bookmarks[bookmark_count].pos = *pos;
154 bookmarks[bookmark_count].flag = TV_BOOKMARK_SYSTEM;
155 bookmark_count++;
156 }
157}
158
159void tv_select_bookmark(void)
160{
161 int i;
162 struct tv_screen_pos select_pos;
163
164 for (i = 0; i < bookmark_count; i++)
165 {
166 if (bookmarks[i].flag & TV_BOOKMARK_SYSTEM)
167 break;
168 }
169
170 /* if does not find the system bookmark, add the system bookmark. */
171 if (i >= bookmark_count)
172 tv_create_system_bookmark();
173
174 if (bookmark_count == 1)
175 select_pos = bookmarks[0].pos;
176 else
177 {
178 int selected = -1;
179 struct opt_items items[bookmark_count];
180 unsigned char names[bookmark_count][24];
181
182 rb->qsort(bookmarks, bookmark_count, sizeof(struct tv_bookmark_info), bm_comp);
183
184 for (i = 0; i < bookmark_count; i++)
185 {
186 rb->snprintf(names[i], sizeof(names[0]),
187#if CONFIG_KEYPAD != PLAYER_PAD
188 "%cPage: %d Line: %d",
189#else
190 "%cP:%d L:%d",
191#endif
192 (bookmarks[i].flag & TV_BOOKMARK_SYSTEM)? '*' : ' ',
193 bookmarks[i].pos.page + 1,
194 bookmarks[i].pos.line + 1);
195 items[i].string = names[i];
196 items[i].voice_id = -1;
197 }
198
199 rb->set_option("Select bookmark", &selected, INT, items,
200 bookmark_count, NULL);
201
202 if (selected >= 0 && selected < bookmark_count)
203 select_pos = bookmarks[selected].pos;
204 else
205 {
206 /* when does not select any bookmarks, move to the current page */
207 tv_copy_screen_pos(&select_pos);
208
209 if (select_pos.file_pos == 0)
210 rb->splash(HZ, "Start the first page");
211 else
212 rb->splash(HZ, "Return to the current page");
213 }
214 }
215
216 /* deletes the system bookmark */
217 for (i = 0; i < bookmark_count; i++)
218 {
219 if ((bookmarks[i].flag &= TV_BOOKMARK_USER) == 0)
220 {
221 tv_remove_bookmark(i);
222 break;
223 }
224 }
225
226 /* move to the select position */
227 if (tv_get_preferences()->scroll_mode == PAGE)
228 select_pos.line = 0;
229
230 tv_move_screen(select_pos.page, select_pos.line, SEEK_SET);
231}
232
233/* serialize or deserialize of the bookmark array */
234static bool tv_read_bookmark_info(int fd, struct tv_bookmark_info *b)
235{
236 unsigned char buf[SERIALIZE_BOOKMARK_SIZE];
237
238 if (rb->read(fd, buf, sizeof(buf)) < 0)
239 return false;
240
241 b->pos.file_pos = (buf[0] << 24)|(buf[1] << 16)|(buf[2] << 8)|buf[3];
242 b->pos.page = (buf[4] << 8)|buf[5];
243 b->pos.line = buf[6];
244 b->flag = buf[7];
245
246 return true;
247}
248
249bool tv_deserialize_bookmarks(int fd)
250{
251 int i;
252 bool res = true;
253
254 if (rb->read(fd, &bookmark_count, 1) < 0)
255 return false;
256
257 for (i = 0; i < bookmark_count; i++)
258 {
259 if (!tv_read_bookmark_info(fd, &bookmarks[i]))
260 {
261 res = false;
262 break;
263 }
264 }
265
266 bookmark_count = i;
267 return res;
268}
269
270static bool tv_write_bookmark_info(int fd, const struct tv_bookmark_info *b)
271{
272 unsigned char buf[SERIALIZE_BOOKMARK_SIZE];
273 unsigned char *p = buf;
274
275 *p++ = b->pos.file_pos >> 24;
276 *p++ = b->pos.file_pos >> 16;
277 *p++ = b->pos.file_pos >> 8;
278 *p++ = b->pos.file_pos;
279
280 *p++ = b->pos.page >> 8;
281 *p++ = b->pos.page;
282
283 *p++ = b->pos.line;
284 *p = b->flag;
285
286 return (rb->write(fd, buf, SERIALIZE_BOOKMARK_SIZE) >= 0);
287}
288
289int tv_serialize_bookmarks(int fd)
290{
291 int i;
292
293 if (rb->write(fd, &bookmark_count, 1) < 0)
294 return 0;
295
296 for (i = 0; i < bookmark_count; i++)
297 {
298 if (!tv_write_bookmark_info(fd, &bookmarks[i]))
299 break;
300 }
301 return i * SERIALIZE_BOOKMARK_SIZE + 1;
302}
diff --git a/apps/plugins/text_viewer/tv_bookmark.h b/apps/plugins/text_viewer/tv_bookmark.h
new file mode 100644
index 0000000000..d61af41620
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_bookmark.h
@@ -0,0 +1,85 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_BOOKMARK_H
24#define PLUGIN_TEXT_VIEWER_BOOKMARK_H
25
26#include "tv_screen_pos.h"
27
28/* stuff for the bookmarking */
29
30/* Maximum amount of register possible bookmarks */
31#define TV_MAX_BOOKMARKS 16
32
33/* initialize the bookmark module */
34void tv_init_bookmark(void);
35
36/*
37 * get the positions which registered bookmarks
38 *
39 * [Out] pos_array
40 * the array which store positions of all bookmarks
41 *
42 * return
43 * bookmark count
44 */
45int tv_get_bookmark_positions(struct tv_screen_pos *pos_array);
46
47/*
48 * the function that a bookmark add when there is not a bookmark in the given position
49 * or the bookmark remove when there exist a bookmark in the given position.
50 */
51void tv_toggle_bookmark(void);
52
53/*
54 * The menu that can select registered bookmarks is displayed, one is selected from
55 * among them, and moves to the page which selected bookmarks.
56 */
57void tv_select_bookmark(void);
58
59/* creates system bookmark */
60void tv_create_system_bookmark(void);
61
62/*
63 * serialize the bookmark array
64 *
65 * [In] fd
66 * the file descripter which is stored the result.
67 *
68 * Return
69 * the size of the result
70 */
71int tv_serialize_bookmarks(int fd);
72
73/*
74 * deserialize the bookmark array
75 *
76 * [In] fd
77 * the file descripter which is stored the serialization of the bookmark array.
78 *
79 * Return
80 * true success
81 * false failure
82 */
83bool tv_deserialize_bookmarks(int fd);
84
85#endif
diff --git a/apps/plugins/text_viewer/tv_button.h b/apps/plugins/text_viewer/tv_button.h
new file mode 100644
index 0000000000..53114c6169
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_button.h
@@ -0,0 +1,424 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_BUTTON_H
24#define PLUGIN_TEXT_VIEWER_BUTTON_H
25
26/* variable button definitions */
27
28/*
29 * [required]
30 * TV_QUIT exit txit viewer
31 * TV_SCROLL_UP scroll up
32 * TV_SCROLL_DOWN scroll down
33 * TV_SCREEN_LEFT scroll left (when wide mode)/scroll previous page (when narrow mode)
34 * TV_SCREEN_RIGHT scroll right (when wide mode)/scroll next page (when narrow mode)
35 * TV_MENU enter menu
36 * TV_AUTOSCROLL toggle autoscroll
37 * TV_BOOKMARK set/reset bookmark
38 *
39 * [optional]
40 * TV_RC_QUIT exit text plugin (remote key only)
41 * TV_LINE_UP one line up
42 * TV_LINE_DOWN one line down
43 * TV_COLUMN_LEFT one column left
44 * TV_COLUMN_RIGHT one column right
45 */
46
47/* Recorder keys */
48#if CONFIG_KEYPAD == RECORDER_PAD
49#define TV_QUIT BUTTON_OFF
50#define TV_SCROLL_UP BUTTON_UP
51#define TV_SCROLL_DOWN BUTTON_DOWN
52#define TV_SCREEN_LEFT BUTTON_LEFT
53#define TV_SCREEN_RIGHT BUTTON_RIGHT
54#define TV_MENU BUTTON_F1
55#define TV_AUTOSCROLL BUTTON_PLAY
56#define TV_LINE_UP (BUTTON_ON | BUTTON_UP)
57#define TV_LINE_DOWN (BUTTON_ON | BUTTON_DOWN)
58#define TV_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT)
59#define TV_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT)
60#define TV_BOOKMARK BUTTON_F2
61
62/* Archos AV300 keys */
63#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
64#define TV_QUIT BUTTON_OFF
65#define TV_SCROLL_UP BUTTON_UP
66#define TV_SCROLL_DOWN BUTTON_DOWN
67#define TV_SCREEN_LEFT BUTTON_LEFT
68#define TV_SCREEN_RIGHT BUTTON_RIGHT
69#define TV_MENU BUTTON_F1
70#define TV_AUTOSCROLL BUTTON_SELECT
71#define TV_LINE_UP (BUTTON_ON | BUTTON_UP)
72#define TV_LINE_DOWN (BUTTON_ON | BUTTON_DOWN)
73#define TV_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT)
74#define TV_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT)
75#define TV_BOOKMARK BUTTON_F2
76
77/* Ondio keys */
78#elif CONFIG_KEYPAD == ONDIO_PAD
79#define TV_QUIT BUTTON_OFF
80#define TV_SCROLL_UP BUTTON_UP
81#define TV_SCROLL_DOWN BUTTON_DOWN
82#define TV_SCREEN_LEFT BUTTON_LEFT
83#define TV_SCREEN_RIGHT BUTTON_RIGHT
84#define TV_MENU (BUTTON_MENU|BUTTON_REPEAT)
85#define TV_AUTOSCROLL_PRE BUTTON_MENU
86#define TV_AUTOSCROLL (BUTTON_MENU|BUTTON_REL)
87#define TV_BOOKMARK (BUTTON_MENU|BUTTON_OFF)
88
89/* Player keys */
90#elif CONFIG_KEYPAD == PLAYER_PAD
91#define TV_QUIT BUTTON_STOP
92#define TV_SCROLL_UP BUTTON_LEFT
93#define TV_SCROLL_DOWN BUTTON_RIGHT
94#define TV_SCREEN_LEFT (BUTTON_ON|BUTTON_LEFT)
95#define TV_SCREEN_RIGHT (BUTTON_ON|BUTTON_RIGHT)
96#define TV_MENU BUTTON_MENU
97#define TV_AUTOSCROLL BUTTON_PLAY
98#define TV_BOOKMARK BUTTON_ON
99
100/* iRiver H1x0 && H3x0 keys */
101#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
102 (CONFIG_KEYPAD == IRIVER_H300_PAD)
103#define TV_QUIT BUTTON_OFF
104#define TV_RC_QUIT BUTTON_RC_STOP
105#define TV_SCROLL_UP BUTTON_UP
106#define TV_SCROLL_DOWN BUTTON_DOWN
107#define TV_SCREEN_LEFT BUTTON_LEFT
108#define TV_SCREEN_RIGHT BUTTON_RIGHT
109#define TV_MENU BUTTON_MODE
110#define TV_AUTOSCROLL BUTTON_SELECT
111#define TV_LINE_UP (BUTTON_ON | BUTTON_UP)
112#define TV_LINE_DOWN (BUTTON_ON | BUTTON_DOWN)
113#define TV_COLUMN_LEFT (BUTTON_ON | BUTTON_LEFT)
114#define TV_COLUMN_RIGHT (BUTTON_ON | BUTTON_RIGHT)
115#define TV_BOOKMARK (BUTTON_ON | BUTTON_SELECT)
116
117/* iPods */
118#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
119 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
120 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
121#define TV_QUIT_PRE BUTTON_SELECT
122#define TV_QUIT (BUTTON_SELECT | BUTTON_MENU)
123#define TV_SCROLL_UP BUTTON_SCROLL_BACK
124#define TV_SCROLL_DOWN BUTTON_SCROLL_FWD
125#define TV_SCREEN_LEFT BUTTON_LEFT
126#define TV_SCREEN_RIGHT BUTTON_RIGHT
127#define TV_MENU BUTTON_MENU
128#define TV_AUTOSCROLL BUTTON_PLAY
129#define TV_BOOKMARK BUTTON_SELECT
130
131/* iFP7xx keys */
132#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
133#define TV_QUIT BUTTON_PLAY
134#define TV_SCROLL_UP BUTTON_UP
135#define TV_SCROLL_DOWN BUTTON_DOWN
136#define TV_SCREEN_LEFT BUTTON_LEFT
137#define TV_SCREEN_RIGHT BUTTON_RIGHT
138#define TV_MENU BUTTON_MODE
139#define TV_AUTOSCROLL BUTTON_SELECT
140#define TV_BOOKMARK (BUTTON_LEFT|BUTTON_SELECT)
141
142/* iAudio X5 keys */
143#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
144#define TV_QUIT BUTTON_POWER
145#define TV_SCROLL_UP BUTTON_UP
146#define TV_SCROLL_DOWN BUTTON_DOWN
147#define TV_SCREEN_LEFT BUTTON_LEFT
148#define TV_SCREEN_RIGHT BUTTON_RIGHT
149#define TV_MENU BUTTON_SELECT
150#define TV_AUTOSCROLL BUTTON_PLAY
151#define TV_BOOKMARK BUTTON_REC
152
153/* GIGABEAT keys */
154#elif CONFIG_KEYPAD == GIGABEAT_PAD
155#define TV_QUIT BUTTON_POWER
156#define TV_SCROLL_UP BUTTON_UP
157#define TV_SCROLL_DOWN BUTTON_DOWN
158#define TV_SCREEN_LEFT BUTTON_LEFT
159#define TV_SCREEN_RIGHT BUTTON_RIGHT
160#define TV_MENU BUTTON_MENU
161#define TV_AUTOSCROLL BUTTON_A
162#define TV_BOOKMARK BUTTON_SELECT
163
164/* Sansa E200 keys */
165#elif CONFIG_KEYPAD == SANSA_E200_PAD
166#define TV_QUIT BUTTON_POWER
167#define TV_SCROLL_UP BUTTON_UP
168#define TV_SCROLL_DOWN BUTTON_DOWN
169#define TV_SCREEN_LEFT BUTTON_LEFT
170#define TV_SCREEN_RIGHT BUTTON_RIGHT
171#define TV_MENU BUTTON_SELECT
172#define TV_AUTOSCROLL BUTTON_REC
173#define TV_LINE_UP BUTTON_SCROLL_BACK
174#define TV_LINE_DOWN BUTTON_SCROLL_FWD
175#define TV_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT)
176
177/* Sansa Fuze keys */
178#elif CONFIG_KEYPAD == SANSA_FUZE_PAD
179#define TV_QUIT (BUTTON_HOME|BUTTON_REPEAT)
180#define TV_SCROLL_UP BUTTON_UP
181#define TV_SCROLL_DOWN BUTTON_DOWN
182#define TV_SCREEN_LEFT BUTTON_LEFT
183#define TV_SCREEN_RIGHT BUTTON_RIGHT
184#define TV_MENU BUTTON_SELECT|BUTTON_REPEAT
185#define TV_AUTOSCROLL BUTTON_SELECT|BUTTON_DOWN
186#define TV_LINE_UP BUTTON_SCROLL_BACK
187#define TV_LINE_DOWN BUTTON_SCROLL_FWD
188#define TV_BOOKMARK BUTTON_SELECT
189
190/* Sansa C200 keys */
191#elif CONFIG_KEYPAD == SANSA_C200_PAD
192#define TV_QUIT BUTTON_POWER
193#define TV_SCROLL_UP BUTTON_VOL_UP
194#define TV_SCROLL_DOWN BUTTON_VOL_DOWN
195#define TV_SCREEN_LEFT BUTTON_LEFT
196#define TV_SCREEN_RIGHT BUTTON_RIGHT
197#define TV_MENU BUTTON_SELECT
198#define TV_AUTOSCROLL BUTTON_REC
199#define TV_LINE_UP BUTTON_UP
200#define TV_LINE_DOWN BUTTON_DOWN
201#define TV_BOOKMARK (BUTTON_DOWN | BUTTON_SELECT)
202
203/* Sansa Clip keys */
204#elif CONFIG_KEYPAD == SANSA_CLIP_PAD
205#define TV_QUIT BUTTON_POWER
206#define TV_SCROLL_UP BUTTON_VOL_UP
207#define TV_SCROLL_DOWN BUTTON_VOL_DOWN
208#define TV_SCREEN_LEFT BUTTON_LEFT
209#define TV_SCREEN_RIGHT BUTTON_RIGHT
210#define TV_MENU BUTTON_SELECT
211#define TV_AUTOSCROLL BUTTON_HOME
212#define TV_LINE_UP BUTTON_UP
213#define TV_LINE_DOWN BUTTON_DOWN
214#define TV_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT)
215
216/* Sansa M200 keys */
217#elif CONFIG_KEYPAD == SANSA_M200_PAD
218#define TV_QUIT BUTTON_POWER
219#define TV_SCROLL_UP BUTTON_VOL_UP
220#define TV_SCROLL_DOWN BUTTON_VOL_DOWN
221#define TV_SCREEN_LEFT BUTTON_LEFT
222#define TV_SCREEN_RIGHT BUTTON_RIGHT
223#define TV_MENU (BUTTON_SELECT | BUTTON_UP)
224#define TV_AUTOSCROLL (BUTTON_SELECT | BUTTON_REL)
225#define TV_LINE_UP BUTTON_UP
226#define TV_LINE_DOWN BUTTON_DOWN
227#define TV_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT)
228
229/* iriver H10 keys */
230#elif CONFIG_KEYPAD == IRIVER_H10_PAD
231#define TV_QUIT BUTTON_POWER
232#define TV_SCROLL_UP BUTTON_SCROLL_UP
233#define TV_SCROLL_DOWN BUTTON_SCROLL_DOWN
234#define TV_SCREEN_LEFT BUTTON_LEFT
235#define TV_SCREEN_RIGHT BUTTON_RIGHT
236#define TV_MENU BUTTON_REW
237#define TV_AUTOSCROLL BUTTON_PLAY
238#define TV_BOOKMARK BUTTON_FF
239
240/*M-Robe 500 keys */
241#elif CONFIG_KEYPAD == MROBE500_PAD
242#define TV_QUIT BUTTON_POWER
243#define TV_SCROLL_UP BUTTON_RC_PLAY
244#define TV_SCROLL_DOWN BUTTON_RC_DOWN
245#define TV_SCREEN_LEFT BUTTON_LEFT
246#define TV_SCREEN_RIGHT BUTTON_RIGHT
247#define TV_MENU BUTTON_RC_HEART
248#define TV_AUTOSCROLL BUTTON_RC_MODE
249#define TV_BOOKMARK BUTTON_CENTER
250
251/*Gigabeat S keys */
252#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
253#define TV_QUIT BUTTON_BACK
254#define TV_SCROLL_UP BUTTON_PREV
255#define TV_SCROLL_DOWN BUTTON_NEXT
256#define TV_SCREEN_LEFT (BUTTON_PLAY | BUTTON_LEFT)
257#define TV_SCREEN_RIGHT (BUTTON_PLAY | BUTTON_RIGHT)
258#define TV_MENU BUTTON_MENU
259#define TV_AUTOSCROLL_PRE BUTTON_PLAY
260#define TV_AUTOSCROLL (BUTTON_PLAY|BUTTON_REL)
261#define TV_LINE_UP BUTTON_UP
262#define TV_LINE_DOWN BUTTON_DOWN
263#define TV_COLUMN_LEFT BUTTON_LEFT
264#define TV_COLUMN_RIGHT BUTTON_RIGHT
265#define TV_BOOKMARK BUTTON_SELECT
266
267/*M-Robe 100 keys */
268#elif CONFIG_KEYPAD == MROBE100_PAD
269#define TV_QUIT BUTTON_POWER
270#define TV_SCROLL_UP BUTTON_UP
271#define TV_SCROLL_DOWN BUTTON_DOWN
272#define TV_SCREEN_LEFT BUTTON_LEFT
273#define TV_SCREEN_RIGHT BUTTON_RIGHT
274#define TV_MENU BUTTON_MENU
275#define TV_AUTOSCROLL BUTTON_DISPLAY
276#define TV_BOOKMARK BUTTON_SELECT
277
278/* iAUdio M3 keys */
279#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
280#define TV_QUIT BUTTON_REC
281#define TV_RC_QUIT BUTTON_RC_REC
282#define TV_SCROLL_UP BUTTON_RC_VOL_UP
283#define TV_SCROLL_DOWN BUTTON_RC_VOL_DOWN
284#define TV_SCREEN_LEFT BUTTON_RC_REW
285#define TV_SCREEN_RIGHT BUTTON_RC_FF
286#define TV_MENU BUTTON_RC_MENU
287#define TV_AUTOSCROLL BUTTON_RC_MODE
288#define TV_BOOKMARK BUTTON_RC_PLAY
289
290/* Cowon D2 keys */
291#elif CONFIG_KEYPAD == COWON_D2_PAD
292#define TV_QUIT BUTTON_POWER
293#define TV_MENU BUTTON_MENU
294#define TV_SCROLL_UP BUTTON_MINUS
295#define TV_SCROLL_DOWN BUTTON_PLUS
296#define TV_BOOKMARK (BUTTON_MENU|BUTTON_PLUS)
297
298#elif CONFIG_KEYPAD == IAUDIO67_PAD
299#define TV_QUIT BUTTON_POWER
300#define TV_SCROLL_UP BUTTON_VOLUP
301#define TV_SCROLL_DOWN BUTTON_VOLDOWN
302#define TV_SCREEN_LEFT BUTTON_LEFT
303#define TV_SCREEN_RIGHT BUTTON_RIGHT
304#define TV_MENU BUTTON_MENU
305#define TV_AUTOSCROLL BUTTON_PLAY
306#define TV_RC_QUIT BUTTON_STOP
307#define TV_BOOKMARK (BUTTON_LEFT|BUTTON_PLAY)
308
309/* Creative Zen Vision:M keys */
310#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
311#define TV_QUIT BUTTON_BACK
312#define TV_SCROLL_UP BUTTON_UP
313#define TV_SCROLL_DOWN BUTTON_DOWN
314#define TV_SCREEN_LEFT BUTTON_LEFT
315#define TV_SCREEN_RIGHT BUTTON_RIGHT
316#define TV_MENU BUTTON_MENU
317#define TV_AUTOSCROLL BUTTON_SELECT
318#define TV_BOOKMARK BUTTON_PLAY
319
320/* Philips HDD1630 keys */
321#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
322#define TV_QUIT BUTTON_POWER
323#define TV_SCROLL_UP BUTTON_UP
324#define TV_SCROLL_DOWN BUTTON_DOWN
325#define TV_SCREEN_LEFT BUTTON_LEFT
326#define TV_SCREEN_RIGHT BUTTON_RIGHT
327#define TV_MENU BUTTON_MENU
328#define TV_AUTOSCROLL BUTTON_VIEW
329#define TV_BOOKMARK BUTTON_SELECT
330
331/* Philips SA9200 keys */
332#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
333#define TV_QUIT BUTTON_POWER
334#define TV_SCROLL_UP BUTTON_UP
335#define TV_SCROLL_DOWN BUTTON_DOWN
336#define TV_SCREEN_LEFT BUTTON_PREV
337#define TV_SCREEN_RIGHT BUTTON_NEXT
338#define TV_MENU BUTTON_MENU
339#define TV_AUTOSCROLL BUTTON_PLAY
340#define TV_BOOKMARK BUTTON_RIGHT
341
342/* Onda VX747 keys */
343#elif CONFIG_KEYPAD == ONDAVX747_PAD
344#define TV_QUIT BUTTON_POWER
345#define TV_MENU BUTTON_MENU
346#define TV_BOOKMARK (BUTTON_RIGHT|BUTTON_POWER)
347
348/* Onda VX777 keys */
349#elif CONFIG_KEYPAD == ONDAVX777_PAD
350#define TV_QUIT BUTTON_POWER
351#define TV_BOOKMARK (BUTTON_RIGHT|BUTTON_POWER)
352
353/* SAMSUNG YH-820 / YH-920 / YH-925 keys */
354#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
355#define TV_QUIT BUTTON_REC
356#define TV_SCROLL_UP BUTTON_UP
357#define TV_SCROLL_DOWN BUTTON_DOWN
358#define TV_SCREEN_LEFT BUTTON_LEFT
359#define TV_SCREEN_RIGHT BUTTON_RIGHT
360#define TV_MENU BUTTON_PLAY
361#define TV_AUTOSCROLL BUTTON_REW
362#define TV_BOOKMARK BUTTON_FFWD
363
364/* Packard Bell Vibe 500 keys */
365#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
366#define TV_QUIT BUTTON_REC
367#define TV_SCROLL_UP BUTTON_OK
368#define TV_SCROLL_DOWN BUTTON_CANCEL
369#define TV_LINE_UP BUTTON_UP
370#define TV_LINE_DOWN BUTTON_DOWN
371#define TV_SCREEN_LEFT BUTTON_PREV
372#define TV_SCREEN_RIGHT BUTTON_NEXT
373#define TV_MENU BUTTON_MENU
374#define TV_AUTOSCROLL BUTTON_PLAY
375#define TV_BOOKMARK BUTTON_POWER
376
377/* MPIO HD200 keys */
378#elif CONFIG_KEYPAD == MPIO_HD200_PAD
379#define TV_QUIT (BUTTON_REC | BUTTON_PLAY)
380#define TV_SCROLL_UP BUTTON_PREV
381#define TV_SCROLL_DOWN BUTTON_NEXT
382#define TV_SCREEN_LEFT BUTTON_VOL_DOWN
383#define TV_SCREEN_RIGHT BUTTON_VOL_UP
384#define TV_MENU BUTTON_SELECT
385#define TV_AUTOSCROLL BUTTON_PLAY
386#define TV_BOOKMARK BUTTON_REC
387
388#else
389#error No keymap defined!
390#endif
391
392#ifdef HAVE_TOUCHSCREEN
393#ifdef TV_QUIT
394#define TV_QUIT2 BUTTON_TOPLEFT
395#else
396#define TV_QUIT BUTTON_TOPLEFT
397#endif
398#ifdef TV_SCROLL_UP
399#define TV_SCROLL_UP2 BUTTON_TOPMIDDLE
400#else
401#define TV_SCROLL_UP BUTTON_TOPMIDDLE
402#endif
403#ifdef TV_SCROLL_DOWN
404#define TV_SCROLL_DOWN2 BUTTON_BOTTOMMIDDLE
405#else
406#define TV_SCROLL_DOWN BUTTON_BOTTOMMIDDLE
407#endif
408#ifndef TV_SCREEN_LEFT
409#define TV_SCREEN_LEFT BUTTON_MIDLEFT
410#endif
411#ifndef TV_SCREEN_RIGHT
412#define TV_SCREEN_RIGHT BUTTON_MIDRIGHT
413#endif
414#ifdef TV_MENU
415#define TV_MENU2 BUTTON_TOPRIGHT
416#else
417#define TV_MENU BUTTON_TOPRIGHT
418#endif
419#ifndef TV_AUTOSCROLL
420#define TV_AUTOSCROLL BUTTON_CENTER
421#endif
422#endif
423
424#endif
diff --git a/apps/plugins/text_viewer/tv_menu.c b/apps/plugins/text_viewer/tv_menu.c
new file mode 100644
index 0000000000..f40afb8848
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_menu.c
@@ -0,0 +1,349 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "lib/playback_control.h"
25#include "tv_bookmark.h"
26#include "tv_menu.h"
27#include "tv_settings.h"
28
29/* settings helper functions */
30
31static struct tv_preferences new_prefs;
32
33static bool tv_encoding_setting(void)
34{
35 static struct opt_items names[NUM_CODEPAGES];
36 int idx;
37
38 for (idx = 0; idx < NUM_CODEPAGES; idx++)
39 {
40 names[idx].string = rb->get_codepage_name(idx);
41 names[idx].voice_id = -1;
42 }
43
44 return rb->set_option("Encoding", &new_prefs.encoding, INT, names,
45 sizeof(names) / sizeof(names[0]), NULL);
46}
47
48static bool tv_word_wrap_setting(void)
49{
50 static const struct opt_items names[] = {
51 {"On", -1},
52 {"Off (Chop Words)", -1},
53 };
54
55 return rb->set_option("Word Wrap", &new_prefs.word_mode, INT,
56 names, 2, NULL);
57}
58
59static bool tv_line_mode_setting(void)
60{
61 static const struct opt_items names[] = {
62 {"Normal", -1},
63 {"Join Lines", -1},
64 {"Expand Lines", -1},
65 {"Reflow Lines", -1},
66 };
67
68 return rb->set_option("Line Mode", &new_prefs.line_mode, INT, names,
69 sizeof(names) / sizeof(names[0]), NULL);
70}
71
72static bool tv_view_mode_setting(void)
73{
74 static const struct opt_items names[] = {
75 {"No (Narrow)", -1},
76 {"Yes", -1},
77 };
78
79 return rb->set_option("Wide View", &new_prefs.view_mode, INT,
80 names , 2, NULL);
81}
82
83static bool tv_scroll_mode_setting(void)
84{
85 static const struct opt_items names[] = {
86 {"Scroll by Page", -1},
87 {"Scroll by Line", -1},
88 };
89
90 return rb->set_option("Scroll Mode", &new_prefs.scroll_mode, INT,
91 names, 2, NULL);
92}
93
94static bool tv_alignment_setting(void)
95{
96 static const struct opt_items names[] = {
97 {"Left", -1},
98 {"Right", -1},
99 };
100
101 return rb->set_option("Alignment", &new_prefs.alignment, INT,
102 names , 2, NULL);
103}
104
105#ifdef HAVE_LCD_BITMAP
106static bool tv_page_mode_setting(void)
107{
108 static const struct opt_items names[] = {
109 {"No", -1},
110 {"Yes", -1},
111 };
112
113 return rb->set_option("Overlap Pages", &new_prefs.page_mode, INT,
114 names, 2, NULL);
115}
116
117static bool tv_scrollbar_setting(void)
118{
119 static const struct opt_items names[] = {
120 {"Off", -1},
121 {"On", -1}
122 };
123
124 return rb->set_option("Show Scrollbar", &new_prefs.scrollbar_mode, INT,
125 names, 2, NULL);
126}
127
128static bool tv_header_setting(void)
129{
130 int len = (rb->global_settings->statusbar == STATUSBAR_TOP)? 4 : 2;
131 struct opt_items names[len];
132
133 names[0].string = "None";
134 names[0].voice_id = -1;
135 names[1].string = "File path";
136 names[1].voice_id = -1;
137
138 if (rb->global_settings->statusbar == STATUSBAR_TOP)
139 {
140 names[2].string = "Status bar";
141 names[2].voice_id = -1;
142 names[3].string = "Both";
143 names[3].voice_id = -1;
144 }
145
146 return rb->set_option("Show Header", &new_prefs.header_mode, INT,
147 names, len, NULL);
148}
149
150static bool tv_footer_setting(void)
151{
152 int len = (rb->global_settings->statusbar == STATUSBAR_BOTTOM)? 4 : 2;
153 struct opt_items names[len];
154
155 names[0].string = "None";
156 names[0].voice_id = -1;
157 names[1].string = "Page Num";
158 names[1].voice_id = -1;
159
160 if (rb->global_settings->statusbar == STATUSBAR_BOTTOM)
161 {
162 names[2].string = "Status bar";
163 names[2].voice_id = -1;
164 names[3].string = "Both";
165 names[3].voice_id = -1;
166 }
167
168 return rb->set_option("Show Footer", &new_prefs.footer_mode, INT,
169 names, len, NULL);
170}
171
172static int tv_font_comp(const void *a, const void *b)
173{
174 struct opt_items *pa;
175 struct opt_items *pb;
176
177 pa = (struct opt_items *)a;
178 pb = (struct opt_items *)b;
179
180 return rb->strcmp(pa->string, pb->string);
181}
182
183static bool tv_font_setting(void)
184{
185 int count = 0;
186 DIR *dir;
187 struct dirent *entry;
188 int i = 0;
189 int len;
190 int new_font = 0;
191 int old_font;
192 bool res;
193 int size = 0;
194
195 dir = rb->opendir(FONT_DIR);
196 if (!dir)
197 {
198 rb->splash(HZ/2, "font dir does not access");
199 return false;
200 }
201
202 while ((entry = rb->readdir(dir)) != NULL)
203 {
204 len = rb->strlen(entry->d_name);
205 if (len < 4 || rb->strcmp(entry->d_name + len - 4, ".fnt"))
206 continue;
207 size += len - 3;
208 count++;
209 }
210 rb->closedir(dir);
211
212 struct opt_items names[count];
213 unsigned char font_names[size];
214 unsigned char *p = font_names;
215
216 dir = rb->opendir(FONT_DIR);
217 if (!dir)
218 {
219 rb->splash(HZ/2, "font dir does not access");
220 return false;
221 }
222
223 while ((entry = rb->readdir(dir)) != NULL)
224 {
225 len = rb->strlen(entry->d_name);
226 if (len < 4 || rb->strcmp(entry->d_name + len - 4, ".fnt"))
227 continue;
228
229 rb->strlcpy(p, entry->d_name, len - 3);
230 names[i].string = p;
231 names[i].voice_id = -1;
232 p += len - 3;
233 if (++i >= count)
234 break;
235 }
236 rb->closedir(dir);
237
238 rb->qsort(names, count, sizeof(struct opt_items), tv_font_comp);
239
240 for (i = 0; i < count; i++)
241 {
242 if (!rb->strcmp(names[i].string, new_prefs.font_name))
243 {
244 new_font = i;
245 break;
246 }
247 }
248 old_font = new_font;
249
250 res = rb->set_option("Select Font", &new_font, INT,
251 names, count, NULL);
252
253 if (new_font != old_font)
254 {
255 rb->memset(new_prefs.font_name, 0, MAX_PATH);
256 rb->strlcpy(new_prefs.font_name, names[new_font].string, MAX_PATH);
257 }
258
259 return res;
260}
261#endif
262
263static bool tv_autoscroll_speed_setting(void)
264{
265 return rb->set_int("Auto-scroll Speed", "", UNIT_INT,
266 &new_prefs.autoscroll_speed, NULL, 1, 1, 10, NULL);
267}
268
269MENUITEM_FUNCTION(encoding_item, 0, "Encoding", tv_encoding_setting,
270 NULL, NULL, Icon_NOICON);
271MENUITEM_FUNCTION(word_wrap_item, 0, "Word Wrap", tv_word_wrap_setting,
272 NULL, NULL, Icon_NOICON);
273MENUITEM_FUNCTION(line_mode_item, 0, "Line Mode", tv_line_mode_setting,
274 NULL, NULL, Icon_NOICON);
275MENUITEM_FUNCTION(view_mode_item, 0, "Wide View", tv_view_mode_setting,
276 NULL, NULL, Icon_NOICON);
277MENUITEM_FUNCTION(alignment_item, 0, "Alignment", tv_alignment_setting,
278 NULL, NULL, Icon_NOICON);
279#ifdef HAVE_LCD_BITMAP
280MENUITEM_FUNCTION(scrollbar_item, 0, "Show Scrollbar", tv_scrollbar_setting,
281 NULL, NULL, Icon_NOICON);
282MENUITEM_FUNCTION(page_mode_item, 0, "Overlap Pages", tv_page_mode_setting,
283 NULL, NULL, Icon_NOICON);
284MENUITEM_FUNCTION(header_item, 0, "Show Header", tv_header_setting,
285 NULL, NULL, Icon_NOICON);
286MENUITEM_FUNCTION(footer_item, 0, "Show Footer", tv_footer_setting,
287 NULL, NULL, Icon_NOICON);
288MENUITEM_FUNCTION(font_item, 0, "Font", tv_font_setting,
289 NULL, NULL, Icon_NOICON);
290#endif
291MENUITEM_FUNCTION(scroll_mode_item, 0, "Scroll Mode", tv_scroll_mode_setting,
292 NULL, NULL, Icon_NOICON);
293MENUITEM_FUNCTION(autoscroll_speed_item, 0, "Auto-Scroll Speed",
294 tv_autoscroll_speed_setting, NULL, NULL, Icon_NOICON);
295MAKE_MENU(option_menu, "Viewer Options", NULL, Icon_NOICON,
296 &encoding_item, &word_wrap_item, &line_mode_item, &view_mode_item,
297 &alignment_item,
298#ifdef HAVE_LCD_BITMAP
299 &scrollbar_item, &page_mode_item, &header_item, &footer_item, &font_item,
300#endif
301 &scroll_mode_item, &autoscroll_speed_item);
302
303static enum tv_menu_result tv_options_menu(void)
304{
305 bool result = TV_MENU_RESULT_EXIT_MENU;
306
307 if (rb->do_menu(&option_menu, NULL, NULL, false) == MENU_ATTACHED_USB)
308 result = TV_MENU_RESULT_ATTACHED_USB;
309
310 return result;
311}
312
313enum tv_menu_result tv_display_menu(void)
314{
315 int result = TV_MENU_RESULT_EXIT_MENU;
316
317 MENUITEM_STRINGLIST(menu, "Viewer Menu", NULL,
318 "Return", "Viewer Options",
319 "Show Playback Menu", "Select Bookmark",
320 "Global Settings", "Quit");
321
322 switch (rb->do_menu(&menu, NULL, NULL, false))
323 {
324 case 0: /* return */
325 break;
326 case 1: /* change settings */
327 tv_copy_preferences(&new_prefs);
328 result = tv_options_menu();
329 tv_set_preferences(&new_prefs);
330 break;
331 case 2: /* playback control */
332 playback_control(NULL);
333 break;
334 case 3: /* select bookmark */
335 tv_select_bookmark();
336 break;
337 case 4: /* change global settings */
338 if (!tv_load_global_settings(&new_prefs))
339 tv_set_default_preferences(&new_prefs);
340
341 result = tv_options_menu();
342 tv_save_global_settings(&new_prefs);
343 break;
344 case 5: /* quit */
345 result = TV_MENU_RESULT_EXIT_PLUGIN;
346 break;
347 }
348 return result;
349}
diff --git a/apps/plugins/text_viewer/tv_menu.h b/apps/plugins/text_viewer/tv_menu.h
new file mode 100644
index 0000000000..35886d3c10
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_menu.h
@@ -0,0 +1,43 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_MENU_H
24#define PLUGIN_TEXT_VIEWER_MENU_H
25
26enum tv_menu_result {
27 TV_MENU_RESULT_EXIT_MENU,
28 TV_MENU_RESULT_EXIT_PLUGIN,
29 TV_MENU_RESULT_ATTACHED_USB,
30};
31
32/*
33 * display the setting menu
34 *
35 * return
36 * the following value returns
37 * TV_MENU_RESULT_EXIT_MENU menu exit and continue this plugin
38 * TV_MENU_RESULT_EXIT_PLUGIN request to exit this plugin
39 * TV_MENU_RESULT_ATTACHED_USB connect USB cable
40 */
41enum tv_menu_result tv_display_menu(void);
42
43#endif
diff --git a/apps/plugins/text_viewer/tv_pager.c b/apps/plugins/text_viewer/tv_pager.c
new file mode 100644
index 0000000000..d98fe4627d
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_pager.c
@@ -0,0 +1,337 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "tv_pager.h"
25#include "tv_preferences.h"
26#include "tv_reader.h"
27#include "tv_window.h"
28
29#if PLUGIN_BUFFER_SIZE < 0x13000
30#define TV_MAX_PAGE 999
31#else
32#define TV_MAX_PAGE 9999
33#endif
34
35#define TV_PAGER_MEMSIZE (4 * TV_MAX_PAGE)
36
37static unsigned char *pager_buffer;
38
39static struct tv_screen_pos cur_pos;
40
41static int parse_page;
42static int last_page;
43static int max_page;
44
45static int lines_per_page;
46
47static int line_pos[LCD_HEIGHT / 2];
48static int parse_page;
49static int parse_top_line;
50static int parse_lines;
51
52static void set_uint32(unsigned char *p, unsigned int val)
53{
54 *p++ = val & 0xff;
55 *p++ = (val >> 8) & 0xff;
56 *p++ = (val >> 16) & 0xff;
57 *p = (val >> 24) & 0xff;
58}
59
60static unsigned int get_uint32(const unsigned char *p)
61{
62 return (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0];
63}
64
65static void tv_set_fpos(int page, off_t pos)
66{
67 if (page >= 0 && page <= max_page)
68 set_uint32(pager_buffer + page * 4, pos);
69}
70
71static off_t tv_get_fpos(int page)
72{
73 if (page >= 0 && page <= max_page)
74 return get_uint32(pager_buffer + page * 4);
75 return 0;
76}
77
78static void tv_change_preferences(const struct tv_preferences *oldp)
79{
80 (void)oldp;
81
82 cur_pos.page = 0;
83 cur_pos.line = 0;
84 last_page = 0;
85 max_page = TV_MAX_PAGE - 1;
86 tv_set_fpos(cur_pos.page, 0);
87 tv_seek(0, SEEK_SET);
88}
89
90bool tv_init_pager(unsigned char *buf, size_t bufsize, size_t *used_size)
91{
92 if (bufsize < TV_PAGER_MEMSIZE)
93 return false;
94
95 pager_buffer = buf;
96 tv_set_screen_pos(&cur_pos);
97 tv_add_preferences_change_listner(tv_change_preferences);
98
99 /* valid page: 0, ..., max_page. */
100 max_page = TV_MAX_PAGE - 1;
101
102 line_pos[0] = 0;
103
104 buf += TV_PAGER_MEMSIZE;
105 bufsize -= TV_PAGER_MEMSIZE;
106 if (!tv_init_reader(buf, bufsize, used_size))
107 return false;
108
109 *used_size += TV_PAGER_MEMSIZE;
110
111 return true;
112}
113
114void tv_finalize_pager(void)
115{
116 tv_finalize_reader();
117}
118
119void tv_reset_line_positions(void)
120{
121 parse_page = cur_pos.page;
122 parse_top_line = cur_pos.line;
123 parse_lines = 0;
124}
125
126void tv_move_next_line(int size)
127{
128 if (!tv_is_eof())
129 {
130 tv_seek(size, SEEK_CUR);
131 cur_pos.file_pos = tv_get_current_file_pos();
132 cur_pos.line++;
133 parse_lines++;
134 line_pos[cur_pos.line] = line_pos[cur_pos.line - 1] + size;
135 }
136}
137
138int tv_get_line_positions(int offset)
139{
140 int line = cur_pos.line + offset;
141
142 if (line < 0)
143 line = 0;
144 else if (line > parse_lines)
145 line = parse_lines;
146
147 return line_pos[parse_top_line + line] - line_pos[parse_top_line];
148}
149
150void tv_new_page(void)
151{
152 parse_page = cur_pos.page;
153 if (cur_pos.page == last_page && last_page < max_page)
154 {
155 if (!tv_is_eof())
156 tv_set_fpos(++last_page, tv_get_current_file_pos());
157 else
158 max_page = last_page;
159 }
160
161 if (++cur_pos.page > max_page)
162 cur_pos.page = max_page;
163
164 lines_per_page = cur_pos.line;
165 cur_pos.line = 0;
166}
167
168static void tv_seek_page(int offset, int whence)
169{
170 int new_page = offset;
171
172 switch (whence)
173 {
174 case SEEK_CUR:
175 new_page += cur_pos.page;
176 break;
177 case SEEK_SET:
178 break;
179 case SEEK_END:
180 new_page += last_page;
181 whence = SEEK_SET;
182 break;
183 default:
184 return;
185 break;
186 }
187 if (new_page < 0)
188 new_page = 0;
189 else if (new_page >= last_page)
190 new_page = last_page;
191
192 cur_pos.page = new_page;
193 cur_pos.line = 0;
194 cur_pos.file_pos = tv_get_fpos(new_page);
195 tv_seek(cur_pos.file_pos, SEEK_SET);
196}
197
198static bool tv_create_line_positions(void)
199{
200 bool res;
201
202 if (tv_is_eof())
203 return false;
204
205 cur_pos.line = 0;
206 tv_reset_line_positions();
207 res = tv_traverse_lines();
208 lines_per_page = cur_pos.line;
209 tv_new_page();
210
211 return res;
212}
213
214void tv_convert_fpos(off_t fpos, struct tv_screen_pos *pos)
215{
216 int i;
217
218 for (i = 0; i < last_page; i++)
219 {
220 if (tv_get_fpos(i) <= fpos && tv_get_fpos(i + 1) > fpos)
221 break;
222 }
223
224 pos->page = i;
225 pos->line = 0;
226 pos->file_pos = fpos;
227
228 if (tv_get_fpos(i) == fpos)
229 return;
230
231 tv_seek_page(i, SEEK_SET);
232 while (tv_create_line_positions() && cur_pos.file_pos < fpos)
233 rb->splashf(0, "converting %ld%%...", 100 * cur_pos.file_pos / fpos);
234
235 if (cur_pos.page < max_page)
236 cur_pos.page--;
237 tv_seek_page(cur_pos.page, SEEK_SET);
238 for (i = 0; i < lines_per_page; i++)
239 {
240 if (cur_pos.file_pos + tv_get_line_positions(i) >= fpos)
241 break;
242 }
243
244 pos->page = cur_pos.page;
245 pos->line = i;
246}
247
248static void tv_seek_to_bottom_line(void)
249{
250 off_t total_size = tv_get_file_size();
251
252 tv_seek_page(0, SEEK_END);
253 while (tv_create_line_positions())
254 rb->splashf(0, "loading %ld%%...", 100 * cur_pos.file_pos / total_size);
255
256 cur_pos.line = lines_per_page - 1;
257}
258
259void tv_move_screen(int page_offset, int line_offset, int whence)
260{
261 struct tv_screen_pos new_pos;
262 int i;
263
264 switch (whence)
265 {
266 case SEEK_CUR:
267 cur_pos.page += page_offset;
268 cur_pos.line += line_offset;
269 break;
270 case SEEK_SET:
271 cur_pos.page = page_offset;
272 cur_pos.line = line_offset;
273 break;
274 case SEEK_END:
275 tv_seek_to_bottom_line();
276 cur_pos.page += page_offset;
277 cur_pos.line += line_offset;
278 break;
279 default:
280 return;
281 break;
282 }
283
284 if (cur_pos.page < 0 || (cur_pos.page == 0 && cur_pos.line < 0))
285 {
286 tv_seek_page(0, SEEK_SET);
287 return;
288 }
289 else if (cur_pos.page > max_page)
290 {
291 tv_seek_page(max_page, SEEK_SET);
292 return;
293 }
294
295 new_pos = cur_pos;
296 if (cur_pos.line < 0)
297 new_pos.page--;
298
299 tv_seek_page(new_pos.page, SEEK_SET);
300 while (cur_pos.page < new_pos.page && tv_create_line_positions())
301 rb->splashf(0, "loading %d%%...", 100 * cur_pos.page / new_pos.page);
302
303 if (new_pos.line == 0)
304 return;
305
306 if (parse_page == cur_pos.page)
307 {
308 if (cur_pos.page < max_page && new_pos.line == lines_per_page)
309 {
310 tv_seek(line_pos[lines_per_page], SEEK_CUR);
311 for (i = 0; i < parse_lines; i++)
312 line_pos[i] = line_pos[i + lines_per_page] - line_pos[lines_per_page];
313
314 cur_pos.page++;
315 cur_pos.line = 0;
316 parse_top_line = 0;
317 new_pos.line = 0;
318 }
319 }
320 else
321 {
322 tv_create_line_positions();
323 tv_seek_page(new_pos.page, SEEK_SET);
324 }
325
326 cur_pos.line = new_pos.line;
327 if (cur_pos.line >= lines_per_page)
328 cur_pos.line = lines_per_page - 1;
329 else if (cur_pos.line < 0)
330 {
331 cur_pos.line += lines_per_page;
332 if (cur_pos.line < 0)
333 cur_pos.line = 0;
334 }
335 tv_seek(line_pos[cur_pos.line], SEEK_CUR);
336 cur_pos.file_pos += line_pos[cur_pos.line];
337}
diff --git a/apps/plugins/text_viewer/tv_pager.h b/apps/plugins/text_viewer/tv_pager.h
new file mode 100644
index 0000000000..798d694ce5
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_pager.h
@@ -0,0 +1,104 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_PAGER_H
24#define PLUGIN_TEXT_VIEWER_PAGER_H
25
26#include "tv_screen_pos.h"
27
28/* stuff for the paging */
29
30/*
31 * initialize the pager module
32 *
33 * [In] buf
34 * the start pointer of the buffer
35 *
36 * [In] size
37 * enabled buffer size
38 *
39 * [Out] used_size
40 * the size of the buffer which the pager uses
41 *
42 * return
43 * true initialize success
44 * false initialize failure
45 */
46bool tv_init_pager(unsigned char *buf, size_t bufsize, size_t *used_size);
47
48/* finalize the pager module */
49void tv_finalize_pager(void);
50
51/* reset the stored line positions */
52void tv_reset_line_positions(void);
53
54/*
55 * move to the next line
56 *
57 * [In] size
58 * the current line size
59 */
60void tv_move_next_line(int size);
61
62/*
63 * return the distance from the top of the current page
64 *
65 * [In] offset
66 * the difference between the current line
67 *
68 * return
69 * difference between the current line + offset from the top of the current page
70 */
71int tv_get_line_positions(int offset);
72
73/* change the new page */
74void tv_new_page(void);
75
76/*
77 * convert the given file position to the nearest the position (page, line)
78 *
79 * [In] fpos
80 * the file position which want to convert
81 *
82 * [Out] pos
83 * result
84 */
85void tv_convert_fpos(off_t fpos, struct tv_screen_pos *pos);
86
87/*
88 * move to the given page and line
89 *
90 * [In] page_offset
91 * page offset
92 *
93 * [In] line_offset
94 * line offset
95 *
96 * [In] whence
97 * SEEK_CUR seek to the current page + offset page, the current line + offset line.
98 * SEEK_SET seek to the offset page, offset line.
99 * SEEK_END seek to the reading last page + offset page,
100 * the last line of the reading last page + offset line.
101 */
102void tv_move_screen(int page_offset, int line_offset, int whence);
103
104#endif
diff --git a/apps/plugins/text_viewer/tv_preferences.c b/apps/plugins/text_viewer/tv_preferences.c
new file mode 100644
index 0000000000..cd3560db93
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_preferences.c
@@ -0,0 +1,119 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "tv_preferences.h"
25
26static struct tv_preferences prefs;
27static bool is_initialized = false;
28static int listner_count = 0;
29
30#define TV_MAX_LISTNERS 4
31static void (*listners[TV_MAX_LISTNERS])(const struct tv_preferences *oldp);
32
33static void tv_notify_change_preferences(const struct tv_preferences *oldp,
34 const struct tv_preferences *newp)
35{
36 int i;
37
38 /*
39 * the following items do not check.
40 * - alignment
41 * - scroll_mode
42 * - page_mode
43 * - font
44 * - autoscroll_speed
45 */
46 if ((oldp == NULL) ||
47 (oldp->word_mode != newp->word_mode) ||
48 (oldp->line_mode != newp->line_mode) ||
49 (oldp->view_mode != newp->view_mode) ||
50 (oldp->scrollbar_mode != newp->scrollbar_mode) ||
51 (oldp->encoding != newp->encoding) ||
52#ifdef HAVE_LCD_BITMAP
53 (oldp->header_mode != newp->header_mode) ||
54 (oldp->footer_mode != newp->footer_mode) ||
55 (rb->strcmp(oldp->font_name, newp->font_name)) ||
56#endif
57 (rb->strcmp(oldp->file_name, newp->file_name)))
58 {
59 for (i = listner_count - 1; i >= 0; i--)
60 listners[i](oldp);
61 }
62}
63
64const struct tv_preferences *tv_get_preferences(void)
65{
66 return &prefs;
67}
68
69void tv_set_preferences(const struct tv_preferences *new_prefs)
70{
71 struct tv_preferences *oldp = NULL;
72 struct tv_preferences old_prefs;
73
74 if (!is_initialized)
75 is_initialized = true;
76 else
77 {
78 old_prefs = prefs;
79 oldp = &old_prefs;
80 }
81 rb->memcpy(&prefs, new_prefs, sizeof(struct tv_preferences));
82 tv_notify_change_preferences(oldp, &prefs);
83}
84
85void tv_copy_preferences(struct tv_preferences *copy_prefs)
86{
87 rb->memcpy(copy_prefs, &prefs, sizeof(struct tv_preferences));
88}
89
90void tv_set_default_preferences(struct tv_preferences *p)
91{
92 p->word_mode = WRAP;
93 p->line_mode = NORMAL;
94 p->view_mode = NARROW;
95 p->alignment = LEFT;
96 p->scroll_mode = PAGE;
97 p->page_mode = NO_OVERLAP;
98 p->scrollbar_mode = SB_OFF;
99 rb->memset(p->font_name, 0, MAX_PATH);
100#ifdef HAVE_LCD_BITMAP
101 p->header_mode = HD_BOTH;
102 p->footer_mode = FT_BOTH;
103 rb->strlcpy(p->font_name, rb->global_settings->font_file, MAX_PATH);
104 p->font = rb->font_get(FONT_UI);
105#else
106 p->header_mode = HD_NONE;
107 p->footer_mode = FT_NONE;
108#endif
109 p->autoscroll_speed = 1;
110 /* Set codepage to system default */
111 p->encoding = rb->global_settings->default_codepage;
112 p->file_name[0] = '\0';
113}
114
115void tv_add_preferences_change_listner(void (*listner)(const struct tv_preferences *oldp))
116{
117 if (listner_count < TV_MAX_LISTNERS)
118 listners[listner_count++] = listner;
119}
diff --git a/apps/plugins/text_viewer/tv_preferences.h b/apps/plugins/text_viewer/tv_preferences.h
new file mode 100644
index 0000000000..64ab0d102f
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_preferences.h
@@ -0,0 +1,129 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_PREFERENCES_H
24#define PLUGIN_TEXT_VIEWER_PREFERENCES_H
25
26struct tv_preferences {
27 enum {
28 WRAP = 0,
29 CHOP,
30 } word_mode;
31
32 enum {
33 NORMAL = 0,
34 JOIN,
35 EXPAND,
36 REFLOW,
37 } line_mode;
38
39 enum {
40 NARROW = 0,
41 WIDE,
42 } view_mode;
43
44 enum {
45 LEFT = 0,
46 RIGHT,
47 } alignment;
48
49 enum codepages encoding;
50
51 enum {
52 SB_OFF = 0,
53 SB_ON,
54 } scrollbar_mode;
55
56 enum {
57 NO_OVERLAP = 0,
58 OVERLAP,
59 } page_mode;
60
61 enum {
62 HD_NONE = 0,
63 HD_PATH,
64 HD_SBAR,
65 HD_BOTH,
66 } header_mode;
67
68 enum {
69 FT_NONE = 0,
70 FT_PAGE,
71 FT_SBAR,
72 FT_BOTH,
73 } footer_mode;
74
75 enum {
76 PAGE=0,
77 LINE,
78 } scroll_mode;
79
80 int autoscroll_speed;
81
82 unsigned char font_name[MAX_PATH];
83#ifdef HAVE_LCD_BITMAP
84 struct font *font;
85#endif
86 unsigned char file_name[MAX_PATH];
87};
88
89/*
90 * return the preferences
91 *
92 * return
93 * the pointer the preferences
94 */
95const struct tv_preferences *tv_get_preferences(void);
96
97/*
98 * change the preferences
99 *
100 * [In] new_prefs
101 * new preferences
102 */
103void tv_set_preferences(const struct tv_preferences *new_prefs);
104
105/*
106 * copy the preferences
107 *
108 * [Out] copy_prefs
109 * the preferences in copy destination
110 */
111void tv_copy_preferences(struct tv_preferences *copy_prefs);
112
113/*
114 * set the default settings
115 *
116 * [Out] p
117 * the preferences which store the default settings
118 */
119void tv_set_default_preferences(struct tv_preferences *p);
120
121/*
122 * register the function to be executed when the current preferences is changed
123 *
124 * [In] listner
125 * the function to be executed when the current preferences is changed
126 */
127void tv_add_preferences_change_listner(void (*listner)(const struct tv_preferences *oldp));
128
129#endif
diff --git a/apps/plugins/text_viewer/tv_reader.c b/apps/plugins/text_viewer/tv_reader.c
new file mode 100644
index 0000000000..6dc66ef567
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_reader.c
@@ -0,0 +1,191 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "tv_preferences.h"
25#include "tv_reader.h"
26
27#if PLUGIN_BUFFER_SIZE < 0x10000
28#define TV_MIN_BLOCK_SIZE 0x800
29#else
30#define TV_MIN_BLOCK_SIZE 0x1000
31#endif
32
33/* UTF-8 BOM */
34#define BOM "\xef\xbb\xbf"
35#define BOM_SIZE 3
36
37static int fd = -1;
38
39static off_t file_pos;
40static off_t start_file_pos;
41
42static off_t file_size;
43
44static unsigned char *reader_buffer;
45static ssize_t buffer_size;
46static ssize_t block_size;
47
48static ssize_t buf_pos;
49static ssize_t read_size;
50
51off_t tv_get_file_size(void)
52{
53 return file_size;
54}
55
56bool tv_is_eof(void)
57{
58 return (file_pos + buf_pos >= file_size);
59}
60
61off_t tv_get_current_file_pos(void)
62{
63 return file_pos + buf_pos;
64}
65
66const unsigned char *tv_get_buffer(ssize_t *bufsize)
67{
68 *bufsize = read_size - buf_pos;
69 return reader_buffer + buf_pos;
70}
71
72static ssize_t tv_read(unsigned char *buf, ssize_t reqsize)
73{
74 if (buf - reader_buffer + reqsize > buffer_size)
75 reqsize = buffer_size - (buf - reader_buffer);
76
77 return rb->read(fd, buf, reqsize);
78}
79
80void tv_seek(off_t offset, int whence)
81{
82 ssize_t size;
83
84 switch (whence)
85 {
86 case SEEK_SET:
87 if (offset >= file_pos && offset < file_pos + read_size)
88 {
89 buf_pos = offset - file_pos;
90 return;
91 }
92 file_pos = offset;
93 break;
94
95 case SEEK_CUR:
96 buf_pos += offset;
97 if (buf_pos >= 0 && buf_pos < read_size)
98 {
99 if (buf_pos > block_size)
100 {
101 buf_pos -= block_size;
102 file_pos += block_size;
103 size = read_size - block_size;
104 rb->memcpy(reader_buffer, reader_buffer + block_size, size);
105 read_size = tv_read(reader_buffer + block_size, block_size);
106 if (read_size < 0)
107 read_size = 0;
108
109 read_size += size;
110 }
111 return;
112 }
113 file_pos += buf_pos;
114 whence = SEEK_SET;
115 break;
116
117 default:
118 return;
119 break;
120 }
121
122 if (whence == SEEK_SET)
123 {
124 if (file_pos < 0)
125 file_pos = 0;
126 else if (file_pos > file_size)
127 file_pos = file_size;
128
129 rb->lseek(fd, file_pos + start_file_pos, SEEK_SET);
130 buf_pos = 0;
131 read_size = tv_read(reader_buffer, buffer_size);
132 }
133}
134
135static void tv_change_preferences(const struct tv_preferences *oldp)
136{
137 unsigned char bom[BOM_SIZE];
138 const struct tv_preferences *prefs = tv_get_preferences();
139 int cur_start_file_pos = start_file_pos;
140 off_t cur_file_pos = file_pos + buf_pos;
141
142 file_pos = 0;
143 buf_pos = 0;
144 read_size = 0;
145 start_file_pos = 0;
146
147 /* open the new file */
148 if (oldp == NULL || rb->strcmp(oldp->file_name, prefs->file_name))
149 {
150 if (fd >= 0)
151 rb->close(fd);
152
153 fd = rb->open(prefs->file_name, O_RDONLY);
154 if (fd < 0)
155 return;
156 }
157
158 /*
159 * When a file is UTF-8 file with BOM, if prefs.encoding is UTF-8,
160 * then file size decreases only BOM_SIZE.
161 */
162 if (prefs->encoding == UTF_8)
163 {
164 rb->lseek(fd, 0, SEEK_SET);
165 rb->read(fd, bom, BOM_SIZE);
166 if (rb->memcmp(bom, BOM, BOM_SIZE) == 0)
167 start_file_pos = BOM_SIZE;
168 }
169
170 file_size = rb->filesize(fd) - start_file_pos;
171 tv_seek(cur_file_pos + cur_start_file_pos - start_file_pos, SEEK_SET);
172}
173
174bool tv_init_reader(unsigned char *buf, size_t bufsize, size_t *used_size)
175{
176 if (bufsize < 2 * TV_MIN_BLOCK_SIZE)
177 return false;
178
179 reader_buffer = buf;
180 block_size = bufsize / 2;
181 buffer_size = 2 * block_size;
182 *used_size = buffer_size;
183 tv_add_preferences_change_listner(tv_change_preferences);
184 return true;
185}
186
187void tv_finalize_reader(void)
188{
189 if (fd >= 0)
190 rb->close(fd);
191}
diff --git a/apps/plugins/text_viewer/tv_reader.h b/apps/plugins/text_viewer/tv_reader.h
new file mode 100644
index 0000000000..464af1027a
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_reader.h
@@ -0,0 +1,102 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_READER_H
24#define PLUGIN_TEXT_VIEWER_READER_H
25
26/* stuff for the reading file */
27
28/*
29 * initialize the reader module
30 *
31 * [In] buf
32 * the start pointer of the buffer
33 *
34 * [In] size
35 * enabled buffer size
36 *
37 * [Out] used_size
38 * the size of the buffer which the pager uses
39 *
40 * return
41 * true initialize success
42 * false initialize failure
43 */
44bool tv_init_reader(unsigned char *buf, size_t bufsize, size_t *used_size);
45
46/* finalize the reader module */
47void tv_finalize_reader(void);
48
49/*
50 * return the file size
51 *
52 * return
53 * file size
54 *
55 * Note: when the file is UTF-8 file with BOM, if the encoding of the text viewer is UTF-8,
56 * then file size decreases only BOM size.
57 */
58off_t tv_get_file_size(void);
59
60/*
61 * return the whether is the end of file or not
62 *
63 * return
64 * true EOF
65 * false not EOF
66 */
67bool tv_is_eof(void);
68
69/*
70 * return the current file position
71 *
72 * return
73 * the current file position
74 */
75off_t tv_get_current_file_pos(void);
76
77/*
78 * return the bufer which store text data
79 *
80 * [Out] bufsize
81 * buffer size
82 *
83 * return
84 * the pointer of the buffer
85 */
86const unsigned char *tv_get_buffer(ssize_t *bufsize);
87
88/*
89 * seek to the given offset
90 *
91 * [In] offset
92 * offset size
93 *
94 * [In] whence
95 * SEEK_CUR seek to the current position + offset.
96 * SEEK_SET seek to the offset.
97 *
98 * Note: whence supports SEEK_CUR and SEEK_SET only.
99 */
100void tv_seek(off_t offset, int whence);
101
102#endif
diff --git a/apps/plugins/text_viewer/tv_screen_pos.c b/apps/plugins/text_viewer/tv_screen_pos.c
new file mode 100644
index 0000000000..001bd478de
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_screen_pos.c
@@ -0,0 +1,41 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "tv_screen_pos.h"
25
26static const struct tv_screen_pos *screen_pos;
27
28const struct tv_screen_pos *tv_get_screen_pos(void)
29{
30 return screen_pos;
31}
32
33void tv_set_screen_pos(const struct tv_screen_pos *pos)
34{
35 screen_pos = pos;
36}
37
38void tv_copy_screen_pos(struct tv_screen_pos *pos)
39{
40 *pos = *screen_pos;
41}
diff --git a/apps/plugins/text_viewer/tv_screen_pos.h b/apps/plugins/text_viewer/tv_screen_pos.h
new file mode 100644
index 0000000000..3ee8c10d89
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_screen_pos.h
@@ -0,0 +1,56 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_SCREEN_POS_H
24#define PLUGIN_TEXT_VIEWER_SCREEN_POS_H
25
26struct tv_screen_pos {
27 off_t file_pos;
28 int page;
29 int line;
30};
31
32/*
33 * return the current position
34 *
35 * return
36 * the pointer which is stored the current position
37 */
38const struct tv_screen_pos *tv_get_screen_pos(void);
39
40/*
41 * set the current position
42 *
43 * [In] pos
44 * the pointer which is stored the current position
45 */
46void tv_set_screen_pos(const struct tv_screen_pos *pos);
47
48/*
49 * the current position set to the given structure
50 *
51 * [Out] pos
52 * the pointer in order to store the current position
53 */
54void tv_copy_screen_pos(struct tv_screen_pos *pos);
55
56#endif
diff --git a/apps/plugins/text_viewer/tv_settings.c b/apps/plugins/text_viewer/tv_settings.c
new file mode 100644
index 0000000000..bb4ead7b5d
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_settings.c
@@ -0,0 +1,519 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "tv_bookmark.h"
25#include "tv_reader.h"
26#include "tv_settings.h"
27
28/* global settings file
29 * binary file, so dont use .cfg
30 *
31 * setting file format
32 *
33 * part byte count
34 * --------------------------------
35 * 'TVGS' 4
36 * version 1
37 * word_mode 1
38 * line_mode 1
39 * view_mode 1
40 * alignment 1
41 * encoding 1
42 * scrollbar_mode 1
43 * (unused) 1 (for compatibility)
44 * page_mode 1
45 * page_number_mode 1
46 * title_mode 1
47 * scroll_mode 1
48 * autoscroll_speed 1
49 * font name MAX_PATH
50 */
51
52#define VIEWER_GLOBAL_SETTINGS_FILE VIEWERS_DIR "/viewer.dat"
53#define TV_GLOBAL_SETTINGS_FILE VIEWERS_DIR "/tv_global.dat"
54
55#define TV_GLOBAL_SETTINGS_HEADER "\x54\x56\x47\x53" /* "TVGS" */
56#define TV_GLOBAL_SETTINGS_VERSION 0x32
57#define TV_GLOBAL_SETTINGS_HEADER_SIZE 5
58#define TV_GLOBAL_SETTINGS_FIRST_VERSION 0x31
59
60/* preferences and bookmarks at each file
61 * binary file, so dont use .cfg
62 *
63 * setting file format
64 *
65 * part byte count
66 * --------------------------------
67 * 'TVS' 3
68 * version 1
69 * file count 2
70 * [1st file]
71 * file path MAX_PATH
72 * next file pos 2 (prefences size + bookmark count * bookmark size + 1)
73 * [preferences]
74 * word_mode 1
75 * line_mode 1
76 * view_mode 1
77 * alignment 1
78 * encoding 1
79 * scrollbar_mode 1
80 * (unused) 1 (for compatibility)
81 * page_mode 1
82 * header_mode 1
83 * footer_mode 1
84 * scroll_mode 1
85 * autoscroll_speed 1
86 * font name MAX_PATH
87 * bookmark count 1
88 * [1st bookmark]
89 * file_position 4
90 * page 2
91 * line 1
92 * flag 1
93 * [2nd bookmark]
94 * ...
95 * [last bookmark]
96 * [2nd file]
97 * ...
98 * [last file]
99 */
100#define VIEWER_SETTINGS_FILE VIEWERS_DIR "/viewer_file.dat"
101#define TV_SETTINGS_FILE VIEWERS_DIR "/tv_file.dat"
102
103/* temporary file */
104#define TV_SETTINGS_TMP_FILE VIEWERS_DIR "/tv_file.tmp"
105
106#define TV_SETTINGS_HEADER "\x54\x56\x53" /* "TVS" */
107#define TV_SETTINGS_VERSION 0x33
108#define TV_SETTINGS_HEADER_SIZE 4
109#define TV_SETTINGS_FIRST_VERSION 0x32
110
111#define TV_PREFERENCES_SIZE (12 + MAX_PATH)
112
113/* ----------------------------------------------------------------------------
114 * read/write the preferences
115 * ----------------------------------------------------------------------------
116 */
117
118static bool tv_read_preferences(int pfd, int version, struct tv_preferences *prefs)
119{
120 unsigned char buf[TV_PREFERENCES_SIZE];
121 const unsigned char *p = buf;
122 int read_size = TV_PREFERENCES_SIZE;
123
124 if (version == 0)
125 read_size--;
126
127 if (rb->read(pfd, buf, read_size) < 0)
128 return false;
129
130 prefs->word_mode = *p++;
131 prefs->line_mode = *p++;
132 prefs->view_mode = *p++;
133 if (version > 0)
134 prefs->alignment = *p++;
135 else
136 prefs->alignment = LEFT;
137 prefs->encoding = *p++;
138 prefs->scrollbar_mode = *p++;
139 /* skip need_scrollbar */
140 p++;
141 prefs->page_mode = *p++;
142 prefs->header_mode = *p++;
143 prefs->footer_mode = *p++;
144 prefs->scroll_mode = *p++;
145 prefs->autoscroll_speed = *p++;
146 rb->memcpy(prefs->font_name, p, MAX_PATH);
147#ifdef HAVE_LCD_BITMAP
148 prefs->font = rb->font_get(FONT_UI);
149#endif
150
151 return true;
152}
153
154static bool tv_write_preferences(int pfd, const struct tv_preferences *prefs)
155{
156 unsigned char buf[TV_PREFERENCES_SIZE];
157 unsigned char *p = buf;
158
159 *p++ = prefs->word_mode;
160 *p++ = prefs->line_mode;
161 *p++ = prefs->view_mode;
162 *p++ = prefs->alignment;
163 *p++ = prefs->encoding;
164 *p++ = prefs->scrollbar_mode;
165 /* skip need_scrollbar */
166 p++;
167 *p++ = prefs->page_mode;
168 *p++ = prefs->header_mode;
169 *p++ = prefs->footer_mode;
170 *p++ = prefs->scroll_mode;
171 *p++ = prefs->autoscroll_speed;
172 rb->memcpy(p, prefs->font_name, MAX_PATH);
173
174 return (rb->write(pfd, buf, TV_PREFERENCES_SIZE) >= 0);
175}
176
177/* ----------------------------------------------------------------------------
178 * convert vewer.rock's settings file to text_viewer.rock's settings file
179 * ----------------------------------------------------------------------------
180 */
181
182static bool tv_convert_settings(int sfd, int dfd, int old_ver)
183{
184 struct tv_preferences new_prefs;
185 off_t old_pos;
186 off_t new_pos;
187 unsigned char buf[MAX_PATH + 2];
188 int settings_size;
189
190 rb->read(sfd, buf, MAX_PATH + 2);
191 rb->write(dfd, buf, MAX_PATH + 2);
192
193 settings_size = (buf[MAX_PATH] << 8) | buf[MAX_PATH + 1];
194
195 old_pos = rb->lseek(sfd, 0, SEEK_CUR);
196 new_pos = rb->lseek(dfd, 0, SEEK_CUR);
197
198 /*
199 * when the settings size != preferences size + bookmarks size,
200 * settings data are considered to be old version.
201 */
202 if (old_ver > 0 && ((settings_size - TV_PREFERENCES_SIZE) % 8) == 0)
203 old_ver = 0;
204
205 if (!tv_read_preferences(sfd, old_ver, &new_prefs))
206 return false;
207
208 if (!tv_write_preferences(dfd, &new_prefs))
209 return false;
210
211 settings_size -= (rb->lseek(sfd, 0, SEEK_CUR) - old_pos);
212
213 if (settings_size > 0)
214 {
215 rb->read(sfd, buf, settings_size);
216 rb->write(dfd, buf, settings_size);
217 }
218
219 settings_size = rb->lseek(dfd, 0, SEEK_CUR) - new_pos;
220 buf[0] = settings_size >> 8;
221 buf[1] = settings_size;
222 rb->lseek(dfd, new_pos - 2, SEEK_SET);
223 rb->write(dfd, buf, 2);
224 rb->lseek(dfd, settings_size, SEEK_CUR);
225 return true;
226}
227
228static void tv_convert_settings_file(void)
229{
230 unsigned char buf[TV_SETTINGS_HEADER_SIZE + 2];
231 int sfd;
232 int tfd;
233 int i;
234 int fcount;
235 int version;
236 bool res = false;
237
238 if ((sfd = rb->open(VIEWER_SETTINGS_FILE, O_RDONLY)) < 0)
239 return;
240
241 if ((tfd = rb->open(TV_SETTINGS_TMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
242 {
243 rb->close(sfd);
244 return;
245 }
246
247 if (rb->read(sfd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0)
248 {
249 version = buf[TV_SETTINGS_HEADER_SIZE - 1] - TV_SETTINGS_FIRST_VERSION;
250 fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE + 1];
251 buf[TV_SETTINGS_HEADER_SIZE - 1] = TV_SETTINGS_VERSION;
252
253 if (rb->write(tfd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0)
254 {
255 res = true;
256 for (i = 0; i < fcount; i++)
257 {
258 if (!tv_convert_settings(sfd, tfd, version))
259 {
260 res = false;
261 break;
262 }
263 }
264 }
265 }
266
267 rb->close(sfd);
268 rb->close(tfd);
269
270 if (res)
271 rb->rename(TV_SETTINGS_TMP_FILE, TV_SETTINGS_FILE);
272 else
273 rb->remove(TV_SETTINGS_TMP_FILE);
274
275 return;
276}
277
278/* ----------------------------------------------------------------------------
279 * load/save the global settings
280 * ----------------------------------------------------------------------------
281 */
282
283bool tv_load_global_settings(struct tv_preferences *prefs)
284{
285 unsigned char buf[TV_GLOBAL_SETTINGS_HEADER_SIZE];
286 int fd;
287 int version;
288 bool res = false;
289
290 /*
291 * the viewer.rock's setting file read when the text_viewer.rock's setting file
292 * does not read.
293 */
294 if ((fd = rb->open(TV_GLOBAL_SETTINGS_FILE, O_RDONLY)) < 0)
295 fd = rb->open(VIEWER_GLOBAL_SETTINGS_FILE, O_RDONLY);
296
297 if (fd >= 0)
298 {
299 if ((rb->read(fd, buf, TV_GLOBAL_SETTINGS_HEADER_SIZE) > 0) &&
300 (rb->memcmp(buf, TV_GLOBAL_SETTINGS_HEADER, TV_GLOBAL_SETTINGS_HEADER_SIZE - 1) == 0))
301 {
302 version = buf[TV_GLOBAL_SETTINGS_HEADER_SIZE - 1] - TV_GLOBAL_SETTINGS_FIRST_VERSION;
303 res = tv_read_preferences(fd, version, prefs);
304 }
305 rb->close(fd);
306 }
307 return res;
308}
309
310bool tv_save_global_settings(const struct tv_preferences *prefs)
311{
312 unsigned char buf[TV_GLOBAL_SETTINGS_HEADER_SIZE];
313 int fd;
314 bool res;
315
316 if ((fd = rb->open(TV_SETTINGS_TMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
317 return false;
318
319 rb->memcpy(buf, TV_GLOBAL_SETTINGS_HEADER, TV_GLOBAL_SETTINGS_HEADER_SIZE - 1);
320 buf[TV_GLOBAL_SETTINGS_HEADER_SIZE - 1] = TV_GLOBAL_SETTINGS_VERSION;
321
322 res = (rb->write(fd, buf, TV_GLOBAL_SETTINGS_HEADER_SIZE) >= 0) &&
323 (tv_write_preferences(fd, prefs));
324 rb->close(fd);
325
326 if (res)
327 {
328 rb->remove(TV_GLOBAL_SETTINGS_FILE);
329 rb->rename(TV_SETTINGS_TMP_FILE, TV_GLOBAL_SETTINGS_FILE);
330 }
331 else
332 rb->remove(TV_SETTINGS_TMP_FILE);
333
334 return res;
335}
336
337/* ----------------------------------------------------------------------------
338 * load/save the settings
339 * ----------------------------------------------------------------------------
340 */
341
342void tv_load_settings(const unsigned char *file_name)
343{
344 unsigned char buf[MAX_PATH+2];
345 unsigned int fcount;
346 unsigned int i;
347 bool res = false;
348 int fd;
349 int version;
350 unsigned int size;
351 struct tv_preferences prefs;
352
353 if (!rb->file_exists(TV_SETTINGS_FILE))
354 tv_convert_settings_file();
355
356 if ((fd = rb->open(TV_SETTINGS_FILE, O_RDONLY)) >= 0)
357 {
358 if ((rb->read(fd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0) &&
359 (rb->memcmp(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1) == 0))
360 {
361 version = buf[TV_SETTINGS_HEADER_SIZE - 1] - TV_SETTINGS_FIRST_VERSION;
362 fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE+1];
363
364 for (i = 0; i < fcount; i++)
365 {
366 if (rb->read(fd, buf, MAX_PATH+2) >= 0)
367 {
368 size = (buf[MAX_PATH] << 8) | buf[MAX_PATH+1];
369 if (rb->strcmp(buf, file_name) == 0)
370 {
371 if (tv_read_preferences(fd, version, &prefs))
372 res = tv_deserialize_bookmarks(fd);
373
374 break;
375 }
376 rb->lseek(fd, size, SEEK_CUR);
377 }
378 }
379 rb->close(fd);
380 }
381 else
382 {
383 /* when the settings file is illegal, removes it */
384 rb->close(fd);
385 rb->remove(TV_SETTINGS_FILE);
386 }
387 }
388 if (!res)
389 {
390 /* specifications are acquired from the global settings */
391 if (!tv_load_global_settings(&prefs))
392 tv_set_default_preferences(&prefs);
393 }
394 rb->strlcpy(prefs.file_name, file_name, MAX_PATH);
395 tv_set_preferences(&prefs);
396}
397
398static bool tv_copy_settings(int sfd, int dfd, int size)
399{
400 unsigned char buf[MAX_PATH];
401 int i = size / MAX_PATH;
402
403 size %= MAX_PATH;
404
405 while (i--)
406 {
407 if ((rb->read(sfd, buf, MAX_PATH) < 0) || (rb->write(dfd, buf, MAX_PATH) < 0))
408 return false;
409 }
410
411 return ((rb->read(sfd, buf, size) >= 0) && (rb->write(dfd, buf, size) >= 0));
412}
413
414bool tv_save_settings(void)
415{
416 const struct tv_preferences *prefs = tv_get_preferences();
417 unsigned char buf[MAX_PATH+2];
418 unsigned int fcount = 0;
419 unsigned int i;
420 int ofd = -1;
421 int tfd;
422 off_t size;
423 bool res = true;
424
425 /* add reading page to bookmarks */
426 tv_create_system_bookmark();
427
428 if (!rb->file_exists(TV_SETTINGS_FILE))
429 tv_convert_settings_file();
430
431 /* create header for the temporary file */
432 rb->memcpy(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1);
433 buf[TV_SETTINGS_HEADER_SIZE - 1] = TV_SETTINGS_VERSION;
434
435 if ((tfd = rb->open(TV_SETTINGS_TMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
436 return false;
437
438 if (rb->write(tfd, buf, TV_SETTINGS_HEADER_SIZE + 2) < 0)
439 {
440 rb->close(tfd);
441 return false;
442 }
443
444 if ((ofd = rb->open(TV_SETTINGS_FILE, O_RDONLY)) >= 0)
445 {
446 res = ((rb->read(ofd, buf, TV_SETTINGS_HEADER_SIZE + 2) >= 0) &&
447 (rb->memcmp(buf, TV_SETTINGS_HEADER, TV_SETTINGS_HEADER_SIZE - 1) == 0));
448
449 if (res)
450 {
451 fcount = (buf[TV_SETTINGS_HEADER_SIZE] << 8) | buf[TV_SETTINGS_HEADER_SIZE + 1];
452 for (i = 0; i < fcount; i++)
453 {
454 if (rb->read(ofd, buf, MAX_PATH + 2) < 0)
455 {
456 res = false;
457 break;
458 }
459
460 size = (buf[MAX_PATH] << 8) | buf[MAX_PATH + 1];
461 if (rb->strcmp(buf, prefs->file_name) == 0)
462 rb->lseek(ofd, size, SEEK_CUR);
463 else
464 {
465 if ((rb->write(tfd, buf, MAX_PATH + 2) < 0) ||
466 (!tv_copy_settings(ofd, tfd, size)))
467 {
468 res = false;
469 break;
470 }
471 }
472 }
473 }
474 rb->close(ofd);
475 }
476
477 if (res)
478 {
479 /* save to current read file's preferences and bookmarks */
480 res = false;
481 rb->memset(buf, 0, MAX_PATH);
482 rb->strlcpy(buf, prefs->file_name, MAX_PATH);
483
484 if (rb->write(tfd, buf, MAX_PATH + 2) >= 0)
485 {
486 if (tv_write_preferences(tfd, prefs))
487 {
488 size = tv_serialize_bookmarks(tfd);
489 if (size > 0)
490 {
491 size += TV_PREFERENCES_SIZE;
492 rb->lseek(tfd, -size - 2, SEEK_CUR);
493 buf[0] = size >> 8;
494 buf[1] = size;
495 if (rb->write(tfd, buf, 2) >= 0)
496 {
497 rb->lseek(tfd, TV_SETTINGS_HEADER_SIZE, SEEK_SET);
498
499 fcount++;
500 buf[0] = fcount >> 8;
501 buf[1] = fcount;
502 res = (rb->write(tfd, buf, 2) >= 0);
503 }
504 }
505 }
506 }
507 }
508 rb->close(tfd);
509
510 if (res)
511 {
512 rb->remove(TV_SETTINGS_FILE);
513 rb->rename(TV_SETTINGS_TMP_FILE, TV_SETTINGS_FILE);
514 }
515 else
516 rb->remove(TV_SETTINGS_TMP_FILE);
517
518 return res;
519}
diff --git a/apps/plugins/text_viewer/tv_settings.h b/apps/plugins/text_viewer/tv_settings.h
new file mode 100644
index 0000000000..c2218e7d9f
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_settings.h
@@ -0,0 +1,73 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_SETTINGS_H
24#define PLUGIN_TEXT_VIEWER_SETTINGS_H
25
26#include "tv_preferences.h"
27
28/*
29 * load from the global settings file
30 *
31 * [Out] prefs
32 * the structure which read settings is stored
33 *
34 * return
35 * true success
36 * false failure
37 */
38bool tv_load_global_settings(struct tv_preferences *prefs);
39
40/*
41 * save to the global settings file
42 *
43 * [In] prefs
44 * the structure with settings to save
45 *
46 * return
47 * true success
48 * false failure
49 */
50bool tv_save_global_settings(const struct tv_preferences *prefs);
51
52/*
53 * load the settings at each file
54 *
55 * [In] file_name
56 * the file name of file that wants to read settings
57 *
58 * return
59 * true success
60 * false failure
61 */
62void tv_load_settings(const unsigned char *file_name);
63
64/*
65 * save the settings at each file
66 *
67 * return
68 * true success
69 * false failure
70 */
71bool tv_save_settings(void);
72
73#endif
diff --git a/apps/plugins/text_viewer/tv_text_processor.c b/apps/plugins/text_viewer/tv_text_processor.c
new file mode 100644
index 0000000000..8cdd78df15
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_text_processor.c
@@ -0,0 +1,576 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "ctype.h"
25#include "tv_preferences.h"
26#include "tv_text_processor.h"
27
28enum tv_text_type {
29 TV_TEXT_UNKNOWN,
30 TV_TEXT_MAC,
31 TV_TEXT_UNIX,
32 TV_TEXT_WIN,
33};
34
35/* the max characters of each blocks */
36#ifdef HAVE_LCD_BITMAP
37#define TV_MAX_CHARS_PER_BLOCK (LCD_WIDTH / 2 + 1)
38#else
39#define TV_MAX_CHARS_PER_BLOCK (LCD_WIDTH + 1)
40#endif
41
42#define TV_MAX_BLOCKS 2
43
44/*
45 * number of spaces to indent first paragraph
46 * (this value uses the line mode is REFLOW only)
47 */
48#define TV_INDENT_SPACES 2
49
50static const struct tv_preferences *prefs;
51static enum tv_text_type text_type = TV_TEXT_UNKNOWN;
52
53static const unsigned char *end_ptr;
54
55static unsigned short *ucsbuf[TV_MAX_BLOCKS];
56static unsigned char *utf8buf;
57static unsigned char *outbuf;
58
59static int block_count;
60static int block_width;
61
62/* if this value is true, then tv_create_line_text returns a blank line. */
63static bool expand_extra_line = false;
64
65/* when a line is divided, this value sets true. */
66static bool is_break_line = false;
67
68static unsigned short break_chars[] =
69 {
70 0,
71 /* halfwidth characters */
72 '\t', '\n', 0x0b, 0x0c, ' ', '!', ',', '-', '.', ':', ';', '?', 0xb7,
73 /* fullwidth characters */
74 0x2010, /* hyphen */
75 0x3000, /* fullwidth space */
76 0x3001, /* ideographic comma */
77 0x3002, /* ideographic full stop */
78 0x30fb, /* katakana middle dot */
79 0x30fc, /* katakana-hiragana prolonged sound mark */
80 0xff01, /* fullwidth exclamation mark */
81 0xff0c, /* fullwidth comma */
82 0xff0d, /* fullwidth hyphen-minus */
83 0xff0e, /* fullwidth full stop */
84 0xff1a, /* fullwidth colon */
85 0xff1b, /* fullwidth semicolon */
86 0xff1f, /* fullwidth question mark */
87 };
88
89/* the characters which is not judged as space with isspace() */
90static unsigned short extra_spaces[] = { 0, 0x3000 };
91
92static int tv_glyph_width(int ch)
93{
94 if (ch == '\n')
95 return 0;
96
97 if (ch == 0)
98 ch = ' ';
99
100#ifdef HAVE_LCD_BITMAP
101 /* the width of the diacritics charcter is 0 */
102 if (rb->is_diacritic(ch, NULL))
103 return 0;
104
105 return rb->font_get_width(prefs->font, ch);
106#else
107 return 1;
108#endif
109}
110
111static unsigned char *tv_get_ucs(const unsigned char *str, unsigned short *ch)
112{
113 int count = 1;
114 unsigned char utf8_tmp[3];
115
116 /* distinguish the text_type */
117 if (*str == '\r')
118 {
119 if (text_type == TV_TEXT_WIN || text_type == TV_TEXT_UNKNOWN)
120 {
121 if (str + 1 < end_ptr && *(str+1) == '\n')
122 {
123 if (text_type == TV_TEXT_UNKNOWN)
124 text_type = TV_TEXT_WIN;
125
126 *ch = '\n';
127 return (unsigned char *)str + 2;
128 }
129
130 if (text_type == TV_TEXT_UNKNOWN)
131 text_type = TV_TEXT_MAC;
132 }
133 *ch = (text_type == TV_TEXT_MAC)? '\n' : ' ';
134 return (unsigned char *)str + 1;
135 }
136 else if (*str == '\n')
137 {
138 if (text_type == TV_TEXT_UNKNOWN)
139 text_type = TV_TEXT_UNIX;
140
141 *ch = (text_type == TV_TEXT_UNIX)? '\n' : ' ';
142 return (unsigned char *)str + 1;
143 }
144
145 if (prefs->encoding == UTF_8)
146 return (unsigned char*)rb->utf8decode(str, ch);
147
148#ifdef HAVE_LCD_BITMAP
149 if ((*str >= 0x80) &&
150 ((prefs->encoding > SJIS) ||
151 (prefs->encoding == SJIS && (*str <= 0xa0 || *str >= 0xe0))))
152 {
153 if (str + 1 >= end_ptr)
154 {
155 end_ptr = str;
156 *ch = 0;
157 return (unsigned char *)str;
158 }
159 count = 2;
160 }
161#endif
162 rb->iso_decode(str, utf8_tmp, prefs->encoding, count);
163 rb->utf8decode(utf8_tmp, ch);
164 return (unsigned char *)str + count;
165}
166
167static void tv_decode2utf8(const unsigned short *ucs, int count)
168{
169 int i;
170
171 for (i = 0; i < count; i++)
172 outbuf = rb->utf8encode(ucs[i], outbuf);
173
174 *outbuf = '\0';
175}
176
177static bool tv_is_line_break_char(unsigned short ch)
178{
179 size_t i;
180
181 /* when the word mode is CHOP, all characters does not break line. */
182 if (prefs->word_mode == CHOP)
183 return false;
184
185 for (i = 0; i < sizeof(break_chars); i++)
186 {
187 if (break_chars[i] == ch)
188 return true;
189 }
190 return false;
191}
192
193static bool tv_isspace(unsigned short ch)
194{
195 size_t i;
196
197 if (ch < 128 && isspace(ch))
198 return true;
199
200 for (i = 0; i < sizeof(extra_spaces); i++)
201 {
202 if (extra_spaces[i] == ch)
203 return true;
204 }
205 return false;
206}
207
208static bool tv_is_break_line_join_mode(const unsigned char *next_str)
209{
210 unsigned short ch;
211
212 tv_get_ucs(next_str, &ch);
213 return tv_isspace(ch);
214}
215
216static int tv_form_reflow_line(unsigned short *ucs, int chars)
217{
218 unsigned short new_ucs[TV_MAX_CHARS_PER_BLOCK];
219 unsigned short *p = new_ucs;
220 unsigned short ch;
221 int i;
222 int k;
223 int expand_spaces;
224 int indent_chars = 0;
225 int nonspace_chars = 0;
226 int nonspace_width = 0;
227 int remain_spaces;
228 int spaces = 0;
229 int words_spaces;
230
231 if (prefs->alignment == LEFT)
232 {
233 while (chars > 0 && ucs[chars-1] == ' ')
234 chars--;
235 }
236
237 if (chars == 0)
238 return 0;
239
240 while (ucs[indent_chars] == ' ')
241 indent_chars++;
242
243 for (i = indent_chars; i < chars; i++)
244 {
245 ch = ucs[i];
246 if (ch == ' ')
247 spaces++;
248 else
249 {
250 nonspace_chars++;
251 nonspace_width += tv_glyph_width(ch);
252 }
253 }
254
255 if (spaces == 0)
256 return chars;
257
258 expand_spaces = (block_width - nonspace_width) / tv_glyph_width(' ') - indent_chars;
259 if (indent_chars + nonspace_chars + expand_spaces > TV_MAX_CHARS_PER_BLOCK)
260 expand_spaces = TV_MAX_CHARS_PER_BLOCK - indent_chars - nonspace_chars;
261
262 words_spaces = expand_spaces / spaces;
263 remain_spaces = expand_spaces - words_spaces * spaces;
264
265 for (i = 0; i < indent_chars; i++)
266 *p++ = ' ';
267
268 for ( ; i < chars; i++)
269 {
270 ch = ucs[i];
271 *p++ = ch;
272 if (ch == ' ')
273 {
274 for (k = ((remain_spaces > 0)? 0 : 1); k < words_spaces; k++)
275 *p++ = ch;
276
277 remain_spaces--;
278 }
279 }
280
281 rb->memcpy(ucs, new_ucs, sizeof(unsigned short) * TV_MAX_CHARS_PER_BLOCK);
282 return indent_chars + nonspace_chars + expand_spaces;
283}
284
285static void tv_align_right(int *block_chars)
286{
287 unsigned short *cur_text;
288 unsigned short *prev_text;
289 unsigned short ch;
290 int cur_block = block_count - 1;
291 int prev_block;
292 int cur_chars;
293 int prev_chars;
294 int idx;
295 int break_pos;
296 int break_width = 0;
297 int append_width;
298 int width;
299
300 while (cur_block > 0)
301 {
302 cur_text = ucsbuf[cur_block];
303 cur_chars = block_chars[cur_block];
304 idx = cur_chars;
305 width = 0;
306 while(--idx >= 0)
307 width += tv_glyph_width(cur_text[idx]);
308
309 width = block_width - width;
310 prev_block = cur_block - 1;
311
312 do {
313 prev_text = ucsbuf[prev_block];
314 prev_chars = block_chars[prev_block];
315
316 idx = prev_chars;
317 append_width = 0;
318 break_pos = prev_chars;
319 while (append_width < width && idx > 0)
320 {
321 ch = prev_text[--idx];
322 if (tv_is_line_break_char(ch))
323 {
324 break_pos = idx + 1;
325 break_width = append_width;
326 }
327 append_width += tv_glyph_width(ch);
328 }
329 if (append_width > width)
330 idx++;
331
332 if (idx == 0)
333 {
334 break_pos = 0;
335 break_width = append_width;
336 }
337
338 if (break_pos < prev_chars)
339 append_width = break_width;
340 /* the case of
341 * (1) when the first character of the cur_text concatenates
342 * the last character of the prev_text.
343 * (2) the length of ucsbuf[block] is short (< 0.75 * block width)
344 */
345 else if (((!tv_isspace(*cur_text) && !tv_isspace(prev_text[prev_chars - 1])) ||
346 (4 * width >= 3 * block_width)))
347 {
348 break_pos = idx;
349 }
350
351 if (break_pos < prev_chars)
352 {
353 rb->memmove(cur_text + prev_chars - break_pos,
354 cur_text, block_chars[cur_block] * sizeof(unsigned short));
355 rb->memcpy(cur_text, prev_text + break_pos,
356 (prev_chars - break_pos) * sizeof(unsigned short));
357
358 block_chars[prev_block] = break_pos;
359 block_chars[cur_block ] += prev_chars - break_pos;
360 }
361 } while ((width -= append_width) > 0 && --prev_block >= 0);
362 cur_block--;
363 }
364}
365
366static int tv_parse_text(const unsigned char *src, unsigned short *ucs,
367 int *ucs_chars, bool is_indent)
368{
369 const unsigned char *cur = src;
370 const unsigned char *next = src;
371 const unsigned char *line_break_ptr = NULL;
372 const unsigned char *line_end_ptr = NULL;
373 unsigned short ch = 0;
374 unsigned short prev_ch;
375 int chars = 0;
376 int gw;
377 int i;
378 int line_break_width = 0;
379 int line_end_chars = 0;
380 int width = 0;
381 bool is_space = false;
382
383 while (true) {
384 cur = next;
385 if (cur >= end_ptr)
386 {
387 line_end_ptr = cur;
388 line_end_chars = chars;
389 is_break_line = true;
390 break;
391 }
392
393 prev_ch = ch;
394 next = tv_get_ucs(cur, &ch);
395 if (ch == '\n')
396 {
397 if (prefs->line_mode != JOIN || tv_is_break_line_join_mode(next))
398 {
399 line_end_ptr = next;
400 line_end_chars = chars;
401 is_break_line = false;
402 break;
403 }
404
405 if (prefs->word_mode == CHOP || tv_isspace(prev_ch))
406 continue;
407
408 /*
409 * when the line mode is JOIN and the word mode is WRAP,
410 * the next character does not concatenate with the
411 * previous character.
412 */
413 ch = ' ';
414 }
415 else if ((is_space = tv_isspace(ch)) == true)
416 {
417 /*
418 * when the line mode is REFLOW:
419 * (1) spacelike character convert to ' '
420 * (2) plural spaces are collected to one
421 */
422 if (prefs->line_mode == REFLOW)
423 {
424 ch = ' ';
425 if (prev_ch == ch)
426 continue;
427 }
428
429 /* when the alignment is RIGHT, ignores indent spaces. */
430 if (prefs->alignment == RIGHT && is_indent)
431 continue;
432 }
433 else
434 is_indent = false;
435
436 if (prefs->line_mode == REFLOW && is_indent)
437 gw = tv_glyph_width(ch) * TV_INDENT_SPACES;
438 else
439 gw = tv_glyph_width(ch);
440
441 width += gw;
442 if (width > block_width)
443 {
444 width -= gw;
445 if (is_space)
446 {
447 line_end_ptr = cur;
448 line_end_chars = chars;
449 }
450 is_break_line = true;
451 break;
452 }
453
454 if (prefs->line_mode == REFLOW && is_indent)
455 {
456 for (i = 1; i < TV_INDENT_SPACES; i++)
457 ucs[chars++] = ch;
458 }
459 ucs[chars++] = ch;
460
461 if (tv_is_line_break_char(ch))
462 {
463 line_break_ptr = next;
464 line_break_width = width;
465 line_end_chars = chars;
466 }
467 if (chars >= TV_MAX_CHARS_PER_BLOCK)
468 {
469 is_break_line = true;
470 break;
471 }
472 }
473
474 /* set the end position and character count */
475 if (line_end_ptr == NULL)
476 {
477 /*
478 * when the last line break position is too short (line length < 0.75 * block width),
479 * the line is cut off at the position where it is closest to the displayed width.
480 */
481 if ((prefs->line_mode == REFLOW && line_break_ptr == NULL) ||
482 (4 * line_break_width < 3 * block_width))
483 {
484 line_end_ptr = cur;
485 line_end_chars = chars;
486 }
487 else
488 line_end_ptr = line_break_ptr;
489 }
490
491 *ucs_chars = line_end_chars;
492 return line_end_ptr - src;
493}
494
495int tv_create_formed_text(const unsigned char *src, ssize_t bufsize,
496 int block, bool is_multi, const unsigned char **dst)
497{
498 unsigned short ch;
499 int chars[block_count];
500 int i;
501 int size = 0;
502 bool is_indent;
503
504 outbuf = utf8buf;
505 *outbuf = '\0';
506
507 for (i = 0; i < block_count; i++)
508 chars[i] = 0;
509
510 if (dst != NULL)
511 *dst = utf8buf;
512
513 if (prefs->line_mode == EXPAND && (expand_extra_line = !expand_extra_line) == true)
514 return 0;
515
516 end_ptr = src + bufsize;
517
518 tv_get_ucs(src, &ch);
519 is_indent = (tv_isspace(ch) && !is_break_line);
520
521 for (i = 0; i < block_count; i++)
522 {
523 size += tv_parse_text(src + size, ucsbuf[i], &chars[i], is_indent);
524 if (!is_break_line)
525 break;
526
527 is_indent = false;
528 }
529
530 if (dst != NULL)
531 {
532 if (prefs->alignment == RIGHT)
533 tv_align_right(chars);
534
535 for (i = 0; i < block_count; i++)
536 {
537 if (i == block || (is_multi && i == block + 1))
538 {
539 if (is_break_line && prefs->line_mode == REFLOW)
540 chars[i] = tv_form_reflow_line(ucsbuf[i], chars[i]);
541
542 tv_decode2utf8(ucsbuf[i], chars[i]);
543 }
544 }
545 }
546
547 return size;
548}
549
550bool tv_init_text_processor(unsigned char *buf, size_t bufsize, size_t *used_size)
551{
552 int i;
553
554 *used_size = TV_MAX_CHARS_PER_BLOCK * (2 * 3 + TV_MAX_BLOCKS * sizeof(unsigned short));
555 if (bufsize < *used_size)
556 return false;
557
558 prefs = tv_get_preferences();
559 text_type = TV_TEXT_UNKNOWN;
560 expand_extra_line = false;
561 is_break_line = false;
562
563 ucsbuf[0] = (unsigned short*)buf;
564 for (i = 1; i < TV_MAX_BLOCKS; i++)
565 ucsbuf[i] = ucsbuf[i - 1] + TV_MAX_CHARS_PER_BLOCK;
566
567 utf8buf = buf + TV_MAX_CHARS_PER_BLOCK * TV_MAX_BLOCKS * sizeof(unsigned short);
568
569 return true;
570}
571
572void tv_set_creation_conditions(int blocks, int width)
573{
574 block_count = blocks;
575 block_width = width;
576}
diff --git a/apps/plugins/text_viewer/tv_text_processor.h b/apps/plugins/text_viewer/tv_text_processor.h
new file mode 100644
index 0000000000..3cb2a96448
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_text_processor.h
@@ -0,0 +1,80 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_TEXT_PROCESSOR_H
24#define PLUGIN_TEXT_VIEWER_TEXT_PROCESSOR_H
25
26/*
27 * initialize the text processor module
28 *
29 * [In] buf
30 * the start pointer of the buffer
31 *
32 * [In] size
33 * enabled buffer size
34 *
35 * [Out] used_size
36 * the size of the buffer which the pager uses
37 *
38 * return
39 * true initialize success
40 * false initialize failure
41 */
42bool tv_init_text_processor(unsigned char *buf, size_t bufsize, size_t *used_size);
43
44/*
45 * set the processing conditions
46 *
47 * [In] blocks
48 * total block count
49 *
50 * [In] width
51 * the block width
52 */
53void tv_set_creation_conditions(int blocks, int width);
54
55/*
56 * create the displayed text
57 *
58 * [In] src
59 * the start pointer of the buffer
60 *
61 * [In] bufsize
62 * buffer size
63 *
64 * [In] block
65 * the index of block to read text
66 *
67 * [In] is_multi
68 * true read 2 blocks
69 * false read 1 block
70 *
71 * [Out] dst
72 * the pointer of the pointer which store the text
73 *
74 * return
75 * the size of the text
76 */
77int tv_create_formed_text(const unsigned char *src, ssize_t bufsize,
78 int block, bool is_multi, const unsigned char **dst);
79
80#endif
diff --git a/apps/plugins/text_viewer/tv_text_reader.c b/apps/plugins/text_viewer/tv_text_reader.c
new file mode 100644
index 0000000000..28cfa565c3
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_text_reader.c
@@ -0,0 +1,91 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "tv_pager.h"
25#include "tv_reader.h"
26#include "tv_text_processor.h"
27#include "tv_text_reader.h"
28
29static int get_block;
30static bool get_double_blocks;
31
32bool tv_init_text_reader(unsigned char *buf, size_t bufsize, size_t *used_size)
33{
34 size_t size;
35
36 if (!tv_init_text_processor(buf, bufsize, used_size))
37 return false;
38
39 size = *used_size;
40 if (!tv_init_pager(buf + size, bufsize - size, used_size))
41 return false;
42
43 *used_size += size;
44 return true;
45}
46
47void tv_finalize_text_reader(void)
48{
49 tv_finalize_pager();
50}
51
52void tv_set_read_conditions(int blocks, int width)
53{
54 tv_set_creation_conditions(blocks, width);
55}
56
57off_t tv_get_total_text_size(void)
58{
59 return tv_get_file_size();
60}
61
62bool tv_get_next_line(const unsigned char **buf)
63{
64 ssize_t bufsize;
65 const unsigned char *buffer = tv_get_buffer(&bufsize);
66
67 if (bufsize > 0)
68 {
69 tv_move_next_line(
70 tv_create_formed_text(buffer, bufsize, get_block, get_double_blocks, buf));
71 return true;
72 }
73 return false;
74}
75
76void tv_read_start(int block, bool is_multi)
77{
78 get_block = block;
79 get_double_blocks = is_multi;
80 tv_reset_line_positions();
81}
82
83int tv_read_end(void)
84{
85 return tv_get_line_positions(0);
86}
87
88void tv_seek_top(void)
89{
90 tv_move_screen(0, 0, SEEK_SET);
91}
diff --git a/apps/plugins/text_viewer/tv_text_reader.h b/apps/plugins/text_viewer/tv_text_reader.h
new file mode 100644
index 0000000000..e8c712c76f
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_text_reader.h
@@ -0,0 +1,101 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_TEXT_READER_H
24#define PLUGIN_TEXT_VIEWER_TEXT_READER_H
25
26/*
27 * initialize the text reader module
28 *
29 * [In] buf
30 * the start pointer of the buffer
31 *
32 * [In] size
33 * enabled buffer size
34 *
35 * [Out] used_size
36 * the size of the buffer which the pager uses
37 *
38 * return
39 * true initialize success
40 * false initialize failure
41 */
42bool tv_init_text_reader(unsigned char *buf, size_t bufsize, size_t *used_size);
43
44/* finalize the text reader module */
45void tv_finalize_text_reader(void);
46
47/*
48 * set the read conditions
49 *
50 * [In] blocks
51 * block count
52 *
53 * [In] width
54 * block width
55 */
56void tv_set_read_conditions(int blocks, int width);
57
58/*
59 * return the total text size
60 *
61 * return
62 * the total text size
63 */
64off_t tv_get_total_text_size(void);
65
66/*
67 * get the text of the next line
68 *
69 * [Out] buf
70 * the pointer of the pointer which store the text
71 *
72 * return
73 * true next line exists
74 * false next line does not exist
75 */
76bool tv_get_next_line(const unsigned char **buf);
77
78/*
79 * start to read lines
80 *
81 * [In] block
82 * the index of block to read text
83 *
84 * [In] is_multi
85 * true read 2 blocks
86 * false read 1 block
87 */
88void tv_read_start(int block, bool is_multi);
89
90/*
91 * end to read lines
92 *
93 * return
94 * read text size
95 */
96int tv_read_end(void);
97
98/* seek to the head of the file */
99void tv_seek_top(void);
100
101#endif
diff --git a/apps/plugins/text_viewer/tv_window.c b/apps/plugins/text_viewer/tv_window.c
new file mode 100644
index 0000000000..43a24ca4bc
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_window.c
@@ -0,0 +1,394 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "plugin.h"
24#include "tv_bookmark.h"
25#include "tv_preferences.h"
26#include "tv_screen_pos.h"
27#include "tv_text_reader.h"
28#include "tv_window.h"
29
30#define TV_WINDOWS_PER_SCREEN 2
31
32#define TV_SCROLLBAR_WIDTH rb->global_settings->scrollbar_width
33
34#ifndef HAVE_LCD_BITMAP
35#define TV_BOOKMARK_ICON 0xe101
36#endif
37
38#ifdef HAVE_LCD_BITMAP
39static int header_height;
40static int footer_height;
41static bool need_scrollbar = false;
42#endif
43
44static int start_width;
45static int display_lines;
46
47static int window_width;
48static int window_columns;
49static int col_width;
50
51static int max_windows;
52
53static int cur_window;
54static int cur_column;
55
56static const struct tv_preferences *prefs = NULL;
57
58#ifdef HAVE_LCD_BITMAP
59static bool tv_set_font(const unsigned char *font)
60{
61 unsigned char path[MAX_PATH];
62
63 if (font != NULL && *font != '\0')
64 {
65 rb->snprintf(path, MAX_PATH, "%s/%s.fnt", FONT_DIR, font);
66 if (rb->font_load(NULL, path) < 0)
67 {
68 rb->splash(HZ/2, "font load failed");
69 return false;
70 }
71 }
72 return true;
73}
74
75static void tv_check_header_and_footer(void)
76{
77 struct tv_preferences new_prefs;
78
79 tv_copy_preferences(&new_prefs);
80
81 if (rb->global_settings->statusbar != STATUSBAR_TOP)
82 {
83 if (new_prefs.header_mode == HD_SBAR)
84 new_prefs.header_mode = HD_NONE;
85 else if (new_prefs.header_mode == HD_BOTH)
86 new_prefs.header_mode = HD_PATH;
87 }
88 if (rb->global_settings->statusbar != STATUSBAR_BOTTOM)
89 {
90 if (new_prefs.footer_mode == FT_SBAR)
91 new_prefs.footer_mode = FT_NONE;
92 else if (new_prefs.footer_mode == FT_BOTH)
93 new_prefs.footer_mode = FT_PAGE;
94 }
95 tv_set_preferences(&new_prefs);
96}
97
98static void tv_show_header(void)
99{
100 if (prefs->header_mode == HD_SBAR || prefs->header_mode == HD_BOTH)
101 rb->gui_syncstatusbar_draw(rb->statusbars, true);
102
103 if (prefs->header_mode == HD_PATH || prefs->header_mode == HD_BOTH)
104 rb->lcd_putsxy(0, header_height - prefs->font->height, prefs->file_name);
105}
106
107static void tv_show_footer(const struct tv_screen_pos *pos)
108{
109 unsigned char buf[12];
110
111 if (prefs->footer_mode == FT_SBAR || prefs->footer_mode == FT_BOTH)
112 rb->gui_syncstatusbar_draw(rb->statusbars, true);
113
114 if (prefs->footer_mode == FT_PAGE || prefs->footer_mode == FT_BOTH)
115 {
116 if (pos->line == 0)
117 rb->snprintf(buf, sizeof(buf), "%d", pos->page + 1);
118 else
119 rb->snprintf(buf, sizeof(buf), "%d - %d", pos->page + 1, pos->page + 2);
120
121 rb->lcd_putsxy(0, LCD_HEIGHT - footer_height, buf);
122 }
123}
124
125static void tv_show_scrollbar(off_t cur_pos, int size)
126{
127 int items;
128 int min_shown;
129 int max_shown;
130 int sb_begin_y;
131 int sb_height;
132
133 if (!need_scrollbar)
134 return;
135
136 items = (int) tv_get_total_text_size();
137 min_shown = (int) cur_pos;
138
139 max_shown = min_shown + size;
140
141 sb_begin_y = header_height;
142 sb_height = LCD_HEIGHT - header_height - footer_height;
143
144 rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],0, sb_begin_y,
145 TV_SCROLLBAR_WIDTH-1, sb_height,
146 items, min_shown, max_shown, VERTICAL);
147}
148
149static int tv_calc_display_lines(void)
150{
151 header_height = (prefs->header_mode == HD_SBAR || prefs->header_mode == HD_BOTH)?
152 STATUSBAR_HEIGHT : 0;
153
154 footer_height = (prefs->footer_mode == FT_SBAR || prefs->footer_mode == FT_BOTH)?
155 STATUSBAR_HEIGHT : 0;
156
157 if (prefs->header_mode == HD_NONE || prefs->header_mode == HD_PATH ||
158 prefs->footer_mode == FT_NONE || prefs->footer_mode == FT_PAGE)
159 rb->gui_syncstatusbar_draw(rb->statusbars, false);
160
161 if (prefs->header_mode == HD_PATH || prefs->header_mode == HD_BOTH)
162 header_height += prefs->font->height;
163
164 if (prefs->footer_mode == FT_PAGE || prefs->footer_mode == FT_BOTH)
165 footer_height += prefs->font->height;
166
167 return (LCD_HEIGHT - header_height - footer_height) / prefs->font->height;
168}
169#endif
170
171static void tv_show_bookmarks(const struct tv_screen_pos *top_pos)
172{
173 struct tv_screen_pos bookmarks[TV_MAX_BOOKMARKS];
174 int count = tv_get_bookmark_positions(bookmarks);
175 int line;
176
177#ifdef HAVE_LCD_BITMAP
178 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
179#endif
180 while (count--)
181 {
182 line = (bookmarks[count].page - top_pos->page) * display_lines
183 + (bookmarks[count].line - top_pos->line);
184 if (line >= 0 && line < display_lines)
185 {
186#ifdef HAVE_LCD_BITMAP
187 rb->lcd_fillrect(start_width, header_height + line * prefs->font->height,
188 window_width, prefs->font->height);
189#else
190 rb->lcd_putc(start_width - 1, line, TV_BOOKMARK_ICON);
191#endif
192 }
193 }
194#ifdef HAVE_LCD_BITMAP
195 rb->lcd_set_drawmode(DRMODE_SOLID);
196#endif
197}
198
199void tv_draw_window(void)
200{
201 struct tv_screen_pos pos;
202 const unsigned char *line_buf;
203 int line;
204 int offset = cur_column * col_width;
205 int size = 0;
206 int line_width;
207 int draw_width = (max_windows - cur_window) * LCD_WIDTH - offset;
208 int dx = start_width - offset;
209
210 tv_copy_screen_pos(&pos);
211 rb->lcd_clear_display();
212
213 if (prefs->alignment == LEFT)
214 tv_read_start(cur_window, (cur_column > 0));
215 else
216 tv_read_start(0, prefs->view_mode == WIDE);
217
218 for (line = 0; line < display_lines; line++)
219 {
220 if (!tv_get_next_line(&line_buf))
221 break;
222
223 if (prefs->alignment == RIGHT)
224 {
225 rb->lcd_getstringsize(line_buf, &line_width, NULL);
226 dx = draw_width - line_width;
227 }
228
229#ifdef HAVE_LCD_BITMAP
230 rb->lcd_putsxy(dx, header_height + line * prefs->font->height, line_buf);
231#else
232 rb->lcd_puts(dx, line, line_buf);
233#endif
234 }
235
236 size = tv_read_end();
237
238 tv_show_bookmarks(&pos);
239
240#ifdef HAVE_LCD_BITMAP
241 tv_show_scrollbar(pos.file_pos, size);
242 tv_show_header();
243 tv_show_footer(&pos);
244#endif
245
246 rb->lcd_update();
247}
248
249bool tv_traverse_lines(void)
250{
251 int i;
252 bool res = true;
253
254 tv_read_start(0, false);
255 for (i = 0; i < display_lines; i++)
256 {
257 if (!tv_get_next_line(NULL))
258 {
259 res = false;
260 break;
261 }
262 }
263 tv_read_end();
264 return res;
265}
266
267static void tv_change_preferences(const struct tv_preferences *oldp)
268{
269#ifdef HAVE_LCD_BITMAP
270 static bool is_executing = false;
271
272 is_executing = true;
273
274 /* change font */
275 if (oldp == NULL || rb->strcmp(oldp->font_name, prefs->font_name))
276 {
277 if (!tv_set_font(prefs->font_name))
278 {
279 struct tv_preferences new_prefs = *prefs;
280 const unsigned char *font_str;
281
282 font_str = (oldp == NULL)? rb->global_settings->font_file : oldp->font_name;
283
284 if (!tv_set_font(font_str) && oldp != NULL)
285 {
286 font_str = rb->global_settings->font_file;
287 tv_set_font(new_prefs.font_name);
288 }
289
290 rb->strlcpy(new_prefs.font_name, font_str, MAX_PATH);
291 tv_set_preferences(&new_prefs);
292 }
293 }
294
295 /* calculates display lines */
296 tv_check_header_and_footer();
297 display_lines = tv_calc_display_lines();
298
299 if (!is_executing)
300 return;
301
302 is_executing = false;
303#else
304 (void)oldp;
305
306 /* REAL fixed pitch :) all chars use up 1 cell */
307 display_lines = 2;
308#endif
309
310#ifdef HAVE_LCD_BITMAP
311 col_width = 2 * rb->font_get_width(prefs->font, ' ');
312#else
313 col_width = 1;
314#endif
315
316 max_windows = (prefs->view_mode == NARROW)? 1: TV_WINDOWS_PER_SCREEN;
317 if (cur_window >= max_windows)
318 cur_window = 0;
319
320 window_width = LCD_WIDTH;
321#ifdef HAVE_LCD_BITMAP
322 need_scrollbar = false;
323 start_width = 0;
324 tv_seek_top();
325 tv_set_read_conditions(max_windows, window_width);
326 if (tv_traverse_lines() && prefs->scrollbar_mode)
327 {
328 need_scrollbar = true;
329 start_width = TV_SCROLLBAR_WIDTH;
330 }
331 tv_seek_top();
332#else
333 start_width = 1;
334#endif
335 window_width -= start_width;
336 window_columns = window_width / col_width;
337
338 cur_column = 0;
339
340 tv_set_read_conditions(max_windows, window_width);
341}
342
343bool tv_init_window(unsigned char *buf, size_t bufsize, size_t *used_size)
344{
345 tv_add_preferences_change_listner(tv_change_preferences);
346 if (!tv_init_text_reader(buf, bufsize, used_size))
347 return false;
348
349 prefs = tv_get_preferences();
350 return true;
351}
352
353void tv_finalize_window(void)
354{
355 tv_finalize_text_reader();
356}
357
358void tv_move_window(int window_delta, int column_delta)
359{
360 cur_window += window_delta;
361 cur_column += column_delta;
362
363 if (cur_window < 0)
364 {
365 cur_window = 0;
366 cur_column = 0;
367 }
368 else if (cur_window >= max_windows)
369 {
370 cur_window = max_windows - 1;
371 cur_column = 0;
372 }
373
374 if (cur_column < 0)
375 {
376 if (cur_window == 0)
377 cur_column = 0;
378 else
379 {
380 cur_window--;
381 cur_column = window_columns - 1;
382 }
383 }
384 else
385 {
386 if (cur_window == max_windows - 1)
387 cur_column = 0;
388 else if (cur_column >= window_columns)
389 {
390 cur_window++;
391 cur_column = 0;
392 }
393 }
394}
diff --git a/apps/plugins/text_viewer/tv_window.h b/apps/plugins/text_viewer/tv_window.h
new file mode 100644
index 0000000000..fe87ec6569
--- /dev/null
+++ b/apps/plugins/text_viewer/tv_window.h
@@ -0,0 +1,69 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#ifndef PLUGIN_TEXT_VIEWER_WINDOW_H
24#define PLUGIN_TEXT_VIEWER_WINDOW_H
25
26/*
27 * initialize the window module
28 *
29 * [In] buf
30 * the start pointer of the buffer
31 *
32 * [In] size
33 * enabled buffer size
34 *
35 * [Out] used_size
36 * the size of the buffer which the pager uses
37 *
38 * return
39 * true initialize success
40 * false initialize failure
41 */
42bool tv_init_window(unsigned char *buf, size_t bufsize, size_t *used_size);
43
44/* finalize the window module */
45void tv_finalize_window(void);
46
47/* draw the display */
48void tv_draw_window(void);
49
50/* traverse all lines of the current page */
51bool tv_traverse_lines(void);
52
53/*
54 * move to the window
55 *
56 * new position
57 * new window: the current window + window_delta
58 * new column: the current column + column_delta
59 *
60 * [In] window_delta
61 * variation of the window
62 *
63 * [In] column_delta
64 * variation of the column
65 *
66 */
67void tv_move_window(int window_delta, int column_delta);
68
69#endif
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index 1c70c2957f..2a98bb6ed7 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -1,6 +1,6 @@
1ch8,viewers/chip8,0 1ch8,viewers/chip8,0
2txt,viewers/viewer,1 2txt,viewers/text_viewer,1
3nfo,viewers/viewer,1 3nfo,viewers/text_viewer,1
4txt,apps/text_editor,2 4txt,apps/text_editor,2
5bmp,viewers/bmp,2 5bmp,viewers/bmp,2
6jpg,viewers/jpeg,2 6jpg,viewers/jpeg,2