1 /*  Copyright (C) 2001-2004  Kenichi Suto
2  *
3  *  This program is free software; you can redistribute it and/or modify
4  *  it under the terms of the GNU General Public License as published by
5  *  the Free Software Foundation; either version 2 of the License, or
6  *  (at your option) any later version.
7  *
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License
14  *  along with this program; if not, write to the Free Software
15  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 */
17 
18 #include "defs.h"
19 #include "global.h"
20 
21 #include "bmh.h"
22 #include "eb.h"
23 #include "history.h"
24 #include "hook.h"
25 #include "jcode.h"
26 #include "headword.h"
27 #include "dialog.h"
28 #include "xmlinternal.h"
29 #include "thread_search.h"
30 #include "dirtree.h"
31 
32 
33 #define MAX_HITS            50
34 #define MAXLEN_HEADING     65535
35 #define MAXLEN_TEXT      65535
36 
37 #define EBOOK_MAX_KEYWORDS 256
38 #define MAX_BUFSIZE 65535
39 
40 extern GList *group_list;
41 extern GList *book_list;
42 extern gint global_multi_code;
43 
44 gint ebook_simple_search(BOOK_INFO *binfo, char *word, gint method, gchar *title);
45 static gint ebook_ending_search(BOOK_INFO *binfo, char *word, gint method, gchar *title);
46 static void sort_result(gchar *word);
47 static void plain_heading();
48 
49 extern EB_Hookset text_hookset;
50 extern EB_Hookset heading_hookset;
51 extern EB_Hookset candidate_hookset;
52 
53 static gboolean ebook_initialized = FALSE;
54 
55 gboolean full_text_search_ignore_case = TRUE;
56 
57 EB_Error_Code ebook_set_subbook(BOOK_INFO *binfo);
58 
59 static gchar *ebook_message = NULL;
60 
ebook_error_message(error_code)61 gchar *ebook_error_message(error_code)
62 {
63 	const gchar *message;
64 
65 	if(ebook_message)
66 		g_free(ebook_message);
67 
68 	message = eb_error_message(error_code);
69 	ebook_message = iconv_convert(fs_codeset, "utf-8", message);
70 	return(ebook_message);
71 }
72 
73 
ebook_search_method()74 gint ebook_search_method(){
75 	const char *text;
76 	int i;
77 
78 	LOG(LOG_DEBUG, "IN : ebook_search_method()");
79 
80 	text = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo_method)->entry));
81 	for(i=0 ; search_method[i].name != 0 ; i ++){
82 		if(strcmp(text, search_method[i].name) == 0){
83 			LOG(LOG_DEBUG, "OUT : ebook_search_method()=%d", search_method[i].code);
84 			return(search_method[i].code);
85 		}
86 	}
87 
88 	LOG(LOG_DEBUG, "OUT : ebook_search_method()=%d", SEARCH_METHOD_UNKNOWN);
89 
90 	return(SEARCH_METHOD_UNKNOWN);
91 }
92 
load_book(const char * book_path,int subbook_no,gchar * appendix_path,gint appendix_subbook_no,gchar * fg,gchar * bg)93 BOOK_INFO *load_book(const char *book_path, int subbook_no, gchar *appendix_path, gint appendix_subbook_no, gchar *fg, gchar *bg)
94 {
95 	EB_Error_Code error_code;
96 	BOOK_INFO *binfo;
97 	EB_Subbook_Code sublist[EB_MAX_SUBBOOKS];
98 	int subcount;
99 	char buff[512];
100 #if 0
101 	GList *book_item;
102 #endif
103 
104 	LOG(LOG_DEBUG, "IN : load_book(%s, %d, %s, %d, %s %s)", book_path, subbook_no, appendix_path, appendix_subbook_no, fg, bg);
105 
106 	if(book_path == NULL){
107 		LOG(LOG_DEBUG, "OUT : load_book() = NULL");
108 		return(NULL);
109 	}
110 
111 	// Search if there is the same book already.
112 #if 0
113 	book_item = g_list_first(book_list);
114 	while(book_item != NULL){
115 		binfo = (BOOK_INFO *)(book_item->data);
116 		if((strcmp(binfo->book_path, book_path) == 0) &&
117 		   (binfo->subbook_no == subbook_no)) {
118 			if((binfo->appendix_path != NULL) &&
119 			   (appendix_path != NULL) &&
120 			   (strcmp(binfo->appendix_path, appendix_path) == 0) &&
121 			   (binfo->appendix_subbook_no == appendix_subbook_no)) {
122 				return(binfo);
123 			} else {
124 				unload_book(binfo);
125 				g_free(binfo);
126 				break;
127 			}
128 		}
129 		book_item = g_list_next(book_item);
130 	}
131 #endif
132 
133 	binfo = (BOOK_INFO *)calloc(sizeof(BOOK_INFO),1);
134 	if(binfo == NULL){
135 		LOG(LOG_ERROR, "No memory");
136 		exit(1);
137 	}
138 
139 	binfo->book_path = fs_to_unicode((gchar *)book_path);
140 	binfo->subbook_no = subbook_no;
141 	if(appendix_path){
142 		binfo->appendix_path = fs_to_unicode(appendix_path);
143 		binfo->appendix_subbook_no = appendix_subbook_no;
144 	}
145 
146 
147 	binfo->book = (EB_Book *) malloc(sizeof(EB_Book));
148 	eb_initialize_book(binfo->book);
149 	error_code = eb_bind(binfo->book,
150 			     book_path);
151 	if(error_code != EB_SUCCESS){
152 		LOG(LOG_CRITICAL, "Failed to bind the book : %s",
153 			ebook_error_message(error_code));
154 		goto FAILED;
155 	}
156 
157 	error_code = eb_subbook_list(
158 		binfo->book,
159 		sublist,
160 		&subcount);
161 	if(error_code != EB_SUCCESS){
162 		LOG(LOG_CRITICAL, "Failed to get a subbook list : %s",
163 			ebook_error_message(error_code));
164 		goto FAILED;
165 	}
166 
167 
168 	error_code = eb_subbook_directory2(
169 		binfo->book,
170 		sublist[binfo->subbook_no],
171 		buff);
172 	if (error_code != EB_SUCCESS){
173 		LOG(LOG_CRITICAL, "Failed to get the directory : %s",
174 			ebook_error_message(error_code));
175 		goto FAILED;
176 	}
177 	binfo->subbook_dir = strdup(buff);
178 
179 	error_code = eb_subbook_title2(
180 		binfo->book,
181 		sublist[binfo->subbook_no],
182 		buff);
183 	if (error_code != EB_SUCCESS){
184 		LOG(LOG_CRITICAL, "Failed to get the title : %s",
185 			ebook_error_message(error_code));
186 		goto FAILED;
187 	}
188 	binfo->subbook_title = iconv_convert("euc-jp", "utf-8", buff);
189 
190 
191 	if(binfo->appendix_path != NULL){
192 		binfo->appendix = (EB_Appendix *) malloc(sizeof(EB_Appendix));
193 		eb_initialize_appendix(binfo->appendix);
194 
195 		error_code = eb_bind_appendix(binfo->appendix,
196 					      appendix_path);
197 		if(error_code != EB_SUCCESS){
198 			LOG(LOG_CRITICAL, "Failed to bind appendix : %s",
199 				ebook_error_message(error_code));
200 			goto FAILED;
201 		}
202 	}
203 
204 
205 
206 	ebook_set_subbook(binfo);
207 
208 	binfo->available = TRUE;
209 
210 	if(eb_have_word_search(binfo->book)){
211 		binfo->search_method[SEARCH_METHOD_WORD] = TRUE;
212 	}
213 
214 	if(eb_have_endword_search(binfo->book)){
215 		binfo->search_method[SEARCH_METHOD_ENDWORD] = TRUE;
216 	}
217 
218 	if(eb_have_exactword_search(binfo->book)){
219 		binfo->search_method[SEARCH_METHOD_EXACTWORD] = TRUE;
220 	}
221 
222 	if(eb_have_keyword_search(binfo->book)){
223 		binfo->search_method[SEARCH_METHOD_KEYWORD] = TRUE;
224 	}
225 /*
226 	eb_multi_search_list(binfo->book, multi_list, &multi_count);
227 	for (i = 0; i < multi_count; i++) {
228 		binfo->search_method[SEARCH_METHOD_MULTI1+i] = TRUE;
229 	}
230 */
231 	if(eb_have_multi_search(binfo->book)){
232 		binfo->search_method[SEARCH_METHOD_MULTI] = TRUE;
233 	}
234 
235 	if(eb_have_menu(binfo->book)){
236 		binfo->search_method[SEARCH_METHOD_MENU] = TRUE;
237 	}
238 
239 	if(eb_have_copyright(binfo->book)){
240 		binfo->search_method[SEARCH_METHOD_COPYRIGHT] = TRUE;
241 	}
242 
243 	if (eb_have_font(binfo->book, EB_FONT_16)){
244 		error_code = eb_set_font(binfo->book, EB_FONT_16);
245 		if (error_code != EB_SUCCESS) {
246 			LOG(LOG_CRITICAL, "Failed to set font : subbook=%s\n%s",
247 				binfo->subbook_title,
248 				ebook_error_message(error_code));
249 		}
250 	}
251 
252 	if(bg && (strlen(bg) != 0))
253 		binfo->bg = strdup(bg);
254 
255 	if(fg && (strlen(fg) != 0))
256 		binfo->fg = strdup(fg);
257 
258 	book_list = g_list_append(book_list, binfo);
259 
260 	LOG(LOG_DEBUG, "OUT : load_book()");
261 	return(binfo);
262 
263  FAILED:
264 	binfo->available = FALSE;
265 
266 	LOG(LOG_DEBUG, "OUT : load_book() = NULL");
267 
268 	return(NULL);
269 }
270 
free_gaiji(BOOK_INFO * binfo)271 static void free_gaiji(BOOK_INFO *binfo){
272 
273 	GList *lists[8];
274 	GList *item;
275 	gint i;
276 
277 	LOG(LOG_DEBUG, "IN : free_gaiji()");
278 
279 	lists[0] = binfo->gaiji_narrow16;
280 	lists[1] = binfo->gaiji_narrow24;
281 	lists[2] = binfo->gaiji_narrow30;
282 	lists[3] = binfo->gaiji_narrow48;
283 	lists[4] = binfo->gaiji_wide16;
284 	lists[5] = binfo->gaiji_wide24;
285 	lists[6] = binfo->gaiji_wide30;
286 	lists[7] = binfo->gaiji_wide48;
287 
288 
289 
290 	for(i=0; i < 8 ; i ++){
291 		item = g_list_first(lists[i]);
292 		while(item){
293 			free(item->data);
294 			item = g_list_next(item);
295 		}
296 		g_list_free(lists[i]);
297 	}
298 
299 	binfo->gaiji_narrow16 = NULL;
300 	binfo->gaiji_narrow24 = NULL;
301 	binfo->gaiji_narrow30 = NULL;
302 	binfo->gaiji_narrow48 = NULL;
303 	binfo->gaiji_wide16 = NULL;
304 	binfo->gaiji_wide24 = NULL;
305 	binfo->gaiji_wide30 = NULL;
306 	binfo->gaiji_wide48 = NULL;
307 
308 	LOG(LOG_DEBUG, "OUT : free_gaiji()");
309 }
310 
unload_book(BOOK_INFO * binfo)311 void unload_book(BOOK_INFO *binfo)
312 {
313 
314 	LOG(LOG_DEBUG, "IN : unload_book()");
315 
316 	eb_unset_subbook(binfo->book);
317 	eb_finalize_book(binfo->book);
318 	free(binfo->book_path);
319 	free(binfo->appendix_path);
320 	free(binfo->subbook_dir);
321 	free(binfo->subbook_title);
322 
323 	free_gaiji(binfo);
324 
325 	book_list = g_list_remove(book_list, binfo);
326 
327 	LOG(LOG_DEBUG, "OUT : unload_book()");
328 	return;
329 }
330 
check_search_method()331 void check_search_method()
332 {
333 
334 #if 0
335 	BOOK_INFO *binfo;
336 	GList *book_item;
337 #endif
338 	gint method_count=0;
339 
340 	LOG(LOG_DEBUG, "IN : check_search_method()");
341 
342 #if 0
343 	menu_word_search = FALSE;
344 	menu_endword_search = FALSE;
345 	menu_exactword_search = FALSE;
346 	menu_keyword_search = FALSE;
347 	menu_menu = FALSE;
348 	menu_copyright = FALSE;
349 	menu_multi_search = FALSE;
350 
351 	book_item = g_list_first(book_list);
352 	while(book_item != NULL){
353 		binfo = (BOOK_INFO *)(book_item->data);
354 		if(binfo->search_method[SEARCH_METHOD_WORD] == TRUE)
355 			menu_word_search = TRUE;
356 		if(binfo->search_method[SEARCH_METHOD_ENDWORD] == TRUE)
357 			menu_endword_search = TRUE;
358 		if(binfo->search_method[SEARCH_METHOD_EXACTWORD] == TRUE)
359 			menu_exactword_search = TRUE;
360 		if(binfo->search_method[SEARCH_METHOD_KEYWORD] == TRUE)
361 			menu_keyword_search = TRUE;
362 		if(binfo->search_method[SEARCH_METHOD_MENU] == TRUE)
363 			menu_menu = TRUE;
364 		if(binfo->search_method[SEARCH_METHOD_COPYRIGHT] == TRUE)
365 			menu_copyright = TRUE;
366 		if(binfo->search_method[SEARCH_METHOD_MULTI] == TRUE)
367 			menu_multi_search = TRUE;
368 
369 		book_item = g_list_next(book_item);
370 	}
371 
372 	method_count = 0;
373 
374 	search_method[method_count].code = SEARCH_METHOD_AUTOMATIC;
375 	search_method[method_count].name = strdup(_("Automatic Search"));
376 	method_count ++;
377 
378 	if(menu_exactword_search == TRUE){
379 		search_method[method_count].code = SEARCH_METHOD_EXACTWORD;
380 		search_method[method_count].name = strdup(_("Exactword Search"));
381 		method_count ++;
382 	}
383 
384 	if(menu_word_search == TRUE){
385 		search_method[method_count].code = SEARCH_METHOD_WORD;
386 		search_method[method_count].name = strdup(_("Forward Search"));
387 		method_count ++;
388 	}
389 
390 	if(menu_endword_search == TRUE){
391 		search_method[method_count].code = SEARCH_METHOD_ENDWORD;
392 		search_method[method_count].name = strdup(_("Backward Search"));
393 		method_count ++;
394 	}
395 
396 	if(menu_keyword_search == TRUE){
397 		search_method[method_count].code = SEARCH_METHOD_KEYWORD;
398 		search_method[method_count].name = strdup(_("Keyword Search"));
399 		method_count ++;
400 	}
401 
402 	if(menu_multi_search == TRUE){
403 		search_method[method_count].code = SEARCH_METHOD_MULTI;
404 		search_method[method_count].name = strdup(_("Multiword Search"));
405 		method_count ++;
406 	}
407 
408 /*
409 	if(menu_menu == TRUE){
410 		search_method[method_count].code = SEARCH_METHOD_MENU;
411 		search_method[method_count].name = strdup(_("Menu"));
412 		method_count ++;
413 	}
414 
415 	if(menu_copyright == TRUE){
416 		search_method[method_count].code = SEARCH_METHOD_COPYRIGHT;
417 		search_method[method_count].name = strdup(_("Copyright"));
418 		method_count ++;
419 	}
420 */
421 
422 	search_method[method_count].code = SEARCH_METHOD_FULL_TEXT;
423 	search_method[method_count].name = strdup(_("Full Text Search"));
424 	method_count ++;
425 
426 	search_method[method_count].code = SEARCH_METHOD_INTERNET;
427 	search_method[method_count].name = strdup(_("Internet Search"));
428 	method_count ++;
429 
430 	search_method[method_count].code = SEARCH_METHOD_GREP;
431 	search_method[method_count].name = strdup(_("File Search"));
432 	method_count ++;
433 
434 
435 	search_method[method_count].name = NULL;
436 
437 #endif
438 
439 	method_count = 0;
440 
441 	search_method[method_count].code = SEARCH_METHOD_AUTOMATIC;
442 	search_method[method_count].name = strdup(_("Automatic Search"));
443 	method_count ++;
444 
445 	search_method[method_count].code = SEARCH_METHOD_EXACTWORD;
446 	search_method[method_count].name = strdup(_("Exactword Search"));
447 	method_count ++;
448 
449 	search_method[method_count].code = SEARCH_METHOD_WORD;
450 	search_method[method_count].name = strdup(_("Forward Search"));
451 	method_count ++;
452 
453 	search_method[method_count].code = SEARCH_METHOD_ENDWORD;
454 	search_method[method_count].name = strdup(_("Backward Search"));
455 	method_count ++;
456 
457 	search_method[method_count].code = SEARCH_METHOD_KEYWORD;
458 	search_method[method_count].name = strdup(_("Keyword Search"));
459 	method_count ++;
460 
461 	search_method[method_count].code = SEARCH_METHOD_MULTI;
462 	search_method[method_count].name = strdup(_("Multiword Search"));
463 	method_count ++;
464 
465 /*
466 	search_method[method_count].code = SEARCH_METHOD_MENU;
467 	search_method[method_count].name = strdup(_("Menu"));
468 	method_count ++;
469 
470 	search_method[method_count].code = SEARCH_METHOD_COPYRIGHT;
471 	search_method[method_count].name = strdup(_("Copyright"));
472 	method_count ++;
473 */
474 
475 	search_method[method_count].code = SEARCH_METHOD_FULL_TEXT;
476 	search_method[method_count].name = strdup(_("Full Text Search"));
477 	method_count ++;
478 
479 	search_method[method_count].code = SEARCH_METHOD_INTERNET;
480 	search_method[method_count].name = strdup(_("Internet Search"));
481 	method_count ++;
482 
483 	search_method[method_count].code = SEARCH_METHOD_GREP;
484 	search_method[method_count].name = strdup(_("File Search"));
485 	method_count ++;
486 
487 	search_method[method_count].name = NULL;
488 
489 
490 	LOG(LOG_DEBUG, "OUT : check_search_method()");
491 
492 }
493 
ebook_start()494 gint ebook_start(){
495 	EB_Error_Code error_code;
496 
497 	LOG(LOG_DEBUG, "IN : ebook_start()");
498 
499 	error_code = eb_initialize_library();
500 	if(error_code != EB_SUCCESS){
501 		LOG(LOG_CRITICAL, "Failed to initialize library : %s",
502 			ebook_error_message(error_code));
503 		return(1);
504 	}
505 
506 	error_code = initialize_hooksets();
507 	if(error_code != EB_SUCCESS){
508 		return(1);
509 	}
510 
511 	ebook_initialized = TRUE;
512 
513 	LOG(LOG_DEBUG, "OUT : ebook_start()");
514 	return(0);
515 
516 }
517 
ebook_end()518 gint ebook_end(){
519 
520 	BOOK_INFO *binfo;
521 	GList *book_item;
522 
523 	LOG(LOG_DEBUG, "IN : ebook_end()");
524 
525 	if(ebook_initialized == TRUE) {
526 		LOG(LOG_DEBUG, "OUT : ebook_end()");
527 		return(0);
528 	}
529 
530 	book_item = g_list_first(book_list);
531 	while(book_item != NULL){
532 		binfo = (BOOK_INFO *)(book_item->data);
533 		eb_unset_subbook(binfo->book);
534 		eb_finalize_book(binfo->book);
535 	        free(binfo->book_path);
536 	        free(binfo->appendix_path);
537 	        free(binfo->subbook_dir);
538 	        free(binfo->subbook_title);
539 
540 		free_gaiji(binfo);
541 
542 		g_list_remove(book_list, book_item->data);
543 		book_item = g_list_next(book_item);
544 	}
545 
546 	finalize_hooksets();
547 
548 	book_list = NULL;
549 	ebook_initialized = FALSE;
550 
551 	LOG(LOG_DEBUG, "OUT : ebook_end()");
552 	return(0);
553 }
554 
split_word(const gchar * word,gchar ** keywords)555 void split_word(const gchar *word, gchar **keywords)
556 {
557 	gint i,j;
558 	gchar *p;
559 	gchar buff[512];
560 	gint quoted=0;
561 
562 	LOG(LOG_DEBUG, "IN : split_word(%s)", word);
563 
564 	p = (gchar *)word;
565 	i = 0;
566 	j = 0;
567 	keywords[0] = NULL;
568 
569 	if(strlen(word) > 512){
570 		return;
571 	}
572 
573 	while(1){
574 		switch(*p){
575 		case '\"':
576 			if(quoted)
577 				quoted = 0;
578 			else
579 				quoted = 1;
580 			break;
581 		case ' ':
582 		case '\t':
583 		case '\n':
584 			if(quoted){
585 				buff[j] = *p;
586 				j ++;
587 			} else {
588 				buff[j] = '\0';
589 				keywords[i] = strdup(buff);
590 				i ++;
591 				keywords[i] = NULL;
592 				j = 0;
593 			}
594 			break;
595 		default:
596 			buff[j] = *p;
597 			j ++;
598 		}
599 		p++;
600 		if(*p == '\0'){
601 			buff[j] = '\0';
602 			if(strlen(buff) != 0){
603 				keywords[i] = strdup(buff);
604 				i ++;
605 			}
606 			keywords[i] = NULL;
607 			break;
608 		} else if(i == EBOOK_MAX_KEYWORDS) {
609 			break;
610 		}
611 	}
612 
613 	for(i=0; ; i++){
614 		if(keywords[i] == NULL)
615 			break;
616 	}
617 
618 	LOG(LOG_DEBUG, "OUT : split_word()");
619 }
620 
cat_word(char * string,char ** words)621 void cat_word(char *string, char **words){
622 	gint i;
623 	gint len = 0;
624 
625 	LOG(LOG_DEBUG, "IN : cat_word()");
626 
627 	sprintf(string, "%s", words[0]);
628 	len = strlen(words[0]);
629 
630 	for(i=1 ; words[i] != NULL ; i++){
631 		strcat(string, " ");
632 		strcat(string, words[i]);
633 		len = len + strlen(words[i]) + 1;
634 	}
635 	string[len] = '\0';
636 
637 	LOG(LOG_DEBUG, "OUT : cat_word() = %s", string);
638 }
639 
free_words(char ** words)640 void free_words(char **words){
641 	gint i;
642 
643 	LOG(LOG_DEBUG, "IN : free_words()");
644 
645 	for(i=0; words[i] != NULL ; i++)
646 		free(words[i]);
647 
648 	LOG(LOG_DEBUG, "OUT : free_words()");
649 }
650 
check_duplicate_hit(EB_Position pos)651 static gboolean check_duplicate_hit(EB_Position pos){
652 	GList *l;
653 	RESULT *rp;
654 
655 	l = search_result;
656 	while(l != NULL){
657 		rp = (RESULT *)(l->data);
658 		if((rp->data.eb.pos_text.page == pos.page) &&
659 		   (rp->data.eb.pos_text.offset == pos.offset))
660 			return(TRUE);
661 		l = g_list_next(l);
662 	}
663 	return(FALSE);
664 }
665 
count_result(GList * result)666 static gint count_result(GList *result)
667 {
668 	return(g_list_length(result));
669 }
670 
ebook_my_backward_text(BOOK_INFO * binfo)671 EB_Error_Code ebook_my_backward_text(BOOK_INFO *binfo)
672 {
673 
674 	EB_Error_Code error_code=EB_SUCCESS;
675 	EB_Position text_position;
676 	char data[EB_SIZE_PAGE+4];
677 	int i;
678 	ssize_t length;
679 
680 	int start_page;
681 	int end_page;
682 	int current_page;
683 	int current_offset;
684 	int offset;
685 	int read_page;
686 
687 	int stop_code;
688 
689 
690 	error_code = ebook_set_subbook(binfo);
691 	if(error_code != EB_SUCCESS){
692 		LOG(LOG_CRITICAL, "Failed to set subbook : %s",
693 			ebook_error_message(error_code));
694 		return(error_code);
695 	}
696 
697 	start_page = binfo->book->subbook_current->text.start_page;
698 	end_page = binfo->book->subbook_current->text.end_page;
699 
700 	error_code = eb_tell_text(binfo->book, &text_position);
701 	if(error_code != EB_SUCCESS){
702 		LOG(LOG_CRITICAL, "Failed to tell text : %s",
703 			ebook_error_message(error_code));
704 		return(error_code);
705 	}
706 
707 	current_page = text_position.page;
708 	current_offset = text_position.offset;
709 
710 	offset = current_offset;
711 
712 	stop_code = binfo->book->text_context.auto_stop_code;
713 
714 	for(read_page = current_page ; read_page >= start_page ; read_page --){
715 
716 		text_position.page = read_page;
717 		text_position.offset = 0;
718 
719 		error_code = eb_seek_text(binfo->book, &text_position);
720 		if (error_code != EB_SUCCESS) {
721 			LOG(LOG_CRITICAL, "Failed to seek text : %s",
722 				ebook_error_message(error_code));
723 			return(error_code);
724 		}
725 
726 		memset(data, 0, EB_SIZE_PAGE + 4);
727 
728 		error_code = eb_read_rawtext(binfo->book,
729 					     EB_SIZE_PAGE+2,
730 					     data,
731 					     &length);
732 		if (error_code != EB_SUCCESS || length != EB_SIZE_PAGE+2){
733 			LOG(LOG_CRITICAL, "Failed to read rawtext : %s",
734 				ebook_error_message(error_code));
735 			return(error_code);
736 		}
737 
738 		if(stop_code != -1)
739 			binfo->book->text_context.auto_stop_code = stop_code;
740 
741 
742 		for(i=offset-2 ; i >= 0 ; i -=2){
743 			if(((binfo->appendix != NULL) &&
744 			    (eb_uint2(&data[i]) == binfo->appendix->subbook_current->stop_code0) &&
745 			    (eb_uint2(&data[i+2]) == binfo->appendix->subbook_current->stop_code1)) ||
746 
747 			   ((binfo->appendix == NULL) &&
748 			    (eb_uint2(&data[i]) == 0x1f41) &&
749 			    (eb_uint1(&data[i+2]) == 0x01)) ||
750 			   (eb_uint2(&data[i]) == 0x1f02))
751 			{
752 
753 				text_position.page = read_page;
754 				text_position.offset = i;
755 
756 				error_code = eb_seek_text(binfo->book, &text_position);
757 				if (error_code != EB_SUCCESS) {
758 					LOG(LOG_CRITICAL, "Failed to seek text : %s",
759 						ebook_error_message(error_code));
760 					return(error_code);
761 				}
762 
763 				if(stop_code != -1)
764 					binfo->book->text_context.auto_stop_code = stop_code;
765 
766 				return(EB_SUCCESS);
767 
768 			}
769 
770 		}
771 
772 		offset = EB_SIZE_PAGE + 2;
773 	}
774 
775 	text_position.page = current_page;
776 	text_position.offset = current_offset;
777 
778 	error_code = eb_seek_text(binfo->book, &text_position);
779 	if (error_code != EB_SUCCESS) {
780 		LOG(LOG_CRITICAL, "Failed to seek text : %s",
781 			ebook_error_message(error_code));
782 		return(error_code);
783 	}
784 
785 	return(EB_ERR_FAIL_SEEK_TEXT);
786 
787 }
788 
789 gint ascii_to_jisx2080_table [] = {
790 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00
791 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x08
792 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x10
793 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x18
794 	0x2121, 0x212a, 0x2140, 0x2174, 0x2170, 0x2173, 0x2175, 0x2147, // 0x20
795 	0x214a, 0x214b, 0x2176, 0x215c, 0x2124, 0x215d, 0x2125, 0x213f, // 0x28
796 	0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337, // 0x30
797 	0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, 0x2129, // 0x38
798 	0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347, // 0x40
799 	0x2348, 0x2349, 0x234a, 0x234b, 0x234c, 0x234d, 0x234e, 0x234f, // 0x48
800 	0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357, // 0x50
801 	0x2358, 0x2359, 0x235a, 0x214e, 0x216f, 0x214f, 0x2130, 0x2132, // 0x58
802 	0x212e, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367, // 0x60
803 	0x2368, 0x2369, 0x236a, 0x236b, 0x236c, 0x236d, 0x236e, 0x236f, // 0x68
804 	0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377, // 0x70
805 	0x2378, 0x2379, 0x237a, 0x2150, 0x2143, 0x2151, 0x2141, 0x0000  // 0x78
806 };
807 
euc2jis(gchar * inbuf)808 static gchar *euc2jis(gchar *inbuf){
809 	guchar *euc_p;
810 	guchar *jisbuf=NULL;
811 	guchar *jis_p;
812 
813 	euc_p = inbuf;
814 	jis_p = jisbuf = malloc(strlen(euc_p)*2);
815 
816 	while(*euc_p != '\0'){
817 		if(( 0x20 <= *euc_p) && (*euc_p <= 0x7e) && (ascii_to_jisx2080_table[*euc_p] != 0x00)){
818 			*jis_p = (ascii_to_jisx2080_table[*euc_p] & 0xff00) >> 8;
819 			jis_p ++;
820 			*jis_p = ascii_to_jisx2080_table[*euc_p] & 0xff;
821 			jis_p ++;
822 		}
823 		else if(iseuc(euc_p)){
824 			*jis_p = *euc_p - 0x80;
825 			jis_p ++;
826 			euc_p++;
827 			*jis_p = *euc_p - 0x80;
828 			jis_p ++;
829 		}
830 
831 		else if(*euc_p == 0x20){
832 			*jis_p = 0x21;
833 			jis_p ++;
834 			*jis_p = 0x21;
835 			jis_p ++;
836 		}
837 
838 		else {
839 			*jis_p = 0x21;
840 			jis_p ++;
841 			*jis_p = 0x29;
842 			jis_p ++;
843 		}
844 
845 		euc_p ++;
846 	}
847 	*jis_p = '\0';
848 
849 	return(jisbuf);
850 }
851 
ebook_full_search_old(BOOK_INFO * binfo,char * word,gint method,gchar * title)852 static gint ebook_full_search_old(BOOK_INFO *binfo, char *word, gint method, gchar *title)
853 {
854 
855 	EB_Error_Code error_code=EB_SUCCESS;
856 	EB_Position text_position;
857 	char data[EB_SIZE_PAGE];
858 	char *jisword;
859 	char *word_p;
860 	int i;
861 	ssize_t length;
862 	char *p;
863 	char heading[MAXLEN_TEXT + 1];
864 	RESULT *rp;
865 
866 	int start_page;
867 	int end_page;
868 	int current_page;
869 
870 	int stop_code;
871 	int page_count=0;
872 
873 	LOG(LOG_DEBUG, "IN : ebook_full_search(%s)", word);
874 
875 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
876 		return(error_code);
877 
878 	start_page = binfo->book->subbook_current->text.start_page;
879 	end_page = binfo->book->subbook_current->text.end_page;
880 
881 	// Read once in order to determine auto_stop_code
882 	p = ebook_get_text(binfo, start_page, 0);
883 	if(p)
884 		free(p);
885 	stop_code = binfo->book->text_context.auto_stop_code;
886 
887 	jisword = euc2jis(word);
888 	word_p = jisword;
889 
890 	for(current_page = start_page ; current_page <= end_page ; current_page ++){
891 
892 		set_progress((float)(current_page - start_page) / (end_page - start_page + 1));
893 		page_count ++;
894 
895 		text_position.page = current_page;
896 		text_position.offset = 0;
897 
898 		error_code = eb_seek_text(binfo->book, &text_position);
899 		if (error_code != EB_SUCCESS) {
900 			LOG(LOG_CRITICAL, "Failed to seek text : %s",
901 				ebook_error_message(error_code));
902 			return(error_code);
903 		}
904 
905 		error_code = eb_read_rawtext(binfo->book,
906 					     EB_SIZE_PAGE,
907 					     data,
908 					     &length);
909 		if (error_code != EB_SUCCESS || length != EB_SIZE_PAGE){
910 			LOG(LOG_CRITICAL, "Failed to read rawtext : %s",
911 				ebook_error_message(error_code));
912 			return(error_code);
913 		}
914 
915 		for(i=0 ; i < EB_SIZE_PAGE ; i +=2){
916 
917 			// skip control characters
918 			if(isjisp(&data[i]) != TRUE){
919 				continue;
920 
921 			// match
922 			} else if((data[i] == *word_p) &&
923 				  (data[i+1] == *(word_p+1))){
924 
925 				// See if keyword continues
926 				if (*(word_p+2) != '\0'){
927 					word_p += 2;
928 					continue;
929 				}
930 			// In case ignoring upper letters and lower letters
931 			} else if(full_text_search_ignore_case){
932 				guint c1, c2;
933 
934 				c1 = eb_uint2(&data[i]);
935 				c2 = eb_uint2(word_p);
936 
937 				// Alphabet
938 				if ((0x2341 <= c1) && (c1 <= 0x237a) &&
939 				    (0x2341 <= c2) && (c2 <= 0x237a)){
940 					// Convert to lower and do match
941 					if(((0x2361 <= c1) ? (c1 - 0x20) : c1) == ((0x2361 <= c2) ? (c2 - 0x20) : c2)){
942 						// See if keyword continues
943 						if (*(word_p+2) != '\0'){
944 							word_p += 2;
945 							continue;
946 						}
947 					} else {
948 						goto NO_MATCH;
949 					}
950 				} else {
951 					goto NO_MATCH;
952 				}
953 			} else {
954 				goto NO_MATCH;
955 			}
956 
957 
958 			// Match then read
959 
960 			text_position.page = current_page;
961 			text_position.offset = i;
962 
963 			error_code = eb_seek_text(binfo->book, &text_position);
964 			if (error_code != EB_SUCCESS) {
965 				LOG(LOG_CRITICAL, "Failed to seek text : %s",
966 					ebook_error_message(error_code));
967 				// Do nothing
968 				goto NO_MATCH;
969 			}
970 
971 			// Because eb_seek_text() will clear auto_stop_code,
972 			// restore old value.
973 			if(stop_code != -1)
974 				binfo->book->text_context.auto_stop_code = stop_code;
975 
976 			error_code = ebook_my_backward_text(binfo);
977 			if(error_code != EB_SUCCESS){
978 				LOG(LOG_CRITICAL, "Failed to back text : %s",
979 					ebook_error_message(error_code));
980 				// Do nothing
981 				goto NO_MATCH;
982 			}
983 
984 
985 			error_code = eb_tell_text(binfo->book, &text_position);
986 			if(error_code != EB_SUCCESS){
987 				LOG(LOG_CRITICAL, "Failed to tell text : %s",
988 					ebook_error_message(error_code));
989 				// Do nothing
990 				goto NO_MATCH;
991 			}
992 
993 			if(check_duplicate_hit(text_position) == TRUE){
994 				// Do nothing
995 				goto NO_MATCH;
996 			}
997 
998 
999 			error_code = eb_read_text(binfo->book, binfo->appendix, &heading_hookset,
1000 						  NULL, MAXLEN_TEXT, heading, &length);
1001 			if (error_code != EB_SUCCESS) {
1002 				LOG(LOG_CRITICAL, "Failed to read text : %s",
1003 					ebook_error_message(error_code));
1004 				// Do nothing
1005 				goto NO_MATCH;
1006 			}
1007 			heading[length] = '\0';
1008 
1009 			p = strchr(heading, '\n');
1010 			if(p != NULL)
1011 				*p = '\0';
1012 
1013 
1014 			rp = (RESULT *)calloc(sizeof(RESULT),1);
1015 			if(rp == NULL){
1016 				LOG(LOG_ERROR, "No memory");
1017 				exit(1);
1018 			}
1019 
1020 			rp->heading = iconv_convert("euc-jp", "utf-8", heading);
1021 			rp->word = iconv_convert("euc-jp", "utf-8", word);
1022 			rp->type = RESULT_TYPE_EB;
1023 			rp->data.eb.book_info = binfo;
1024 			rp->data.eb.search_method = method;
1025 			rp->data.eb.dict_title = strdup(title);
1026 
1027 			rp->data.eb.pos_heading = text_position;
1028 			rp->data.eb.pos_text = text_position;
1029 
1030 			add_result(rp);
1031 
1032 			if((binfo->book->text_context.auto_stop_code != stop_code) &&
1033 			   (binfo->book->text_context.auto_stop_code != -1))
1034 				stop_code = binfo->book->text_context.auto_stop_code;
1035 			pthread_testcancel();
1036 
1037 		NO_MATCH:
1038 			word_p = jisword;
1039 			continue;
1040 		}
1041 	}
1042 
1043 	free(jisword);
1044 
1045 	LOG(LOG_DEBUG, "OUT : ebook_full_search()");
1046 	return(error_code);
1047 }
1048 
1049 // Full text search using BMH method.
ebook_full_search(BOOK_INFO * binfo,char * word,gint method,gchar * title)1050 static gint ebook_full_search(BOOK_INFO *binfo, char *word, gint method, gchar *title)
1051 {
1052 
1053 	EB_Error_Code error_code=EB_SUCCESS;
1054 	EB_Position text_position;
1055 	char data[EB_SIZE_PAGE];
1056 	char *jisword;
1057 	char *word_p;
1058 	ssize_t length;
1059 	char *p;
1060 	char heading[MAXLEN_TEXT + 1];
1061 	RESULT *rp;
1062 
1063 	int start_page;
1064 	int end_page;
1065 	int current_page;
1066 
1067 	int stop_code;
1068 	int page_count=0;
1069 
1070 	BMH_TABLE *bmh;
1071 	gchar *start_p;
1072 	gint word_len;
1073 
1074 	LOG(LOG_DEBUG, "IN : ebook_full_search(%s)", word);
1075 
1076 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
1077 		return(error_code);
1078 
1079 	start_page = binfo->book->subbook_current->text.start_page;
1080 	end_page = binfo->book->subbook_current->text.end_page;
1081 
1082 	// Read once in order to get auto_stop_code.
1083 	p = ebook_get_text(binfo, start_page, 0);
1084 	if(p)
1085 		free(p);
1086 	stop_code = binfo->book->text_context.auto_stop_code;
1087 
1088 	jisword = euc2jis(word);
1089 	word_p = jisword;
1090 
1091 	bmh = bmh_prepare(jisword, TRUE);
1092 
1093 	word_len = strlen(jisword);
1094 	memset(data, 0, word_len);
1095 
1096 	for(current_page = start_page ; current_page <= end_page ; current_page ++){
1097 
1098 		set_progress((float)(current_page - start_page) / (end_page - start_page + 1));
1099 		page_count ++;
1100 
1101 		text_position.page = current_page;
1102 		text_position.offset = 0;
1103 
1104 		error_code = eb_seek_text(binfo->book, &text_position);
1105 		if (error_code != EB_SUCCESS) {
1106 			LOG(LOG_CRITICAL, "Failed to seek text : %s",
1107 				ebook_error_message(error_code));
1108 			return(error_code);
1109 		}
1110 
1111 		error_code = eb_read_rawtext(binfo->book,
1112 					     EB_SIZE_PAGE,
1113 					     &data[word_len],
1114 					     &length);
1115 		if (error_code != EB_SUCCESS || length != EB_SIZE_PAGE){
1116 			LOG(LOG_CRITICAL, "Failed to read rawtext : %s",
1117 				ebook_error_message(error_code));
1118 			return(error_code);
1119 		}
1120 
1121 		start_p = data;
1122 		while(start_p){
1123 
1124 			start_p = bmh_search(bmh, start_p, EB_SIZE_PAGE + word_len - (start_p - data));
1125 
1126 			if(start_p == NULL)
1127 				break;
1128 
1129 			// Match then read
1130 
1131 			if((start_p - data) <= word_len) {
1132 				text_position.page = current_page - 1;
1133 				text_position.offset = EB_SIZE_PAGE - word_len;
1134 			} else {
1135 				text_position.page = current_page;
1136 				text_position.offset = start_p - data - word_len;
1137 			}
1138 
1139 			error_code = eb_seek_text(binfo->book, &text_position);
1140 			if (error_code != EB_SUCCESS) {
1141 				LOG(LOG_CRITICAL, "Failed to seek text : %s",
1142 					ebook_error_message(error_code));
1143 				// Do nothing
1144 				goto NO_MATCH;
1145 			}
1146 
1147 			// Because eb_seek_text() will clear auto_stop_code,
1148 			// restore old value.
1149 			if(stop_code != -1)
1150 				binfo->book->text_context.auto_stop_code = stop_code;
1151 
1152 			error_code = ebook_my_backward_text(binfo);
1153 			if(error_code != EB_SUCCESS){
1154 				LOG(LOG_CRITICAL, "Failed to back text : %s",
1155 					ebook_error_message(error_code));
1156 				// Do nothing
1157 				goto NO_MATCH;
1158 			}
1159 
1160 
1161 			error_code = eb_tell_text(binfo->book, &text_position);
1162 			if(error_code != EB_SUCCESS){
1163 				LOG(LOG_CRITICAL, "Failed to tell text : %s",
1164 					ebook_error_message(error_code));
1165 				// Do nothing
1166 				goto NO_MATCH;
1167 			}
1168 
1169 			if(check_duplicate_hit(text_position) == TRUE){
1170 				// Do nothing
1171 				goto NO_MATCH;
1172 			}
1173 
1174 
1175 			error_code = eb_read_text(binfo->book, binfo->appendix, &heading_hookset,
1176 						  NULL, MAXLEN_TEXT, heading, &length);
1177 			if (error_code != EB_SUCCESS) {
1178 				LOG(LOG_CRITICAL, "Failed to read text : %s",
1179 					ebook_error_message(error_code));
1180 				// Do nothing
1181 				goto NO_MATCH;
1182 			}
1183 			heading[length] = '\0';
1184 
1185 			p = strchr(heading, '\n');
1186 			if(p != NULL)
1187 				*p = '\0';
1188 
1189 
1190 			rp = (RESULT *)calloc(sizeof(RESULT),1);
1191 			if(rp == NULL){
1192 				LOG(LOG_ERROR, "No memory");
1193 				exit(1);
1194 			}
1195 
1196 			rp->heading = iconv_convert("euc-jp", "utf-8", heading);
1197 			rp->word = iconv_convert("euc-jp", "utf-8", word);
1198 			rp->type = RESULT_TYPE_EB;
1199 			rp->data.eb.book_info = binfo;
1200 			rp->data.eb.search_method = method;
1201 			rp->data.eb.dict_title = strdup(title);
1202 
1203 			rp->data.eb.pos_heading = text_position;
1204 			rp->data.eb.pos_text = text_position;
1205 
1206 			add_result(rp);
1207 
1208 			if((binfo->book->text_context.auto_stop_code != stop_code) &&
1209 			   (binfo->book->text_context.auto_stop_code != -1))
1210 				stop_code = binfo->book->text_context.auto_stop_code;
1211 			pthread_testcancel();
1212 
1213 		NO_MATCH:
1214 			start_p += word_len;
1215 			continue;
1216 		}
1217 
1218 	}
1219 
1220 	bmh_free(bmh);
1221 	free(jisword);
1222 
1223 	LOG(LOG_DEBUG, "OUT : ebook_full_search()");
1224 	return(error_code);
1225 }
1226 
1227 // Sort by dictionary, then search method
ebook_search2(char * g_word,GtkTreeIter * parent)1228 static gint ebook_search2(char *g_word, GtkTreeIter *parent)
1229 {
1230 
1231 	int j;
1232 	int method;
1233 	EB_Error_Code error_code=EB_SUCCESS;
1234 	GtkTreeIter iter;
1235 
1236 	gchar *word  = strdup(g_word);
1237 
1238 	LOG(LOG_DEBUG, "IN : ebook_search2()");
1239 
1240 	clear_search_result();
1241 
1242 	method = ebook_search_method();
1243 
1244 
1245 	if(gtk_tree_model_iter_children(GTK_TREE_MODEL(dict_store), &iter, parent) == TRUE){
1246 		do {
1247 
1248 			gint type;
1249 			gchar *title;
1250 			gboolean active;
1251 			BOOK_INFO *binfo;
1252 
1253 			gtk_tree_model_get(GTK_TREE_MODEL(dict_store),
1254 					   &iter,
1255 					   DICT_TYPE_COLUMN, &type,
1256 					   DICT_TITLE_COLUMN, &title,
1257 					   DICT_ACTIVE_COLUMN, &active,
1258 					   DICT_MEMBER_COLUMN, &binfo,
1259 					   -1);
1260 
1261 			if(active != TRUE)
1262 				continue;
1263 			if(binfo == NULL)
1264 				continue;
1265 			if(binfo->available == FALSE)
1266 				continue;
1267 
1268 
1269 			if(method == SEARCH_METHOD_AUTOMATIC){
1270 				for(j=SEARCH_METHOD_MIN ; j<=SEARCH_METHOD_MAX ; j++){
1271 
1272 				// Except word search and backward search.
1273 					if((j == SEARCH_METHOD_WORD) && (!bword_search_automatic))
1274 						continue;
1275 
1276 					if(j == SEARCH_METHOD_ENDWORD)
1277 						continue;
1278 
1279 					if(binfo->search_method[j] == TRUE){
1280 						if(bending_correction == 0){
1281 							error_code = ebook_simple_search(binfo, word, j, title);
1282 						} else {
1283 							error_code = ebook_ending_search(binfo, word, j, title);
1284 						}
1285 						if (error_code != EB_SUCCESS){
1286 							if(error_code == EB_ERR_TOO_MANY_WORDS)
1287 								continue;
1288 							LOG(LOG_CRITICAL, "Failed to search : %s",
1289 							    ebook_error_message(error_code));
1290 							goto END;
1291 						}
1292 					}
1293 				}
1294 			} else if((method == SEARCH_METHOD_FULL_TEXT) ||
1295 				  (method == SEARCH_METHOD_FULL_HEADING)){
1296 				set_cancel_dlg_text(binfo->subbook_title);
1297 				error_code = ebook_full_search(binfo, word, method, title);							goto END;
1298 			} else {
1299 				if(binfo->search_method[method] == TRUE){
1300 					if(bending_correction == 0){
1301 						error_code = ebook_simple_search(binfo, word, method, title);
1302 					} else {
1303 						error_code = ebook_ending_search(binfo, word, method, title);
1304 					}
1305 				}
1306 			}
1307 
1308 			g_free (title);
1309 			if(error_code != EB_SUCCESS)
1310 				goto END;
1311 
1312 		} while (gtk_tree_model_iter_next(GTK_TREE_MODEL(dict_store), &iter) == TRUE);
1313 	}
1314 
1315  END:
1316 	LOG(LOG_DEBUG, "OUT : ebook_search2()");
1317 	return 0;
1318 }
1319 
1320 // Sort by search method, then dictionary
ebook_search3(char * g_word,GtkTreeIter * parent)1321 static gint ebook_search3(char *g_word, GtkTreeIter *parent)
1322 {
1323 
1324 	int j;
1325 	int method;
1326 	EB_Error_Code error_code=EB_SUCCESS;
1327 	GtkTreeIter iter;
1328 
1329 	gchar *word  = strdup(g_word);
1330 
1331 	LOG(LOG_DEBUG, "IN : ebook_search3()");
1332 
1333 	clear_search_result();
1334 
1335 	method = ebook_search_method();
1336 
1337 
1338 	if(method == SEARCH_METHOD_AUTOMATIC){
1339 		for(j=SEARCH_METHOD_MIN ; j<=SEARCH_METHOD_MAX ; j++){
1340 
1341 			// Except word search and backward search
1342 			if((j == SEARCH_METHOD_WORD) && (!bword_search_automatic))
1343 				continue;
1344 
1345 			if(j == SEARCH_METHOD_ENDWORD)
1346 				continue;
1347 
1348 			if(gtk_tree_model_iter_children(GTK_TREE_MODEL(dict_store), &iter, parent) == TRUE){
1349 				do {
1350 					gint type;
1351 					gchar *title;
1352 					gboolean active;
1353 					BOOK_INFO *binfo;
1354 
1355 					gtk_tree_model_get(GTK_TREE_MODEL(dict_store),
1356 							   &iter,
1357 							   DICT_TYPE_COLUMN, &type,
1358 							   DICT_TITLE_COLUMN, &title,
1359 							   DICT_ACTIVE_COLUMN, &active,
1360 							   DICT_MEMBER_COLUMN, &binfo,
1361 							   -1);
1362 
1363 					if(active != TRUE)
1364 						continue;
1365 					if(binfo == NULL)
1366 						continue;
1367 					if(binfo->available == FALSE)
1368 						continue;
1369 
1370 
1371 					if(binfo->search_method[j] == TRUE){
1372 						if(bending_correction == 0){
1373 							error_code = ebook_simple_search(binfo, word, j, title);
1374 						} else {
1375 							error_code = ebook_ending_search(binfo, word, j, title);
1376 						}
1377 						if (error_code != EB_SUCCESS){
1378 							if(error_code == EB_ERR_TOO_MANY_WORDS)
1379 								continue;
1380 							LOG(LOG_CRITICAL, "Failed to search : %s",
1381 								ebook_error_message(error_code));
1382 							goto END;
1383 						}
1384 					}
1385 
1386 					g_free (title);
1387 
1388 				} while (gtk_tree_model_iter_next(GTK_TREE_MODEL(dict_store), &iter) == TRUE);
1389 			}
1390 
1391 		}
1392 
1393 	}
1394 
1395  END:
1396 	plain_heading();
1397 	sort_result(g_word);
1398 
1399 	LOG(LOG_DEBUG, "OUT : ebook_search3()");
1400 	return 0;
1401 }
1402 
plain_heading()1403 static void plain_heading()
1404 {
1405 	RESULT *rp;
1406 	GList *l;
1407 	gint len;
1408 	gchar *p;
1409 	gchar *pp;
1410 	guchar body[65536];
1411 	gint i;
1412 	gunichar ch;
1413 
1414 	gchar start_tag[512];
1415 	gchar tag_name[512];
1416 
1417 	for(l = search_result ; l != NULL; l = g_list_next(l)){
1418 		rp = (RESULT *)(l->data);
1419 
1420 
1421 		len = g_utf8_strlen(rp->heading, -1);
1422 		p = rp->heading;
1423 		pp = body;
1424 
1425 		for(i=0;i<len;i++){
1426 			ch = g_utf8_get_char(p);
1427 			if(ch == '<'){
1428 				get_start_tag(p, start_tag);
1429 				get_tag_name(start_tag, tag_name);
1430 
1431 				if(strcmp(tag_name, "gaiji") == 0){
1432 					skip_start_tag(&p, tag_name);
1433 				} else if(strcmp(tag_name, "sub") == 0){
1434 					skip_end_tag(&p, tag_name);
1435 				} else if(strcmp(tag_name, "sup") == 0){
1436 					skip_end_tag(&p, tag_name);
1437 
1438 				}
1439 			} else if(g_unichar_isspace(ch)){
1440 				p = g_utf8_next_char(p);
1441 			} else {
1442 				pp += g_unichar_to_utf8(ch,
1443 							pp);
1444 				*pp = '\0';
1445 				p = g_utf8_next_char(p);
1446 			}
1447 		}
1448 
1449 		rp->data.eb.plain_heading = g_strdup(body);
1450 
1451 	}
1452 }
1453 
sort_result(gchar * word)1454 static void sort_result(gchar *word)
1455 {
1456 	RESULT *rp;
1457 	GList *l;
1458 	GList *insert;
1459 	gchar l_word[512];
1460 	gunichar ch;
1461 	gint i;
1462 	gint len;
1463 	gchar *p;
1464         gchar *pp;
1465 
1466 	char *keywords[EBOOK_MAX_KEYWORDS + 1];
1467 
1468 	len = g_utf8_strlen(word, -1);
1469 
1470 	p = word;
1471 	pp = l_word;
1472 
1473 	for(i=0;i<len;i++){
1474 		ch = g_utf8_get_char(p);
1475 		if(g_unichar_isspace(ch) == FALSE){
1476 			pp += g_unichar_to_utf8(ch, pp);
1477 			*pp = '\0';
1478 		}
1479 		p = g_utf8_next_char(p);
1480 	}
1481 
1482 	insert = g_list_first(search_result);
1483 
1484 	// Exact match
1485 	for(l = search_result ; l != NULL; ){
1486 		rp = (RESULT *)(l->data);
1487 
1488 		if((strstr(rp->data.eb.plain_heading, l_word) == rp->data.eb.plain_heading) &&
1489 		   (strlen(rp->data.eb.plain_heading) == strlen(l_word))){
1490 			if(l != insert){
1491 				l = g_list_next(l);
1492 				search_result = g_list_remove(search_result, rp);
1493 				search_result = g_list_insert_before(search_result, insert, rp);
1494 				continue;
1495 			} else {
1496 				insert = g_list_next(insert);
1497 			}
1498 		}
1499 		l = g_list_next(l);
1500 	}
1501 
1502 	// Forward match
1503 	for(l = insert ; l != NULL; ){
1504 		rp = (RESULT *)(l->data);
1505 
1506 		if(strstr(rp->data.eb.plain_heading, l_word) == rp->data.eb.plain_heading){
1507 			if(l != insert){
1508 				l = g_list_next(l);
1509 				search_result = g_list_remove(search_result, rp);
1510 				search_result = g_list_insert_before(search_result, insert, rp);
1511 				continue;
1512 			} else {
1513 				insert = g_list_next(insert);
1514 			}
1515 		}
1516 		l = g_list_next(l);
1517 	}
1518 
1519 	// Partial match
1520 	for(l = insert ; l != NULL; ){
1521 		rp = (RESULT *)(l->data);
1522 
1523 		if(strstr(rp->data.eb.plain_heading, l_word) != NULL){
1524 			if(l != insert){
1525 				l = g_list_next(l);
1526 				search_result = g_list_remove(search_result, rp);
1527 				search_result = g_list_insert_before(search_result, insert, rp);
1528 				continue;
1529 			} else {
1530 				insert = g_list_next(insert);
1531 			}
1532 		}
1533 		l = g_list_next(l);
1534 	}
1535 
1536 
1537 	// keyword match
1538 	split_word(word, keywords);
1539 	for(l = insert ; l != NULL; ){
1540 		rp = (RESULT *)(l->data);
1541 
1542 		for(i=0 ; ; i++){
1543 			if(keywords[i] == NULL){
1544 				if(l != insert){
1545 					l = g_list_next(l);
1546 					search_result = g_list_remove(search_result, rp);
1547 					search_result = g_list_insert_before(search_result, insert, rp);
1548 					continue;
1549 				} else {
1550 					insert = g_list_next(insert);
1551 				}
1552 			}
1553 			if(strstr(rp->data.eb.plain_heading, l_word) == NULL)
1554 				break;
1555 		}
1556 		l = g_list_next(l);
1557 	}
1558 
1559 	free_words(keywords);
1560 
1561 }
1562 
ebook_search_thread(void * arg)1563 static void *ebook_search_thread(void *arg)
1564 {
1565 	char word[MAX_BUFSIZE];
1566 	gboolean active;
1567 	GtkTreeIter iter;
1568 	gint state;
1569 
1570 
1571 	LOG(LOG_DEBUG, "IN : ebook_search_thread(%s)", arg);
1572 
1573 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &state);
1574 	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &state);
1575 
1576 
1577 	strncpy(word, arg, sizeof(word) -1);
1578 	word[sizeof(word)-1] = '\0';
1579 
1580 	if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dict_store), &iter) == TRUE){
1581 		do {
1582 			gtk_tree_model_get (GTK_TREE_MODEL(dict_store),
1583 					    &iter,
1584 					    DICT_ACTIVE_COLUMN, &active,
1585 					    -1);
1586 			if(active == TRUE){
1587 				if((ebook_search_method() == SEARCH_METHOD_AUTOMATIC) &&
1588 				   (bsort_by_dictionary == FALSE)){
1589 					ebook_search3(word, &iter);
1590 				} else {
1591 					ebook_search2(word, &iter);
1592 				}
1593 				thread_end();
1594 				break;
1595 			}
1596 	       } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(dict_store), &iter) == TRUE);
1597 	}
1598 
1599 	LOG(LOG_DEBUG, "OUT : ebook_search_thread()");
1600 
1601 	return(NULL);
1602 }
1603 
1604 static gchar *gword=NULL;
1605 
ebook_search(const char * word,gint method)1606 gint ebook_search(const char *word, gint method)
1607 {
1608 	LOG(LOG_DEBUG, "IN : ebook_search(%s)", word);
1609 
1610 	if(gword != NULL)
1611 		g_free(gword);
1612 
1613 	gword = strdup(word);
1614 
1615 	if(method == SEARCH_METHOD_FULL_TEXT){
1616 		// Cancelable
1617 		thread_search(TRUE, _("Fulltext search"),
1618 			      ebook_search_thread, (void *)gword);
1619 	} else {
1620 		// Non-cancelable
1621 		thread_search(FALSE, _("Fulltext search"),
1622 			      ebook_search_thread, (void *)gword);
1623 	}
1624 
1625 	LOG(LOG_DEBUG, "OUT : ebook_search()");
1626 
1627 	return(0);
1628 
1629 }
1630 
ebook_search_auto(char * g_word,gint method)1631 gint ebook_search_auto(char *g_word, gint method)
1632 {
1633 	GtkTreeIter iter;
1634 
1635 	LOG(LOG_DEBUG, "IN : ebook_search_auto()");
1636 
1637 	if(method == SEARCH_METHOD_FULL_TEXT) {
1638 		LOG(LOG_DEBUG, "OUT : ebook_search_auto()");
1639 		return(0);
1640 	}
1641 
1642 	// Search group named "selection" and use it if exests
1643 	if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dict_store), &iter) == TRUE){
1644 		do {
1645 			gchar *title;
1646 
1647 			gtk_tree_model_get (GTK_TREE_MODEL(dict_store),
1648 					    &iter,
1649 					    DICT_TITLE_COLUMN, &title,
1650 					    -1);
1651 			if(strcasecmp(title, "selection") == 0){
1652 				g_free(title);
1653 				ebook_search2(g_word, &iter);
1654 				return(0);
1655 			}
1656 			g_free(title);
1657 	       } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(dict_store), &iter) == TRUE);
1658 	}
1659 
1660 	// If there is no "selection" group, use active group
1661 	if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dict_store), &iter) == TRUE){
1662 		do {
1663 			gboolean active;
1664 
1665 			gtk_tree_model_get (GTK_TREE_MODEL(dict_store),
1666 					    &iter,
1667 					    DICT_ACTIVE_COLUMN, &active,
1668 					    -1);
1669 			if(active == TRUE){
1670 				ebook_search2(g_word, &iter);
1671 				return(0);
1672 			}
1673 	       } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(dict_store), &iter) == TRUE);
1674 	}
1675 
1676 	LOG(LOG_DEBUG, "OUT : ebook_search_auto()");
1677 	return(0);
1678 }
1679 
1680 
ebook_simple_search2(BOOK_INFO * binfo,char * word,gint method,gchar * title)1681 gint ebook_simple_search2(BOOK_INFO *binfo, char *word, gint method, gchar *title)
1682 {
1683 	EB_Error_Code error_code=EB_SUCCESS;
1684 	int i, total_hits=0;
1685         ssize_t len;
1686 	EB_Hit hits[MAX_HITS];
1687 	int hitcount;
1688 	char heading[MAXLEN_HEADING + 1];
1689 	char *keywords[EBOOK_MAX_KEYWORDS + 1];
1690 	RESULT *rp;
1691 
1692 	LOG(LOG_DEBUG, "IN : ebook_simple_search2(%s, %s, %d, %s)", binfo->subbook_title, word, method, title);
1693 
1694 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS){
1695 		LOG(LOG_DEBUG, "OUT : ebook_simple_search2()");
1696 		return(error_code);
1697 	}
1698 
1699 	switch(method){
1700 	case SEARCH_METHOD_WORD:
1701 		error_code = eb_search_word(binfo->book, word);
1702 		break;
1703 	case SEARCH_METHOD_ENDWORD:
1704 		error_code = eb_search_endword(binfo->book, word);
1705 		break;
1706 	case SEARCH_METHOD_EXACTWORD:
1707 		error_code = eb_search_exactword(binfo->book, word);
1708 		break;
1709 	case SEARCH_METHOD_KEYWORD:
1710 		split_word(word, keywords);
1711 		error_code = eb_search_keyword(binfo->book,
1712 					       (const char * const *)keywords);
1713 		free_words(keywords);
1714 		break;
1715 	case SEARCH_METHOD_MULTI:
1716 		split_word(word, keywords);
1717 
1718 		for(i=0;i<EBOOK_MAX_KEYWORDS;i++){
1719 			if(keywords[i] == NULL)
1720 				break;
1721 		}
1722 
1723 		error_code = eb_search_multi(binfo->book,
1724 					       global_multi_code,
1725 					       (const char * const *)keywords);
1726 		free_words(keywords);
1727 		break;
1728 	default:
1729 		error_code = EB_ERR_NO_SUCH_SEARCH;
1730 		break;
1731 	}
1732 
1733 	if (error_code != EB_SUCCESS){
1734 		LOG(LOG_CRITICAL, "Failed to search : %s",
1735 			ebook_error_message(error_code));
1736 		return(error_code);
1737 	}
1738 
1739 	total_hits = count_result(search_result);
1740 
1741 	while(1){
1742 		error_code = eb_hit_list(binfo->book,
1743 					 MAX_HITS,
1744 					 hits,
1745 					 &hitcount);
1746 		if(error_code != EB_SUCCESS){
1747 			return(error_code);
1748 		}
1749 
1750 		if(hitcount == 0)
1751 			break;
1752 		LOG(LOG_DEBUG, "%d HIT", hitcount);
1753 
1754 		for(i = 0 ; i < hitcount ; i ++){
1755 			if((max_search != 0) && (total_hits >= max_search))
1756 				return(EB_SUCCESS);
1757 
1758 			if(check_duplicate_hit(hits[i].text) == TRUE)
1759 				continue;
1760 
1761 			rp = (RESULT *)calloc(sizeof(RESULT),1);
1762 			if(rp == NULL){
1763 				LOG(LOG_ERROR, "No memory");
1764 				exit(1);
1765 			}
1766 
1767 			error_code = eb_seek_text(binfo->book,
1768 						  &(hits[i].heading));
1769 
1770 			if(error_code != EB_SUCCESS){
1771 				return(error_code);
1772 			}
1773 
1774 			error_code = eb_read_heading(binfo->book,
1775 						     binfo->appendix,
1776 						     &heading_hookset,
1777 						     NULL,
1778 						     MAXLEN_HEADING,
1779 						     heading,
1780 						     &len);
1781 			if (error_code != EB_SUCCESS) {
1782 				return(error_code);
1783 			}
1784 			heading[len] = '\0';
1785 
1786 			rp->heading = iconv_convert("euc-jp", "utf-8", heading);
1787 			if(method == SEARCH_METHOD_MULTI)
1788 				rp->word = NULL;
1789 			else
1790 				rp->word = iconv_convert("euc-jp", "utf-8", word);
1791 
1792 			rp->type = RESULT_TYPE_EB;
1793 			rp->data.eb.book_info = binfo;
1794 			rp->data.eb.search_method = method;
1795 			rp->data.eb.dict_title = strdup(title);
1796 
1797 			rp->data.eb.pos_heading = hits[i].heading;
1798 			rp->data.eb.pos_text = hits[i].text;
1799 
1800 			add_result(rp);
1801 
1802 			total_hits ++;
1803 
1804 		}
1805 	}
1806 
1807 	LOG(LOG_DEBUG, "OUT : ebook_simple_search2()");
1808 	return(error_code);
1809 }
1810 
ebook_simple_search(BOOK_INFO * binfo,char * word,gint method,gchar * title)1811 gint ebook_simple_search(BOOK_INFO *binfo, char *word, gint method, gchar *title)
1812 {
1813 	gchar *l_word=NULL;
1814 	EB_Error_Code error_code=EB_SUCCESS;
1815 
1816 	LOG(LOG_DEBUG, "IN : ebook_simple_search()");
1817 
1818 	// If the keyword is Japanese, try Hiragana and Katakana
1819 
1820 	if(iseuc(word)){
1821 		l_word = g_strdup(word);
1822 		katakana_to_hiragana(l_word);
1823 		error_code = ebook_simple_search2(binfo, l_word, method, title);
1824 		if(error_code != EB_SUCCESS){
1825 			goto END;
1826 		}
1827 
1828 		hiragana_to_katakana(l_word);
1829 		error_code = ebook_simple_search2(binfo, l_word, method, title);
1830 	} else {
1831 		// Not Japanese
1832 		error_code = ebook_simple_search2(binfo, word, method, title);
1833 	}
1834  END:
1835 	g_free(l_word);
1836 	LOG(LOG_DEBUG, "OUT : ebook_simple_search()");
1837 	return(error_code);
1838 }
1839 
ebook_ending_search(BOOK_INFO * binfo,char * word,gint method,gchar * title)1840 static gint ebook_ending_search(BOOK_INFO *binfo, char *word, gint method, gchar *title)
1841 {
1842 	EB_Error_Code error_code=EB_SUCCESS;
1843 	gint i;
1844 	gint len_word, len_ending;
1845 	char *keywords[EBOOK_MAX_KEYWORDS + 1];
1846 	char new_word[MAX_BUFSIZE];
1847 	char new_key[256];
1848 	char *save_key;
1849 
1850 	GtkTreeIter   iter;
1851 
1852 	LOG(LOG_DEBUG, "IN : ebook_ending_search(method=%d)", method);
1853 
1854 
1855 	g_assert(binfo != NULL);
1856 	g_assert(word != NULL);
1857 
1858 	error_code = ebook_simple_search(binfo, word, method, title);
1859 
1860 	if((bending_only_nohit == 1) && (count_result(search_result) != 0)){
1861 		return(error_code);
1862 	}
1863 
1864 	split_word(word, keywords);
1865 
1866 	for(i=0; keywords[i] != NULL ; i++){
1867 
1868 		if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(stemming_en_store), &iter) == TRUE){
1869 			do {
1870 				gchar *pattern;
1871 				gchar *normal;
1872 
1873 				gtk_tree_model_get(GTK_TREE_MODEL(stemming_en_store),
1874 						   &iter,
1875 						   STEMMING_PATTERN_COLUMN, &pattern,
1876 						   STEMMING_NORMAL_COLUMN, &normal,
1877 						   -1);
1878 
1879 
1880 				len_word = strlen(keywords[i]);
1881 				len_ending = strlen(pattern);
1882 				if(len_word < len_ending){
1883 					continue;
1884 				}
1885 
1886 				if(strcmp(&keywords[i][len_word - len_ending], pattern) == 0){
1887 					memcpy(new_key, keywords[i], len_word - len_ending);
1888 					if(normal)
1889 						sprintf(&new_key[len_word - len_ending],"%s", normal);
1890 					else
1891 						new_key[len_word - len_ending] = '\0';
1892 					save_key = keywords[i];
1893 					keywords[i] = new_key;
1894 					cat_word(new_word, keywords);
1895 					error_code = ebook_simple_search(binfo, new_word, method, title);
1896 					keywords[i] = save_key;
1897 					if(error_code != EB_SUCCESS){
1898 						return(error_code);
1899 					}
1900 				}
1901 
1902 				g_free(pattern);
1903 				g_free(normal);
1904 
1905 			} while (gtk_tree_model_iter_next(GTK_TREE_MODEL(stemming_en_store), &iter) == TRUE);
1906 		}
1907 
1908 
1909 	}
1910 
1911 	// Japanese stemming
1912 	// Japanese keyword must not be multiple words.
1913 
1914 	if(keywords[1] == NULL){
1915 
1916 		if((count_result(search_result) != 0) &&
1917 		   (bending_only_nohit == 1))
1918 			goto END;
1919 
1920 		if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(stemming_ja_store), &iter) == TRUE){
1921 			do {
1922 				gchar *pattern;
1923 				gchar *normal;
1924 				gchar *tmp;
1925 
1926 				gtk_tree_model_get(GTK_TREE_MODEL(stemming_ja_store),
1927 						   &iter,
1928 						   STEMMING_PATTERN_COLUMN, &pattern,
1929 						   STEMMING_NORMAL_COLUMN, &normal,
1930 						   -1);
1931 
1932 				tmp = iconv_convert("utf-8", "euc-jp", pattern);
1933 				g_free(pattern);
1934 				pattern = tmp;
1935 
1936 				tmp = iconv_convert("utf-8", "euc-jp", normal);
1937 				g_free(normal);
1938 				normal = tmp;
1939 
1940 				len_word = strlen(keywords[0]);
1941 				len_ending = strlen(pattern);
1942 				if(len_word < len_ending){
1943 					continue;
1944 				}
1945 
1946 
1947 				for(i=0; i<len_word; i+=2){
1948 					if(strncmp(&keywords[0][i], pattern, len_ending) == 0){
1949 						memcpy(new_key, keywords[0], i);
1950 						sprintf(&new_key[i],"%s", normal);
1951 						error_code = ebook_simple_search(binfo, new_key, method, title);
1952 						if(error_code != EB_SUCCESS){
1953 							return(error_code);
1954 						}
1955 					}
1956 				}
1957 
1958 
1959 				g_free(pattern);
1960 				g_free(normal);
1961 
1962 			} while (gtk_tree_model_iter_next(GTK_TREE_MODEL(stemming_ja_store), &iter) == TRUE);
1963 		}
1964 
1965 		// If there is no hit, try using only Kanji part.
1966 		if((count_result(search_result) == 0) &&
1967 		   (iseuckanji(keywords[0]))){
1968 			len_word = strlen(keywords[0]);
1969 			strcpy(new_key, keywords[0]);
1970 			for(i=0; i<len_word; i+=2){
1971 				if(!iseuckanji(&new_key[i])) {
1972 					new_key[i] = '\0';
1973 					break;
1974 				}
1975 			}
1976 
1977 			error_code = ebook_simple_search(binfo, new_key, method, title);
1978 			if(error_code != EB_SUCCESS){
1979 				return(error_code);
1980 			}
1981 		}
1982 	}
1983 
1984  END:
1985 	free_words(keywords);
1986 
1987 	LOG(LOG_DEBUG, "OUT : ebook_ending_search()");
1988 	return(error_code);
1989 }
1990 
ebook_get_heading(BOOK_INFO * binfo,int page,int offset)1991 gchar *ebook_get_heading(BOOK_INFO *binfo, int page, int offset)
1992 {
1993 	EB_Error_Code error_code;
1994 	ssize_t len;
1995 	char heading[MAXLEN_HEADING + 1];
1996 	EB_Position position;
1997 	gchar *p;
1998 
1999 	LOG(LOG_DEBUG, "IN : ebook_get_heading()");
2000 
2001 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
2002 		return(NULL);
2003 
2004 	error_code = eb_seek_text(binfo->book, &position);
2005 	if(error_code != EB_SUCCESS){
2006 		LOG(LOG_CRITICAL, "Failed to seek text : %s",
2007 		       ebook_error_message(error_code));
2008 		return(NULL);
2009 	}
2010 
2011 	error_code = eb_read_heading(binfo->book, binfo->appendix, &text_hookset, NULL, MAXLEN_HEADING, heading, &len);
2012 	if (error_code != EB_SUCCESS) {
2013 		LOG(LOG_CRITICAL, "Failed to read heading : %s",
2014 		       ebook_error_message(error_code));
2015 		return(NULL);
2016 	}
2017 	heading[len] = '\0';
2018 
2019 	p = malloc(len+1);
2020 	memcpy(p, heading, len+1);
2021 	LOG(LOG_DEBUG, "OUT : ebook_get_heading()");
2022 	return(p);
2023 }
2024 
ebook_get_text(BOOK_INFO * binfo,int page,int offset)2025 gchar *ebook_get_text(BOOK_INFO *binfo, int page, int offset){
2026 	EB_Error_Code error_code;
2027 	ssize_t len;
2028 	char text[MAXLEN_TEXT + 1];
2029 	EB_Position position;
2030 	gchar *p;
2031 
2032 	LOG(LOG_DEBUG, "IN : ebook_get_text()");
2033 
2034 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
2035 		return(NULL);
2036 
2037 
2038 	position.page = page;
2039 	position.offset = offset;
2040 
2041 	error_code = eb_seek_text(binfo->book, &position);
2042 	if(error_code != EB_SUCCESS){
2043 		LOG(LOG_CRITICAL, "Failed to seek text : %s",
2044 		       ebook_error_message(error_code));
2045 		LOG(LOG_DEBUG, "OUT : ebook_get_text()=NULL");
2046 		return(NULL);
2047 	}
2048 
2049 
2050 	error_code = eb_read_text(binfo->book, binfo->appendix, &text_hookset,
2051 				  NULL, MAXLEN_TEXT, text, &len);
2052 	if (error_code != EB_SUCCESS) {
2053 		LOG(LOG_CRITICAL, "Failed to read text : %s",
2054 		       ebook_error_message(error_code));
2055 		LOG(LOG_DEBUG, "OUT : ebook_get_text()=NULL");
2056 		return(NULL);
2057 	}
2058 	text[len] = '\0';
2059 
2060 	p = malloc(len+1);
2061 	memcpy(p, text, len+1);
2062 
2063 	LOG(LOG_DEBUG, "OUT : ebook_get_text()");
2064 	return(p);
2065 }
2066 
ebook_get_candidate(BOOK_INFO * binfo,int page,int offset)2067 gchar *ebook_get_candidate(BOOK_INFO *binfo, int page, int offset)
2068 {
2069 	EB_Error_Code error_code;
2070 	ssize_t len;
2071 	char text[MAXLEN_TEXT + 1];
2072 	EB_Position position;
2073 	gchar *p;
2074 
2075 
2076 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
2077 		return(NULL);
2078 
2079 
2080 	position.page = page;
2081 	position.offset = offset;
2082 
2083 	error_code = eb_seek_text(binfo->book, &position);
2084 	if(error_code != EB_SUCCESS){
2085 		LOG(LOG_CRITICAL, "Failed to seek text : %s",
2086 		       ebook_error_message(error_code));
2087 		return(NULL);
2088 	}
2089 
2090 	error_code = eb_read_text(binfo->book, binfo->appendix, &candidate_hookset,
2091 				  NULL, MAXLEN_TEXT, text, &len);
2092 	if (error_code != EB_SUCCESS) {
2093 		LOG(LOG_CRITICAL, "Failed to read text : %s",
2094 		       ebook_error_message(error_code));
2095 		return(NULL);
2096 	}
2097 	text[len] = '\0';
2098 
2099 	p = malloc(len+1);
2100 	memcpy(p, text, len+1);
2101 	return(p);
2102 }
2103 
ebook_forward_text(BOOK_INFO * binfo)2104 EB_Error_Code ebook_forward_text(BOOK_INFO *binfo)
2105 {
2106 	EB_Error_Code error_code;
2107 
2108 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
2109 		return(error_code);
2110 
2111 	error_code = eb_seek_text(binfo->book, &current_result->data.eb.pos_text);
2112 	if(error_code != EB_SUCCESS){
2113 		LOG(LOG_CRITICAL, "Failed to seek text : %s",
2114 		       ebook_error_message(error_code));
2115 		return(error_code);
2116 	}
2117 
2118 	error_code = eb_forward_text(binfo->book, binfo->appendix);
2119 	if(error_code != EB_SUCCESS){
2120 		LOG(LOG_CRITICAL, "Failed to forward text : %s",
2121 		       ebook_error_message(error_code));
2122 		return(error_code);
2123 	}
2124 
2125 	return(EB_SUCCESS);
2126 }
2127 
ebook_backward_text(BOOK_INFO * binfo)2128 EB_Error_Code ebook_backward_text(BOOK_INFO *binfo)
2129 {
2130 	EB_Error_Code error_code;
2131 	int stop_code = -1;
2132 
2133 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
2134 		return(error_code);
2135 
2136 	stop_code = binfo->book->text_context.auto_stop_code;
2137 
2138 	error_code = eb_seek_text(binfo->book, &current_result->data.eb.pos_text);
2139 	if(error_code != EB_SUCCESS){
2140 		LOG(LOG_CRITICAL, "Failed to seek text : %s",
2141 		       ebook_error_message(error_code));
2142 		return(error_code);
2143 	}
2144 
2145 	if(stop_code != -1)
2146 		binfo->book->text_context.auto_stop_code = stop_code;
2147 
2148 	error_code = ebook_my_backward_text(binfo);
2149 	if(error_code != EB_SUCCESS){
2150 		LOG(LOG_CRITICAL, "Failed to back text : %s",
2151 		       ebook_error_message(error_code));
2152 		return(error_code);
2153 	}
2154 
2155 	return(EB_SUCCESS);
2156 }
2157 
ebook_tell_text(BOOK_INFO * binfo,gint * page,gint * offset)2158 void ebook_tell_text(BOOK_INFO *binfo, gint *page, gint *offset)
2159 {
2160 	EB_Error_Code error_code;
2161 	EB_Position position;
2162 
2163 	error_code = eb_tell_text(binfo->book, &position);
2164 	if(error_code != EB_SUCCESS){
2165 		LOG(LOG_CRITICAL, "Failed to tell text : %s",
2166 		       ebook_error_message(error_code));
2167 		return;
2168 	}
2169 
2170 	*page = position.page;
2171 	*offset = position.offset;
2172 
2173 	return;
2174 }
2175 
ebook_menu(BOOK_INFO * binfo,EB_Position * pos)2176 EB_Error_Code ebook_menu(BOOK_INFO *binfo, EB_Position *pos)
2177 {
2178 	EB_Error_Code error_code=EB_SUCCESS;
2179 
2180 	error_code = eb_menu(binfo->book, pos);
2181 	if(error_code != EB_SUCCESS) {
2182 		LOG(LOG_CRITICAL, "Failed to get menu position : %s",
2183 		       ebook_error_message(error_code));
2184 	}
2185 	return(error_code);
2186 }
2187 
ebook_copyright(BOOK_INFO * binfo,EB_Position * pos)2188 EB_Error_Code ebook_copyright(BOOK_INFO *binfo, EB_Position *pos)
2189 {
2190 	EB_Error_Code error_code=EB_SUCCESS;
2191 
2192 	error_code = eb_copyright(binfo->book, pos);
2193 	if(error_code != EB_SUCCESS) {
2194 		LOG(LOG_CRITICAL, "Failed to get copyright position : %s",
2195 		       ebook_error_message(error_code));
2196 	}
2197 	return(error_code);
2198 }
2199 
ebook_bitmap_to_xbm(const char * bitmap,int width,int height,char * xbm,size_t * xbm_length)2200 static void ebook_bitmap_to_xbm(const char *bitmap, int width, int height, char *xbm, size_t *xbm_length)
2201 {
2202     char *xbm_p = xbm;
2203     const unsigned char *bitmap_p = (const unsigned char *)bitmap;
2204     int bitmap_size = (width + 7) / 8 * height;
2205     int hex;
2206     int i;
2207 
2208     for (i = 0; i < bitmap_size; i++) {
2209 	hex = 0;
2210         if (*bitmap_p & 0x80)
2211             hex |= 0x01;
2212         if (*bitmap_p & 0x40)
2213             hex |= 0x02;
2214         if (*bitmap_p & 0x20)
2215             hex |= 0x04;
2216         if (*bitmap_p & 0x10)
2217             hex |= 0x08;
2218         if (*bitmap_p & 0x08)
2219             hex |= 0x10;
2220         if (*bitmap_p & 0x04)
2221             hex |= 0x20;
2222         if (*bitmap_p & 0x02)
2223             hex |= 0x40;
2224         if (*bitmap_p & 0x01)
2225             hex |= 0x80;
2226 	bitmap_p++;
2227 
2228 	*xbm_p = hex;
2229 	xbm_p ++;
2230     }
2231 
2232     *xbm_length = (xbm_p - xbm);
2233 }
2234 
check_gaiji_size(BOOK_INFO * binfo,gint prefered_size)2235 gint check_gaiji_size(BOOK_INFO *binfo, gint prefered_size){
2236 	gint size;
2237 
2238 	size = prefered_size;
2239 
2240 	switch(size){
2241 	case 48:
2242 		if (eb_have_font(binfo->book, EB_FONT_48)){
2243 			size = 48;
2244 			break;
2245 		}
2246 		size = 30;
2247 	case 30:
2248 		if (eb_have_font(binfo->book, EB_FONT_30)){
2249 			size = 30;
2250 			break;
2251 		}
2252 		size = 24;
2253 	case 24:
2254 		if (eb_have_font(binfo->book, EB_FONT_24)){
2255 			size = 24;
2256 			break;
2257 		}
2258 		size = 16;
2259 	case 16:
2260 		if (eb_have_font(binfo->book, EB_FONT_16)){
2261 			size = 16;
2262 			break;
2263 		}
2264 		LOG(LOG_CRITICAL, "Failed to find 16 dot gaiji : subbook=%s",
2265 			binfo->subbook_title);
2266 		return(-1);
2267 
2268 	}
2269 
2270 	if(size != prefered_size){
2271 		LOG(LOG_CRITICAL, "Cannot find %d dot gaiji. Use %d dot instead",
2272 			prefered_size, size);
2273 	}
2274 
2275 	return(size);
2276 
2277 }
2278 
read_gaiji_as_bitmap(BOOK_INFO * binfo,gchar * name,gint size,gint * width,gint * height)2279 guchar *read_gaiji_as_bitmap(BOOK_INFO *binfo, gchar *name, gint size, gint *width, gint *height)
2280 {
2281 	EB_Error_Code error_code = EB_SUCCESS;
2282 	gint char_no;
2283 	gchar bitmap_data[EB_SIZE_WIDE_FONT_48];
2284 	guchar *image_data;
2285 	size_t image_size;
2286 	int image_width;
2287 	int image_height;
2288 	EB_Subbook *subbook;
2289 
2290 
2291 	char_no = strtol(&name[1], NULL, 16);
2292 
2293 	subbook = binfo->book->subbook_current;
2294 
2295 	switch (size) {
2296 	case 16:
2297 		error_code = eb_set_font(binfo->book, EB_FONT_16);
2298 		break;
2299 	case 24:
2300 		error_code = eb_set_font(binfo->book, EB_FONT_24);
2301 		break;
2302 	case 30:
2303 		error_code = eb_set_font(binfo->book, EB_FONT_30);
2304 		break;
2305 	case 48:
2306 		error_code = eb_set_font(binfo->book, EB_FONT_48);
2307 		break;
2308 	}
2309 
2310 	if (error_code != EB_SUCCESS) {
2311 		LOG(LOG_CRITICAL, "Failed to set font : subbook=%s\n%s",
2312 			binfo->subbook_title,
2313 			ebook_error_message(error_code));
2314 				return(NULL);
2315 	}
2316 
2317 
2318 	error_code = eb_font_height(binfo->book, &image_height);
2319 	if (error_code != EB_SUCCESS) {
2320 		LOG(LOG_CRITICAL, "Failed to get font height : subbook=%s\n%s",
2321 			binfo->subbook_title,
2322 			ebook_error_message(error_code));
2323 		return(NULL);
2324 	}
2325 
2326 
2327 	if(name[0] == 'h'){
2328 		if (!eb_have_narrow_font(binfo->book)){
2329 			LOG(LOG_CRITICAL, "%s does not have narrow font",
2330 				binfo->subbook_title);
2331 			return(NULL);
2332 		}
2333 		error_code = eb_narrow_font_width(binfo->book, &image_width);
2334 		if (error_code != EB_SUCCESS) {
2335 			LOG(LOG_CRITICAL, "Failed to get font width : subbook=%s\n%s",
2336 				binfo->subbook_title,
2337 				ebook_error_message(error_code));
2338 			return(NULL);
2339 		}
2340 		error_code = eb_narrow_font_character_bitmap(
2341 			binfo->book,
2342 			char_no,
2343 			bitmap_data);
2344 		if (error_code != EB_SUCCESS) {
2345 			LOG(LOG_CRITICAL, "Failed to read narrow font : subbook=%s, character=0x%04x\n%s",
2346 				binfo->subbook_title,
2347 				char_no,
2348 				ebook_error_message(error_code));
2349 			return(NULL);
2350 
2351 		}
2352 	} else {
2353 		if (!eb_have_wide_font(binfo->book)){
2354 			LOG(LOG_CRITICAL, "%s does not have wide font",
2355 				binfo->subbook_title);
2356 			return(NULL);
2357 		}
2358 		error_code = eb_wide_font_width(binfo->book, &image_width);
2359 		if (error_code != EB_SUCCESS) {
2360 			LOG(LOG_CRITICAL, "Failed to get font width : subbook=%s\n%s",
2361 				binfo->subbook_title,
2362 				ebook_error_message(error_code));
2363 			return(NULL);
2364 		}
2365 		error_code = eb_wide_font_character_bitmap(
2366 			binfo->book,
2367 			char_no,
2368 			bitmap_data);
2369 		if (error_code != EB_SUCCESS) {
2370 			LOG(LOG_CRITICAL, "Failed to read wide font : subbook=%s, character=0x%04x\n%s",
2371 				binfo->subbook_title,
2372 				char_no,
2373 				ebook_error_message(error_code));
2374 			return(NULL);
2375 		}
2376 	}
2377 
2378 	image_data = malloc(image_width * image_height / 8);
2379 	ebook_bitmap_to_xbm(bitmap_data, image_width,
2380 			    image_height, image_data, &image_size);
2381 
2382 	*width = image_width;
2383 	*height = image_height;
2384 
2385 	return(image_data);
2386 
2387 }
2388 
ebook_bitmap_to_xpm(const gchar * bitmap,gint width,gint height,gchar * color)2389 static gchar **ebook_bitmap_to_xpm(const gchar *bitmap, gint width, gint height, gchar *color)
2390 {
2391 	gchar **xpm;
2392 	gchar *xpm_p;
2393 	int i, j;
2394 	const unsigned char *bitmap_p = (const unsigned char *)bitmap;
2395 
2396 	xpm = g_new(gchar *, height + 4 + gaiji_adjustment);
2397 
2398 	xpm[0] = g_strdup_printf("%d %d 2 1", width, height+gaiji_adjustment);
2399 	xpm[1] = g_strdup_printf(" 	c None");
2400 	if(color == NULL)
2401 		xpm[2] = g_strdup_printf(". 	c Black");
2402 	else
2403 		xpm[2] = g_strdup_printf(". 	c %s", color);
2404 
2405 	for (i = 0; i < gaiji_adjustment; i++) {
2406 		xpm[i+3] = g_new(guchar, width + 1);
2407 		memset(xpm[i+3], ' ', width);
2408 		xpm[i+3][width] = '\0';
2409 	}
2410 
2411 	for (;i < height + gaiji_adjustment; i++) {
2412 		xpm[i+3] = g_new(guchar, width + 1);
2413 		xpm_p = xpm[i+3];
2414 		for (j = 0; j + 7 < width; j += 8, bitmap_p++) {
2415 			*xpm_p++ = (*bitmap_p & 0x80) ? '.' : ' ';
2416 			*xpm_p++ = (*bitmap_p & 0x40) ? '.' : ' ';
2417 			*xpm_p++ = (*bitmap_p & 0x20) ? '.' : ' ';
2418 			*xpm_p++ = (*bitmap_p & 0x10) ? '.' : ' ';
2419 			*xpm_p++ = (*bitmap_p & 0x08) ? '.' : ' ';
2420 			*xpm_p++ = (*bitmap_p & 0x04) ? '.' : ' ';
2421 			*xpm_p++ = (*bitmap_p & 0x02) ? '.' : ' ';
2422 			*xpm_p++ = (*bitmap_p & 0x01) ? '.' : ' ';
2423 		}
2424 
2425 		if (j < width) {
2426 			if (j++ < width)
2427 				*xpm_p++ = (*bitmap_p & 0x80) ? '.' : ' ';
2428 			if (j++ < width)
2429 				*xpm_p++ = (*bitmap_p & 0x40) ? '.' : ' ';
2430 			if (j++ < width)
2431 				*xpm_p++ = (*bitmap_p & 0x20) ? '.' : ' ';
2432 			if (j++ < width)
2433 				*xpm_p++ = (*bitmap_p & 0x10) ? '.' : ' ';
2434 			if (j++ < width)
2435 				*xpm_p++ = (*bitmap_p & 0x08) ? '.' : ' ';
2436 			if (j++ < width)
2437 				*xpm_p++ = (*bitmap_p & 0x04) ? '.' : ' ';
2438 			if (j++ < width)
2439 				*xpm_p++ = (*bitmap_p & 0x02) ? '.' : ' ';
2440 			if (j++ < width)
2441 				*xpm_p++ = (*bitmap_p & 0x01) ? '.' : ' ';
2442 			bitmap_p++;
2443 		}
2444 		*xpm_p = '\0';
2445 	}
2446 	xpm[i+3] = '\0';
2447 
2448 	return(xpm);
2449 }
2450 
2451 
read_gaiji_as_xpm(BOOK_INFO * binfo,gchar * name,gint size,gint * width,gint * height,gchar * color)2452 gchar **read_gaiji_as_xpm(BOOK_INFO *binfo, gchar *name, gint size, gint *width, gint *height, gchar *color)
2453 {
2454 	EB_Error_Code error_code = EB_SUCCESS;
2455 	gint char_no;
2456 	gchar bitmap_data[EB_SIZE_WIDE_FONT_48];
2457 	guchar *image_data;
2458 	int image_width;
2459 	int image_height;
2460 	EB_Subbook *subbook;
2461 	gchar **xpm;
2462 
2463 	LOG(LOG_DEBUG, "IN : read_gaiji_as_xpm(name=%s, size=%d)", name, size);
2464 
2465 	char_no = strtol(&name[1], NULL, 16);
2466 
2467 	subbook = binfo->book->subbook_current;
2468 
2469 	switch (size) {
2470 	case 16:
2471 		error_code = eb_set_font(binfo->book, EB_FONT_16);
2472 		break;
2473 	case 24:
2474 		error_code = eb_set_font(binfo->book, EB_FONT_24);
2475 		break;
2476 	case 30:
2477 		error_code = eb_set_font(binfo->book, EB_FONT_30);
2478 		break;
2479 	case 48:
2480 		error_code = eb_set_font(binfo->book, EB_FONT_48);
2481 		break;
2482 	}
2483 
2484 	if (error_code != EB_SUCCESS) {
2485 		LOG(LOG_CRITICAL, "Failed to set font : subbook=%s\n%s",
2486 			binfo->subbook_title,
2487 			ebook_error_message(error_code));
2488 				return(NULL);
2489 	}
2490 
2491 
2492 	error_code = eb_font_height(binfo->book, &image_height);
2493 	if (error_code != EB_SUCCESS) {
2494 		LOG(LOG_CRITICAL, "Failed to get font height : subbook=%s\n%s",
2495 			binfo->subbook_title,
2496 			ebook_error_message(error_code));
2497 		return(NULL);
2498 	}
2499 
2500 
2501 	if(name[0] == 'h'){
2502 		if (!eb_have_narrow_font(binfo->book)){
2503 			LOG(LOG_CRITICAL, "%s does not have narrow font",
2504 				binfo->subbook_title);
2505 			return(NULL);
2506 		}
2507 		error_code = eb_narrow_font_width(binfo->book, &image_width);
2508 		if (error_code != EB_SUCCESS) {
2509 			LOG(LOG_CRITICAL, "Failed to get font width : subbook=%s\n%s",
2510 				binfo->subbook_title,
2511 				ebook_error_message(error_code));
2512 			return(NULL);
2513 		}
2514 		error_code = eb_narrow_font_character_bitmap(
2515 			binfo->book,
2516 			char_no,
2517 			bitmap_data);
2518 		if (error_code != EB_SUCCESS) {
2519 			LOG(LOG_CRITICAL, "Failed to read narrow font : subbook=%s, character=0x%04x\n%s",
2520 				binfo->subbook_title,
2521 				char_no,
2522 				ebook_error_message(error_code));
2523 			return(NULL);
2524 
2525 		}
2526 	} else {
2527 		if (!eb_have_wide_font(binfo->book)){
2528 			LOG(LOG_CRITICAL, "%s does not have wide font",
2529 				binfo->subbook_title);
2530 			return(NULL);
2531 		}
2532 		error_code = eb_wide_font_width(binfo->book, &image_width);
2533 		if (error_code != EB_SUCCESS) {
2534 			LOG(LOG_CRITICAL, "Failed to get font width : subbook=%s\n%s",
2535 				binfo->subbook_title,
2536 				ebook_error_message(error_code));
2537 			return(NULL);
2538 		}
2539 		error_code = eb_wide_font_character_bitmap(
2540 			binfo->book,
2541 			char_no,
2542 			bitmap_data);
2543 		if (error_code != EB_SUCCESS) {
2544 			LOG(LOG_CRITICAL, "Failed to read wide font : subbook=%s, character=0x%04x\n%s",
2545 				binfo->subbook_title,
2546 				char_no,
2547 				ebook_error_message(error_code));
2548 			return(NULL);
2549 		}
2550 	}
2551 
2552 	image_data = malloc((image_width + 4)* (image_height* 5));
2553 	xpm = ebook_bitmap_to_xpm(bitmap_data, image_width, image_height, color);
2554 
2555 	*width = image_width;
2556 	*height = image_height + gaiji_adjustment;
2557 
2558 #if 0
2559 	{
2560 		gint i;
2561 		for(i=0; i < size+3 ; i ++){
2562 			printf("%s\n", xpm[i]);
2563 		}
2564 	}
2565 #endif
2566 
2567 	LOG(LOG_DEBUG, "OUT : read_gaiji_as_xpm()");
2568 
2569 	return(xpm);
2570 
2571 }
2572 
2573 #define GIF_PREAMBLE_LENGTH	38
2574 
2575 static const unsigned char gif_preamble[GIF_PREAMBLE_LENGTH] = {
2576     /*
2577      * Header. (6 bytes)
2578      */
2579     'G', 'I', 'F', '8', '9', 'a',
2580 
2581     /*
2582      * Logical Screen Descriptor. (7 bytes)
2583      *   global color table flag = 1.
2584      *   color resolution = 1 - 1 = 0.
2585      *   sort flag = 0.
2586      *   size of global color table = 1 - 1 = 0.
2587      *   background color index = 0.
2588      *   the pixel aspect ratio = 0 (unused)
2589      * Logical screen width and height are set at run time.
2590      */
2591     0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
2592 
2593     /*
2594      * Global Color Table. (6 bytes)
2595      * These are set at run time.
2596      */
2597     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2598 
2599     /*
2600      * Graphic Control Extension. (8 bytes)
2601      *   disposal method = 0.
2602      *   user input flag = 0.
2603      *   transparency flag = 1.
2604      *   delay time = 0.
2605      *   transparent color index = 0.
2606      */
2607     0x21, 0xf9, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00,
2608 
2609     /*
2610      * Image Descriptor. (10 bytes)
2611      *   image left position = 0.
2612      *   image top position = 0.
2613      *   local color table flag = 0.
2614      *   interlace flag = 0.
2615      *   sort flag = 0.
2616      *   size of local color table = 0.
2617      * Image width and height are set at run time.
2618      */
2619     0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2620 
2621     /*
2622      * Code size. (1byte)
2623      */
2624     0x03
2625 };
2626 
2627 
ebook_bitmap_to_gif(bitmap,width,height,gif,gif_length,fg,bg)2628 static void ebook_bitmap_to_gif(bitmap, width, height, gif, gif_length, fg, bg)
2629     const char *bitmap;
2630     int width;
2631     int height;
2632     char *gif;
2633     guint *gif_length;
2634     guint fg;
2635     guint bg;
2636 {
2637     unsigned char *gif_p = (unsigned char *)gif;
2638     const unsigned char *bitmap_p = (const unsigned char *)bitmap;
2639     int i, j;
2640 
2641 
2642     /*
2643      * Copy the default preamble.
2644      */
2645     memcpy(gif_p, gif_preamble, GIF_PREAMBLE_LENGTH);
2646 
2647     /*
2648      * Set logical screen width and height.
2649      */
2650     gif_p[6] = width & 0xff;
2651     gif_p[7] = (width >> 8) & 0xff;
2652     gif_p[8] = height & 0xff;
2653     gif_p[9] = (height >> 8) & 0xff;
2654 
2655     /*
2656      * Set global colors.
2657      */
2658     gif_p[13] = (bg >> 16) & 0xff;
2659     gif_p[14] = (bg >> 8) & 0xff;
2660     gif_p[15] = bg & 0xff;
2661     gif_p[16] = (fg >> 16) & 0xff;
2662     gif_p[17] = (fg >> 8) & 0xff;
2663     gif_p[18] = fg & 0xff;
2664 
2665     /*
2666      * Set image width and height.
2667      */
2668     gif_p[32] = width & 0xff;
2669     gif_p[33] = (width >> 8) & 0xff;
2670     gif_p[34] = height & 0xff;
2671     gif_p[35] = (height >> 8) & 0xff;
2672 
2673     gif_p += GIF_PREAMBLE_LENGTH;
2674 
2675     /*
2676      * Output image data.
2677      */
2678     for (i = 0;  i < height; i++) {
2679 	*gif_p++ = (unsigned char)width;
2680 	for (j = 0; j + 7 < width; j += 8, bitmap_p++) {
2681 	    *gif_p++ = (*bitmap_p & 0x80) ? 0x81 : 0x80;
2682 	    *gif_p++ = (*bitmap_p & 0x40) ? 0x81 : 0x80;
2683 	    *gif_p++ = (*bitmap_p & 0x20) ? 0x81 : 0x80;
2684 	    *gif_p++ = (*bitmap_p & 0x10) ? 0x81 : 0x80;
2685 	    *gif_p++ = (*bitmap_p & 0x08) ? 0x81 : 0x80;
2686 	    *gif_p++ = (*bitmap_p & 0x04) ? 0x81 : 0x80;
2687 	    *gif_p++ = (*bitmap_p & 0x02) ? 0x81 : 0x80;
2688 	    *gif_p++ = (*bitmap_p & 0x01) ? 0x81 : 0x80;
2689 	}
2690 
2691 	if (j < width) {
2692 	    if (j++ < width)
2693 		*gif_p++ = (*bitmap_p & 0x80) ? 0x81 : 0x80;
2694 	    if (j++ < width)
2695 		*gif_p++ = (*bitmap_p & 0x40) ? 0x81 : 0x80;
2696 	    if (j++ < width)
2697 		*gif_p++ = (*bitmap_p & 0x20) ? 0x81 : 0x80;
2698 	    if (j++ < width)
2699 		*gif_p++ = (*bitmap_p & 0x10) ? 0x81 : 0x80;
2700 	    if (j++ < width)
2701 		*gif_p++ = (*bitmap_p & 0x08) ? 0x81 : 0x80;
2702 	    if (j++ < width)
2703 		*gif_p++ = (*bitmap_p & 0x04) ? 0x81 : 0x80;
2704 	    if (j++ < width)
2705 		*gif_p++ = (*bitmap_p & 0x02) ? 0x81 : 0x80;
2706 	    if (j++ < width)
2707 		*gif_p++ = (*bitmap_p & 0x01) ? 0x81 : 0x80;
2708 	    bitmap_p++;
2709 	}
2710     }
2711 
2712     /*
2713      * Output a trailer.
2714      */
2715     memcpy(gif_p, "\001\011\000\073", 4);
2716     gif_p += 4;
2717 
2718     if (gif_length != NULL)
2719 	*gif_length = ((char *)gif_p - gif);
2720 
2721 }
2722 
2723 
read_gaiji_as_xbm(BOOK_INFO * binfo,gchar * name,gchar * fname,guint fg,guint bg)2724 guchar *read_gaiji_as_xbm(BOOK_INFO *binfo, gchar *name, gchar *fname, guint fg, guint bg)
2725 {
2726 	EB_Error_Code error_code;
2727 	gint char_no;
2728 	gchar bitmap_data[EB_SIZE_WIDE_FONT_48];
2729 	guchar image_data[EB_SIZE_FONT_IMAGE];
2730 	size_t image_size;
2731 	int image_width;
2732 	int image_height;
2733 	EB_Subbook *subbook;
2734 	FILE *fp;
2735 
2736 
2737 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
2738 		return(NULL);
2739 
2740 	char_no = strtol(&name[1], NULL, 16);
2741 
2742 	subbook = binfo->book->subbook_current;
2743 
2744 	error_code = eb_font_height(binfo->book, &image_height);
2745 	if (error_code != EB_SUCCESS) {
2746 		LOG(LOG_CRITICAL, "Failed to get font height : subbook=%s\n%s",
2747 			binfo->subbook_title,
2748 			ebook_error_message(error_code));
2749 		return(NULL);
2750 	}
2751 
2752 
2753 	if(name[0] == 'h'){
2754 		if (!eb_have_narrow_font(binfo->book)){
2755 			LOG(LOG_CRITICAL, "%s does not have narrow font",
2756 				binfo->subbook_title);
2757 			return(NULL);
2758 		}
2759 		error_code = eb_narrow_font_width(binfo->book, &image_width);
2760 		if (error_code != EB_SUCCESS) {
2761 			LOG(LOG_CRITICAL, "Failed to get font width : subbook=%s\n%s",
2762 				binfo->subbook_title,
2763 				ebook_error_message(error_code));
2764 			return(NULL);
2765 		}
2766 		error_code = eb_narrow_font_character_bitmap(
2767 			binfo->book,
2768 			char_no,
2769 			bitmap_data);
2770 		if (error_code != EB_SUCCESS) {
2771 			LOG(LOG_CRITICAL, "Failed to read narrow font : subbook=%s, character=0x%04x\n%s",
2772 				binfo->subbook_title,
2773 				char_no,
2774 				ebook_error_message(error_code));
2775 			return(NULL);
2776 
2777 		}
2778 	} else {
2779 		if (!eb_have_wide_font(binfo->book)){
2780 			LOG(LOG_CRITICAL, "%s does not have wide font",
2781 				binfo->subbook_title);
2782 			return(NULL);
2783 		}
2784 		error_code = eb_wide_font_width(binfo->book, &image_width);
2785 		if (error_code != EB_SUCCESS) {
2786 			LOG(LOG_CRITICAL, "Failed to get font width : subbook=%s\n%s",
2787 				binfo->subbook_title,
2788 				ebook_error_message(error_code));
2789 			return(NULL);
2790 		}
2791 		error_code = eb_wide_font_character_bitmap(
2792 			binfo->book,
2793 			char_no,
2794 			bitmap_data);
2795 		if (error_code != EB_SUCCESS) {
2796 			LOG(LOG_CRITICAL, "Failed to read wide font : subbook=%s, character=0x%04x\n%s",
2797 				binfo->subbook_title,
2798 				char_no,
2799 				ebook_error_message(error_code));
2800 			return(NULL);
2801 		}
2802 	}
2803 
2804 
2805 	ebook_bitmap_to_gif(bitmap_data, image_width,
2806 			    image_height, image_data, &image_size, fg, bg);
2807 
2808 
2809 	fp = fopen(fname, "wb");
2810 	if(fp == NULL){
2811 		LOG(LOG_CRITICAL, "file open failed : %s", fname);
2812 	}
2813 	fwrite(image_data, image_size, 1, fp);
2814 	fclose(fp);
2815 
2816 	return(NULL);
2817 
2818 }
2819 
ebook_output_wave(BOOK_INFO * binfo,gchar * filename,gint page,gint offset,gint size)2820 EB_Error_Code ebook_output_wave(BOOK_INFO *binfo, gchar *filename, gint page, gint offset, gint size)
2821 {
2822 	EB_Position pos;
2823 	char binary_data[EB_SIZE_PAGE];
2824 	EB_Error_Code error_code;
2825 	EB_Position end_position;
2826 	ssize_t read_length;
2827 	FILE *fp;
2828 
2829 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
2830 		return(error_code);
2831 
2832 	pos.page = page;
2833 	pos.offset = offset;
2834 
2835 	end_position.page = pos.page
2836 		+ (size / EB_SIZE_PAGE);
2837 	end_position.offset = pos.offset
2838 		+ (size % EB_SIZE_PAGE);
2839 	if (EB_SIZE_PAGE <= end_position.offset) {
2840 		end_position.offset -= EB_SIZE_PAGE;
2841 		end_position.page++;
2842 	}
2843 
2844 	/*
2845 	 * Read sound data.
2846 	 */
2847 	error_code = eb_set_binary_wave(binfo->book,
2848 					&pos, &end_position);
2849 	if (error_code != EB_SUCCESS){
2850 		LOG(LOG_CRITICAL, "Failed to set binary wave : %s",
2851 				ebook_error_message(error_code));
2852 		return(error_code);
2853 	}
2854 
2855 	fp = fopen(filename, "wb");
2856 	if(fp == NULL){
2857 		LOG(LOG_CRITICAL, "Failed to open file : %s",
2858 			filename);
2859 		return(EB_ERR_BAD_FILE_NAME);
2860 	}
2861 
2862 	for (;;) {
2863 		error_code = eb_read_binary(binfo->book,
2864 					    EB_SIZE_PAGE,
2865 					    binary_data, &read_length);
2866 		if (error_code != EB_SUCCESS || read_length == 0){
2867 			fclose(fp);
2868 			return(error_code);
2869 		}
2870 
2871 		// If there are extra data (32 bytes) before fmt chunk,remove them.
2872 		if((strncmp("fmt ", &binary_data[44], 4) == 0) &&
2873 		   (strncmp("fmt ", &binary_data[12], 4) != 0)){
2874 			LOG(LOG_CRITICAL, "Warning: extra header found in WAVE data.");
2875 			fwrite(binary_data, 12, 1, fp);
2876 			fwrite(&binary_data[44], read_length - 44, 1, fp);
2877 		} else {
2878 			fwrite(binary_data, read_length, 1, fp);
2879 		}
2880 	}
2881 
2882 	/* not reached */
2883 	return(EB_SUCCESS);
2884 }
2885 
ebook_output_mpeg(BOOK_INFO * binfo,gchar * srcname,gchar * destname)2886 EB_Error_Code ebook_output_mpeg(BOOK_INFO *binfo, gchar *srcname, gchar *destname)
2887 {
2888 	char binary_data[EB_SIZE_PAGE];
2889 	guint argv[4];
2890 	EB_Error_Code error_code;
2891 	ssize_t read_length;
2892 	FILE *fp;
2893 
2894 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
2895 		return(error_code);
2896 
2897 	if((error_code = eb_decompose_movie_file_name(argv, srcname)) != EB_SUCCESS)
2898 		return(error_code);
2899 
2900 	/*
2901 	 * Read sound data.
2902 	 */
2903 	error_code = eb_set_binary_mpeg(binfo->book, argv);
2904 	if (error_code != EB_SUCCESS){
2905 		LOG(LOG_CRITICAL, "Failed to set binary mpeg : %s",
2906 				ebook_error_message(error_code));
2907 		return(error_code);
2908 	}
2909 
2910 	fp = fopen(destname, "wb");
2911 	if(fp == NULL){
2912 		LOG(LOG_CRITICAL, "Failed to open file : %s", destname);
2913 		return(EB_ERR_BAD_FILE_NAME);
2914 	}
2915 
2916 	for (;;) {
2917 		error_code = eb_read_binary(binfo->book,
2918 					    EB_SIZE_PAGE,
2919 					    binary_data, &read_length);
2920 		if (error_code != EB_SUCCESS || read_length == 0){
2921 			fclose(fp);
2922 			return(error_code);
2923 		}
2924 		fwrite(binary_data, read_length, 1, fp);
2925 	}
2926 
2927 	/* not reached */
2928 	return(EB_SUCCESS);
2929 }
2930 
ebook_output_color(BOOK_INFO * binfo,gchar * filename,gint page,gint offset)2931 EB_Error_Code ebook_output_color(BOOK_INFO *binfo, gchar *filename, gint page, gint offset)
2932 {
2933 	EB_Position pos;
2934 	char binary_data[EB_SIZE_PAGE];
2935 	EB_Error_Code error_code;
2936 	ssize_t read_length;
2937 	FILE *fp;
2938 
2939 	pos.page = page;
2940 	pos.offset = offset;
2941 
2942 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
2943 		return(error_code);
2944 
2945 	error_code = eb_set_binary_color_graphic(binfo->book,
2946 						 &pos);
2947 
2948 	if (error_code != EB_SUCCESS){
2949 		LOG(LOG_CRITICAL, "Failed to set binary color graphic : %s",
2950 			ebook_error_message(error_code));
2951 		return(error_code);
2952 	}
2953 
2954 	fp = fopen(filename, "wb");
2955 	if(fp == NULL){
2956 		LOG(LOG_CRITICAL, "Failed to open file : %s",
2957 			filename);
2958 		return(EB_ERR_BAD_FILE_NAME);
2959 	}
2960 
2961 	for (;;) {
2962 		error_code = eb_read_binary(binfo->book, EB_SIZE_PAGE,
2963 					    binary_data, &read_length);
2964 		if (error_code != EB_SUCCESS || read_length == 0){
2965 			fclose(fp);
2966 			return(error_code);
2967 		}
2968 		fwrite(binary_data, read_length, 1, fp);
2969 	}
2970 
2971 	/* not reached */
2972 	return(EB_SUCCESS);
2973 }
2974 
2975 
ebook_output_gray(BOOK_INFO * binfo,gchar * filename,gint page,gint offset,gint width,gint height)2976 EB_Error_Code ebook_output_gray(BOOK_INFO *binfo, gchar *filename, gint page, gint offset, gint width, gint height)
2977 {
2978 	EB_Position pos;
2979 	char binary_data[EB_SIZE_PAGE];
2980 	EB_Error_Code error_code;
2981 	ssize_t read_length;
2982 	FILE *fp;
2983 
2984 	pos.page = page;
2985 	pos.offset = offset;
2986 
2987 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
2988 		return(error_code);
2989 
2990 	error_code = eb_set_binary_gray_graphic(binfo->book,
2991 						 &pos, width, height);
2992 	if (error_code != EB_SUCCESS){
2993 		LOG(LOG_CRITICAL, "Failed to set binary gray graphic : %s",
2994 			ebook_error_message(error_code));
2995 		return(error_code);
2996 	}
2997 
2998 	fp = fopen(filename, "wb");
2999 	if(fp == NULL){
3000 		LOG(LOG_CRITICAL, "Failed to open file : %s",
3001 			filename);
3002 		return(EB_ERR_BAD_FILE_NAME);
3003 	}
3004 
3005 	for (;;) {
3006 		error_code = eb_read_binary(binfo->book, EB_SIZE_PAGE,
3007 					    binary_data, &read_length);
3008 		if (error_code != EB_SUCCESS || read_length == 0){
3009 			fclose(fp);
3010 			return(error_code);
3011 		}
3012 		fwrite(binary_data, read_length, 1, fp);
3013 	}
3014 
3015 	/* not reached */
3016 	return(EB_SUCCESS);
3017 }
3018 
ebook_output_mono(BOOK_INFO * binfo,gchar * filename,gint page,gint offset,gint width,gint height)3019 EB_Error_Code ebook_output_mono(BOOK_INFO *binfo, gchar *filename, gint page, gint offset, gint width, gint height)
3020 {
3021 	FILE *fp;
3022 	EB_Error_Code error_code;
3023 	EB_Position pos;
3024 	char *binary_data;
3025 	ssize_t read_length;
3026 	gint data_size;
3027 	gchar *bmp_data;
3028 	gint bmp_length;
3029 
3030 #ifdef COLOR_HACK
3031 
3032 	guchar fg[4];
3033 	guchar bg[4];
3034 	GdkColor color;
3035 
3036 	color = dict_area->area->style->fg[GTK_STATE_NORMAL];
3037 	fg[0] = (guchar)color.red;
3038 	fg[1] = (guchar)color.green;
3039 	fg[2] = (guchar)color.blue;
3040 	fg[3] = 0x0;
3041 
3042 	color = dict_area->area->style->bg[GTK_STATE_NORMAL];
3043 	bg[0] = (guchar)color.red;
3044 	bg[1] = (guchar)color.green;
3045 	bg[2] = (guchar)color.blue;
3046 	bg[3] = 0x0;
3047 
3048 #endif
3049 
3050 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
3051 		return(error_code);
3052 
3053 	fp = fopen(filename, "wb");
3054 	if(fp == NULL){
3055 		LOG(LOG_CRITICAL, "Failed to open file : %s",
3056 			filename);
3057 		return(EB_ERR_BAD_FILE_NAME);
3058 	}
3059 
3060 	pos.page = page;
3061 	pos.offset = offset;
3062 
3063 	eb_seek_text(binfo->book, &pos);
3064 
3065 	error_code = eb_set_binary_mono_graphic(binfo->book,
3066 					&pos, width, height);
3067 
3068 
3069 	// Workaround for dictionaries such as Super Tougou Jisho 2000,
3070 	// whose graphics data is in Honmon2.
3071 	// Fixed in eb-3.3.
3072 	if (error_code != EB_SUCCESS){
3073 
3074 		if((width % 8) != 0)
3075 			width = (width / 8)*8 + 8;
3076 
3077 		data_size = width * height / 8;
3078 
3079 		binary_data = malloc(data_size);
3080 		bmp_data = malloc(data_size*10);
3081 
3082 
3083 		pos.page = page;
3084 		pos.offset = offset;
3085 
3086 		eb_seek_text(binfo->book, &pos);
3087 		error_code = eb_read_rawtext(binfo->book,
3088 					     data_size,
3089 					     binary_data,
3090 					     &read_length);
3091 		if (error_code != EB_SUCCESS || read_length == 0){
3092 			return(error_code);
3093 		}
3094 
3095 		 eb_bitmap_to_bmp(binary_data,
3096 				  width,
3097 				  height,
3098 				  bmp_data,
3099 				  &bmp_length);
3100 
3101 		fwrite(bmp_data, bmp_length, 1, fp);
3102 
3103 #ifdef COLOR_HACK
3104 		fseek(fp, 54, SEEK_SET);
3105 		fwrite(bg, 4, 1, fp);
3106 		fseek(fp, 58, SEEK_SET);
3107 		fwrite(fg, 4, 1, fp);
3108 #endif
3109 		fclose(fp);
3110 		free(binary_data);
3111 		free(bmp_data);
3112 		return(EB_SUCCESS);
3113 	}
3114 
3115 
3116 	if (error_code != EB_SUCCESS){
3117 		LOG(LOG_CRITICAL, "Failed to set binary mono : %s",
3118 				ebook_error_message(error_code));
3119 		return(error_code);
3120 	}
3121 
3122 	for (;;) {
3123 		char binary_data[EB_SIZE_PAGE];
3124 
3125 		error_code = eb_read_binary(binfo->book,
3126 					    EB_SIZE_PAGE,
3127 					    binary_data, &read_length);
3128 		if (error_code != EB_SUCCESS || read_length == 0){
3129 			fclose(fp);
3130 			return(error_code);
3131 		}
3132 #ifdef COLOR_HACK
3133 		memcpy(&binary_data[54], bg, 4);
3134 		memcpy(&binary_data[58], fg, 4);
3135 #endif
3136 		fwrite(binary_data, read_length, 1, fp);
3137 	}
3138 
3139 	/* not reached */
3140 	fclose(fp);
3141 	return(EB_SUCCESS);
3142 }
3143 
ebook_get_rawtext(BOOK_INFO * binfo,gint page,gint offset)3144 gchar *ebook_get_rawtext(BOOK_INFO *binfo, gint page, gint offset)
3145 {
3146 	EB_Position pos;
3147 	char *binary_data;
3148 	EB_Error_Code error_code;
3149 	ssize_t read_length;
3150 
3151 	binary_data = malloc(EB_SIZE_PAGE);
3152 
3153 	if((error_code = ebook_set_subbook(binfo)) != EB_SUCCESS)
3154 		return(NULL);
3155 
3156 	pos.page = page;
3157 	pos.offset = offset;
3158 
3159 	eb_seek_text(binfo->book, &pos);
3160 	error_code = eb_read_rawtext(binfo->book,
3161 				     EB_SIZE_PAGE,
3162 				     binary_data,
3163 				     &read_length);
3164 	if (error_code != EB_SUCCESS || read_length == 0){
3165 		return(NULL);
3166 	}
3167 
3168 	return(binary_data);
3169 }
3170 
ebook_set_subbook(BOOK_INFO * binfo)3171 EB_Error_Code ebook_set_subbook(BOOK_INFO *binfo)
3172 {
3173 
3174 	EB_Error_Code error_code;
3175 
3176 	error_code = eb_set_subbook(binfo->book, binfo->subbook_no);
3177 	if (error_code != EB_SUCCESS){
3178 		LOG(LOG_CRITICAL, "Failed to set subbook %s, %d : %s",
3179 			binfo->book_path, binfo->subbook_no,
3180 			ebook_error_message(error_code));
3181 		return(error_code);
3182 	}
3183 
3184 
3185 	if(binfo->appendix != NULL){
3186 		error_code = eb_set_appendix_subbook(binfo->appendix,
3187 					    binfo->appendix_subbook_no);
3188 		if (error_code != EB_SUCCESS){
3189 			LOG(LOG_CRITICAL, "Failed to set appendix subbook : %s",
3190 				ebook_error_message(error_code));
3191 			return(error_code);
3192 		}
3193 	}
3194 	return(EB_SUCCESS);
3195 
3196 }
3197 
3198