summaryrefslogtreecommitdiff
path: root/apps/plugins/text_viewer/tv_bookmark.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/text_viewer/tv_bookmark.c')
-rw-r--r--apps/plugins/text_viewer/tv_bookmark.c302
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
30enum {
31 TV_BOOKMARK_SYSTEM = 1,
32 TV_BOOKMARK_USER = 2,
33};
34
35#define SERIALIZE_BOOKMARK_SIZE 8
36
37struct tv_bookmark_info {
38 struct tv_screen_pos pos;
39 unsigned char flag;
40};
41
42/* bookmark stored array */
43struct tv_bookmark_info bookmarks[TV_MAX_BOOKMARKS + 1];
44static unsigned char bookmark_count;
45
46static int tv_compare_screen_pos(const struct tv_screen_pos *p1, const struct tv_screen_pos *p2)
47{
48 if (p1->page != p2->page)
49 return p1->page - p2->page;
50
51 return p1->line - p2->line;
52}
53
54static int bm_comp(const void *a, const void *b)
55{
56 struct tv_bookmark_info *pa;
57 struct tv_bookmark_info *pb;
58
59 pa = (struct tv_bookmark_info*)a;
60 pb = (struct tv_bookmark_info*)b;
61
62 return tv_compare_screen_pos(&pa->pos, &pb->pos);
63}
64
65static int tv_add_bookmark(const struct tv_screen_pos *pos)
66{
67 if (bookmark_count >= TV_MAX_BOOKMARKS)
68 return -1;
69
70 bookmarks[bookmark_count].pos = *pos;
71 bookmarks[bookmark_count].flag = TV_BOOKMARK_USER;
72
73 return bookmark_count++;
74}
75
76static void tv_remove_bookmark(int idx)
77{
78 int k;
79
80 if (idx >= 0 && idx < bookmark_count)
81 {
82 for (k = idx + 1; k < bookmark_count; k++)
83 bookmarks[k-1] = bookmarks[k];
84
85 bookmark_count--;
86 }
87}
88
89static int tv_find_bookmark(const struct tv_screen_pos *pos)
90{
91 int i;
92
93 for (i = 0; i < bookmark_count; i++)
94 {
95 if (tv_compare_screen_pos(&bookmarks[i].pos, pos) == 0)
96 return i;
97 }
98 return -1;
99}
100
101static void tv_change_preferences(const struct tv_preferences *oldp)
102{
103 int i;
104
105 if (oldp == NULL)
106 return;
107
108 for (i = 0; i < bookmark_count; i++)
109 tv_convert_fpos(bookmarks[i].pos.file_pos, &bookmarks[i].pos);
110}
111
112void tv_init_bookmark(void)
113{
114 tv_add_preferences_change_listner(tv_change_preferences);
115}
116
117int tv_get_bookmark_positions(struct tv_screen_pos *pos_array)
118{
119 int i;
120
121 for(i = 0; i < bookmark_count; i++)
122 *pos_array++ = bookmarks[i].pos;
123
124 return bookmark_count;
125}
126
127void tv_toggle_bookmark(void)
128{
129 const struct tv_screen_pos *pos = tv_get_screen_pos();
130 int idx = tv_find_bookmark(pos);
131
132 if (idx < 0)
133 {
134 if (tv_add_bookmark(pos) >= 0)
135 rb->splash(HZ/2, "Bookmark add");
136 else
137 rb->splash(HZ/2, "No more add bookmark");
138 return;
139 }
140 tv_remove_bookmark(idx);
141 rb->splash(HZ/2, "Bookmark remove");
142}
143
144void tv_create_system_bookmark(void)
145{
146 const struct tv_screen_pos *pos = tv_get_screen_pos();
147 int idx = tv_find_bookmark(pos);
148
149 if (idx >= 0)
150 bookmarks[idx].flag |= TV_BOOKMARK_SYSTEM;
151 else
152 {
153 bookmarks[bookmark_count].pos = *pos;
154 bookmarks[bookmark_count].flag = TV_BOOKMARK_SYSTEM;
155 bookmark_count++;
156 }
157}
158
159void tv_select_bookmark(void)
160{
161 int i;
162 struct tv_screen_pos select_pos;
163
164 for (i = 0; i < bookmark_count; i++)
165 {
166 if (bookmarks[i].flag & TV_BOOKMARK_SYSTEM)
167 break;
168 }
169
170 /* if does not find the system bookmark, add the system bookmark. */
171 if (i >= bookmark_count)
172 tv_create_system_bookmark();
173
174 if (bookmark_count == 1)
175 select_pos = bookmarks[0].pos;
176 else
177 {
178 int selected = -1;
179 struct opt_items items[bookmark_count];
180 unsigned char names[bookmark_count][24];
181
182 rb->qsort(bookmarks, bookmark_count, sizeof(struct tv_bookmark_info), bm_comp);
183
184 for (i = 0; i < bookmark_count; i++)
185 {
186 rb->snprintf(names[i], sizeof(names[0]),
187#if CONFIG_KEYPAD != PLAYER_PAD
188 "%cPage: %d Line: %d",
189#else
190 "%cP:%d L:%d",
191#endif
192 (bookmarks[i].flag & TV_BOOKMARK_SYSTEM)? '*' : ' ',
193 bookmarks[i].pos.page + 1,
194 bookmarks[i].pos.line + 1);
195 items[i].string = names[i];
196 items[i].voice_id = -1;
197 }
198
199 rb->set_option("Select bookmark", &selected, INT, items,
200 bookmark_count, NULL);
201
202 if (selected >= 0 && selected < bookmark_count)
203 select_pos = bookmarks[selected].pos;
204 else
205 {
206 /* when does not select any bookmarks, move to the current page */
207 tv_copy_screen_pos(&select_pos);
208
209 if (select_pos.file_pos == 0)
210 rb->splash(HZ, "Start the first page");
211 else
212 rb->splash(HZ, "Return to the current page");
213 }
214 }
215
216 /* deletes the system bookmark */
217 for (i = 0; i < bookmark_count; i++)
218 {
219 if ((bookmarks[i].flag &= TV_BOOKMARK_USER) == 0)
220 {
221 tv_remove_bookmark(i);
222 break;
223 }
224 }
225
226 /* move to the select position */
227 if (tv_get_preferences()->scroll_mode == PAGE)
228 select_pos.line = 0;
229
230 tv_move_screen(select_pos.page, select_pos.line, SEEK_SET);
231}
232
233/* serialize or deserialize of the bookmark array */
234static bool tv_read_bookmark_info(int fd, struct tv_bookmark_info *b)
235{
236 unsigned char buf[SERIALIZE_BOOKMARK_SIZE];
237
238 if (rb->read(fd, buf, sizeof(buf)) < 0)
239 return false;
240
241 b->pos.file_pos = (buf[0] << 24)|(buf[1] << 16)|(buf[2] << 8)|buf[3];
242 b->pos.page = (buf[4] << 8)|buf[5];
243 b->pos.line = buf[6];
244 b->flag = buf[7];
245
246 return true;
247}
248
249bool tv_deserialize_bookmarks(int fd)
250{
251 int i;
252 bool res = true;
253
254 if (rb->read(fd, &bookmark_count, 1) < 0)
255 return false;
256
257 for (i = 0; i < bookmark_count; i++)
258 {
259 if (!tv_read_bookmark_info(fd, &bookmarks[i]))
260 {
261 res = false;
262 break;
263 }
264 }
265
266 bookmark_count = i;
267 return res;
268}
269
270static bool tv_write_bookmark_info(int fd, const struct tv_bookmark_info *b)
271{
272 unsigned char buf[SERIALIZE_BOOKMARK_SIZE];
273 unsigned char *p = buf;
274
275 *p++ = b->pos.file_pos >> 24;
276 *p++ = b->pos.file_pos >> 16;
277 *p++ = b->pos.file_pos >> 8;
278 *p++ = b->pos.file_pos;
279
280 *p++ = b->pos.page >> 8;
281 *p++ = b->pos.page;
282
283 *p++ = b->pos.line;
284 *p = b->flag;
285
286 return (rb->write(fd, buf, SERIALIZE_BOOKMARK_SIZE) >= 0);
287}
288
289int tv_serialize_bookmarks(int fd)
290{
291 int i;
292
293 if (rb->write(fd, &bookmark_count, 1) < 0)
294 return 0;
295
296 for (i = 0; i < bookmark_count; i++)
297 {
298 if (!tv_write_bookmark_info(fd, &bookmarks[i]))
299 break;
300 }
301 return i * SERIALIZE_BOOKMARK_SIZE + 1;
302}