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.zip rockbox-fdba8404503af0448586615330a7b27f2ced531c.tar.gz rockbox-fdba8404503af0448586615330a7b27f2ced531c.tar.bz2 rockbox-fdba8404503af0448586615330a7b27f2ced531c.tar.xz | |
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 0000000..6dc66ef --- /dev/null +++ b/apps/plugins/text_viewer/tv_reader.c @@ -0,0 +1,191 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002 Gilles Roux + * 2003 Garrett Derner + * 2010 Yoshihisa Uchida + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "plugin.h" +#include "tv_preferences.h" +#include "tv_reader.h" + +#if PLUGIN_BUFFER_SIZE < 0x10000 +#define TV_MIN_BLOCK_SIZE 0x800 +#else +#define TV_MIN_BLOCK_SIZE 0x1000 +#endif + +/* UTF-8 BOM */ +#define BOM "\xef\xbb\xbf" +#define BOM_SIZE 3 + +static int fd = -1; + +static off_t file_pos; +static off_t start_file_pos; + +static off_t file_size; + +static unsigned char *reader_buffer; +static ssize_t buffer_size; +static ssize_t block_size; + +static ssize_t buf_pos; +static ssize_t read_size; + +off_t tv_get_file_size(void) +{ + return file_size; +} + +bool tv_is_eof(void) +{ + return (file_pos + buf_pos >= file_size); +} + +off_t tv_get_current_file_pos(void) +{ + return file_pos + buf_pos; +} + +const unsigned char *tv_get_buffer(ssize_t *bufsize) +{ + *bufsize = read_size - buf_pos; + return reader_buffer + buf_pos; +} + +static ssize_t tv_read(unsigned char *buf, ssize_t reqsize) +{ + if (buf - reader_buffer + reqsize > buffer_size) + reqsize = buffer_size - (buf - reader_buffer); + + return rb->read(fd, buf, reqsize); +} + +void tv_seek(off_t offset, int whence) +{ + ssize_t size; + + switch (whence) + { + case SEEK_SET: + if (offset >= file_pos && offset < file_pos + read_size) + { + buf_pos = offset - file_pos; + return; + } + file_pos = offset; + break; + + case SEEK_CUR: + buf_pos += offset; + if (buf_pos >= 0 && buf_pos < read_size) + { + if (buf_pos > block_size) + { + buf_pos -= block_size; + file_pos += block_size; + size = read_size - block_size; + rb->memcpy(reader_buffer, reader_buffer + block_size, size); + read_size = tv_read(reader_buffer + block_size, block_size); + if (read_size < 0) + read_size = 0; + + read_size += size; + } + return; + } + file_pos += buf_pos; + whence = SEEK_SET; + break; + + default: + return; + break; + } + + if (whence == SEEK_SET) + { + if (file_pos < 0) + file_pos = 0; + else if (file_pos > file_size) + file_pos = file_size; + + rb->lseek(fd, file_pos + start_file_pos, SEEK_SET); + buf_pos = 0; + read_size = tv_read(reader_buffer, buffer_size); + } +} + +static void tv_change_preferences(const struct tv_preferences *oldp) +{ + unsigned char bom[BOM_SIZE]; + const struct tv_preferences *prefs = tv_get_preferences(); + int cur_start_file_pos = start_file_pos; + off_t cur_file_pos = file_pos + buf_pos; + + file_pos = 0; + buf_pos = 0; + read_size = 0; + start_file_pos = 0; + + /* open the new file */ + if (oldp == NULL || rb->strcmp(oldp->file_name, prefs->file_name)) + { + if (fd >= 0) + rb->close(fd); + + fd = rb->open(prefs->file_name, O_RDONLY); + if (fd < 0) + return; + } + + /* + * When a file is UTF-8 file with BOM, if prefs.encoding is UTF-8, + * then file size decreases only BOM_SIZE. + */ + if (prefs->encoding == UTF_8) + { + rb->lseek(fd, 0, SEEK_SET); + rb->read(fd, bom, BOM_SIZE); + if (rb->memcmp(bom, BOM, BOM_SIZE) == 0) + start_file_pos = BOM_SIZE; + } + + file_size = rb->filesize(fd) - start_file_pos; + tv_seek(cur_file_pos + cur_start_file_pos - start_file_pos, SEEK_SET); +} + +bool tv_init_reader(unsigned char *buf, size_t bufsize, size_t *used_size) +{ + if (bufsize < 2 * TV_MIN_BLOCK_SIZE) + return false; + + reader_buffer = buf; + block_size = bufsize / 2; + buffer_size = 2 * block_size; + *used_size = buffer_size; + tv_add_preferences_change_listner(tv_change_preferences); + return true; +} + +void tv_finalize_reader(void) +{ + if (fd >= 0) + rb->close(fd); +} |