diff options
author | Yoshihisa Uchida <uchida@rockbox.org> | 2010-06-05 10:30:08 +0000 |
---|---|---|
committer | Yoshihisa Uchida <uchida@rockbox.org> | 2010-06-05 10:30:08 +0000 |
commit | fdba8404503af0448586615330a7b27f2ced531c (patch) | |
tree | bb15677a7a720675ac2666f11e62042f3b2639ad /apps/plugins/text_viewer/tv_reader.c | |
parent | 991e92fd3dc15f1e365761264c26305559ddb0a4 (diff) | |
download | rockbox-fdba8404503af0448586615330a7b27f2ced531c.tar.gz rockbox-fdba8404503af0448586615330a7b27f2ced531c.zip |
reworks text viewer plugin. (FS#11209)
new text viewer plugin: text_viewer.rock.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26571 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/text_viewer/tv_reader.c')
-rw-r--r-- | apps/plugins/text_viewer/tv_reader.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/apps/plugins/text_viewer/tv_reader.c b/apps/plugins/text_viewer/tv_reader.c new file mode 100644 index 0000000000..6dc66ef567 --- /dev/null +++ b/apps/plugins/text_viewer/tv_reader.c | |||
@@ -0,0 +1,191 @@ | |||
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_preferences.h" | ||
25 | #include "tv_reader.h" | ||
26 | |||
27 | #if PLUGIN_BUFFER_SIZE < 0x10000 | ||
28 | #define TV_MIN_BLOCK_SIZE 0x800 | ||
29 | #else | ||
30 | #define TV_MIN_BLOCK_SIZE 0x1000 | ||
31 | #endif | ||
32 | |||
33 | /* UTF-8 BOM */ | ||
34 | #define BOM "\xef\xbb\xbf" | ||
35 | #define BOM_SIZE 3 | ||
36 | |||
37 | static int fd = -1; | ||
38 | |||
39 | static off_t file_pos; | ||
40 | static off_t start_file_pos; | ||
41 | |||
42 | static off_t file_size; | ||
43 | |||
44 | static unsigned char *reader_buffer; | ||
45 | static ssize_t buffer_size; | ||
46 | static ssize_t block_size; | ||
47 | |||
48 | static ssize_t buf_pos; | ||
49 | static ssize_t read_size; | ||
50 | |||
51 | off_t tv_get_file_size(void) | ||
52 | { | ||
53 | return file_size; | ||
54 | } | ||
55 | |||
56 | bool tv_is_eof(void) | ||
57 | { | ||
58 | return (file_pos + buf_pos >= file_size); | ||
59 | } | ||
60 | |||
61 | off_t tv_get_current_file_pos(void) | ||
62 | { | ||
63 | return file_pos + buf_pos; | ||
64 | } | ||
65 | |||
66 | const unsigned char *tv_get_buffer(ssize_t *bufsize) | ||
67 | { | ||
68 | *bufsize = read_size - buf_pos; | ||
69 | return reader_buffer + buf_pos; | ||
70 | } | ||
71 | |||
72 | static ssize_t tv_read(unsigned char *buf, ssize_t reqsize) | ||
73 | { | ||
74 | if (buf - reader_buffer + reqsize > buffer_size) | ||
75 | reqsize = buffer_size - (buf - reader_buffer); | ||
76 | |||
77 | return rb->read(fd, buf, reqsize); | ||
78 | } | ||
79 | |||
80 | void tv_seek(off_t offset, int whence) | ||
81 | { | ||
82 | ssize_t size; | ||
83 | |||
84 | switch (whence) | ||
85 | { | ||
86 | case SEEK_SET: | ||
87 | if (offset >= file_pos && offset < file_pos + read_size) | ||
88 | { | ||
89 | buf_pos = offset - file_pos; | ||
90 | return; | ||
91 | } | ||
92 | file_pos = offset; | ||
93 | break; | ||
94 | |||
95 | case SEEK_CUR: | ||
96 | buf_pos += offset; | ||
97 | if (buf_pos >= 0 && buf_pos < read_size) | ||
98 | { | ||
99 | if (buf_pos > block_size) | ||
100 | { | ||
101 | buf_pos -= block_size; | ||
102 | file_pos += block_size; | ||
103 | size = read_size - block_size; | ||
104 | rb->memcpy(reader_buffer, reader_buffer + block_size, size); | ||
105 | read_size = tv_read(reader_buffer + block_size, block_size); | ||
106 | if (read_size < 0) | ||
107 | read_size = 0; | ||
108 | |||
109 | read_size += size; | ||
110 | } | ||
111 | return; | ||
112 | } | ||
113 | file_pos += buf_pos; | ||
114 | whence = SEEK_SET; | ||
115 | break; | ||
116 | |||
117 | default: | ||
118 | return; | ||
119 | break; | ||
120 | } | ||
121 | |||
122 | if (whence == SEEK_SET) | ||
123 | { | ||
124 | if (file_pos < 0) | ||
125 | file_pos = 0; | ||
126 | else if (file_pos > file_size) | ||
127 | file_pos = file_size; | ||
128 | |||
129 | rb->lseek(fd, file_pos + start_file_pos, SEEK_SET); | ||
130 | buf_pos = 0; | ||
131 | read_size = tv_read(reader_buffer, buffer_size); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | static void tv_change_preferences(const struct tv_preferences *oldp) | ||
136 | { | ||
137 | unsigned char bom[BOM_SIZE]; | ||
138 | const struct tv_preferences *prefs = tv_get_preferences(); | ||
139 | int cur_start_file_pos = start_file_pos; | ||
140 | off_t cur_file_pos = file_pos + buf_pos; | ||
141 | |||
142 | file_pos = 0; | ||
143 | buf_pos = 0; | ||
144 | read_size = 0; | ||
145 | start_file_pos = 0; | ||
146 | |||
147 | /* open the new file */ | ||
148 | if (oldp == NULL || rb->strcmp(oldp->file_name, prefs->file_name)) | ||
149 | { | ||
150 | if (fd >= 0) | ||
151 | rb->close(fd); | ||
152 | |||
153 | fd = rb->open(prefs->file_name, O_RDONLY); | ||
154 | if (fd < 0) | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * When a file is UTF-8 file with BOM, if prefs.encoding is UTF-8, | ||
160 | * then file size decreases only BOM_SIZE. | ||
161 | */ | ||
162 | if (prefs->encoding == UTF_8) | ||
163 | { | ||
164 | rb->lseek(fd, 0, SEEK_SET); | ||
165 | rb->read(fd, bom, BOM_SIZE); | ||
166 | if (rb->memcmp(bom, BOM, BOM_SIZE) == 0) | ||
167 | start_file_pos = BOM_SIZE; | ||
168 | } | ||
169 | |||
170 | file_size = rb->filesize(fd) - start_file_pos; | ||
171 | tv_seek(cur_file_pos + cur_start_file_pos - start_file_pos, SEEK_SET); | ||
172 | } | ||
173 | |||
174 | bool tv_init_reader(unsigned char *buf, size_t bufsize, size_t *used_size) | ||
175 | { | ||
176 | if (bufsize < 2 * TV_MIN_BLOCK_SIZE) | ||
177 | return false; | ||
178 | |||
179 | reader_buffer = buf; | ||
180 | block_size = bufsize / 2; | ||
181 | buffer_size = 2 * block_size; | ||
182 | *used_size = buffer_size; | ||
183 | tv_add_preferences_change_listner(tv_change_preferences); | ||
184 | return true; | ||
185 | } | ||
186 | |||
187 | void tv_finalize_reader(void) | ||
188 | { | ||
189 | if (fd >= 0) | ||
190 | rb->close(fd); | ||
191 | } | ||