/* Copyright (C) 2001-2002 Kenichi Suto * * 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 program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "defs.h" #include "global.h" #include "eb.h" #include "jcode.h" #include "dictheading.h" #include "dialog.h" #ifdef __FreeBSD__ #include #endif #include #include #include #define MAX_HITS 50 #define MAXLEN_HEADING 65535 #define MAXLEN_TEXT 65535 #define EBOOK_MAX_KEYWORDS 256 #define MAX_BUFSIZE 65535 extern GList *group_list; extern GList *book_list; extern gint global_multi_code; static GtkWidget *cancel_dialog; static GtkWidget *label_match; static GtkWidget *progress; static pthread_t tid; static gint tag_timeout; static gint thread_running = 0; static gint hit_count=0; static gfloat search_progress; gint ebook_simple_search(BOOK_INFO *binfo, char *word, gint method); static gint ebook_ending_search(BOOK_INFO *binfo, char *word, gint method); static EB_Hookset text_hookset; static EB_Hookset heading_hookset; static EB_Hookset candidate_hookset; static gboolean ebook_initialized = FALSE; EB_Error_Code ebook_set_subbook(BOOK_INFO *binfo); static EB_Error_Code hook_initialize(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_narrow_font(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_wide_font(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_indent(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_newline(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_no_newline(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_reference(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_candidate(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_narrow(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_superscript(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_subscript(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_emphasis(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_keyword(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_modification(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_euc_to_ascii(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_color(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_mono(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_gray(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_wave(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_mpeg(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Error_Code hook_graphic_reference(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv); static EB_Hook text_hooks[] = { // {EB_HOOK_INITIALIZE, hook_initialize}, // {EB_HOOK_STOP_CODE, eb_hook_stop_code}, // {EB_HOOK_STOP_CODE, hook_stopcode}, {EB_HOOK_SET_INDENT, hook_indent}, {EB_HOOK_NEWLINE, hook_newline}, {EB_HOOK_NARROW_FONT, hook_narrow_font}, {EB_HOOK_WIDE_FONT, hook_wide_font}, {EB_HOOK_BEGIN_REFERENCE, hook_reference}, {EB_HOOK_END_REFERENCE, hook_reference}, {EB_HOOK_BEGIN_CANDIDATE, hook_candidate}, {EB_HOOK_END_CANDIDATE_LEAF, hook_candidate}, {EB_HOOK_END_CANDIDATE_GROUP, hook_candidate}, // {EB_HOOK_NARROW_JISX0208, hook_euc_to_ascii}, {EB_HOOK_BEGIN_COLOR_BMP, hook_color}, {EB_HOOK_BEGIN_COLOR_JPEG, hook_color}, {EB_HOOK_END_COLOR_GRAPHIC, hook_color}, {EB_HOOK_BEGIN_MONO_GRAPHIC, hook_mono}, {EB_HOOK_END_MONO_GRAPHIC, hook_mono}, {EB_HOOK_BEGIN_GRAY_GRAPHIC, hook_gray}, {EB_HOOK_END_GRAY_GRAPHIC, hook_gray}, {EB_HOOK_BEGIN_WAVE, hook_wave}, {EB_HOOK_END_WAVE, hook_wave}, {EB_HOOK_BEGIN_MPEG, hook_mpeg}, {EB_HOOK_END_MPEG, hook_mpeg}, // {EB_HOOK_BEGIN_GRAPHIC_REFERENCE,hook_graphic_reference}, // {EB_HOOK_END_GRAPHIC_REFERENCE, hook_graphic_reference}, // {EB_HOOK_GRAPHIC_REFERENCE, hook_graphic_reference}, // {EB_HOOK_BEGIN_NO_NEWLINE, hook_no_newline}, // {EB_HOOK_END_NO_NEWLINE, hook_no_newline}, // {EB_HOOK_BEGIN_NARROW, hook_narrow}, // {EB_HOOK_END_NARROW, hook_narrow}, {EB_HOOK_BEGIN_SUPERSCRIPT, hook_superscript}, {EB_HOOK_END_SUPERSCRIPT, hook_superscript}, {EB_HOOK_BEGIN_SUBSCRIPT, hook_subscript}, {EB_HOOK_END_SUBSCRIPT, hook_subscript}, {EB_HOOK_BEGIN_EMPHASIS, hook_emphasis}, {EB_HOOK_END_EMPHASIS, hook_emphasis}, {EB_HOOK_BEGIN_KEYWORD, hook_keyword}, {EB_HOOK_END_KEYWORD, hook_keyword}, #ifdef EB_HOOK_BEGIN_DECORATION {EB_HOOK_BEGIN_DECORATION, hook_modification}, #endif #ifdef EB_HOOK_END_DECORATION {EB_HOOK_END_DECORATION, hook_modification}, #endif {EB_HOOK_NULL, NULL}, }; static EB_Hook heading_hooks[] = { {EB_HOOK_NEWLINE, hook_newline}, {EB_HOOK_NARROW_FONT, hook_narrow_font}, {EB_HOOK_WIDE_FONT, hook_wide_font}, // {EB_HOOK_BEGIN_CANDIDATE, hook_candidate}, // {EB_HOOK_END_CANDIDATE_LEAF, hook_candidate}, // {EB_HOOK_END_CANDIDATE_GROUP, hook_candidate}, {EB_HOOK_NARROW_JISX0208, eb_hook_euc_to_ascii}, {EB_HOOK_BEGIN_SUPERSCRIPT, hook_superscript}, {EB_HOOK_END_SUPERSCRIPT, hook_superscript}, {EB_HOOK_BEGIN_SUBSCRIPT, hook_subscript}, {EB_HOOK_END_SUBSCRIPT, hook_subscript}, {EB_HOOK_NULL, NULL}, }; static EB_Hook candidate_hooks[] = { {EB_HOOK_NARROW_FONT, hook_narrow_font}, {EB_HOOK_WIDE_FONT, hook_wide_font}, {EB_HOOK_BEGIN_CANDIDATE, hook_candidate}, {EB_HOOK_END_CANDIDATE_LEAF, hook_candidate}, {EB_HOOK_END_CANDIDATE_GROUP, hook_candidate}, {EB_HOOK_NULL, NULL}, }; static EB_Error_Code hook_initialize(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { return EB_SUCCESS; } static EB_Error_Code hook_narrow_font(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { char text[64]; sprintf (text, "", argv[0]); eb_write_text_string(book, text); return EB_SUCCESS; } static EB_Error_Code hook_wide_font(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { char text[64]; sprintf (text, "", argv[0]); eb_write_text_string(book, text); return EB_SUCCESS; } static EB_Error_Code hook_indent(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { char text[64]; sprintf (text, "", argv[1]); eb_write_text_string(book, text); /* for(i = 0 ; i < argv[1] ; i ++){ eb_write_text_string(book, " "); } */ return EB_SUCCESS; } static EB_Error_Code hook_newline(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { eb_write_text_string(book, "\n"); return EB_SUCCESS; } static EB_Error_Code hook_narrow(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { switch (code) { case EB_HOOK_BEGIN_NARROW: // eb_write_text_string(book, ""); break; case EB_HOOK_END_NARROW: // eb_write_text_string(book, ""); break; } return EB_SUCCESS; } static EB_Error_Code hook_no_newline(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { switch (code) { case EB_HOOK_BEGIN_NO_NEWLINE: // eb_write_text_string(book, ""); break; case EB_HOOK_END_NO_NEWLINE: // eb_write_text_string(book, ""); break; } return EB_SUCCESS; } static EB_Error_Code hook_reference(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { gchar text[64]; switch (code) { case EB_HOOK_BEGIN_REFERENCE: eb_write_text_string(book, ""); break; case EB_HOOK_END_REFERENCE: sprintf (text, "", argv[1], argv[2]); eb_write_text_string(book, text); break; } return EB_SUCCESS; } static EB_Error_Code hook_candidate(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { gchar text[64]; switch (code) { case EB_HOOK_BEGIN_CANDIDATE: eb_write_text_string(book, ""); break; case EB_HOOK_END_CANDIDATE_LEAF: sprintf (text, "", argv[1], argv[2]); eb_write_text_string(book, text); break; case EB_HOOK_END_CANDIDATE_GROUP: sprintf (text, "", argv[1], argv[2]); eb_write_text_string(book, text); break; } return EB_SUCCESS; } static EB_Error_Code hook_superscript(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { gchar text[64]; switch (code) { case EB_HOOK_BEGIN_SUPERSCRIPT: eb_write_text_string(book, ""); break; case EB_HOOK_END_SUPERSCRIPT: sprintf (text, ""); eb_write_text_string(book, text); break; } return EB_SUCCESS; } static EB_Error_Code hook_subscript(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { gchar text[64]; switch (code) { case EB_HOOK_BEGIN_SUBSCRIPT: eb_write_text_string(book, ""); break; case EB_HOOK_END_SUBSCRIPT: sprintf (text, ""); eb_write_text_string(book, text); break; } return EB_SUCCESS; } static EB_Error_Code hook_emphasis(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { gchar text[64]; switch (code) { case EB_HOOK_BEGIN_EMPHASIS: eb_write_text_string(book, ""); break; case EB_HOOK_END_EMPHASIS: sprintf (text, ""); eb_write_text_string(book, text); break; } return EB_SUCCESS; } static EB_Error_Code hook_keyword(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { gchar text[64]; switch (code) { case EB_HOOK_BEGIN_KEYWORD: sprintf (text, "", argv[1]); eb_write_text_string(book, text); break; case EB_HOOK_END_KEYWORD: sprintf (text, ""); eb_write_text_string(book, text); break; } return EB_SUCCESS; } static EB_Error_Code hook_modification(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { gchar text[64]; #ifdef EB_HOOK_BEGIN_DECORATION #ifdef EB_HOOK_END_DECORATION switch (code) { case EB_HOOK_BEGIN_DECORATION: sprintf (text, "", argv[1]); eb_write_text_string(book, text); break; case EB_HOOK_END_DECORATION: sprintf (text, ""); eb_write_text_string(book, text); break; } #endif #endif return EB_SUCCESS; } /* * Hook for a reference to color graphic data. */ static EB_Error_Code hook_color(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { gchar text[64]; switch (code) { case EB_HOOK_BEGIN_COLOR_JPEG: sprintf (text, "", argv[2], argv[3]); eb_write_text_string(book, text); break; case EB_HOOK_BEGIN_COLOR_BMP: sprintf (text, "", argv[2], argv[3]); eb_write_text_string(book, text); break; /* case EB_HOOK_END_COLOR_GRAPHIC: sprintf (text, "", argv[2], argv[3]); eb_write_text_string(book, text); break; */ } return EB_SUCCESS; } /* * Hook for a reference to MONO graphic data. */ static EB_Error_Code hook_mono(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { gchar text[64]; switch (code) { case EB_HOOK_BEGIN_MONO_GRAPHIC: // argv[2] : height // argv[3] : width sprintf (text, "", argv[3], argv[2]); eb_write_text_string(book, text); break; case EB_HOOK_END_MONO_GRAPHIC: // argv[1] : block // argv[2] : offset sprintf (text, "", argv[1], argv[2]); eb_write_text_string(book, text); break; } return EB_SUCCESS; } /* * Hook for a reference to GRAY graphic data. */ static EB_Error_Code hook_gray(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { gchar text[64]; switch (code) { case EB_HOOK_BEGIN_GRAY_GRAPHIC: sprintf (text, "", argv[2], argv[3]); eb_write_text_string(book, text); break; /* case EB_HOOK_END_GRAY_GRAPHIC: sprintf (text, "", argv[2], argv[3]); eb_write_text_string(book, text); break; */ } return EB_SUCCESS; } /* * Hook for a reference to WAVE sound data. */ static EB_Error_Code hook_wave(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { off_t start_location; off_t end_location; size_t data_size; gchar text[64]; /* * Set binary context. */ start_location = (off_t)(argv[2] - 1) * EB_SIZE_PAGE + argv[3]; end_location = (off_t)(argv[4] - 1) * EB_SIZE_PAGE + argv[5]; data_size = end_location - start_location; switch (code) { case EB_HOOK_BEGIN_WAVE: eb_write_text_string(book, ""); break; case EB_HOOK_END_WAVE: // sprintf (text, "", argv[2], argv[3], argv[4], argv[5]); sprintf (text, "", argv[2], argv[3], data_size); eb_write_text_string(book, text); break; } return EB_SUCCESS; } /* * Hook for a reference to MPEG sound data. */ static EB_Error_Code hook_mpeg(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { char file_name[EB_MAX_DIRECTORY_NAME_LENGTH + 1]; char text[256]; switch (code) { case EB_HOOK_BEGIN_MPEG: break; case EB_HOOK_END_MPEG: if (eb_compose_movie_file_name(argv + 2, file_name) != EB_SUCCESS) return EB_SUCCESS; sprintf(text, "", file_name); eb_write_text_string(book, text); break; } return EB_SUCCESS; } /* * Hook for a reference to graphic reference. */ static EB_Error_Code hook_graphic_reference(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { /* char file_name[EB_MAX_DIRECTORY_NAME_LENGTH + 1]; */ char text[256]; switch (code) { case EB_HOOK_GRAPHIC_REFERENCE: case EB_HOOK_BEGIN_GRAPHIC_REFERENCE: sprintf (text, "", argv[1], argv[2]); eb_write_text_string(book, text); break; case EB_HOOK_END_GRAPHIC_REFERENCE: break; } return EB_SUCCESS; } /* * EUC JP to ASCII conversion table. */ #define EUC_TO_ASCII_TABLE_START 0xa0 #define EUC_TO_ASCII_TABLE_END 0xff static const unsigned char euc_a1_to_ascii_table[] = { 0x00, 0x20, 0x00, 0x00, 0x2c, 0x2e, 0x00, 0x3a, /* 0xa0 */ 0x3b, 0x3f, 0x21, 0x00, 0x00, 0x00, 0x60, 0x00, /* 0xa8 */ 0x5e, 0x7e, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x2f, /* 0xb8 */ 0x5c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x27, /* 0xc0 */ 0x00, 0x22, 0x28, 0x29, 0x00, 0x00, 0x5b, 0x5d, /* 0xc8 */ 0x7b, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */ 0x00, 0x00, 0x00, 0x00, 0x2b, 0x2d, 0x00, 0x00, /* 0xd8 */ 0x00, 0x3d, 0x00, 0x3c, 0x3e, 0x00, 0x00, 0x00, /* 0xe0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, /* 0xe8 */ 0x24, 0x00, 0x00, 0x25, 0x23, 0x26, 0x2a, 0x40, /* 0xf0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8 */ }; static const unsigned char euc_a3_to_ascii_table[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0xb0 */ 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8 */ 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0xc0 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0xc8 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0xd0 */ 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8 */ 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0xe0 */ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0xe8 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0xf0 */ 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8 */ }; /* * Latin-1 character to entity reference table. * (e.g. 'a --> á) */ const char *latin1_entity_name_table[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x00 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x08 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x10 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x18 */ NULL, NULL, "quot", NULL, NULL, NULL, "amp", NULL, /* 0x20 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x28 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x30 */ NULL, NULL, NULL, NULL, "lt", NULL, "gt", NULL, /* 0x38 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x40 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x48 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x50 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x58 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x60 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x68 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x70 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x78 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x80 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x88 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x90 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x98 */ "nbsp", "iexcl", "cent", "pound", /* 0xa0 */ "curren", "yen", "brvbar", "sect", /* 0xa4 */ "uml", "copy", "ordf", "laquo", /* 0xa8 */ "not", "shy", "reg", "macr", /* 0xac */ "deg", "plusmn", "sup2", "sup3", /* 0xb0 */ "acute", "micro", "para", "middot", /* 0xb4 */ "cedil", "sup1", "ordm", "requo", /* 0xb8 */ "frac14", "frac12", "farc34", "iquest", /* 0xbc */ "Agrave", "Aacute", "Acirc", "Atilde", /* 0xc0 */ "Auml", "Aring", "AElig", "Ccedil", /* 0xc4 */ "Egrave", "Eacute", "Ecirc", "Euml", /* 0xc8 */ "Igrave", "Iacute", "Icirc", "Iuml", /* 0xcc */ "ETH", "Ntilde", "Ograve", "Oacute", /* 0xd0 */ "Ocirc", "Otilde", "Ouml", "times", /* 0xd4 */ "Oslash", "Ugrave", "Uacute", "Ucirc", /* 0xd8 */ "Uuml", "Yacute", "THORN", "szlig", /* 0xdc */ "agrave", "aacute", "acirc", "atilde", /* 0xe0 */ "auml", "aring", "aelig", "ccedil", /* 0xe4 */ "egrave", "eacute", "ecirc", "euml", /* 0xe8 */ "igrave", "iacute", "icirc", "iuml", /* 0xec */ "eth", "ntilde", "ograve", "oacute", /* 0xf0 */ "ocirc", "otilde", "ouml", "divide", /* 0xf4 */ "oslash", "ugrave", "uacute", "ucirc", /* 0xf8 */ "uuml", "yacute", "thorn", "yuml" /* 0xfc */ }; /* * Hook which converts a character from EUC-JP to ASCII. */ static EB_Error_Code hook_euc_to_ascii(EB_Book *book, EB_Appendix *appendix, void *container, EB_Hook_Code code, int argc, const unsigned int *argv) { int in_code1, in_code2; int out_code = 0; const char *entity; in_code1 = argv[0] >> 8; in_code2 = argv[0] & 0xff; if (in_code2 < EUC_TO_ASCII_TABLE_START || EUC_TO_ASCII_TABLE_END < in_code2) { out_code = 0; } else if (in_code1 == 0xa1) { out_code = euc_a1_to_ascii_table[in_code2 - EUC_TO_ASCII_TABLE_START]; } else if (in_code1 == 0xa3) { out_code = euc_a3_to_ascii_table[in_code2 - EUC_TO_ASCII_TABLE_START]; } if (out_code == 0) eb_write_text_byte2(book, in_code1, in_code2); else { entity = latin1_entity_name_table[out_code]; if (entity != NULL) { eb_write_text_byte1(book, '&'); eb_write_text_string(book, entity); eb_write_text_byte1(book, ';'); } else { eb_write_text_byte1(book, out_code); } } return EB_SUCCESS; } gint ebook_search_method(){ char *text; int i; text = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo_method)->entry)); for(i=0 ; search_method[i].name != 0 ; i ++){ if(strcmp(text, search_method[i].name) == 0) return(search_method[i].code); } return(SEARCH_METHOD_UNKNOWN); } BOOK_INFO *load_book(char *book_path, int subbook_no, char *appendix_path, int appendix_subbook_no) { EB_Error_Code error_code; BOOK_INFO *binfo; EB_Subbook_Code sublist[EB_MAX_SUBBOOKS]; /* EB_Multi_Search_Code multi_list[EB_MAX_MULTI_SEARCHES]; */ /* int multi_count; */ int subcount /* , i */; char buff[512]; GList *book_item; // すでに同じ書籍がないか検索する // g_print("load_book(%s, %d, %s, %d\n", book_path, subbook_no, appendix_path, appendix_subbook_no); book_item = g_list_first(book_list); while(book_item != NULL){ binfo = (BOOK_INFO *)(book_item->data); if((strcmp(binfo->book_path, book_path) == 0) && (binfo->subbook_no == subbook_no)) { if((binfo->appendix_path != NULL) && (appendix_path != NULL) && (strcmp(binfo->appendix_path, appendix_path) == 0) && (binfo->appendix_subbook_no == appendix_subbook_no)) { return(binfo); } else { unload_book(binfo); g_free(binfo); break; } } book_item = g_list_next(book_item); } binfo = (BOOK_INFO *)calloc(sizeof(BOOK_INFO),1); if(binfo == NULL){ fprintf(stderr, "No memory\n"); exit(1); } binfo->book_path = strdup(book_path); binfo->subbook_no = subbook_no; if(appendix_path){ binfo->appendix_path = strdup(appendix_path); binfo->appendix_subbook_no = appendix_subbook_no; } binfo->book = (EB_Book *) malloc(sizeof(EB_Book)); eb_initialize_book(binfo->book); error_code = eb_bind(binfo->book, binfo->book_path); if(error_code != EB_SUCCESS){ fprintf(stderr, "Failed to bind the book : %s\n", eb_error_message(error_code)); goto FAILED; } error_code = eb_subbook_list( binfo->book, sublist, &subcount); if(error_code != EB_SUCCESS){ fprintf(stderr, "Failed to get a subbook list : %s\n", eb_error_message(error_code)); goto FAILED; } error_code = eb_subbook_directory2( binfo->book, sublist[binfo->subbook_no], buff); if (error_code != EB_SUCCESS){ fprintf(stderr, "failed to get the directory : %s\n", eb_error_message(error_code)); goto FAILED; } binfo->subbook_dir = strdup(buff); error_code = eb_subbook_title2( binfo->book, sublist[binfo->subbook_no], buff); if (error_code != EB_SUCCESS){ fprintf(stderr, "failed to get the title : %s\n", eb_error_message(error_code)); goto FAILED; } binfo->subbook_title = strdup(buff); if(binfo->appendix_path != NULL){ binfo->appendix = (EB_Appendix *) malloc(sizeof(EB_Appendix)); eb_initialize_appendix(binfo->appendix); error_code = eb_bind_appendix(binfo->appendix, binfo->appendix_path); if(error_code != EB_SUCCESS){ fprintf(stderr, "Failed to bind appendix : %s\n", eb_error_message(error_code)); goto FAILED; } } ebook_set_subbook(binfo); binfo->available = TRUE; if(eb_have_word_search(binfo->book)){ binfo->search_method[SEARCH_METHOD_WORD] = TRUE; } if(eb_have_endword_search(binfo->book)){ binfo->search_method[SEARCH_METHOD_ENDWORD] = TRUE; } if(eb_have_exactword_search(binfo->book)){ binfo->search_method[SEARCH_METHOD_EXACTWORD] = TRUE; } if(eb_have_keyword_search(binfo->book)){ binfo->search_method[SEARCH_METHOD_KEYWORD] = TRUE; } /* eb_multi_search_list(binfo->book, multi_list, &multi_count); for (i = 0; i < multi_count; i++) { binfo->search_method[SEARCH_METHOD_MULTI1+i] = TRUE; } */ if(eb_have_multi_search(binfo->book)){ binfo->search_method[SEARCH_METHOD_MULTI] = TRUE; } if(eb_have_menu(binfo->book)){ binfo->search_method[SEARCH_METHOD_MENU] = TRUE; } if(eb_have_copyright(binfo->book)){ binfo->search_method[SEARCH_METHOD_COPYRIGHT] = TRUE; } if (eb_have_font(binfo->book, EB_FONT_16)){ error_code = eb_set_font(binfo->book, EB_FONT_16); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to set font : subbook=%s\n%s\n", binfo->subbook_title, eb_error_message(error_code)); // return(error_code); } } book_list = g_list_append(book_list, binfo); return(binfo); FAILED: // if((binfo != NULL) && (binfo->book_path != NULL)) // free(binfo->book_path); // if((binfo != NULL) && (binfo->book != NULL)) // free(binfo->book); // if(binfo != NULL) // free(binfo); binfo->available = FALSE; return(binfo); } static void free_gaiji(BOOK_INFO *binfo){ /* GAIJI_CACHE *gaiji , *tmp_g ; */ GList *lists[8]; GList *item; gint i; lists[0] = binfo->gaiji_narrow16; lists[1] = binfo->gaiji_narrow24; lists[2] = binfo->gaiji_narrow30; lists[3] = binfo->gaiji_narrow48; lists[4] = binfo->gaiji_wide16; lists[5] = binfo->gaiji_wide24; lists[6] = binfo->gaiji_wide30; lists[7] = binfo->gaiji_wide48; for(i=0; i < 8 ; i ++){ item = g_list_first(lists[i]); while(item){ free(item->data); item = g_list_next(item); } g_list_free(lists[i]); } binfo->gaiji_narrow16 = NULL; binfo->gaiji_narrow24 = NULL; binfo->gaiji_narrow30 = NULL; binfo->gaiji_narrow48 = NULL; binfo->gaiji_wide16 = NULL; binfo->gaiji_wide24 = NULL; binfo->gaiji_wide30 = NULL; binfo->gaiji_wide48 = NULL; } void unload_book(BOOK_INFO *binfo) { /* GAIJI_CACHE *gaiji, *tmp_g */; eb_unset_subbook(binfo->book); eb_finalize_book(binfo->book); free(binfo->book_path); free(binfo->appendix_path); free(binfo->subbook_dir); free(binfo->subbook_title); free_gaiji(binfo); book_list = g_list_remove(book_list, binfo); return; } void check_search_method() { BOOK_INFO *binfo; GList *book_item; gint method_count=0; /* char buff[512]; */ /* int i; */ menu_word_search = FALSE; menu_endword_search = FALSE; menu_exactword_search = FALSE; menu_keyword_search = FALSE; menu_menu = FALSE; menu_copyright = FALSE; menu_multi_search = FALSE; book_item = g_list_first(book_list); while(book_item != NULL){ binfo = (BOOK_INFO *)(book_item->data); if(binfo->search_method[SEARCH_METHOD_WORD] == TRUE) menu_word_search = TRUE; if(binfo->search_method[SEARCH_METHOD_ENDWORD] == TRUE) menu_endword_search = TRUE; if(binfo->search_method[SEARCH_METHOD_EXACTWORD] == TRUE) menu_exactword_search = TRUE; if(binfo->search_method[SEARCH_METHOD_KEYWORD] == TRUE) menu_keyword_search = TRUE; if(binfo->search_method[SEARCH_METHOD_MENU] == TRUE) menu_menu = TRUE; if(binfo->search_method[SEARCH_METHOD_COPYRIGHT] == TRUE) menu_copyright = TRUE; if(binfo->search_method[SEARCH_METHOD_MULTI] == TRUE) menu_multi_search = TRUE; book_item = g_list_next(book_item); } method_count = 0; search_method[method_count].code = SEARCH_METHOD_AUTOMATIC; search_method[method_count].name = strdup(_("Automatic Search")); method_count ++; if(menu_exactword_search == TRUE){ search_method[method_count].code = SEARCH_METHOD_EXACTWORD; search_method[method_count].name = strdup(_("Exactword Search")); method_count ++; } if(menu_word_search == TRUE){ search_method[method_count].code = SEARCH_METHOD_WORD; search_method[method_count].name = strdup(_("Forward Search")); method_count ++; } if(menu_endword_search == TRUE){ search_method[method_count].code = SEARCH_METHOD_ENDWORD; search_method[method_count].name = strdup(_("Backward Search")); method_count ++; } if(menu_keyword_search == TRUE){ search_method[method_count].code = SEARCH_METHOD_KEYWORD; search_method[method_count].name = strdup(_("Keyword Search")); method_count ++; } if(menu_multi_search == TRUE){ search_method[method_count].code = SEARCH_METHOD_MULTI; search_method[method_count].name = strdup(_("Multiword Search")); method_count ++; } /* if(menu_menu == TRUE){ search_method[method_count].code = SEARCH_METHOD_MENU; search_method[method_count].name = strdup(_("Menu")); method_count ++; } if(menu_copyright == TRUE){ search_method[method_count].code = SEARCH_METHOD_COPYRIGHT; search_method[method_count].name = strdup(_("Copyright")); method_count ++; } */ search_method[method_count].code = SEARCH_METHOD_FULL_TEXT; search_method[method_count].name = strdup(_("Full Text Search")); method_count ++; search_method[method_count].code = SEARCH_METHOD_INTERNET; search_method[method_count].name = strdup(_("Internet Search")); method_count ++; search_method[method_count].name = NULL; } gint ebook_start(){ EB_Error_Code error_code; error_code = eb_initialize_library(); if(error_code != EB_SUCCESS){ fprintf(stderr, "Failed to initialize library : %s\n", eb_error_message(error_code)); return(1); } eb_initialize_hookset (&text_hookset); error_code = eb_set_hooks (&text_hookset, text_hooks); if(error_code != EB_SUCCESS){ fprintf(stderr, "Failed to set hookset(text) : %s\n", eb_error_message(error_code)); return(1); } eb_initialize_hookset (&heading_hookset); error_code = eb_set_hooks (&heading_hookset, heading_hooks); if(error_code != EB_SUCCESS){ fprintf(stderr, "Failed to set hookset(heading) : %s\n", eb_error_message(error_code)); return(1); } eb_initialize_hookset (&candidate_hookset); error_code = eb_set_hooks (&candidate_hookset, candidate_hooks); if(error_code != EB_SUCCESS){ fprintf(stderr, "Failed to set hookset(candidate) : %s\n", eb_error_message(error_code)); return(1); } ebook_initialized = TRUE; return(0); } gint ebook_end(){ /* GAIJI_CACHE *gaiji, *tmp_g ; */ BOOK_INFO *binfo; GList *book_item; if(ebook_initialized == TRUE) { return(0); } book_item = g_list_first(book_list); while(book_item != NULL){ binfo = (BOOK_INFO *)(book_item->data); eb_unset_subbook(binfo->book); eb_finalize_book(binfo->book); free(binfo->book_path); free(binfo->appendix_path); free(binfo->subbook_dir); free(binfo->subbook_title); free_gaiji(binfo); g_list_remove(book_list, book_item->data); book_item = g_list_next(book_item); } book_list = NULL; ebook_initialized = FALSE; return(0); } void split_word(gchar *word, gchar **keywords) { gint i,j; gchar *p; gchar buff[512]; p = word; i = 0; j = 0; keywords[0] = NULL; if(strlen(word) > 512){ return; } while(1){ switch(*p){ case ' ': case '\t': case '\n': case '\0': // if(j != 0){ buff[j] = '\0'; keywords[i] = strdup(buff); i ++; keywords[i] = NULL; j = 0; // } break; default: buff[j] = *p; j ++; } p++; if((*p == '\0') || (i == EBOOK_MAX_KEYWORDS)) break; } buff[j] = '\0'; if(strlen(buff) != 0){ keywords[i] = strdup(buff); i ++; } keywords[i] = NULL; } void cat_word(char *string, char **words){ gint i; gint len = 0; sprintf(string, "%s", words[0]); len = strlen(words[0]); for(i=1 ; words[i] != NULL ; i++){ strcat(string, " "); strcat(string, words[i]); len = len + strlen(words[i]) + 1; } string[len] = '\0'; } void free_words(char **words){ gint i; for(i=0; words[i] != NULL ; i++) free(words[i]); } gboolean iseuckanji(guchar *buff){ g_assert(buff != NULL); if((buff[0] >= 0xb0) && (buff[0] <= 0xf4) && (buff[1] >= 0xa1) && (buff[1] <= 0xfe)) return(TRUE); return(FALSE); } gboolean iseuc(guchar *buff){ g_assert(buff != NULL); if((buff[0] >= 0xa1) && (buff[0] <= 0xf4) && (buff[1] >= 0xa1) && (buff[1] <= 0xfe)) return(TRUE); return(FALSE); } static gchar *locale2jis(gchar *inbuf){ iconv_t cd; const char* ocode = "euc-jp"; const char* icode; // const char* ocode = "iso-2022-jp"; // const char* ocode = "shift_jis"; int r = 0; size_t isize; size_t osize; char *outbuf; guchar *eucbuf=NULL; guchar *euc_p; guchar *jisbuf=NULL; guchar *jis_p; gint i; icode = nl_langinfo(CODESET); if((strcasecmp(icode, "EUC-JP") == 0) || (strcasecmp(icode, "EUCJP") == 0) ){ euc_p = inbuf; } else { cd = iconv_open( ocode, icode ); if( (int)cd == -1 ) return(NULL); isize = strlen(inbuf); osize = isize * 4; eucbuf = outbuf = malloc(osize); #ifdef __FreeBSD__ r = iconv(cd, (const char **)&inbuf, &isize, &outbuf, &osize); #else r = iconv(cd, &inbuf, &isize, &outbuf, &osize); #endif iconv_close(cd); if(r == 1){ perror("iconv"); return(NULL); } euc_p = eucbuf; } jis_p = jisbuf = malloc(strlen(euc_p)*2); while(*euc_p != '\0'){ if(isalnum(*euc_p)){ *jis_p = 0x23; jis_p ++; *jis_p = *euc_p; jis_p ++; } else if(iseuc(euc_p)){ *jis_p = *euc_p - 0x80; jis_p ++; euc_p++; *jis_p = *euc_p - 0x80; jis_p ++; } else if(*euc_p == 0x20){ *jis_p = 0x21; jis_p ++; *jis_p = 0x21; jis_p ++; } else { *jis_p = 0x21; jis_p ++; *jis_p = 0x29; jis_p ++; } euc_p ++; } *jis_p = '\0'; if(eucbuf != NULL) free(eucbuf); for(i=0;;i++){ if(jisbuf[i] == '\0') break; } return(jisbuf); } static int check_match(char *haystack, char *needle){ /* wchar_t *l_haystack; */ /* wchar_t *l_needle; */ char *rp; gint len; len = strlen(needle); rp = haystack; while(*rp != '\0'){ if(strncasecmp(rp, needle, len) == 0) return(0); if(isascii(*rp)) rp += 1; else rp += 2; } return(1); /* l_haystack = any_to_utf8(haystack); l_needle = any_to_utf8(needle); rp = wcsstr(l_haystack, l_needle); free(l_haystack); free(l_needle); if(rp == NULL) return(1); else return(0); */ } gboolean full_text_search_ignore_case = TRUE; static int jiscmp(unsigned char *haystack, unsigned char *needle){ unsigned char *p1, *p2; p1 = haystack; p2 = needle; while(1) { if(isjisp(p1) != TRUE){ p1 +=2; continue; } if(*p2 == '\0') return(0); else if(*p1 == '\0') return(1); else if((*p1 == *p2) && (*(p1+1) == *(p2+1))) { p1 +=2; p2 +=2; continue; } else if(full_text_search_ignore_case){ guint c1, c2; c1 = eb_uint2(p1); c2 = eb_uint2(p2); if ((0x2341 <= c1) && (c1 <= 0x237a) && (0x2341 <= c2) && (c2 <= 0x237a)){ if(((0x2361 <= c1) ? (c1 - 0x20) : c1) == ((0x2361 <= c2) ? (c2 - 0x20) : c2)){ p1 += 2; p2 += 2; continue; } } return(1); } else { return(1); } } } static gboolean check_duplicate_hit(EB_Position pos){ GList *l; SEARCH_RESULT *rp; l = search_result; while(l != NULL){ rp = (SEARCH_RESULT *)(l->data); if((rp->pos_text.page == pos.page) && (rp->pos_text.offset == pos.offset)) return(TRUE); l = g_list_next(l); } return(FALSE); } static gint count_result(GList *result) { return(g_list_length(result)); } EB_Error_Code ebook_my_backward_text(BOOK_INFO *binfo) { EB_Error_Code error_code=EB_SUCCESS; EB_Position text_position; char data[EB_SIZE_PAGE+4]; /* char *jisword; */ /* char *word_p; */ int i, length; /* char *p; */ /* char heading[MAXLEN_TEXT + 1]; */ /* SEARCH_RESULT *rp; */ int start_page; int end_page; int current_page; int current_offset; int offset; int read_page; int stop_code; /* int page_count=0; */ error_code = ebook_set_subbook(binfo); if(error_code != EB_SUCCESS){ fprintf(stderr, "failed to set subbook : %s\n", eb_error_message(error_code)); return(error_code); } start_page = binfo->book->subbook_current->text.start_page; end_page = binfo->book->subbook_current->text.end_page; error_code = eb_tell_text(binfo->book, &text_position); if(error_code != EB_SUCCESS){ fprintf(stderr, "failed to tell text : %s\n", eb_error_message(error_code)); return(error_code); } current_page = text_position.page; current_offset = text_position.offset; offset = current_offset; stop_code = binfo->book->text_context.auto_stop_code; for(read_page = current_page ; read_page >= start_page ; read_page --){ text_position.page = read_page; text_position.offset = 0; error_code = eb_seek_text(binfo->book, &text_position); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to seek text, %s\n", eb_error_message(error_code)); return(error_code); } memset(data, 0, EB_SIZE_PAGE + 4); error_code = eb_read_rawtext(binfo->book, EB_SIZE_PAGE+2, data, &length); if (error_code != EB_SUCCESS || length != EB_SIZE_PAGE+2){ fprintf(stderr, "failed to read rawtext, %s\n", eb_error_message(error_code)); return(error_code); } if(stop_code != -1) binfo->book->text_context.auto_stop_code = stop_code; for(i=offset-2 ; i >= 0 ; i -=2){ if(((binfo->appendix != NULL) && (eb_uint2(&data[i]) == binfo->appendix->subbook_current->stop_code0) && (eb_uint2(&data[i+2]) == binfo->appendix->subbook_current->stop_code1)) || ((binfo->appendix == NULL) && (eb_uint2(&data[i]) == 0x1f41) && (eb_uint1(&data[i+2]) == 0x01)) || (eb_uint2(&data[i]) == 0x1f02)) #if 0 ((eb_uint2(&data[i]) == 0x1f41) && (eb_uint2(&data[i+2]) == binfo->book->text_context.auto_stop_code))) #endif { text_position.page = read_page; text_position.offset = i; error_code = eb_seek_text(binfo->book, &text_position); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to seek text, %s\n", eb_error_message(error_code)); return(error_code); } if(stop_code != -1) binfo->book->text_context.auto_stop_code = stop_code; return(EB_SUCCESS); } } offset = EB_SIZE_PAGE + 2; } text_position.page = current_page; text_position.offset = current_offset; error_code = eb_seek_text(binfo->book, &text_position); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to seek text, %s\n", eb_error_message(error_code)); return(error_code); } return(EB_ERR_FAIL_SEEK_TEXT); } static gint ebook_full_search(BOOK_INFO *binfo, char *word, gint method) { EB_Error_Code error_code=EB_SUCCESS; EB_Position text_position; char data[EB_SIZE_PAGE]; char *jisword; char *word_p; int i, length; char *p; char heading[MAXLEN_TEXT + 1]; SEARCH_RESULT *rp; int start_page; int end_page; int current_page; int stop_code; int page_count=0; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(error_code); start_page = binfo->book->subbook_current->text.start_page; end_page = binfo->book->subbook_current->text.end_page; // g_print("start_page = 0x%0x end_page = 0x%0x\n", // start_page, end_page); // auto_stop_code を取得するためにいったん読む p = ebook_get_text(binfo, start_page, 0); if(p) free(p); stop_code = binfo->book->text_context.auto_stop_code; jisword = locale2jis(word); word_p = jisword; for(current_page = start_page ; current_page <= end_page ; current_page ++){ search_progress = (float)(current_page - start_page) / (end_page - start_page + 1); page_count ++; text_position.page = current_page; text_position.offset = 0; error_code = eb_seek_text(binfo->book, &text_position); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to seek text, %s\n", eb_error_message(error_code)); return(error_code); } error_code = eb_read_rawtext(binfo->book, EB_SIZE_PAGE, data, &length); if (error_code != EB_SUCCESS || length != EB_SIZE_PAGE){ fprintf(stderr, "failed to read rawtext, %s\n", eb_error_message(error_code)); return(error_code); } for(i=0 ; i < EB_SIZE_PAGE ; i +=2){ // 制御文字は読みとばす if(isjisp(&data[i]) != TRUE){ continue; // 一致 } else if((data[i] == *word_p) && (data[i+1] == *(word_p+1))){ // 検索語はまだ続いているか if (*(word_p+2) != '\0'){ word_p += 2; continue; } // 大文字と小文字を区別しない場合 } else if(full_text_search_ignore_case){ guint c1, c2; c1 = eb_uint2(&data[i]); c2 = eb_uint2(word_p); // アルファベットなら if ((0x2341 <= c1) && (c1 <= 0x237a) && (0x2341 <= c2) && (c2 <= 0x237a)){ // 小文字にしてからマッチさせる if(((0x2361 <= c1) ? (c1 - 0x20) : c1) == ((0x2361 <= c2) ? (c2 - 0x20) : c2)){ // 検索語はまだ続いているか if (*(word_p+2) != '\0'){ word_p += 2; continue; } } else { goto NO_MATCH; } } else { goto NO_MATCH; } } else { goto NO_MATCH; } // 一致した場合 // 読み込み処理 text_position.page = current_page; text_position.offset = i; // g_print("found at (0x%x, 0x%x)0x%x\n", current_page, i, (current_page - 1) * EB_SIZE_PAGE + i); error_code = eb_seek_text(binfo->book, &text_position); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to seek text, %s\n", eb_error_message(error_code)); // なかったことに... goto NO_MATCH; } // eb_seek_text() で auto_stop_codeがクリアされるため、 // 以前の値を復元する。 if(stop_code != -1) binfo->book->text_context.auto_stop_code = stop_code; // error_code = eb_backward_text(binfo->book, binfo->appendix); error_code = ebook_my_backward_text(binfo); if(error_code != EB_SUCCESS){ fprintf(stderr, "failed to back text : %s\n", eb_error_message(error_code)); // なかったことに... goto NO_MATCH; } error_code = eb_tell_text(binfo->book, &text_position); if(error_code != EB_SUCCESS){ fprintf(stderr, "failed to tell text : %s\n", eb_error_message(error_code)); // なかったことに... goto NO_MATCH; } // g_print("rewind to (0x%x, 0x%x)\n", text_position.page, text_position.offset); if(check_duplicate_hit(text_position) == TRUE){ // なかったことに... // g_print("duplicate\n"); goto NO_MATCH; } error_code = eb_read_text(binfo->book, binfo->appendix, &heading_hookset, NULL, MAXLEN_TEXT, heading, &length); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to read text : %s\n", eb_error_message(error_code)); // なかったことに... goto NO_MATCH; } heading[length] = '\0'; p = strchr(heading, '\n'); if(p != NULL) *p = '\0'; rp = (SEARCH_RESULT *)calloc(sizeof(SEARCH_RESULT),1); if(rp == NULL){ fprintf(stderr, "No memory\n"); exit(1); } rp->heading = strdup(heading); rp->book_info = binfo; rp->search_method = method; rp->pos_heading = text_position; rp->pos_text = text_position; search_result = g_list_append(search_result, rp); if((binfo->book->text_context.auto_stop_code != stop_code) && (binfo->book->text_context.auto_stop_code != -1)) stop_code = binfo->book->text_context.auto_stop_code; hit_count ++; NO_MATCH: word_p = jisword; continue; } } free(jisword); return(error_code); } static gint ebook_full_heading_search(binfo, word){ return 0 ; } gint ebook_search2(char *g_word, DICT_GROUP *group){ int j; int method; EB_Error_Code error_code=EB_SUCCESS; BOOK_INFO *binfo; DICT_MEMBER *member; GList *member_item=NULL; gchar *word = strdup(g_word); clear_search_result(); method = ebook_search_method(); member_item = group->member; while(member_item != NULL){ member = (DICT_MEMBER *)(member_item->data); if(member->active != TRUE) { member_item = g_list_next(member_item); continue; } if(member->binfo == NULL) { member_item = g_list_next(member_item); continue; } if(member->binfo->available == FALSE) { member_item = g_list_next(member_item); continue; } binfo = member->binfo; if(method == SEARCH_METHOD_AUTOMATIC){ for(j=SEARCH_METHOD_MIN ; j<=SEARCH_METHOD_MAX ; j++){ //前方一致、後方一致はのぞく if((j == SEARCH_METHOD_WORD) || (j == SEARCH_METHOD_ENDWORD)) continue; if(binfo->search_method[j] == TRUE){ if(bending_correction == 0){ error_code = ebook_simple_search(binfo, word, j); } else { error_code = ebook_ending_search(binfo, word, j); } if (error_code != EB_SUCCESS){ if(error_code == EB_ERR_TOO_MANY_WORDS) continue; fprintf(stderr, "failed to search : %s\n", eb_error_message(error_code)); // return(error_code); } } } } else if((method == SEARCH_METHOD_FULL_TEXT) || (method == SEARCH_METHOD_FULL_HEADING)){ error_code = ebook_full_search(binfo, word, method); } else { if(binfo->search_method[method] == TRUE){ if(bending_correction == 0){ ebook_simple_search(binfo, word, method); } else { ebook_ending_search(binfo, word, method); } } } member_item = g_list_next(member_item); } return 0; } static void *ebook_search_thread(void *arg) { GList *group_item; DICT_GROUP *group; char word[MAX_BUFSIZE]; strncpy(word, arg, sizeof(word)-1); group_item = g_list_first(group_list); while(group_item != NULL){ group = (DICT_GROUP *)(group_item->data); if(group->active == TRUE){ break; } group_item = g_list_next(group_item); } if(group_item == NULL) { return(0); } ebook_search2(word, group); thread_running = 0; return NULL ; } static void cancel_thread(GtkWidget *widget, gpointer *data) { gtk_timeout_remove(tag_timeout); gtk_grab_remove(cancel_dialog); gtk_widget_destroy(cancel_dialog); pthread_cancel(tid); thread_running = 0; show_result_tree(); } static gint show_cancel_dialog() { GtkWidget *button; GtkWidget *label; GtkAdjustment *adj; /* int i; */ cancel_dialog = gtk_dialog_new(); gtk_widget_set_usize(cancel_dialog, 200, -1); gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG(cancel_dialog)->vbox), 10); button = gtk_button_new_with_label(_("Cancel")); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (cancel_dialog)->action_area), button, TRUE, TRUE, 0); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (cancel_thread), (gpointer)NULL); label = gtk_label_new (_("Searching")); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (cancel_dialog)->vbox), label, TRUE,TRUE, 5); // progress = gtk_progress_bar_new(); adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 1, 0, 0, 0); progress = gtk_progress_bar_new_with_adjustment (adj); /* gtk_progress_set_activity_mode(GTK_PROGRESS(progress), TRUE); gtk_progress_bar_set_activity_step(GTK_PROGRESS_BAR(progress), 5); gtk_progress_bar_set_activity_blocks(GTK_PROGRESS_BAR(progress), 5); */ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (cancel_dialog)->vbox), progress, TRUE,TRUE, 5); label_match = gtk_label_new ("0 hit"); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (cancel_dialog)->vbox), label_match, TRUE,TRUE, 5); // gtk_window_set_position(GTK_WINDOW(cancel_dialog), GTK_WIN_POS_CENTER_ALWAYS); gtk_widget_show_all(cancel_dialog); center_dialog(window, cancel_dialog); gtk_grab_add(cancel_dialog); return 0 ; } static gint watch_thread(gpointer data){ char msg[256]; /* gchar *label; */ GtkAdjustment *adj; gfloat new_val; if(thread_running){ sprintf(msg, _("%d hit"), hit_count); gtk_label_set_text(GTK_LABEL(label_match), msg); adj = GTK_PROGRESS (progress)->adjustment; new_val = adj->value + 1; if (new_val > adj->upper) new_val = adj->lower; // gtk_progress_set_value (GTK_PROGRESS (progress), new_val); gtk_progress_set_value (GTK_PROGRESS (progress), search_progress); return(1); } gtk_timeout_remove(tag_timeout); show_result_tree(); gtk_grab_remove(cancel_dialog); gtk_widget_destroy(cancel_dialog); return(0); } gint ebook_search(char *word) { gint rc; gint method; void *p ; size_t size ; pthread_attr_t thread_attr ; thread_running = 1; hit_count = 0; pthread_attr_init (&thread_attr) ; pthread_attr_setstacksize (&thread_attr, 512*1024) ; rc = pthread_create(&tid, &thread_attr, ebook_search_thread, (void *)word); if(rc != 0){ perror("pthread_create"); exit(1); } pthread_attr_destroy(&thread_attr); method = ebook_search_method(); if(method == SEARCH_METHOD_FULL_TEXT){ show_cancel_dialog(); tag_timeout = gtk_timeout_add(100, watch_thread, NULL); } else { pthread_join(tid, &p); thread_running = 0; show_result_tree(); } return 0 ; } gint ebook_search_auto(char *g_word) { GList *group_item; DICT_GROUP *group; gint method; method = ebook_search_method(); if(method == SEARCH_METHOD_FULL_TEXT) return(0); group_item = g_list_first(group_list); while(group_item != NULL){ group = (DICT_GROUP *)(group_item->data); if(strcasecmp(group->name, "selection") == 0){ break; } group_item = g_list_next(group_item); } if(group_item == NULL) { group_item = g_list_first(group_list); while(group_item != NULL){ group = (DICT_GROUP *)(group_item->data); if(group->active == TRUE){ break; } group_item = g_list_next(group_item); } } if(group_item == NULL) return(0); return ebook_search2(g_word, group); } gint ebook_simple_search(BOOK_INFO *binfo, char *word, gint method) { EB_Error_Code error_code=EB_SUCCESS; int i, len, total_hits=0; EB_Hit hits[MAX_HITS]; int hitcount; char heading[MAXLEN_HEADING + 1]; char *keywords[EBOOK_MAX_KEYWORDS + 1]; SEARCH_RESULT *rp; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(error_code); switch(method){ case SEARCH_METHOD_WORD: error_code = eb_search_word(binfo->book, word); break; case SEARCH_METHOD_ENDWORD: error_code = eb_search_endword(binfo->book, word); break; case SEARCH_METHOD_EXACTWORD: error_code = eb_search_exactword(binfo->book, word); break; case SEARCH_METHOD_KEYWORD: split_word(word, keywords); error_code = eb_search_keyword(binfo->book, (const char * const *)keywords); free_words(keywords); break; case SEARCH_METHOD_MULTI: split_word(word, keywords); for(i=0;ibook, global_multi_code, (const char * const *)keywords); free_words(keywords); break; default: error_code = EB_ERR_NO_SUCH_SEARCH; break; } if (error_code != EB_SUCCESS){ fprintf(stderr, "failed to search : %s\n", eb_error_message(error_code)); return(error_code); } total_hits = count_result(search_result); while(1){ error_code = eb_hit_list(binfo->book, MAX_HITS, hits, &hitcount); if(error_code != EB_SUCCESS){ /* fprintf(stderr, "an error occurred. : %s\n", eb_error_message(error_code)); */ return(error_code); } if(hitcount == 0) break; for(i = 0 ; i < hitcount ; i ++){ if(total_hits >= max_search) return(EB_SUCCESS); if(check_duplicate_hit(hits[i].text) == TRUE) continue; rp = (SEARCH_RESULT *)calloc(sizeof(SEARCH_RESULT),1); if(rp == NULL){ fprintf(stderr, "No memory\n"); exit(1); } error_code = eb_seek_text(binfo->book, &(hits[i].heading)); if(error_code != EB_SUCCESS){ /* fprintf(stderr, "failed to seek the subbook, %s\n", eb_error_message(error_code)); */ return(error_code); } error_code = eb_read_heading(binfo->book, binfo->appendix, &heading_hookset, NULL, MAXLEN_HEADING, heading, &len); if (error_code != EB_SUCCESS) { /* fprintf(stderr, "failed to read the subbook, %s\n", eb_error_message(error_code)); */ return(error_code); } heading[len] = '\0'; rp->heading = strdup(heading); rp->book_info = binfo; rp->search_method = method; rp->pos_heading = hits[i].heading; rp->pos_text = hits[i].text; search_result = g_list_append(search_result, rp); total_hits ++; } } return(error_code); } static gint ebook_ending_search(BOOK_INFO *binfo, char *word, gint method) { EB_Error_Code error_code=EB_SUCCESS; gint i; gint len_word, len_ending; char *keywords[EBOOK_MAX_KEYWORDS + 1]; char new_word[MAX_BUFSIZE]; char new_key[256]; char *save_key; ENDING *ending; GList *list; g_assert(binfo != NULL); g_assert(word != NULL); error_code = ebook_simple_search(binfo, word, method); if((bending_only_nohit == 1) && (search_result != NULL)){ return(error_code); } split_word(word, keywords); for(i=0; keywords[i] != NULL ; i++){ list = g_list_first(ending_list); while(list){ ending = (ENDING *)(list->data); len_word = strlen(keywords[i]); len_ending = strlen(ending->pattern); if(len_word < len_ending){ list = g_list_next(list); continue; } if(strcmp(&keywords[i][len_word - len_ending],ending->pattern) == 0){ memcpy(new_key, keywords[i], len_word - len_ending); sprintf(&new_key[len_word - len_ending],"%s", ending->normal); save_key = keywords[i]; keywords[i] = new_key; cat_word(new_word, keywords); error_code = ebook_simple_search(binfo, new_word, method); keywords[i] = save_key; if(error_code != EB_SUCCESS){ return(error_code); } } list = g_list_next(list); } } // 日本語の語尾補正 // 日本語は複数の単語にはなっていないはず if((keywords[1] == NULL) && (iseuc(keywords[0]))){ if((count_result(search_result) != 0) && (bending_only_nohit == 1)) goto END; list = g_list_first(ending_list_ja); while(list){ ending = (ENDING *)(list->data); len_word = strlen(keywords[0]); len_ending = strlen(ending->pattern); if(len_word < len_ending){ list = g_list_next(list); continue; } for(i=0; ipattern, len_ending) == 0){ memcpy(new_key, keywords[0], i); sprintf(&new_key[i],"%s", ending->normal); error_code = ebook_simple_search(binfo, new_key, method); if(error_code != EB_SUCCESS){ return(error_code); } } } list = g_list_next(list); } // それでも一件もマッチしなかったら、漢字の部分だけで検索する。 if((count_result(search_result) == 0) && (iseuckanji(keywords[0]))){ len_word = strlen(keywords[0]); strcpy(new_key, keywords[0]); for(i=0; idata); if(rp->heading != NULL) free(rp->heading); l = g_list_next(l); } search_result = NULL; } gchar *ebook_get_heading(BOOK_INFO *binfo, int page, int offset) { EB_Error_Code error_code; int len; char heading[MAXLEN_HEADING + 1]; EB_Position position; gchar *p; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(NULL); error_code = eb_seek_text(binfo->book, &position); if(error_code != EB_SUCCESS){ fprintf(stderr, "Failed to seek text : %s\n", eb_error_message(error_code)); exit(1); } error_code = eb_read_heading(binfo->book, binfo->appendix, &text_hookset, NULL, MAXLEN_HEADING, heading, &len); if (error_code != EB_SUCCESS) { fprintf(stderr, "Failed to read heading : %s\n", eb_error_message(error_code)); exit(1); } heading[len] = '\0'; p = malloc(len+1); memcpy(p, heading, len+1); return(p); } gchar *ebook_get_text(BOOK_INFO *binfo, int page, int offset) { EB_Error_Code error_code; int len; char text[MAXLEN_TEXT + 1]; EB_Position position; gchar *p; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(NULL); position.page = page; position.offset = offset; error_code = eb_seek_text(binfo->book, &position); if(error_code != EB_SUCCESS){ fprintf(stderr, "failed to seek text : %s\n", eb_error_message(error_code)); return(NULL); } error_code = eb_read_text(binfo->book, binfo->appendix, &text_hookset, NULL, MAXLEN_TEXT, text, &len); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to read text : %s\n", eb_error_message(error_code)); return(NULL); } text[len] = '\0'; p = malloc(len+1); memcpy(p, text, len+1); return(p); } gchar *ebook_get_candidate(BOOK_INFO *binfo, int page, int offset) { EB_Error_Code error_code; int len; char text[MAXLEN_TEXT + 1]; EB_Position position; gchar *p; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(NULL); position.page = page; position.offset = offset; error_code = eb_seek_text(binfo->book, &position); if(error_code != EB_SUCCESS){ fprintf(stderr, "failed to seek text : %s\n", eb_error_message(error_code)); return(NULL); } error_code = eb_read_text(binfo->book, binfo->appendix, &candidate_hookset, NULL, MAXLEN_TEXT, text, &len); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to read text : %s\n", eb_error_message(error_code)); return(NULL); } text[len] = '\0'; p = malloc(len+1); memcpy(p, text, len+1); return(p); } EB_Error_Code ebook_forward_text(BOOK_INFO *binfo) { EB_Error_Code error_code; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(error_code); error_code = eb_seek_text(binfo->book, ¤t_position); if(error_code != EB_SUCCESS){ fprintf(stderr, "failed to seek text : %s\n", eb_error_message(error_code)); return(error_code); } error_code = eb_forward_text(binfo->book, binfo->appendix); if(error_code != EB_SUCCESS){ fprintf(stderr, "failed to forward text : %s\n", eb_error_message(error_code)); return(error_code); } return(EB_SUCCESS); } EB_Error_Code ebook_backward_text(BOOK_INFO *binfo) { EB_Error_Code error_code; int stop_code = -1; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(error_code); stop_code = binfo->book->text_context.auto_stop_code; error_code = eb_seek_text(binfo->book, ¤t_position); if(error_code != EB_SUCCESS){ fprintf(stderr, "failed to seek text : %s\n", eb_error_message(error_code)); return(error_code); } if(stop_code != -1) binfo->book->text_context.auto_stop_code = stop_code; // error_code = eb_backward_text(binfo->book, binfo->appendix); error_code = ebook_my_backward_text(binfo); if(error_code != EB_SUCCESS){ fprintf(stderr, "failed to back text : %s\n", eb_error_message(error_code)); return(error_code); } return(EB_SUCCESS); } void ebook_tell_text(BOOK_INFO *binfo, gint *page, gint *offset) { EB_Error_Code error_code; EB_Position position; // if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) // return; error_code = eb_tell_text(binfo->book, &position); if(error_code != EB_SUCCESS){ fprintf(stderr, "failed to tell text : %s\n", eb_error_message(error_code)); exit(1); } *page = position.page; *offset = position.offset; return; } void ebook_menu(BOOK_INFO *binfo, EB_Position *pos) { EB_Error_Code error_code=EB_SUCCESS; error_code = eb_menu(binfo->book, pos); if(error_code != EB_SUCCESS) { fprintf(stderr, "failed to get menu position : %s\n", eb_error_message(error_code)); } } void ebook_copyright(BOOK_INFO *binfo, EB_Position *pos) { EB_Error_Code error_code=EB_SUCCESS; error_code = eb_copyright(binfo->book, pos); if(error_code != EB_SUCCESS) { fprintf(stderr, "failed to get copyright position : %s\n", eb_error_message(error_code)); } } static void ebook_bitmap_to_xbm(const char *bitmap, int width, int height, char *xbm, size_t *xbm_length) { char *xbm_p = xbm; const unsigned char *bitmap_p = (const unsigned char *)bitmap; int bitmap_size = (width + 7) / 8 * height; int hex; int i; for (i = 0; i < bitmap_size; i++) { hex = 0; if (*bitmap_p & 0x80) hex |= 0x01; if (*bitmap_p & 0x40) hex |= 0x02; if (*bitmap_p & 0x20) hex |= 0x04; if (*bitmap_p & 0x10) hex |= 0x08; if (*bitmap_p & 0x08) hex |= 0x10; if (*bitmap_p & 0x04) hex |= 0x20; if (*bitmap_p & 0x02) hex |= 0x40; if (*bitmap_p & 0x01) hex |= 0x80; bitmap_p++; *xbm_p = hex; xbm_p ++; } *xbm_length = (xbm_p - xbm); } gint check_gaiji_size(BOOK_INFO *binfo, gint prefered_size){ gint size; size = prefered_size; switch(size){ case 48: if (eb_have_font(binfo->book, EB_FONT_48)){ size = 48; break; } size = 30; case 30: if (eb_have_font(binfo->book, EB_FONT_30)){ size = 30; break; } size = 24; case 24: if (eb_have_font(binfo->book, EB_FONT_24)){ size = 24; break; } size = 16; case 16: if (eb_have_font(binfo->book, EB_FONT_16)){ size = 16; break; } fprintf(stderr, "failed to find 16 dot gaiji : subbook=%s\n", binfo->subbook_title); return(-1); } if(size != prefered_size){ fprintf(stderr, "Cannot find %d dot gaiji. Use %d dot instead\n", prefered_size, size); } return(size); } void set_gaiji_size(gint font_size){ BOOK_INFO *binfo; GList *book_item; book_item = g_list_first(book_list); while(book_item != NULL){ binfo = (BOOK_INFO *)(book_item->data); book_item = g_list_next(book_item); } } guchar *read_gaiji_as_bitmap(BOOK_INFO *binfo, gchar *name, gint size, gint *width, gint *height) { EB_Error_Code error_code; gint char_no; gchar bitmap_data[EB_SIZE_WIDE_FONT_48]; // char image_data[EB_SIZE_FONT_IMAGE]; guchar *image_data; size_t image_size; int image_width; int image_height; EB_Subbook *subbook; // *pixmap = NULL; // *bitmap = NULL; char_no = strtol(&name[1], NULL, 16); subbook = binfo->book->subbook_current; switch (size) { case 16: error_code = eb_set_font(binfo->book, EB_FONT_16); break; case 24: error_code = eb_set_font(binfo->book, EB_FONT_24); break; case 30: error_code = eb_set_font(binfo->book, EB_FONT_30); break; case 48: error_code = eb_set_font(binfo->book, EB_FONT_48); break; } if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to set font : subbook=%s\n%s\n", binfo->subbook_title, eb_error_message(error_code)); return(NULL); } error_code = eb_font_height(binfo->book, &image_height); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to get font height : subbook=%s\n%s\n", binfo->subbook_title, eb_error_message(error_code)); return(NULL); } if(name[0] == 'h'){ if (!eb_have_narrow_font(binfo->book)){ fprintf(stderr, "%s does not have narrow font\n", binfo->subbook_title); return(NULL); } error_code = eb_narrow_font_width(binfo->book, &image_width); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to get font width : subbook=%s\n%s\n", binfo->subbook_title, eb_error_message(error_code)); return(NULL); } error_code = eb_narrow_font_character_bitmap( binfo->book, char_no, bitmap_data); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to read narrow font : subbook=%s, character=0x%04x\n%s\n", binfo->subbook_title, char_no, eb_error_message(error_code)); return(NULL); } } else { if (!eb_have_wide_font(binfo->book)){ fprintf(stderr, "%s does not have wide font\n", binfo->subbook_title); return(NULL); } error_code = eb_wide_font_width(binfo->book, &image_width); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to get font width : subbook=%s\n%s\n", binfo->subbook_title, eb_error_message(error_code)); return(NULL); } error_code = eb_wide_font_character_bitmap( binfo->book, char_no, bitmap_data); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to read wide font : subbook=%s, character=0x%04x\n%s\n", binfo->subbook_title, char_no, eb_error_message(error_code)); return(NULL); } } image_data = malloc(image_width * image_height / 8); ebook_bitmap_to_xbm(bitmap_data, image_width, image_height, image_data, &image_size); *width = image_width; *height = image_height; return(image_data); } #define GIF_PREAMBLE_LENGTH 38 static const unsigned char gif_preamble[GIF_PREAMBLE_LENGTH] = { /* * Header. (6 bytes) */ 'G', 'I', 'F', '8', '9', 'a', /* * Logical Screen Descriptor. (7 bytes) * global color table flag = 1. * color resolution = 1 - 1 = 0. * sort flag = 0. * size of global color table = 1 - 1 = 0. * background color index = 0. * the pixel aspect ratio = 0 (unused) * Logical screen width and height are set at run time. */ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, /* * Global Color Table. (6 bytes) * These are set at run time. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* * Graphic Control Extension. (8 bytes) * disposal method = 0. * user input flag = 0. * transparency flag = 1. * delay time = 0. * transparent color index = 0. */ 0x21, 0xf9, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, /* * Image Descriptor. (10 bytes) * image left position = 0. * image top position = 0. * local color table flag = 0. * interlace flag = 0. * sort flag = 0. * size of local color table = 0. * Image width and height are set at run time. */ 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* * Code size. (1byte) */ 0x03 }; static void ebook_bitmap_to_gif(bitmap, width, height, gif, gif_length, fg, bg) const char *bitmap; int width; int height; char *gif; size_t *gif_length; uint fg; uint bg; { unsigned char *gif_p = (unsigned char *)gif; const unsigned char *bitmap_p = (const unsigned char *)bitmap; int i, j; /* * Copy the default preamble. */ memcpy(gif_p, gif_preamble, GIF_PREAMBLE_LENGTH); /* * Set logical screen width and height. */ gif_p[6] = width & 0xff; gif_p[7] = (width >> 8) & 0xff; gif_p[8] = height & 0xff; gif_p[9] = (height >> 8) & 0xff; /* * Set global colors. */ gif_p[13] = (bg >> 16) & 0xff; gif_p[14] = (bg >> 8) & 0xff; gif_p[15] = bg & 0xff; gif_p[16] = (fg >> 16) & 0xff; gif_p[17] = (fg >> 8) & 0xff; gif_p[18] = fg & 0xff; /* * Set image width and height. */ gif_p[32] = width & 0xff; gif_p[33] = (width >> 8) & 0xff; gif_p[34] = height & 0xff; gif_p[35] = (height >> 8) & 0xff; gif_p += GIF_PREAMBLE_LENGTH; /* * Output image data. */ for (i = 0; i < height; i++) { *gif_p++ = (unsigned char)width; for (j = 0; j + 7 < width; j += 8, bitmap_p++) { *gif_p++ = (*bitmap_p & 0x80) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x40) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x20) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x10) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x08) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x04) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x02) ? 0x81 : 0x80; *gif_p++ = (*bitmap_p & 0x01) ? 0x81 : 0x80; } if (j < width) { if (j++ < width) *gif_p++ = (*bitmap_p & 0x80) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x40) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x20) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x10) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x08) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x04) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x02) ? 0x81 : 0x80; if (j++ < width) *gif_p++ = (*bitmap_p & 0x01) ? 0x81 : 0x80; bitmap_p++; } } /* * Output a trailer. */ memcpy(gif_p, "\001\011\000\073", 4); gif_p += 4; if (gif_length != NULL) *gif_length = ((char *)gif_p - gif); } guchar *read_gaiji_as_xbm(BOOK_INFO *binfo, gchar *name, gchar *fname, guint fg, guint bg) { EB_Error_Code error_code; gint char_no; gchar bitmap_data[EB_SIZE_WIDE_FONT_48]; guchar image_data[EB_SIZE_FONT_IMAGE]; // guchar *image_data; size_t image_size; int image_width; int image_height; EB_Subbook *subbook; FILE *fp; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(NULL); char_no = strtol(&name[1], NULL, 16); subbook = binfo->book->subbook_current; error_code = eb_font_height(binfo->book, &image_height); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to get font height : subbook=%s\n%s\n", binfo->subbook_title, eb_error_message(error_code)); return(NULL); } if(name[0] == 'h'){ if (!eb_have_narrow_font(binfo->book)){ fprintf(stderr, "%s does not have narrow font\n", binfo->subbook_title); return(NULL); } error_code = eb_narrow_font_width(binfo->book, &image_width); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to get font width : subbook=%s\n%s\n", binfo->subbook_title, eb_error_message(error_code)); return(NULL); } error_code = eb_narrow_font_character_bitmap( binfo->book, char_no, bitmap_data); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to read narrow font : subbook=%s, character=0x%04x\n%s\n", binfo->subbook_title, char_no, eb_error_message(error_code)); return(NULL); } } else { if (!eb_have_wide_font(binfo->book)){ fprintf(stderr, "%s does not have wide font\n", binfo->subbook_title); return(NULL); } error_code = eb_wide_font_width(binfo->book, &image_width); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to get font width : subbook=%s\n%s\n", binfo->subbook_title, eb_error_message(error_code)); return(NULL); } error_code = eb_wide_font_character_bitmap( binfo->book, char_no, bitmap_data); if (error_code != EB_SUCCESS) { fprintf(stderr, "failed to read wide font : subbook=%s, character=0x%04x\n%s\n", binfo->subbook_title, char_no, eb_error_message(error_code)); return(NULL); } } ebook_bitmap_to_gif(bitmap_data, image_width, image_height, image_data, &image_size, fg, bg); fp = fopen(fname, "w"); if(fp == NULL){ fprintf(stderr, "file open failed : %s\n", fname); } fwrite(image_data, image_size, 1, fp); fclose(fp); return(NULL); } EB_Error_Code ebook_output_wave(BOOK_INFO *binfo, gchar *filename, gint page, gint offset, gint size) //EB_Error_Code ebook_output_wave(BOOK_INFO *binfo, gchar *filename, gint start_page, gint start_offset, gint end_page, gint end_offset) { EB_Position pos; char binary_data[EB_SIZE_PAGE]; EB_Error_Code error_code; EB_Position end_position; ssize_t read_length; FILE *fp; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(error_code); fp = fopen(filename, "w"); if(fp == NULL){ fprintf(stderr, "failed to open file : %s\n", filename); return(EB_ERR_BAD_FILE_NAME); } pos.page = page; pos.offset = offset; end_position.page = pos.page + (size / EB_SIZE_PAGE); end_position.offset = pos.offset + (size % EB_SIZE_PAGE); if (EB_SIZE_PAGE <= end_position.offset) { end_position.offset -= EB_SIZE_PAGE; end_position.page++; } /* * Read sound data. */ error_code = eb_set_binary_wave(binfo->book, &pos, &end_position); if (error_code != EB_SUCCESS){ fprintf(stderr, "failed to set binary wave : %s\n", eb_error_message(error_code)); return(error_code); } for (;;) { error_code = eb_read_binary(binfo->book, EB_SIZE_PAGE, binary_data, &read_length); if (error_code != EB_SUCCESS || read_length == 0){ fclose(fp); return(error_code); } // fmtチャンクの前に不要なデータ(32バイト)があったら削除する if((strncmp("fmt ", &binary_data[44], 4) == 0) && (strncmp("fmt ", &binary_data[12], 4) != 0)){ fprintf(stderr, "Warning: extra header found in WAVE data.\n"); fwrite(binary_data, 12, 1, fp); fwrite(&binary_data[44], read_length - 44, 1, fp); } else { fwrite(binary_data, read_length, 1, fp); } } /* not reached */ return(EB_SUCCESS); } EB_Error_Code ebook_output_mpeg(BOOK_INFO *binfo, gchar *srcname, gchar *destname) { char binary_data[EB_SIZE_PAGE]; guint argv[4]; EB_Error_Code error_code; ssize_t read_length; FILE *fp; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(error_code); if((error_code = eb_decompose_movie_file_name(argv, srcname)) != EB_SUCCESS) return(error_code); fp = fopen(destname, "w"); if(fp == NULL){ fprintf(stderr, "failed to open file : %s\n", destname); return(EB_ERR_BAD_FILE_NAME); } /* * Read sound data. */ error_code = eb_set_binary_mpeg(binfo->book, argv); if (error_code != EB_SUCCESS){ fprintf(stderr, "failed to set binary mpeg : %s\n", eb_error_message(error_code)); return(error_code); } for (;;) { error_code = eb_read_binary(binfo->book, EB_SIZE_PAGE, binary_data, &read_length); if (error_code != EB_SUCCESS || read_length == 0){ fclose(fp); return(error_code); } fwrite(binary_data, read_length, 1, fp); } /* not reached */ return(EB_SUCCESS); } EB_Error_Code ebook_output_color(BOOK_INFO *binfo, gchar *filename, gint page, gint offset) { EB_Position pos; char binary_data[EB_SIZE_PAGE]; EB_Error_Code error_code; ssize_t read_length; FILE *fp; fp = fopen(filename, "w"); if(fp == NULL){ fprintf(stderr, "failed to open file : %s\n", filename); return(EB_ERR_BAD_FILE_NAME); } pos.page = page; pos.offset = offset; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(error_code); error_code = eb_set_binary_color_graphic(binfo->book, &pos); // スーパー統合辞書2000の漢字源の場合には図版データが // Honmon2に入っているようなので、NO_SUCH_BINARYとなる。 // とりあえずは自力で読むことにする。 if (error_code == EB_ERR_NO_SUCH_BINARY){ gchar *data; gint file_size; eb_seek_text(binfo->book, &pos); error_code = eb_read_rawtext(binfo->book, 8, binary_data, &read_length); if (error_code != EB_SUCCESS || read_length == 0){ return(error_code); } if(strncmp(binary_data, "data", 4) == 0){ file_size = *(gint *)&binary_data[4]; data = malloc(file_size); error_code = eb_read_rawtext(binfo->book, file_size, data, &read_length); if (error_code != EB_SUCCESS || read_length == 0){ return(error_code); } fwrite(data, read_length, 1, fp); fclose(fp); free(data); } return(EB_SUCCESS); } if (error_code != EB_SUCCESS){ fprintf(stderr, "failed to set binary color graphic : %s\n", eb_error_message(error_code)); return(error_code); } for (;;) { error_code = eb_read_binary(binfo->book, EB_SIZE_PAGE, binary_data, &read_length); if (error_code != EB_SUCCESS || read_length == 0){ fclose(fp); return(error_code); } // output_data(property, binary_data, read_length); fwrite(binary_data, read_length, 1, fp); } /* not reached */ return(EB_SUCCESS); } EB_Error_Code ebook_output_gray(BOOK_INFO *binfo, gchar *filename, gint page, gint offset, gint width, gint height) { EB_Position pos; char binary_data[EB_SIZE_PAGE]; EB_Error_Code error_code; ssize_t read_length; FILE *fp; fp = fopen(filename, "w"); if(fp == NULL){ fprintf(stderr, "failed to open file : %s\n", filename); return(EB_ERR_BAD_FILE_NAME); } pos.page = page; pos.offset = offset; if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(error_code); error_code = eb_set_binary_gray_graphic(binfo->book, &pos, width, height); if (error_code != EB_SUCCESS){ fprintf(stderr, "failed to set binary gray graphic : %s\n", eb_error_message(error_code)); return(error_code); } for (;;) { error_code = eb_read_binary(binfo->book, EB_SIZE_PAGE, binary_data, &read_length); if (error_code != EB_SUCCESS || read_length == 0){ fclose(fp); return(error_code); } // output_data(property, binary_data, read_length); fwrite(binary_data, read_length, 1, fp); } /* not reached */ return(EB_SUCCESS); } extern CONTENT_AREA *dict_area; EB_Error_Code ebook_output_mono(BOOK_INFO *binfo, gchar *filename, gint page, gint offset, gint width, gint height) { FILE *fp; EB_Error_Code error_code; EB_Position pos; char *binary_data; ssize_t read_length; gint data_size; gchar *bmp_data; gint bmp_length; #ifdef COLOR_HACK guchar fg[4]; guchar bg[4]; GdkColor color; // color = window->style->fg[GTK_STATE_NORMAL]; color = dict_area->area->style->fg[GTK_STATE_NORMAL]; fg[0] = (guchar)color.red; fg[1] = (guchar)color.green; fg[2] = (guchar)color.blue; fg[3] = 0x0; // fg = ((guchar)color.red << 16) | ((guchar)color.green << 8) | ((guchar)color.blue) ; // color = window->style->bg[GTK_STATE_NORMAL]; color = dict_area->area->style->bg[GTK_STATE_NORMAL]; bg[0] = (guchar)color.red; bg[1] = (guchar)color.green; bg[2] = (guchar)color.blue; bg[3] = 0x0; // bg = ((guchar)color.red << 16) | ((guchar)color.green << 8) | ((guchar)color.blue) ; #endif if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(error_code); fp = fopen(filename, "w"); if(fp == NULL){ fprintf(stderr, "failed to open file : %s\n", filename); return(EB_ERR_BAD_FILE_NAME); } pos.page = page; pos.offset = offset; eb_seek_text(binfo->book, &pos); error_code = eb_set_binary_mono_graphic(binfo->book, &pos, width, height); // &pos, 0, 0); // スーパー統合辞書2000の漢字源の場合には図版データが // Honmon2に入っているようなので、NO_SUCH_BINARYとなる。 // とりあえずは自力で読むことにする。 // eb-3.3では修正済み // if ((error_code == EB_ERR_NO_SUCH_BINARY) || // (error_code == EB_ERR_FAIL_READ_BINARY)){ if (error_code != EB_SUCCESS){ if((width % 8) != 0) width = (width / 8)*8 + 8; data_size = width * height / 8; binary_data = malloc(data_size); bmp_data = malloc(data_size*10); pos.page = page; pos.offset = offset; eb_seek_text(binfo->book, &pos); error_code = eb_read_rawtext(binfo->book, data_size, binary_data, &read_length); if (error_code != EB_SUCCESS || read_length == 0){ return(error_code); } // eb_bitmap_to_xbm(binary_data, eb_bitmap_to_bmp(binary_data, width, height, bmp_data, &bmp_length); fwrite(bmp_data, bmp_length, 1, fp); #ifdef COLOR_HACK fseek(fp, 54, SEEK_SET); fwrite(bg, 4, 1, fp); fseek(fp, 58, SEEK_SET); fwrite(fg, 4, 1, fp); #endif fclose(fp); free(binary_data); free(bmp_data); return(EB_SUCCESS); } if (error_code != EB_SUCCESS){ fprintf(stderr, "failed to set binary mono : %s\n", eb_error_message(error_code)); return(error_code); } for (;;) { char binary_data[EB_SIZE_PAGE]; error_code = eb_read_binary(binfo->book, EB_SIZE_PAGE, binary_data, &read_length); if (error_code != EB_SUCCESS || read_length == 0){ fclose(fp); return(error_code); } #ifdef COLOR_HACK memcpy(&binary_data[54], bg, 4); memcpy(&binary_data[58], fg, 4); #endif fwrite(binary_data, read_length, 1, fp); } /* not reached */ fclose(fp); return(EB_SUCCESS); } gchar *ebook_get_rawtext(BOOK_INFO *binfo, gint page, gint offset) { EB_Position pos; char *binary_data; EB_Error_Code error_code; ssize_t read_length; binary_data = malloc(EB_SIZE_PAGE); if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS) return(NULL); pos.page = page; pos.offset = offset; eb_seek_text(binfo->book, &pos); error_code = eb_read_rawtext(binfo->book, EB_SIZE_PAGE, binary_data, &read_length); if (error_code != EB_SUCCESS || read_length == 0){ return(NULL); } return(binary_data); } EB_Error_Code ebook_set_subbook(BOOK_INFO *binfo) { EB_Error_Code error_code; error_code = eb_set_subbook(binfo->book, binfo->subbook_no); if (error_code != EB_SUCCESS){ fprintf(stderr, "failed to set subbook %s, %d: %s\n", binfo->book_path, binfo->subbook_no, eb_error_message(error_code)); return(error_code); } if(binfo->appendix != NULL){ error_code = eb_set_appendix_subbook(binfo->appendix, binfo->appendix_subbook_no); if (error_code != EB_SUCCESS){ fprintf(stderr, "failed to set appendix subbook : %s\n", eb_error_message(error_code)); return(error_code); } } return(EB_SUCCESS); }