diff options
Diffstat (limited to 'apps/plugins/textviewer/tv_bookmark.c')
-rw-r--r-- | apps/plugins/textviewer/tv_bookmark.c | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/apps/plugins/textviewer/tv_bookmark.c b/apps/plugins/textviewer/tv_bookmark.c new file mode 100644 index 0000000000..261a319e26 --- /dev/null +++ b/apps/plugins/textviewer/tv_bookmark.c | |||
@@ -0,0 +1,338 @@ | |||
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 | |||
26 | /* text viewer bookmark functions */ | ||
27 | |||
28 | enum | ||
29 | { | ||
30 | BOOKMARK_LAST = 1, | ||
31 | BOOKMARK_USER, | ||
32 | }; | ||
33 | |||
34 | #ifndef HAVE_LCD_BITMAP | ||
35 | #define BOOKMARK_ICON "\xee\x84\x81\x00" | ||
36 | #endif | ||
37 | |||
38 | #define BOOKMARK_SIZE 8 | ||
39 | #define MAX_BOOKMARKS 10 /* user setting bookmarks + last read page */ | ||
40 | |||
41 | |||
42 | struct bookmark_info bookmarks[MAX_BOOKMARKS]; | ||
43 | static int bookmark_count; | ||
44 | |||
45 | static int bm_comp(const void *a, const void *b) | ||
46 | { | ||
47 | struct bookmark_info *pa; | ||
48 | struct bookmark_info *pb; | ||
49 | |||
50 | pa = (struct bookmark_info*)a; | ||
51 | pb = (struct bookmark_info*)b; | ||
52 | |||
53 | if (pa->page != pb->page) | ||
54 | return pa->page - pb->page; | ||
55 | |||
56 | return pa->line - pb->line; | ||
57 | } | ||
58 | |||
59 | int viewer_find_bookmark(int page, int line) | ||
60 | { | ||
61 | int i; | ||
62 | |||
63 | for (i = 0; i < bookmark_count; i++) | ||
64 | { | ||
65 | if (bookmarks[i].page == page && bookmarks[i].line == line) | ||
66 | return i; | ||
67 | } | ||
68 | return -1; | ||
69 | } | ||
70 | |||
71 | void viewer_add_bookmark(int page, int line) | ||
72 | { | ||
73 | if (bookmark_count >= MAX_BOOKMARKS-1) | ||
74 | return; | ||
75 | |||
76 | bookmarks[bookmark_count].file_position | ||
77 | = file_pos + screen_top_ptr - buffer; | ||
78 | bookmarks[bookmark_count].page = page; | ||
79 | bookmarks[bookmark_count].line = line; | ||
80 | bookmarks[bookmark_count].flag = BOOKMARK_USER; | ||
81 | bookmark_count++; | ||
82 | } | ||
83 | |||
84 | static int viewer_add_last_read_bookmark(void) | ||
85 | { | ||
86 | int i; | ||
87 | |||
88 | i = viewer_find_bookmark(cpage, cline); | ||
89 | if (i >= 0) | ||
90 | bookmarks[i].flag |= BOOKMARK_LAST; | ||
91 | else | ||
92 | { | ||
93 | viewer_add_bookmark(); | ||
94 | i = bookmark_count-1; | ||
95 | bookmarks[i].flag = BOOKMARK_LAST; | ||
96 | } | ||
97 | return i; | ||
98 | } | ||
99 | |||
100 | static void viewer_remove_bookmark(int i) | ||
101 | { | ||
102 | int j; | ||
103 | |||
104 | if (i < 0 || i >= bookmark_count) | ||
105 | return; | ||
106 | |||
107 | for (j = i+1; j < bookmark_count; j++) | ||
108 | rb->memcpy(&bookmarks[j-1], &bookmarks[j], | ||
109 | sizeof(struct bookmark_info)); | ||
110 | |||
111 | bookmark_count--; | ||
112 | } | ||
113 | |||
114 | void viewer_remove_last_read_bookmark(void) | ||
115 | { | ||
116 | int i, j; | ||
117 | |||
118 | for (i = 0; i < bookmark_count; i++) | ||
119 | { | ||
120 | if (bookmarks[i].flag & BOOKMARK_LAST) | ||
121 | { | ||
122 | if (bookmarks[i].flag == BOOKMARK_LAST) | ||
123 | { | ||
124 | for (j = i+1; j < bookmark_count; j++) | ||
125 | rb->memcpy(&bookmarks[j-1], &bookmarks[j], | ||
126 | sizeof(struct bookmark_info)); | ||
127 | |||
128 | bookmark_count--; | ||
129 | } | ||
130 | else | ||
131 | bookmarks[i].flag = BOOKMARK_USER; | ||
132 | break; | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /* | ||
138 | * the function that a bookmark add when there is not a bookmark in the given position | ||
139 | * or the bookmark remove when there exist a bookmark in the given position. | ||
140 | * | ||
141 | */ | ||
142 | void viewer_add_remove_bookmark(int page, int line) | ||
143 | { | ||
144 | int idx = viewer_find_bookmark(cpage, cline); | ||
145 | |||
146 | if (idx < 0) | ||
147 | { | ||
148 | if (bookmark_count >= MAX_BOOKMARKS-1) | ||
149 | rb->splash(HZ/2, "No more add bookmark."); | ||
150 | else | ||
151 | { | ||
152 | viewer_add_bookmark(page, line); | ||
153 | rb->splash(HZ/2, "Bookmark add."); | ||
154 | } | ||
155 | } | ||
156 | viewer_remove_bookmark(idx); | ||
157 | rb->splash(HZ/2, "Bookmark remove."); | ||
158 | } | ||
159 | |||
160 | static int viewer_get_last_read_bookmark(void) | ||
161 | { | ||
162 | int i; | ||
163 | |||
164 | for (i = 0; i < bookmark_count; i++) | ||
165 | { | ||
166 | if (bookmarks[i].flag & BOOKMARK_LAST) | ||
167 | return i; | ||
168 | } | ||
169 | return -1; | ||
170 | } | ||
171 | |||
172 | void viewer_select_bookmark(int initval) | ||
173 | { | ||
174 | int i; | ||
175 | int ipage = 0; | ||
176 | int iline = 0; | ||
177 | int screen_pos; | ||
178 | int screen_top; | ||
179 | int selected = -1; | ||
180 | |||
181 | struct opt_items items[bookmark_count]; | ||
182 | unsigned char names[bookmark_count][38]; | ||
183 | |||
184 | if (initval >= 0 && initval < bookmark_count) | ||
185 | { | ||
186 | ipage = bookmarks[initval].page; | ||
187 | iline = bookmarks[initval].line; | ||
188 | } | ||
189 | |||
190 | rb->qsort(bookmarks, bookmark_count, sizeof(struct bookmark_info), | ||
191 | bm_comp); | ||
192 | |||
193 | for (i = 0; i < bookmark_count; i++) | ||
194 | { | ||
195 | rb->snprintf(names[i], sizeof(names[0]), | ||
196 | #if CONFIG_KEYPAD != PLAYER_PAD | ||
197 | "%sPage: %d Line: %d", | ||
198 | #else | ||
199 | "%sP:%d L:%d", | ||
200 | #endif | ||
201 | (bookmarks[i].flag&BOOKMARK_LAST)? "*":" ", | ||
202 | bookmarks[i].page, | ||
203 | bookmarks[i].line); | ||
204 | items[i].string = names[i]; | ||
205 | items[i].voice_id = -1; | ||
206 | if (selected < 0 && bookmarks[i].page == ipage && bookmarks[i].line == iline) | ||
207 | selected = i; | ||
208 | } | ||
209 | |||
210 | rb->set_option("Select bookmark", &selected, INT, items, | ||
211 | sizeof(items) / sizeof(items[0]), NULL); | ||
212 | |||
213 | if (selected < 0 || selected >= bookmark_count) | ||
214 | { | ||
215 | if (initval < 0 || (selected = viewer_get_last_read_bookmark()) < 0) | ||
216 | { | ||
217 | if (initval < 0) | ||
218 | rb->splash(HZ, "Start the first page."); | ||
219 | file_pos = 0; | ||
220 | screen_top_ptr = buffer; | ||
221 | cpage = 1; | ||
222 | cline = 1; | ||
223 | buffer_end = BUFFER_END(); | ||
224 | return; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | screen_pos = bookmarks[selected].file_position; | ||
229 | screen_top = screen_pos % buffer_size; | ||
230 | file_pos = screen_pos - screen_top; | ||
231 | screen_top_ptr = buffer + screen_top; | ||
232 | cpage = bookmarks[selected].page; | ||
233 | cline = bookmarks[selected].line; | ||
234 | buffer_end = BUFFER_END(); | ||
235 | } | ||
236 | |||
237 | |||
238 | static bool viewer_read_bookmark_info(int bfd, struct bookmark_info *b) | ||
239 | { | ||
240 | unsigned char buf[BOOKMARK_SIZE]; | ||
241 | |||
242 | if (rb->read(bfd, buf, sizeof(buf)) != sizeof(buf)) | ||
243 | return false; | ||
244 | |||
245 | b->file_position = (buf[0] << 24)|(buf[1] << 16)|(buf[2] << 8)|buf[3]; | ||
246 | b->page = (buf[4] << 8)|buf[5]; | ||
247 | b->line = buf[6]; | ||
248 | b->flag = buf[7]; | ||
249 | |||
250 | return true; | ||
251 | } | ||
252 | |||
253 | bool viewer_read_bookmark_infos(int fd) | ||
254 | { | ||
255 | unsigned char c; | ||
256 | int i; | ||
257 | |||
258 | if (rb->read(fd, &c, 1) != 1) | ||
259 | { | ||
260 | bookmark_count = 0; | ||
261 | return false; | ||
262 | } | ||
263 | |||
264 | bookmark_count = c; | ||
265 | if (bookmark_count > MAX_BOOKMARKS) | ||
266 | bookmark_count = MAX_BOOKMARKS; | ||
267 | |||
268 | for (i = 0; i < bookmark_count; i++) | ||
269 | { | ||
270 | if (!viewer_read_bookmark_info(fd, &bookmarks[i])) | ||
271 | { | ||
272 | bookmark_count = i; | ||
273 | return false; | ||
274 | } | ||
275 | } | ||
276 | return true; | ||
277 | } | ||
278 | |||
279 | static bool viewer_write_bookmark_info(int bfd, struct bookmark_info *b) | ||
280 | { | ||
281 | unsigned char buf[BOOKMARK_SIZE]; | ||
282 | unsigned char *p = buf; | ||
283 | unsigned long ul; | ||
284 | |||
285 | ul = b->file_position; | ||
286 | *p++ = ul >> 24; | ||
287 | *p++ = ul >> 16; | ||
288 | *p++ = ul >> 8; | ||
289 | *p++ = ul; | ||
290 | |||
291 | ul = b->page; | ||
292 | *p++ = ul >> 8; | ||
293 | *p++ = ul; | ||
294 | |||
295 | *p++ = b->line; | ||
296 | *p = b->flag; | ||
297 | |||
298 | return (rb->write(bfd, buf, sizeof(buf)) == sizeof(buf)); | ||
299 | } | ||
300 | |||
301 | bool viewer_write_bookmark_infos(int fd) | ||
302 | { | ||
303 | unsigned char c = bookmark_count; | ||
304 | int i; | ||
305 | |||
306 | if (rb->write(fd, &c, 1) != 1) | ||
307 | return false; | ||
308 | |||
309 | for (i = 0; i < bookmark_count; i++) | ||
310 | { | ||
311 | if (!viewer_write_bookmark_info(fd, &bookmarks[i])) | ||
312 | return false; | ||
313 | } | ||
314 | |||
315 | return true; | ||
316 | } | ||
317 | |||
318 | bool copy_bookmark_file(int sfd, int dfd, off_t start, off_t size) | ||
319 | { | ||
320 | off_t rsize; | ||
321 | |||
322 | if (rb->lseek(sfd, start, SEEK_SET) < 0) | ||
323 | return false; | ||
324 | |||
325 | while (size > 0) | ||
326 | { | ||
327 | if (size > buffer_size) | ||
328 | rsize = buffer_size; | ||
329 | else | ||
330 | rsize = size; | ||
331 | size -= rsize; | ||
332 | |||
333 | if (rb->read(sfd, buffer, rsize) != rsize || | ||
334 | rb->write(dfd, buffer, rsize) != rsize) | ||
335 | return false; | ||
336 | } | ||
337 | return true; | ||
338 | } | ||