diff options
Diffstat (limited to 'apps/plugins/text_viewer/tv_bookmark.c')
-rw-r--r-- | apps/plugins/text_viewer/tv_bookmark.c | 302 |
1 files changed, 302 insertions, 0 deletions
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 | } | ||