935 lines
24 KiB
C
935 lines
24 KiB
C
/*
|
|
* Copyright (c) 1997-2006 Motoyuki Kasahara
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the project nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "build-pre.h"
|
|
#include "eb.h"
|
|
#include "error.h"
|
|
#include "font.h"
|
|
#include "build-post.h"
|
|
|
|
/*
|
|
* Book ID counter.
|
|
*/
|
|
static EB_Book_Code book_counter = 0;
|
|
|
|
/*
|
|
* Unexported functions.
|
|
*/
|
|
static void eb_fix_misleaded_book(EB_Book *book);
|
|
static EB_Error_Code eb_load_catalog(EB_Book *book);
|
|
static EB_Error_Code eb_load_catalog_eb(EB_Book *book,
|
|
const char *catalog_path);
|
|
static EB_Error_Code eb_load_catalog_epwing(EB_Book *book,
|
|
const char *catalog_path);
|
|
static Zio_Code eb_get_hint_zio_code(int catalog_hint_value);
|
|
static void eb_load_language(EB_Book *book);
|
|
|
|
/*
|
|
* Initialize `book'.
|
|
*/
|
|
void
|
|
eb_initialize_book(EB_Book *book)
|
|
{
|
|
LOG(("in: eb_initialize_book()"));
|
|
|
|
book->code = EB_BOOK_NONE;
|
|
book->disc_code = EB_DISC_INVALID;
|
|
book->character_code = EB_CHARCODE_INVALID;
|
|
book->path = NULL;
|
|
book->path_length = 0;
|
|
book->subbooks = NULL;
|
|
book->subbook_current = NULL;
|
|
eb_initialize_text_context(book);
|
|
eb_initialize_binary_context(book);
|
|
eb_initialize_search_contexts(book);
|
|
eb_initialize_binary_context(book);
|
|
|
|
LOG(("out: eb_initialize_book()"));
|
|
}
|
|
|
|
/*
|
|
* Bind `book' to `path'.
|
|
*/
|
|
EB_Error_Code
|
|
eb_bind(EB_Book *book, const char *path)
|
|
{
|
|
EB_Error_Code error_code;
|
|
char temporary_path[EB_MAX_PATH_LENGTH + 1];
|
|
|
|
LOG(("in: eb_bind(path=%s)", path));
|
|
|
|
/*
|
|
* Clear the book if the book has already been bound.
|
|
*/
|
|
if (book->path != NULL) {
|
|
eb_finalize_book(book);
|
|
eb_initialize_book(book);
|
|
}
|
|
|
|
/*
|
|
* Assign a book code.
|
|
*/
|
|
book->code = book_counter++;
|
|
|
|
/*
|
|
* Set the path of the book.
|
|
* The length of the file name "<path>/subdir/subsubdir/file.ebz;1" must
|
|
* be EB_MAX_PATH_LENGTH maximum.
|
|
*/
|
|
if (EB_MAX_PATH_LENGTH < strlen(path)) {
|
|
error_code = EB_ERR_TOO_LONG_FILE_NAME;
|
|
goto failed;
|
|
}
|
|
strcpy(temporary_path, path);
|
|
error_code = eb_canonicalize_path_name(temporary_path);
|
|
if (error_code != EB_SUCCESS)
|
|
goto failed;
|
|
|
|
book->path_length = strlen(temporary_path);
|
|
if (EB_MAX_PATH_LENGTH
|
|
< book->path_length + 1 + EB_MAX_RELATIVE_PATH_LENGTH) {
|
|
error_code = EB_ERR_TOO_LONG_FILE_NAME;
|
|
goto failed;
|
|
}
|
|
|
|
book->path = (char *)malloc(book->path_length + 1);
|
|
if (book->path == NULL) {
|
|
error_code = EB_ERR_MEMORY_EXHAUSTED;
|
|
goto failed;
|
|
}
|
|
strcpy(book->path, temporary_path);
|
|
|
|
/*
|
|
* Read information from the `LANGUAGE' file.
|
|
* If failed to initialize, JIS X 0208 is assumed.
|
|
*/
|
|
eb_load_language(book);
|
|
|
|
/*
|
|
* Read information from the `CATALOG(S)' file.
|
|
*/
|
|
error_code = eb_load_catalog(book);
|
|
if (error_code != EB_SUCCESS)
|
|
goto failed;
|
|
|
|
LOG(("out: eb_bind(book=%d) = %s", (int)book->code,
|
|
eb_error_string(EB_SUCCESS)));
|
|
return EB_SUCCESS;
|
|
|
|
/*
|
|
* An error occurs...
|
|
*/
|
|
failed:
|
|
eb_finalize_book(book);
|
|
LOG(("out: eb_bind() = %s", eb_error_string(error_code)));
|
|
return error_code;
|
|
}
|
|
|
|
|
|
/*
|
|
* Finish using `book'.
|
|
*/
|
|
void
|
|
eb_finalize_book(EB_Book *book)
|
|
{
|
|
LOG(("in: eb_finalize_book(book=%d)", (int)book->code));
|
|
|
|
eb_unset_subbook(book);
|
|
|
|
if (book->subbooks != NULL) {
|
|
eb_finalize_subbooks(book);
|
|
free(book->subbooks);
|
|
book->subbooks = NULL;
|
|
}
|
|
|
|
book->subbook_current = NULL;
|
|
eb_finalize_text_context(book);
|
|
eb_finalize_binary_context(book);
|
|
eb_finalize_search_contexts(book);
|
|
eb_finalize_binary_context(book);
|
|
|
|
if (book->path != NULL)
|
|
free(book->path);
|
|
|
|
book->code = EB_BOOK_NONE;
|
|
book->disc_code = EB_DISC_INVALID;
|
|
book->character_code = EB_CHARCODE_INVALID;
|
|
book->path = NULL;
|
|
book->path_length = 0;
|
|
|
|
LOG(("out: eb_finalize_book()"));
|
|
}
|
|
|
|
|
|
/*
|
|
* There are some books that EB Library sets wrong character code of
|
|
* the book. They are written in JIS X 0208, but the library sets
|
|
* ISO 8859-1.
|
|
*
|
|
* We fix the character of the books. The following table lists
|
|
* titles of the first subbook in those books.
|
|
*/
|
|
static const char * const misleaded_book_table[] = {
|
|
/* SONY DataDiskMan (DD-DR1) accessories. */
|
|
"%;%s%A%e%j!\\%S%8%M%9!\\%/%i%&%s",
|
|
|
|
/* Shin Eiwa Waei Chujiten (earliest edition) */
|
|
"8&5f<R!!?71QOBCf<-E5",
|
|
|
|
/* EB Kagakugijutsu Yougo Daijiten (YRRS-048) */
|
|
"#E#B2J3X5;=QMQ8lBg<-E5",
|
|
|
|
/* Nichi-Ei-Futsu Jiten (YRRS-059) */
|
|
"#E#N#G!?#J#A#N!J!\\#F#R#E!K",
|
|
|
|
/* Japanese-English-Spanish Jiten (YRRS-060) */
|
|
"#E#N#G!?#J#A#N!J!\\#S#P#A!K",
|
|
|
|
/* Panasonic KX-EBP2 accessories. */
|
|
"%W%m%7!<%I1QOB!&OB1Q<-E5",
|
|
NULL
|
|
};
|
|
|
|
/*
|
|
* Fix chachacter-code of the book if misleaded.
|
|
*/
|
|
static void
|
|
eb_fix_misleaded_book(EB_Book *book)
|
|
{
|
|
const char * const * misleaded;
|
|
EB_Subbook *subbook;
|
|
int i;
|
|
|
|
LOG(("in: eb_fix_misleaded_book(book=%d)", (int)book->code));
|
|
|
|
for (misleaded = misleaded_book_table; *misleaded != NULL; misleaded++) {
|
|
if (strcmp(book->subbooks[0].title, *misleaded) == 0) {
|
|
book->character_code = EB_CHARCODE_JISX0208;
|
|
for (i = 0, subbook = book->subbooks; i < book->subbook_count;
|
|
i++, subbook++) {
|
|
eb_jisx0208_to_euc(subbook->title, subbook->title);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
LOG(("out: eb_fix_misleaded_book()"));
|
|
}
|
|
|
|
/*
|
|
* Read information from the `CATALOG(S)' file in 'book'.
|
|
* Return EB_SUCCESS if it succeeds, error-code otherwise.
|
|
*/
|
|
static EB_Error_Code
|
|
eb_load_catalog(EB_Book *book)
|
|
{
|
|
EB_Error_Code error_code;
|
|
char catalog_file_name[EB_MAX_FILE_NAME_LENGTH + 1];
|
|
char catalog_path_name[EB_MAX_PATH_LENGTH + 1];
|
|
|
|
LOG(("in: eb_load_catalog(book=%d)", (int)book->code));
|
|
|
|
/*
|
|
* Find a catalog file.
|
|
*/
|
|
if (eb_find_file_name(book->path, "catalog", catalog_file_name)
|
|
== EB_SUCCESS) {
|
|
book->disc_code = EB_DISC_EB;
|
|
} else if (eb_find_file_name(book->path, "catalogs", catalog_file_name)
|
|
== EB_SUCCESS) {
|
|
book->disc_code = EB_DISC_EPWING;
|
|
} else {
|
|
error_code = EB_ERR_FAIL_OPEN_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
eb_compose_path_name(book->path, catalog_file_name, catalog_path_name);
|
|
|
|
/*
|
|
* Load the catalog file.
|
|
*/
|
|
if (book->disc_code == EB_DISC_EB)
|
|
error_code = eb_load_catalog_eb(book, catalog_path_name);
|
|
else
|
|
error_code = eb_load_catalog_epwing(book, catalog_path_name);
|
|
if (error_code != EB_SUCCESS)
|
|
goto failed;
|
|
|
|
/*
|
|
* Fix chachacter-code of the book.
|
|
*/
|
|
eb_fix_misleaded_book(book);
|
|
LOG(("out: eb_load_catalog() = %s", eb_error_string(EB_SUCCESS)));
|
|
|
|
return EB_SUCCESS;
|
|
|
|
/*
|
|
* An error occurs...
|
|
*/
|
|
failed:
|
|
if (book->subbooks != NULL) {
|
|
free(book->subbooks);
|
|
book->subbooks = NULL;
|
|
}
|
|
LOG(("out: eb_load_catalog() = %s", eb_error_string(error_code)));
|
|
return error_code;
|
|
}
|
|
|
|
|
|
/*
|
|
* Read information from the `CATALOG' file in 'book'. (EB)
|
|
*/
|
|
static EB_Error_Code
|
|
eb_load_catalog_eb(EB_Book *book, const char *catalog_path)
|
|
{
|
|
EB_Error_Code error_code;
|
|
char buffer[EB_SIZE_PAGE];
|
|
char *space;
|
|
EB_Subbook *subbook;
|
|
Zio zio;
|
|
Zio_Code zio_code;
|
|
int i;
|
|
|
|
LOG(("in: eb_load_catalog_eb(book=%d, catalog=%s)",
|
|
(int)book->code, catalog_path));
|
|
|
|
zio_initialize(&zio);
|
|
|
|
/*
|
|
* Open a catalog file.
|
|
*/
|
|
eb_path_name_zio_code(catalog_path, ZIO_PLAIN, &zio_code);
|
|
if (zio_open(&zio, catalog_path, zio_code) < 0) {
|
|
error_code = EB_ERR_FAIL_OPEN_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Get the number of subbooks in this book.
|
|
*/
|
|
if (zio_read(&zio, buffer, 16) != 16) {
|
|
error_code = EB_ERR_FAIL_READ_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
book->subbook_count = eb_uint2(buffer);
|
|
LOG(("aux: eb_load_catalog_eb(): subbook_count=%d",
|
|
book->subbook_count));
|
|
if (EB_MAX_SUBBOOKS < book->subbook_count)
|
|
book->subbook_count = EB_MAX_SUBBOOKS;
|
|
if (book->subbook_count == 0) {
|
|
error_code = EB_ERR_UNEXP_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Allocate memories for subbook entries.
|
|
*/
|
|
book->subbooks = (EB_Subbook *) malloc(sizeof(EB_Subbook)
|
|
* book->subbook_count);
|
|
if (book->subbooks == NULL) {
|
|
error_code = EB_ERR_MEMORY_EXHAUSTED;
|
|
goto failed;
|
|
}
|
|
eb_initialize_subbooks(book);
|
|
|
|
/*
|
|
* Read information about subbook.
|
|
*/
|
|
for (i = 0, subbook = book->subbooks; i < book->subbook_count;
|
|
i++, subbook++) {
|
|
/*
|
|
* Read data from the catalog file.
|
|
*/
|
|
if (zio_read(&zio, buffer, EB_SIZE_EB_CATALOG)
|
|
!= EB_SIZE_EB_CATALOG) {
|
|
error_code = EB_ERR_FAIL_READ_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Set a directory name.
|
|
*/
|
|
strncpy(subbook->directory_name,
|
|
buffer + 2 + EB_MAX_EB_TITLE_LENGTH,
|
|
EB_MAX_DIRECTORY_NAME_LENGTH);
|
|
subbook->directory_name[EB_MAX_DIRECTORY_NAME_LENGTH] = '\0';
|
|
space = strchr(subbook->directory_name, ' ');
|
|
if (space != NULL)
|
|
*space = '\0';
|
|
eb_fix_directory_name(book->path, subbook->directory_name);
|
|
|
|
/*
|
|
* Set an index page.
|
|
*/
|
|
subbook->index_page = 1;
|
|
|
|
/*
|
|
* Set a title. (Convert from JISX0208 to EUC JP)
|
|
*/
|
|
strncpy(subbook->title, buffer + 2, EB_MAX_EB_TITLE_LENGTH);
|
|
subbook->title[EB_MAX_EB_TITLE_LENGTH] = '\0';
|
|
if (book->character_code != EB_CHARCODE_ISO8859_1)
|
|
eb_jisx0208_to_euc(subbook->title, subbook->title);
|
|
|
|
subbook->initialized = 0;
|
|
subbook->code = i;
|
|
}
|
|
|
|
/*
|
|
* Close the catalog file.
|
|
*/
|
|
zio_close(&zio);
|
|
zio_finalize(&zio);
|
|
|
|
/*
|
|
* Fix chachacter-code of the book.
|
|
*/
|
|
eb_fix_misleaded_book(book);
|
|
LOG(("out: eb_load_catalog_eb() = %s", eb_error_string(EB_SUCCESS)));
|
|
|
|
return EB_SUCCESS;
|
|
|
|
/*
|
|
* An error occurs...
|
|
*/
|
|
failed:
|
|
zio_close(&zio);
|
|
zio_initialize(&zio);
|
|
LOG(("out: eb_load_catalog() = %s", eb_error_string(error_code)));
|
|
return error_code;
|
|
}
|
|
|
|
|
|
/*
|
|
* Read information from the `CATALOGS' file in 'book'. (EPWING)
|
|
*/
|
|
static EB_Error_Code
|
|
eb_load_catalog_epwing(EB_Book *book, const char *catalog_path)
|
|
{
|
|
EB_Error_Code error_code;
|
|
char buffer[EB_SIZE_PAGE];
|
|
char *buffer_p;
|
|
char *space;
|
|
EB_Subbook *subbook;
|
|
EB_Font *font;
|
|
Zio zio;
|
|
Zio_Code zio_code;
|
|
int epwing_version;
|
|
int data_types;
|
|
int i, j;
|
|
|
|
LOG(("in: eb_load_catalog_epwing(book=%d, catalog=%s)",
|
|
(int)book->code, catalog_path));
|
|
|
|
zio_initialize(&zio);
|
|
|
|
/*
|
|
* Open a catalog file.
|
|
*/
|
|
eb_path_name_zio_code(catalog_path, ZIO_PLAIN, &zio_code);
|
|
if (zio_open(&zio, catalog_path, zio_code) < 0) {
|
|
error_code = EB_ERR_FAIL_OPEN_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Get the number of subbooks in this book.
|
|
*/
|
|
if (zio_read(&zio, buffer, 16) != 16) {
|
|
error_code = EB_ERR_FAIL_READ_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
book->subbook_count = eb_uint2(buffer);
|
|
LOG(("aux: eb_load_catalog_epwing(): subbook_count=%d",
|
|
book->subbook_count));
|
|
if (EB_MAX_SUBBOOKS < book->subbook_count)
|
|
book->subbook_count = EB_MAX_SUBBOOKS;
|
|
if (book->subbook_count == 0) {
|
|
error_code = EB_ERR_UNEXP_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
epwing_version = eb_uint2(buffer + 2);
|
|
LOG(("aux: eb_load_catalog_epwing(): epwing_version=%d", epwing_version));
|
|
|
|
/*
|
|
* Allocate memories for subbook entries.
|
|
*/
|
|
book->subbooks = (EB_Subbook *) malloc(sizeof(EB_Subbook)
|
|
* book->subbook_count);
|
|
if (book->subbooks == NULL) {
|
|
error_code = EB_ERR_MEMORY_EXHAUSTED;
|
|
goto failed;
|
|
}
|
|
eb_initialize_subbooks(book);
|
|
|
|
/*
|
|
* Read information about subbook.
|
|
*/
|
|
for (i = 0, subbook = book->subbooks; i < book->subbook_count;
|
|
i++, subbook++) {
|
|
/*
|
|
* Read data from the catalog file.
|
|
*/
|
|
if (zio_read(&zio, buffer, EB_SIZE_EPWING_CATALOG)
|
|
!= EB_SIZE_EPWING_CATALOG) {
|
|
error_code = EB_ERR_FAIL_READ_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Set a directory name.
|
|
*/
|
|
strncpy(subbook->directory_name,
|
|
buffer + 2 + EB_MAX_EPWING_TITLE_LENGTH,
|
|
EB_MAX_DIRECTORY_NAME_LENGTH);
|
|
subbook->directory_name[EB_MAX_DIRECTORY_NAME_LENGTH] = '\0';
|
|
space = strchr(subbook->directory_name, ' ');
|
|
if (space != NULL)
|
|
*space = '\0';
|
|
eb_fix_directory_name(book->path, subbook->directory_name);
|
|
|
|
/*
|
|
* Set an index page.
|
|
*/
|
|
subbook->index_page = eb_uint2(buffer + 2 + EB_MAX_EPWING_TITLE_LENGTH
|
|
+ EB_MAX_DIRECTORY_NAME_LENGTH + 4);
|
|
|
|
/*
|
|
* Set a title. (Convert from JISX0208 to EUC JP)
|
|
*/
|
|
strncpy(subbook->title, buffer + 2, EB_MAX_EPWING_TITLE_LENGTH);
|
|
subbook->title[EB_MAX_EPWING_TITLE_LENGTH] = '\0';
|
|
if (book->character_code != EB_CHARCODE_ISO8859_1)
|
|
eb_jisx0208_to_euc(subbook->title, subbook->title);
|
|
|
|
/*
|
|
* Narrow font file names.
|
|
*/
|
|
buffer_p = buffer + 2 + EB_MAX_EPWING_TITLE_LENGTH + 50;
|
|
for (font = subbook->narrow_fonts, j = 0; j < EB_MAX_FONTS;
|
|
j++, font++) {
|
|
/*
|
|
* Skip this entry if the first character of the file name
|
|
* is not valid.
|
|
*/
|
|
if (*buffer_p == '\0' || 0x80 <= *((unsigned char *)buffer_p)) {
|
|
buffer_p += EB_MAX_DIRECTORY_NAME_LENGTH;
|
|
continue;
|
|
}
|
|
strncpy(font->file_name, buffer_p, EB_MAX_DIRECTORY_NAME_LENGTH);
|
|
font->file_name[EB_MAX_DIRECTORY_NAME_LENGTH] = '\0';
|
|
font->font_code = j;
|
|
font->page = 1;
|
|
space = strchr(font->file_name, ' ');
|
|
if (space != NULL)
|
|
*space = '\0';
|
|
buffer_p += EB_MAX_DIRECTORY_NAME_LENGTH;
|
|
}
|
|
|
|
/*
|
|
* Wide font file names.
|
|
*/
|
|
buffer_p = buffer + 2 + EB_MAX_EPWING_TITLE_LENGTH + 18;
|
|
for (font = subbook->wide_fonts, j = 0; j < EB_MAX_FONTS;
|
|
j++, font++) {
|
|
/*
|
|
* Skip this entry if the first character of the file name
|
|
* is not valid.
|
|
*/
|
|
if (*buffer_p == '\0' || 0x80 <= *((unsigned char *)buffer_p)) {
|
|
buffer_p += EB_MAX_DIRECTORY_NAME_LENGTH;
|
|
continue;
|
|
}
|
|
strncpy(font->file_name, buffer_p, EB_MAX_DIRECTORY_NAME_LENGTH);
|
|
font->file_name[EB_MAX_DIRECTORY_NAME_LENGTH] = '\0';
|
|
font->font_code = j;
|
|
font->page = 1;
|
|
space = strchr(font->file_name, ' ');
|
|
if (space != NULL)
|
|
*space = '\0';
|
|
buffer_p += EB_MAX_DIRECTORY_NAME_LENGTH;
|
|
}
|
|
|
|
subbook->initialized = 0;
|
|
subbook->code = i;
|
|
}
|
|
|
|
/*
|
|
* Set default file names and compression types.
|
|
*/
|
|
for (i = 0, subbook = book->subbooks; i < book->subbook_count;
|
|
i++, subbook++) {
|
|
strcpy(subbook->text_file_name, EB_FILE_NAME_HONMON);
|
|
strcpy(subbook->graphic_file_name, EB_FILE_NAME_HONMON);
|
|
strcpy(subbook->sound_file_name, EB_FILE_NAME_HONMON);
|
|
subbook->text_hint_zio_code = ZIO_PLAIN;
|
|
subbook->graphic_hint_zio_code = ZIO_PLAIN;
|
|
subbook->sound_hint_zio_code = ZIO_PLAIN;
|
|
}
|
|
|
|
if (epwing_version == 1)
|
|
goto succeeded;
|
|
|
|
/*
|
|
* Read extra information about subbook.
|
|
*/
|
|
for (i = 0, subbook = book->subbooks; i < book->subbook_count;
|
|
i++, subbook++) {
|
|
/*
|
|
* Read data from the catalog file.
|
|
*
|
|
* We don't complain about unexpected EOF. In that case, we
|
|
* return EB_SUCCESS.
|
|
*/
|
|
ssize_t read_result = zio_read(&zio, buffer, EB_SIZE_EPWING_CATALOG);
|
|
if (read_result < 0) {
|
|
error_code = EB_ERR_FAIL_READ_CAT;
|
|
goto failed;
|
|
} else if (read_result != EB_SIZE_EPWING_CATALOG) {
|
|
break;
|
|
}
|
|
if (*(buffer + 4) == '\0')
|
|
continue;
|
|
|
|
/*
|
|
* Set a text file name and its compression hint.
|
|
*/
|
|
*(subbook->text_file_name) = '\0';
|
|
strncpy(subbook->text_file_name,
|
|
buffer + 4, EB_MAX_DIRECTORY_NAME_LENGTH);
|
|
subbook->text_file_name[EB_MAX_DIRECTORY_NAME_LENGTH] = '\0';
|
|
space = strchr(subbook->text_file_name, ' ');
|
|
if (space != NULL)
|
|
*space = '\0';
|
|
subbook->text_hint_zio_code
|
|
= eb_get_hint_zio_code(eb_uint1(buffer + 55));
|
|
if (subbook->text_hint_zio_code == ZIO_INVALID) {
|
|
error_code = EB_ERR_UNEXP_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
data_types = eb_uint2(buffer + 41);
|
|
|
|
/*
|
|
* Set a graphic file name and its compression hint.
|
|
*/
|
|
*(subbook->graphic_file_name) = '\0';
|
|
if ((data_types & 0x03) == 0x02) {
|
|
strncpy(subbook->graphic_file_name, buffer + 44,
|
|
EB_MAX_DIRECTORY_NAME_LENGTH);
|
|
subbook->graphic_hint_zio_code
|
|
= eb_get_hint_zio_code(eb_uint1(buffer + 54));
|
|
} else if (((data_types >> 8) & 0x03) == 0x02) {
|
|
strncpy(subbook->graphic_file_name, buffer + 56,
|
|
EB_MAX_DIRECTORY_NAME_LENGTH);
|
|
subbook->graphic_hint_zio_code
|
|
= eb_get_hint_zio_code(eb_uint1(buffer + 53));
|
|
}
|
|
subbook->graphic_file_name[EB_MAX_DIRECTORY_NAME_LENGTH] = '\0';
|
|
space = strchr(subbook->graphic_file_name, ' ');
|
|
if (space != NULL)
|
|
*space = '\0';
|
|
if (*(subbook->graphic_file_name) == '\0') {
|
|
strcpy(subbook->graphic_file_name, subbook->text_file_name);
|
|
subbook->graphic_hint_zio_code = subbook->text_hint_zio_code;
|
|
}
|
|
|
|
if (subbook->graphic_hint_zio_code == ZIO_INVALID) {
|
|
error_code = EB_ERR_UNEXP_CAT;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Set a sound file name and its compression hint.
|
|
*/
|
|
*(subbook->sound_file_name) = '\0';
|
|
if ((data_types & 0x03) == 0x01) {
|
|
strncpy(subbook->sound_file_name, buffer + 44,
|
|
EB_MAX_DIRECTORY_NAME_LENGTH);
|
|
subbook->sound_hint_zio_code
|
|
= eb_get_hint_zio_code(eb_uint1(buffer + 54));
|
|
} else if (((data_types >> 8) & 0x03) == 0x01) {
|
|
strncpy(subbook->sound_file_name, buffer + 56,
|
|
EB_MAX_DIRECTORY_NAME_LENGTH);
|
|
subbook->sound_hint_zio_code
|
|
= eb_get_hint_zio_code(eb_uint1(buffer + 53));
|
|
}
|
|
subbook->sound_file_name[EB_MAX_DIRECTORY_NAME_LENGTH] = '\0';
|
|
space = strchr(subbook->sound_file_name, ' ');
|
|
if (space != NULL)
|
|
*space = '\0';
|
|
if (*(subbook->sound_file_name) == '\0') {
|
|
strcpy(subbook->sound_file_name, subbook->text_file_name);
|
|
subbook->sound_hint_zio_code = subbook->text_hint_zio_code;
|
|
}
|
|
|
|
if (subbook->sound_hint_zio_code == ZIO_INVALID) {
|
|
error_code = EB_ERR_UNEXP_CAT;
|
|
goto failed;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Close the catalog file.
|
|
*/
|
|
succeeded:
|
|
zio_close(&zio);
|
|
zio_finalize(&zio);
|
|
|
|
/*
|
|
* Fix chachacter-code of the book.
|
|
*/
|
|
eb_fix_misleaded_book(book);
|
|
LOG(("out: eb_load_catalog_epwing() = %s", eb_error_string(EB_SUCCESS)));
|
|
|
|
return EB_SUCCESS;
|
|
|
|
/*
|
|
* An error occurs...
|
|
*/
|
|
failed:
|
|
zio_close(&zio);
|
|
zio_initialize(&zio);
|
|
LOG(("out: eb_load_catalog_epwing() = %s", eb_error_string(error_code)));
|
|
return error_code;
|
|
}
|
|
|
|
|
|
static Zio_Code
|
|
eb_get_hint_zio_code(int catalog_hint_value)
|
|
{
|
|
switch (catalog_hint_value) {
|
|
case 0x00:
|
|
return ZIO_PLAIN;
|
|
break;
|
|
case 0x11:
|
|
return ZIO_EPWING;
|
|
break;
|
|
case 0x12:
|
|
return ZIO_EPWING6;
|
|
break;
|
|
}
|
|
|
|
return ZIO_INVALID;
|
|
}
|
|
|
|
|
|
/*
|
|
* Read information from the `LANGUAGE' file in `book'.
|
|
*/
|
|
static void
|
|
eb_load_language(EB_Book *book)
|
|
{
|
|
Zio zio;
|
|
Zio_Code zio_code;
|
|
char language_path_name[EB_MAX_PATH_LENGTH + 1];
|
|
char language_file_name[EB_MAX_FILE_NAME_LENGTH + 1];
|
|
char buffer[16];
|
|
|
|
LOG(("in: eb_load_language(book=%d)", (int)book->code));
|
|
|
|
zio_initialize(&zio);
|
|
book->character_code = EB_CHARCODE_JISX0208;
|
|
|
|
/*
|
|
* Open the language file.
|
|
*/
|
|
if (eb_find_file_name(book->path, "language", language_file_name)
|
|
!= EB_SUCCESS)
|
|
goto failed;
|
|
|
|
eb_compose_path_name(book->path, language_file_name, language_path_name);
|
|
eb_path_name_zio_code(language_path_name, ZIO_PLAIN, &zio_code);
|
|
|
|
if (zio_open(&zio, language_path_name, zio_code) < 0)
|
|
goto failed;
|
|
|
|
/*
|
|
* Get a character code of the book, and get the number of langueages
|
|
* in the file.
|
|
*/
|
|
if (zio_read(&zio, buffer, 16) != 16)
|
|
goto failed;
|
|
|
|
book->character_code = eb_uint2(buffer);
|
|
if (book->character_code != EB_CHARCODE_ISO8859_1
|
|
&& book->character_code != EB_CHARCODE_JISX0208
|
|
&& book->character_code != EB_CHARCODE_JISX0208_GB2312) {
|
|
goto failed;
|
|
}
|
|
|
|
zio_close(&zio);
|
|
LOG(("out: eb_load_language()"));
|
|
|
|
return;
|
|
|
|
/*
|
|
* An error occurs...
|
|
*/
|
|
failed:
|
|
zio_close(&zio);
|
|
LOG(("out: eb_load_language()"));
|
|
}
|
|
|
|
|
|
/*
|
|
* Test whether `book' is bound.
|
|
*/
|
|
int
|
|
eb_is_bound(EB_Book *book)
|
|
{
|
|
int is_bound;
|
|
|
|
LOG(("in: eb_is_bound(book=%d)", (int)book->code));
|
|
|
|
/*
|
|
* Check for the current status.
|
|
*/
|
|
is_bound = (book->path != NULL);
|
|
|
|
LOG(("out: eb_is_bound() = %d", is_bound));
|
|
|
|
return is_bound;
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the bound path of `book'.
|
|
*/
|
|
EB_Error_Code
|
|
eb_path(EB_Book *book, char *path)
|
|
{
|
|
EB_Error_Code error_code;
|
|
|
|
LOG(("in: eb_path(book=%d)", (int)book->code));
|
|
|
|
/*
|
|
* Check for the current status.
|
|
*/
|
|
if (book->path == NULL) {
|
|
error_code = EB_ERR_UNBOUND_BOOK;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Copy the path to `path'.
|
|
*/
|
|
strcpy(path, book->path);
|
|
|
|
LOG(("out: eb_path(path=%s) = %s", path, eb_error_string(EB_SUCCESS)));
|
|
|
|
return EB_SUCCESS;
|
|
|
|
/*
|
|
* An error occurs...
|
|
*/
|
|
failed:
|
|
*path = '\0';
|
|
LOG(("out: eb_path() = %s", eb_error_string(error_code)));
|
|
return error_code;
|
|
}
|
|
|
|
|
|
/*
|
|
* Inspect a disc type.
|
|
*/
|
|
EB_Error_Code
|
|
eb_disc_type(EB_Book *book, EB_Disc_Code *disc_code)
|
|
{
|
|
EB_Error_Code error_code;
|
|
|
|
LOG(("in: eb_disc_type(book=%d)", (int)book->code));
|
|
|
|
/*
|
|
* Check for the current status.
|
|
*/
|
|
if (book->path == NULL) {
|
|
error_code = EB_ERR_UNBOUND_BOOK;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Copy the disc code to `disc_code'.
|
|
*/
|
|
*disc_code = book->disc_code;
|
|
|
|
LOG(("out: eb_disc_type(disc_code=%d) = %s", (int)*disc_code,
|
|
eb_error_string(EB_SUCCESS)));
|
|
|
|
return EB_SUCCESS;
|
|
|
|
/*
|
|
* An error occurs...
|
|
*/
|
|
failed:
|
|
*disc_code = EB_DISC_INVALID;
|
|
LOG(("out: eb_disc_type() = %s", eb_error_string(error_code)));
|
|
return error_code;
|
|
}
|
|
|
|
|
|
/*
|
|
* Inspect a character code used in the book.
|
|
*/
|
|
EB_Error_Code
|
|
eb_character_code(EB_Book *book, EB_Character_Code *character_code)
|
|
{
|
|
EB_Error_Code error_code;
|
|
|
|
LOG(("in: eb_character_code(book=%d)", (int)book->code));
|
|
|
|
/*
|
|
* Check for the current status.
|
|
*/
|
|
if (book->path == NULL) {
|
|
error_code = EB_ERR_UNBOUND_BOOK;
|
|
goto failed;
|
|
}
|
|
|
|
/*
|
|
* Copy the character code to `character_code'.
|
|
*/
|
|
*character_code = book->character_code;
|
|
|
|
LOG(("out: eb_character_code(character_code=%d) = %s",
|
|
(int)*character_code, eb_error_string(EB_SUCCESS)));
|
|
|
|
return EB_SUCCESS;
|
|
|
|
/*
|
|
* An error occurs...
|
|
*/
|
|
failed:
|
|
*character_code = EB_CHARCODE_INVALID;
|
|
LOG(("out: eb_character_code() = %s", eb_error_string(error_code)));
|
|
return error_code;
|
|
}
|