1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Gilles Roux
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 ****************************************************************************/
25 #include "tv_preferences.h"
26 #include "tv_reader.h"
27 #include "tv_window.h"
29 #if PLUGIN_BUFFER_SIZE < 0x13000
30 #define TV_MAX_PAGE 999
32 #define TV_MAX_PAGE 9999
35 static unsigned char pager_buffer
[4 * TV_MAX_PAGE
];
37 static struct tv_screen_pos cur_pos
;
39 static int parse_page
;
43 static int lines_per_page
;
45 static int line_pos
[LCD_HEIGHT
/ 2];
46 static int parse_page
;
47 static int parse_top_line
;
48 static int parse_lines
;
50 static void set_uint32(unsigned char *p
, unsigned int val
)
53 *p
++ = (val
>> 8) & 0xff;
54 *p
++ = (val
>> 16) & 0xff;
55 *p
= (val
>> 24) & 0xff;
58 static unsigned int get_uint32(const unsigned char *p
)
60 return (((((p
[3] << 8) | p
[2]) << 8) | p
[1]) << 8) | p
[0];
63 static void tv_set_fpos(int page
, off_t pos
)
65 if (page
>= 0 && page
<= max_page
)
66 set_uint32(pager_buffer
+ page
* 4, pos
);
69 static off_t
tv_get_fpos(int page
)
71 if (page
>= 0 && page
<= max_page
)
72 return get_uint32(pager_buffer
+ page
* 4);
76 static int tv_change_preferences(const struct tv_preferences
*oldp
)
83 max_page
= TV_MAX_PAGE
- 1;
84 tv_set_fpos(cur_pos
.page
, 0);
86 return TV_CALLBACK_OK
;
89 bool tv_init_pager(unsigned char **buf
, size_t *size
)
91 tv_set_screen_pos(&cur_pos
);
92 tv_add_preferences_change_listner(tv_change_preferences
);
94 /* valid page: 0, ..., max_page. */
95 max_page
= TV_MAX_PAGE
- 1;
99 return tv_init_reader(buf
, size
);
102 void tv_finalize_pager(void)
104 tv_finalize_reader();
107 void tv_reset_line_positions(void)
109 parse_page
= cur_pos
.page
;
110 parse_top_line
= cur_pos
.line
;
114 void tv_move_next_line(int size
)
118 tv_seek(size
, SEEK_CUR
);
119 cur_pos
.file_pos
= tv_get_current_file_pos();
122 line_pos
[cur_pos
.line
] = line_pos
[cur_pos
.line
- 1] + size
;
126 int tv_get_line_positions(int offset
)
128 int line
= cur_pos
.line
+ offset
;
132 else if (line
> parse_lines
)
135 return line_pos
[parse_top_line
+ line
] - line_pos
[parse_top_line
];
138 void tv_new_page(void)
140 parse_page
= cur_pos
.page
;
141 if (cur_pos
.page
== last_page
&& last_page
< max_page
)
144 tv_set_fpos(++last_page
, tv_get_current_file_pos());
146 max_page
= last_page
;
149 if (++cur_pos
.page
> max_page
)
150 cur_pos
.page
= max_page
;
152 lines_per_page
= cur_pos
.line
;
156 static void tv_seek_page(int offset
, int whence
)
158 int new_page
= offset
;
163 new_page
+= cur_pos
.page
;
168 new_page
+= last_page
;
177 else if (new_page
>= last_page
)
178 new_page
= last_page
;
180 cur_pos
.page
= new_page
;
182 cur_pos
.file_pos
= tv_get_fpos(new_page
);
183 tv_seek(cur_pos
.file_pos
, SEEK_SET
);
186 static bool tv_create_line_positions(void)
194 tv_reset_line_positions();
195 res
= tv_traverse_lines();
196 lines_per_page
= cur_pos
.line
;
202 void tv_convert_fpos(off_t fpos
, struct tv_screen_pos
*pos
)
206 for (i
= 0; i
< last_page
; i
++)
208 if (tv_get_fpos(i
) <= fpos
&& tv_get_fpos(i
+ 1) > fpos
)
214 pos
->file_pos
= fpos
;
216 if (tv_get_fpos(i
) == fpos
)
219 tv_seek_page(i
, SEEK_SET
);
220 while (tv_create_line_positions() && cur_pos
.file_pos
< fpos
)
221 rb
->splashf(0, "converting %ld%%...", 100 * cur_pos
.file_pos
/ fpos
);
225 tv_seek_page(cur_pos
.page
, SEEK_SET
);
226 for (i
= 0; i
< lines_per_page
; i
++)
228 if (cur_pos
.file_pos
+ tv_get_line_positions(i
) >= fpos
)
232 pos
->page
= cur_pos
.page
;
236 static void tv_seek_to_bottom_line(void)
238 off_t total_size
= tv_get_file_size();
240 tv_seek_page(0, SEEK_END
);
241 while (tv_create_line_positions())
242 rb
->splashf(0, "loading %ld%%...", 100 * cur_pos
.file_pos
/ total_size
);
244 cur_pos
.line
= lines_per_page
- 1;
247 void tv_move_screen(int page_offset
, int line_offset
, int whence
)
249 struct tv_screen_pos new_pos
;
255 cur_pos
.page
+= page_offset
;
256 cur_pos
.line
+= line_offset
;
259 cur_pos
.page
= page_offset
;
260 cur_pos
.line
= line_offset
;
263 tv_seek_to_bottom_line();
264 cur_pos
.page
+= page_offset
;
265 cur_pos
.line
+= line_offset
;
272 if (cur_pos
.page
< 0 || (cur_pos
.page
== 0 && cur_pos
.line
< 0))
274 tv_seek_page(0, SEEK_SET
);
277 else if (cur_pos
.page
> max_page
)
279 tv_seek_page(max_page
, SEEK_SET
);
284 if (cur_pos
.line
< 0)
287 tv_seek_page(new_pos
.page
, SEEK_SET
);
288 while (cur_pos
.page
< new_pos
.page
&& tv_create_line_positions())
289 rb
->splashf(0, "loading %d%%...", 100 * cur_pos
.page
/ new_pos
.page
);
291 if (new_pos
.line
== 0)
294 if (parse_page
== cur_pos
.page
)
296 if (cur_pos
.page
< max_page
&& new_pos
.line
== lines_per_page
)
298 tv_seek(line_pos
[lines_per_page
], SEEK_CUR
);
299 cur_pos
.file_pos
+= line_pos
[lines_per_page
];
301 for (i
= 0; i
< parse_lines
; i
++)
302 line_pos
[i
] = line_pos
[i
+ lines_per_page
] - line_pos
[lines_per_page
];
312 tv_create_line_positions();
313 tv_seek_page(new_pos
.page
, SEEK_SET
);
316 cur_pos
.line
= new_pos
.line
;
317 if (cur_pos
.line
>= lines_per_page
)
318 cur_pos
.line
= lines_per_page
- 1;
319 else if (cur_pos
.line
< 0)
321 cur_pos
.line
+= lines_per_page
;
322 if (cur_pos
.line
< 0)
325 tv_seek(line_pos
[cur_pos
.line
], SEEK_CUR
);
326 cur_pos
.file_pos
+= line_pos
[cur_pos
.line
];