diff options
Diffstat (limited to 'apps/plugins/text_viewer')
27 files changed, 4794 insertions, 0 deletions
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 @@ | |||
1 | text_viewer.c | ||
2 | tv_action.c | ||
3 | tv_bookmark.c | ||
4 | tv_menu.c | ||
5 | tv_pager.c | ||
6 | tv_preferences.c | ||
7 | tv_reader.c | ||
8 | tv_screen_pos.c | ||
9 | tv_settings.c | ||
10 | tv_text_processor.c | ||
11 | tv_text_reader.c | ||
12 | tv_window.c | ||
diff --git a/apps/plugins/text_viewer/readme.txt b/apps/plugins/text_viewer/readme.txt new file mode 100644 index 0000000000..f124370bdc --- /dev/null +++ b/apps/plugins/text_viewer/readme.txt | |||
@@ -0,0 +1,62 @@ | |||
1 | about the text viewer plugin. | ||
2 | |||
3 | Limitation | ||
4 | for the target which PLUGIN_BUFFER_SIZE < 0x13000 (i.e., archos series), | ||
5 | can only be read up to 999 pages. | ||
6 | |||
7 | |||
8 | Difference 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 | |||
41 | TODO 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 | |||
28 | PLUGIN_HEADER | ||
29 | |||
30 | enum 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 | |||
10 | TEXT_VIEWER_SRCDIR := $(APPSDIR)/plugins/text_viewer | ||
11 | TEXT_VIEWER_BUILDDIR := $(BUILDDIR)/apps/plugins/text_viewer | ||
12 | |||
13 | TEXT_VIEWER_SRC := $(call preprocess, $(TEXT_VIEWER_SRCDIR)/SOURCES) | ||
14 | TEXT_VIEWER_OBJ := $(call c2obj, $(TEXT_VIEWER_SRC)) | ||
15 | |||
16 | OTHER_SRC += $(TEXT_VIEWER_SRC) | ||
17 | |||
18 | ROCKS += $(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 | |||
31 | static const struct tv_preferences *prefs; | ||
32 | |||
33 | bool 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 | |||
62 | void 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 | |||
74 | void 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 | |||
86 | void 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 | |||
102 | void 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 | |||
118 | void 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 | |||
136 | void 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 | |||
154 | void tv_top(void) | ||
155 | { | ||
156 | tv_move_screen(0, 0, SEEK_SET); | ||
157 | } | ||
158 | |||
159 | void 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 | |||
166 | enum 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 | |||
183 | void 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 */ | ||
29 | enum 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 */ | ||
37 | enum 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 | */ | ||
54 | bool tv_init(const unsigned char *file); | ||
55 | |||
56 | /* | ||
57 | * finalize modules | ||
58 | * | ||
59 | * [In] parameter | ||
60 | * this argument does not use | ||
61 | */ | ||
62 | void tv_exit(void *parameter); | ||
63 | |||
64 | /* draw the current page */ | ||
65 | void tv_draw(void); | ||
66 | |||
67 | /* | ||
68 | * scroll up | ||
69 | * | ||
70 | * [In] mode | ||
71 | * scroll mode | ||
72 | */ | ||
73 | void tv_scroll_up(enum tv_vertical_scroll_mode mode); | ||
74 | |||
75 | /* | ||
76 | * scroll down | ||
77 | * | ||
78 | * [In] mode | ||
79 | * scroll mode | ||
80 | */ | ||
81 | void tv_scroll_down(enum tv_vertical_scroll_mode mode); | ||
82 | |||
83 | /* | ||
84 | * scroll left | ||
85 | * | ||
86 | * [In] mode | ||
87 | * scroll mode | ||
88 | */ | ||
89 | void tv_scroll_left(enum tv_horizontal_scroll_mode mode); | ||
90 | |||
91 | /* | ||
92 | * scroll right | ||
93 | * | ||
94 | * [In] mode | ||
95 | * scroll mode | ||
96 | */ | ||
97 | void tv_scroll_right(enum tv_horizontal_scroll_mode mode); | ||
98 | |||
99 | /* jump to the top */ | ||
100 | void tv_top(void); | ||
101 | |||
102 | /* jump to the bottom */ | ||
103 | void 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 | */ | ||
114 | enum tv_menu_result tv_menu(void); | ||
115 | |||
116 | /* add or remove the bookmark to the current position */ | ||
117 | void 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 | |||
30 | enum { | ||
31 | TV_BOOKMARK_SYSTEM = 1, | ||
32 | TV_BOOKMARK_USER = 2, | ||
33 | }; | ||
34 | |||
35 | #define SERIALIZE_BOOKMARK_SIZE 8 | ||
36 | |||
37 | struct tv_bookmark_info { | ||
38 | struct tv_screen_pos pos; | ||
39 | unsigned char flag; | ||
40 | }; | ||
41 | |||
42 | /* bookmark stored array */ | ||
43 | struct tv_bookmark_info bookmarks[TV_MAX_BOOKMARKS + 1]; | ||
44 | static unsigned char bookmark_count; | ||
45 | |||
46 | static 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 | |||
54 | static 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 | |||
65 | static 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 | |||
76 | static 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 | |||
89 | static 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 | |||
101 | static 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 | |||
112 | void tv_init_bookmark(void) | ||
113 | { | ||
114 | tv_add_preferences_change_listner(tv_change_preferences); | ||
115 | } | ||
116 | |||
117 | int 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 | |||
127 | void 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 | |||
144 | void 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 | |||
159 | void 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 */ | ||
234 | static 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 | |||
249 | bool 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 | |||
270 | static 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 | |||
289 | int 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 */ | ||
34 | void 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 | */ | ||
45 | int 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 | */ | ||
51 | void 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 | */ | ||
57 | void tv_select_bookmark(void); | ||
58 | |||
59 | /* creates system bookmark */ | ||
60 | void 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 | */ | ||
71 | int 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 | */ | ||
83 | bool 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 | |||
31 | static struct tv_preferences new_prefs; | ||
32 | |||
33 | static 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 | |||
48 | static 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 | |||
59 | static 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 | |||
72 | static 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 | |||
83 | static 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 | |||
94 | static 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 | ||
106 | static 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 | |||
117 | static 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 | |||
128 | static 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 | |||
150 | static 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 | |||
172 | static 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 | |||
183 | static 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 | |||
263 | static 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 | |||
269 | MENUITEM_FUNCTION(encoding_item, 0, "Encoding", tv_encoding_setting, | ||
270 | NULL, NULL, Icon_NOICON); | ||
271 | MENUITEM_FUNCTION(word_wrap_item, 0, "Word Wrap", tv_word_wrap_setting, | ||
272 | NULL, NULL, Icon_NOICON); | ||
273 | MENUITEM_FUNCTION(line_mode_item, 0, "Line Mode", tv_line_mode_setting, | ||
274 | NULL, NULL, Icon_NOICON); | ||
275 | MENUITEM_FUNCTION(view_mode_item, 0, "Wide View", tv_view_mode_setting, | ||
276 | NULL, NULL, Icon_NOICON); | ||
277 | MENUITEM_FUNCTION(alignment_item, 0, "Alignment", tv_alignment_setting, | ||
278 | NULL, NULL, Icon_NOICON); | ||
279 | #ifdef HAVE_LCD_BITMAP | ||
280 | MENUITEM_FUNCTION(scrollbar_item, 0, "Show Scrollbar", tv_scrollbar_setting, | ||
281 | NULL, NULL, Icon_NOICON); | ||
282 | MENUITEM_FUNCTION(page_mode_item, 0, "Overlap Pages", tv_page_mode_setting, | ||
283 | NULL, NULL, Icon_NOICON); | ||
284 | MENUITEM_FUNCTION(header_item, 0, "Show Header", tv_header_setting, | ||
285 | NULL, NULL, Icon_NOICON); | ||
286 | MENUITEM_FUNCTION(footer_item, 0, "Show Footer", tv_footer_setting, | ||
287 | NULL, NULL, Icon_NOICON); | ||
288 | MENUITEM_FUNCTION(font_item, 0, "Font", tv_font_setting, | ||
289 | NULL, NULL, Icon_NOICON); | ||
290 | #endif | ||
291 | MENUITEM_FUNCTION(scroll_mode_item, 0, "Scroll Mode", tv_scroll_mode_setting, | ||
292 | NULL, NULL, Icon_NOICON); | ||
293 | MENUITEM_FUNCTION(autoscroll_speed_item, 0, "Auto-Scroll Speed", | ||
294 | tv_autoscroll_speed_setting, NULL, NULL, Icon_NOICON); | ||
295 | MAKE_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 | |||
303 | static 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 | |||
313 | enum 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 | |||
26 | enum 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 | */ | ||
41 | enum 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 | |||
37 | static unsigned char *pager_buffer; | ||
38 | |||
39 | static struct tv_screen_pos cur_pos; | ||
40 | |||
41 | static int parse_page; | ||
42 | static int last_page; | ||
43 | static int max_page; | ||
44 | |||
45 | static int lines_per_page; | ||
46 | |||
47 | static int line_pos[LCD_HEIGHT / 2]; | ||
48 | static int parse_page; | ||
49 | static int parse_top_line; | ||
50 | static int parse_lines; | ||
51 | |||
52 | static 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 | |||
60 | static unsigned int get_uint32(const unsigned char *p) | ||
61 | { | ||
62 | return (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0]; | ||
63 | } | ||
64 | |||
65 | static 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 | |||
71 | static 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 | |||
78 | static 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 | |||
90 | bool 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 | |||
114 | void tv_finalize_pager(void) | ||
115 | { | ||
116 | tv_finalize_reader(); | ||
117 | } | ||
118 | |||
119 | void 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 | |||
126 | void 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 | |||
138 | int 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 | |||
150 | void 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 | |||
168 | static 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 | |||
198 | static 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 | |||
214 | void 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 | |||
248 | static 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 | |||
259 | void 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 | */ | ||
46 | bool tv_init_pager(unsigned char *buf, size_t bufsize, size_t *used_size); | ||
47 | |||
48 | /* finalize the pager module */ | ||
49 | void tv_finalize_pager(void); | ||
50 | |||
51 | /* reset the stored line positions */ | ||
52 | void tv_reset_line_positions(void); | ||
53 | |||
54 | /* | ||
55 | * move to the next line | ||
56 | * | ||
57 | * [In] size | ||
58 | * the current line size | ||
59 | */ | ||
60 | void 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 | */ | ||
71 | int tv_get_line_positions(int offset); | ||
72 | |||
73 | /* change the new page */ | ||
74 | void 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 | */ | ||
85 | void 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 | */ | ||
102 | void 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 | |||
26 | static struct tv_preferences prefs; | ||
27 | static bool is_initialized = false; | ||
28 | static int listner_count = 0; | ||
29 | |||
30 | #define TV_MAX_LISTNERS 4 | ||
31 | static void (*listners[TV_MAX_LISTNERS])(const struct tv_preferences *oldp); | ||
32 | |||
33 | static 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 | |||
64 | const struct tv_preferences *tv_get_preferences(void) | ||
65 | { | ||
66 | return &prefs; | ||
67 | } | ||
68 | |||
69 | void 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 | |||
85 | void tv_copy_preferences(struct tv_preferences *copy_prefs) | ||
86 | { | ||
87 | rb->memcpy(copy_prefs, &prefs, sizeof(struct tv_preferences)); | ||
88 | } | ||
89 | |||
90 | void 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 | |||
115 | void 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 | |||
26 | struct 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 | */ | ||
95 | const struct tv_preferences *tv_get_preferences(void); | ||
96 | |||
97 | /* | ||
98 | * change the preferences | ||
99 | * | ||
100 | * [In] new_prefs | ||
101 | * new preferences | ||
102 | */ | ||
103 | void 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 | */ | ||
111 | void 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 | */ | ||
119 | void 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 | */ | ||
127 | void 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 | |||
37 | static int fd = -1; | ||
38 | |||
39 | static off_t file_pos; | ||
40 | static off_t start_file_pos; | ||
41 | |||
42 | static off_t file_size; | ||
43 | |||
44 | static unsigned char *reader_buffer; | ||
45 | static ssize_t buffer_size; | ||
46 | static ssize_t block_size; | ||
47 | |||
48 | static ssize_t buf_pos; | ||
49 | static ssize_t read_size; | ||
50 | |||
51 | off_t tv_get_file_size(void) | ||
52 | { | ||
53 | return file_size; | ||
54 | } | ||
55 | |||
56 | bool tv_is_eof(void) | ||
57 | { | ||
58 | return (file_pos + buf_pos >= file_size); | ||
59 | } | ||
60 | |||
61 | off_t tv_get_current_file_pos(void) | ||
62 | { | ||
63 | return file_pos + buf_pos; | ||
64 | } | ||
65 | |||
66 | const unsigned char *tv_get_buffer(ssize_t *bufsize) | ||
67 | { | ||
68 | *bufsize = read_size - buf_pos; | ||
69 | return reader_buffer + buf_pos; | ||
70 | } | ||
71 | |||
72 | static 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 | |||
80 | void 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 | |||
135 | static 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 | |||
174 | bool 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 | |||
187 | void 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 | */ | ||
44 | bool tv_init_reader(unsigned char *buf, size_t bufsize, size_t *used_size); | ||
45 | |||
46 | /* finalize the reader module */ | ||
47 | void 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 | */ | ||
58 | off_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 | */ | ||
67 | bool tv_is_eof(void); | ||
68 | |||
69 | /* | ||
70 | * return the current file position | ||
71 | * | ||
72 | * return | ||
73 | * the current file position | ||
74 | */ | ||
75 | off_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 | */ | ||
86 | const 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 | */ | ||
100 | void 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 | |||
26 | static const struct tv_screen_pos *screen_pos; | ||
27 | |||
28 | const struct tv_screen_pos *tv_get_screen_pos(void) | ||
29 | { | ||
30 | return screen_pos; | ||
31 | } | ||
32 | |||
33 | void tv_set_screen_pos(const struct tv_screen_pos *pos) | ||
34 | { | ||
35 | screen_pos = pos; | ||
36 | } | ||
37 | |||
38 | void 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 | |||
26 | struct 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 | */ | ||
38 | const 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 | */ | ||
46 | void 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 | */ | ||
54 | void 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 | |||
118 | static 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 | |||
154 | static 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 | |||
182 | static 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 | |||
228 | static 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 | |||
283 | bool 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 | |||
310 | bool 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 | |||
342 | void 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 | |||
398 | static 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 | |||
414 | bool 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 | */ | ||
38 | bool 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 | */ | ||
50 | bool 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 | */ | ||
62 | void 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 | */ | ||
71 | bool 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 | |||
28 | enum 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 | |||
50 | static const struct tv_preferences *prefs; | ||
51 | static enum tv_text_type text_type = TV_TEXT_UNKNOWN; | ||
52 | |||
53 | static const unsigned char *end_ptr; | ||
54 | |||
55 | static unsigned short *ucsbuf[TV_MAX_BLOCKS]; | ||
56 | static unsigned char *utf8buf; | ||
57 | static unsigned char *outbuf; | ||
58 | |||
59 | static int block_count; | ||
60 | static int block_width; | ||
61 | |||
62 | /* if this value is true, then tv_create_line_text returns a blank line. */ | ||
63 | static bool expand_extra_line = false; | ||
64 | |||
65 | /* when a line is divided, this value sets true. */ | ||
66 | static bool is_break_line = false; | ||
67 | |||
68 | static 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() */ | ||
90 | static unsigned short extra_spaces[] = { 0, 0x3000 }; | ||
91 | |||
92 | static 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 | |||
111 | static 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 | |||
167 | static 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 | |||
177 | static 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 | |||
193 | static 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 | |||
208 | static 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 | |||
216 | static 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 | |||
285 | static 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 | |||
366 | static 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 | |||
495 | int 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 | |||
550 | bool 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 | |||
572 | void 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 | */ | ||
42 | bool 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 | */ | ||
53 | void 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 | */ | ||
77 | int 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 | |||
29 | static int get_block; | ||
30 | static bool get_double_blocks; | ||
31 | |||
32 | bool 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 | |||
47 | void tv_finalize_text_reader(void) | ||
48 | { | ||
49 | tv_finalize_pager(); | ||
50 | } | ||
51 | |||
52 | void tv_set_read_conditions(int blocks, int width) | ||
53 | { | ||
54 | tv_set_creation_conditions(blocks, width); | ||
55 | } | ||
56 | |||
57 | off_t tv_get_total_text_size(void) | ||
58 | { | ||
59 | return tv_get_file_size(); | ||
60 | } | ||
61 | |||
62 | bool 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 | |||
76 | void 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 | |||
83 | int tv_read_end(void) | ||
84 | { | ||
85 | return tv_get_line_positions(0); | ||
86 | } | ||
87 | |||
88 | void 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 | */ | ||
42 | bool tv_init_text_reader(unsigned char *buf, size_t bufsize, size_t *used_size); | ||
43 | |||
44 | /* finalize the text reader module */ | ||
45 | void 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 | */ | ||
56 | void 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 | */ | ||
64 | off_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 | */ | ||
76 | bool 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 | */ | ||
88 | void tv_read_start(int block, bool is_multi); | ||
89 | |||
90 | /* | ||
91 | * end to read lines | ||
92 | * | ||
93 | * return | ||
94 | * read text size | ||
95 | */ | ||
96 | int tv_read_end(void); | ||
97 | |||
98 | /* seek to the head of the file */ | ||
99 | void 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 | ||
39 | static int header_height; | ||
40 | static int footer_height; | ||
41 | static bool need_scrollbar = false; | ||
42 | #endif | ||
43 | |||
44 | static int start_width; | ||
45 | static int display_lines; | ||
46 | |||
47 | static int window_width; | ||
48 | static int window_columns; | ||
49 | static int col_width; | ||
50 | |||
51 | static int max_windows; | ||
52 | |||
53 | static int cur_window; | ||
54 | static int cur_column; | ||
55 | |||
56 | static const struct tv_preferences *prefs = NULL; | ||
57 | |||
58 | #ifdef HAVE_LCD_BITMAP | ||
59 | static 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 | |||
75 | static 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 | |||
98 | static 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 | |||
107 | static 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 | |||
125 | static 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 | |||
149 | static 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 | |||
171 | static 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 | |||
199 | void 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 | |||
249 | bool 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 | |||
267 | static 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 | |||
343 | bool 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 | |||
353 | void tv_finalize_window(void) | ||
354 | { | ||
355 | tv_finalize_text_reader(); | ||
356 | } | ||
357 | |||
358 | void 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 | */ | ||
42 | bool tv_init_window(unsigned char *buf, size_t bufsize, size_t *used_size); | ||
43 | |||
44 | /* finalize the window module */ | ||
45 | void tv_finalize_window(void); | ||
46 | |||
47 | /* draw the display */ | ||
48 | void tv_draw_window(void); | ||
49 | |||
50 | /* traverse all lines of the current page */ | ||
51 | bool 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 | */ | ||
67 | void tv_move_window(int window_delta, int column_delta); | ||
68 | |||
69 | #endif | ||