Commit FS#11799 by Alexander Meshcheryakov. Improves the text viewer plugin to write...
[kugel-rb.git] / apps / plugins / text_viewer / tv_bookmark.c
blob5f77d2a92c4f89e7b085600746023f71df13394a
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Gilles Roux
11 * 2003 Garrett Derner
12 * 2010 Yoshihisa Uchida
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.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
23 #include "plugin.h"
24 #include "tv_bookmark.h"
25 #include "tv_pager.h"
26 #include "tv_preferences.h"
28 /* text viewer bookmark functions */
30 enum {
31 TV_BOOKMARK_SYSTEM = 1,
32 TV_BOOKMARK_USER = 2,
36 struct tv_bookmark_info {
37 struct tv_screen_pos pos;
38 unsigned char flag;
41 /* bookmark stored array */
42 struct tv_bookmark_info bookmarks[TV_MAX_BOOKMARKS + 1];
43 static unsigned char bookmark_count;
45 static int tv_compare_screen_pos(const struct tv_screen_pos *p1, const struct tv_screen_pos *p2)
47 if (p1->page != p2->page)
48 return p1->page - p2->page;
50 return p1->line - p2->line;
53 static int bm_comp(const void *a, const void *b)
55 struct tv_bookmark_info *pa;
56 struct tv_bookmark_info *pb;
58 pa = (struct tv_bookmark_info*)a;
59 pb = (struct tv_bookmark_info*)b;
61 return tv_compare_screen_pos(&pa->pos, &pb->pos);
64 static int tv_add_bookmark(const struct tv_screen_pos *pos)
66 if (bookmark_count >= TV_MAX_BOOKMARKS)
67 return -1;
69 bookmarks[bookmark_count].pos = *pos;
70 bookmarks[bookmark_count].flag = TV_BOOKMARK_USER;
72 return bookmark_count++;
75 static void tv_remove_bookmark(int idx)
77 int k;
79 if (idx >= 0 && idx < bookmark_count)
81 for (k = idx + 1; k < bookmark_count; k++)
82 bookmarks[k-1] = bookmarks[k];
84 bookmark_count--;
88 static int tv_find_bookmark(const struct tv_screen_pos *pos)
90 int i;
92 for (i = 0; i < bookmark_count; i++)
94 if (tv_compare_screen_pos(&bookmarks[i].pos, pos) == 0)
95 return i;
97 return -1;
100 static int tv_change_preferences(const struct tv_preferences *oldp)
102 int i;
104 if (oldp)
106 for (i = 0; i < bookmark_count; i++)
107 tv_convert_fpos(bookmarks[i].pos.file_pos, &bookmarks[i].pos);
109 return TV_CALLBACK_OK;
112 bool tv_init_bookmark(unsigned char **buf, size_t *size)
114 (void)buf;
115 (void)size;
117 tv_add_preferences_change_listner(tv_change_preferences);
118 return true;
121 void tv_finalize_bookmark(void)
123 /* no-operation function */
126 int tv_get_bookmark_positions(struct tv_screen_pos *pos_array)
128 int i;
130 for(i = 0; i < bookmark_count; i++)
131 *pos_array++ = bookmarks[i].pos;
133 return bookmark_count;
136 void tv_toggle_bookmark(void)
138 const struct tv_screen_pos *pos = tv_get_screen_pos();
139 int idx = tv_find_bookmark(pos);
141 if (idx < 0)
143 if (tv_add_bookmark(pos) >= 0)
144 rb->splash(HZ/2, "Bookmark add");
145 else
146 rb->splash(HZ/2, "No more add bookmark");
147 return;
149 tv_remove_bookmark(idx);
150 rb->splash(HZ/2, "Bookmark remove");
153 void tv_create_system_bookmark(void)
155 const struct tv_screen_pos *pos = tv_get_screen_pos();
156 int idx = tv_find_bookmark(pos);
158 if (idx >= 0)
159 bookmarks[idx].flag |= TV_BOOKMARK_SYSTEM;
160 else
162 bookmarks[bookmark_count].pos = *pos;
163 bookmarks[bookmark_count].flag = TV_BOOKMARK_SYSTEM;
164 bookmark_count++;
168 static const char* get_bookmark_name(int selected, void * data,
169 char * buffer, size_t buffer_len)
171 (void)data;
172 struct tv_bookmark_info *bookmark = &bookmarks[selected];
173 rb->snprintf(buffer, buffer_len,
174 #ifdef HAVE_LCD_BITMAP
175 "%cPage: %d Line: %d",
176 #else
177 "%cP:%d L:%d",
178 #endif
179 (bookmark->flag & TV_BOOKMARK_SYSTEM)? '*' : ' ',
180 bookmark->pos.page + 1, bookmark->pos.line + 1);
181 return buffer;
184 static int list_action_callback(int action, struct gui_synclist *lists)
186 (void) lists;
187 if (action == ACTION_STD_OK)
188 return ACTION_STD_CANCEL;
189 return action;
192 void tv_select_bookmark(void)
194 int i;
195 struct tv_screen_pos select_pos;
197 for (i = 0; i < bookmark_count; i++)
199 if (bookmarks[i].flag & TV_BOOKMARK_SYSTEM)
200 break;
203 /* if does not find the system bookmark, add the system bookmark. */
204 if (i >= bookmark_count)
205 tv_create_system_bookmark();
207 if (bookmark_count == 1)
208 select_pos = bookmarks[0].pos;
209 else
211 struct simplelist_info info;
213 rb->qsort(bookmarks, bookmark_count, sizeof(struct tv_bookmark_info), bm_comp);
215 rb->simplelist_info_init(&info, "Select bookmark",
216 bookmark_count, bookmarks);
217 info.get_name = get_bookmark_name;
218 info.action_callback = list_action_callback;
219 rb->simplelist_show_list(&info);
221 if (info.selection >= 0 && info.selection < bookmark_count)
222 select_pos = bookmarks[info.selection].pos;
223 else
225 /* when does not select any bookmarks, move to the current page */
226 tv_copy_screen_pos(&select_pos);
228 if (select_pos.file_pos == 0)
229 rb->splash(HZ, "Start the first page");
230 else
231 rb->splash(HZ, "Return to the current page");
235 /* deletes the system bookmark */
236 for (i = 0; i < bookmark_count; i++)
238 if ((bookmarks[i].flag &= TV_BOOKMARK_USER) == 0)
240 tv_remove_bookmark(i);
241 break;
245 /* move to the select position */
246 if (preferences->vertical_scroll_mode == VS_PAGE)
247 select_pos.line = 0;
249 tv_move_screen(select_pos.page, select_pos.line, SEEK_SET);
252 /* serialize or deserialize of the bookmark array */
253 static bool tv_read_bookmark_info(int fd, struct tv_bookmark_info *b)
255 unsigned char buf[SERIALIZE_BOOKMARK_SIZE];
257 if (rb->read(fd, buf, sizeof(buf)) < 0)
258 return false;
260 b->pos.file_pos = (buf[0] << 24)|(buf[1] << 16)|(buf[2] << 8)|buf[3];
261 b->pos.page = (buf[4] << 8)|buf[5];
262 b->pos.line = buf[6];
263 b->flag = buf[7];
265 return true;
268 bool tv_deserialize_bookmarks(int fd)
270 int i;
271 bool res = true;
273 if (rb->read(fd, &bookmark_count, 1) < 0)
274 return false;
276 for (i = 0; i < bookmark_count; i++)
278 if (!tv_read_bookmark_info(fd, &bookmarks[i]))
280 res = false;
281 break;
285 bookmark_count = i;
286 return res;
289 static void tv_write_bookmark_info(unsigned char *p, const struct tv_bookmark_info *b)
291 *p++ = b->pos.file_pos >> 24;
292 *p++ = b->pos.file_pos >> 16;
293 *p++ = b->pos.file_pos >> 8;
294 *p++ = b->pos.file_pos;
296 *p++ = b->pos.page >> 8;
297 *p++ = b->pos.page;
299 *p++ = b->pos.line;
300 *p = b->flag;
303 int tv_serialize_bookmarks(unsigned char *buf)
305 int i;
307 buf[0] = bookmark_count;
309 for (i = 0; i < bookmark_count; i++)
311 tv_write_bookmark_info(buf + i * SERIALIZE_BOOKMARK_SIZE + 1, &bookmarks[i]);
313 return i * SERIALIZE_BOOKMARK_SIZE + 1;