/*  Copyright (C) 2001-2002  Kenichi Suto
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include "defs.h"
#include "global.h"

#include "xml.h"
#include <sys/stat.h>

static GtkWidget *pref_dlg;
static GtkWidget *spin_max_search;
static GtkWidget *spin_dict_label;
static GtkWidget *spin_interval;
static GtkWidget *spin_words;
static GtkWidget *spin_minchar;
static GtkWidget *spin_maxchar;
static GtkWidget *spin_popup_width;
static GtkWidget *spin_popup_height;
static GtkWidget *check_beep;
static GtkWidget *check_popup_title;

extern GList *group_list;
extern GList *web_list;

extern void print_dict_group();

static void ok_pref(GtkWidget *widget,gpointer *data){
	gtk_grab_remove(pref_dlg);
	max_search = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_max_search));
	max_remember_words = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_words));
	dict_label_bytes = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_dict_label));
	auto_interval = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_interval));
	auto_minchar = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_minchar));
	auto_maxchar = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_maxchar));
	popup_width = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_popup_width));
	popup_height = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_popup_height));

	bbeep_on_nohit = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_beep));
	bshow_popup_title = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_popup_title));

	gtk_widget_destroy(GTK_WIDGET(data));
	update_dict_bar();
/*
	if(bauto_lookup) {
		if(tag_timeout != 0)
			gtk_timeout_remove(tag_timeout);
		tag_timeout = gtk_timeout_add(auto_interval, copy_clipboard,NULL);
	}
*/

	auto_lookup_resume();
}

static void delete_event( GtkWidget *widget,
		   GdkEvent  *event,
		   gpointer   data )
{
	
	ok_pref(NULL, NULL);
}

void misc_preference()
{
	GtkWidget *button;
	GtkWidget *vbox;
	GtkWidget *hbox;
	GtkWidget *label;
	GtkObject *adj;
	GtkWidget *note_book;

	auto_lookup_suspend();

	pref_dlg = gtk_dialog_new();
//	gtk_widget_set_usize(pref_dlg,400,280);
	gtk_window_set_position(GTK_WINDOW(pref_dlg), GTK_WIN_POS_CENTER_ALWAYS);

	gtk_grab_add(pref_dlg);

	gtk_signal_connect (GTK_OBJECT (pref_dlg), "delete_event",
			    GTK_SIGNAL_FUNC (delete_event), NULL);


	button = gtk_button_new_with_label(_("Ok"));
	GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pref_dlg)->action_area), button,
			    TRUE, TRUE, 0);
	
	gtk_signal_connect (GTK_OBJECT (button), "clicked",
			    GTK_SIGNAL_FUNC (ok_pref), (gpointer)pref_dlg);
	gtk_widget_grab_default (button);


	note_book = gtk_notebook_new();
	gtk_box_pack_start (GTK_BOX(GTK_DIALOG(pref_dlg)->vbox)
		      , note_book,TRUE, TRUE, 0);

	vbox = gtk_vbox_new(FALSE,10);
	label = gtk_label_new(_("Search"));
	gtk_notebook_append_page(GTK_NOTEBOOK(note_book),vbox,label);

	hbox = gtk_hbox_new(FALSE,10);
	gtk_container_border_width(GTK_CONTAINER(hbox), 2);
	gtk_box_pack_start (GTK_BOX(vbox)
			    , hbox,FALSE, FALSE, 0);

	label = gtk_label_new(_("Maximum hits to display"));
	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
//	gtk_widget_set_usize( label, 120, 20 );
	gtk_box_pack_start (GTK_BOX(hbox), label,FALSE, FALSE, 0);
	

	adj = gtk_adjustment_new( 100, //value
				  1, // lower
				  1000, //upper
                                  1, // step increment
                                  10,// page_increment,
                                  0.0);
	spin_max_search = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_max_search), max_search );
	gtk_widget_set_usize(spin_max_search,60,20);
	gtk_box_pack_end (GTK_BOX(hbox), spin_max_search, FALSE, FALSE, 0);
	gtk_tooltips_set_tip(tooltip, spin_max_search, 
			     _("Maximum number of hits to be displayed.\nIf you increase this number, it takes time to display the results."),"Private");


	hbox = gtk_hbox_new(FALSE,10);
	gtk_container_border_width(GTK_CONTAINER(hbox), 2);
	gtk_box_pack_start (GTK_BOX(vbox)
			    , hbox,FALSE, FALSE, 0);

	label = gtk_label_new(_("Maximum words in history"));
	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
//	gtk_widget_set_usize( label, 120, 20 );
	gtk_box_pack_start (GTK_BOX(hbox), label,FALSE, FALSE, 0);
	

	adj = gtk_adjustment_new( 10, //value
				  0, // lower
				  20, //upper
                                  1, // step increment
                                  10,// page_increment,
                                  (gfloat)0.0);
	spin_words = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_words), max_remember_words );
	gtk_widget_set_usize(spin_words,60,20);
	gtk_box_pack_end (GTK_BOX(hbox), spin_words, FALSE, FALSE, 0);
	gtk_tooltips_set_tip(tooltip, spin_words, 
			     _("Maximum number of words to remember in word history"), "Private");

	hbox = gtk_hbox_new(FALSE,10);
	gtk_container_border_width(GTK_CONTAINER(hbox), 2);
	gtk_box_pack_start (GTK_BOX(vbox)
			    , hbox,FALSE, FALSE, 0);

	label = gtk_label_new(_("Bytes in dictionary bar"));
	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
//	gtk_widget_set_usize( label, 120, 20 );
	gtk_box_pack_start (GTK_BOX(hbox), label,FALSE, FALSE, 0);
	

	adj = gtk_adjustment_new( 10, //value
				  2, // lower
				  32, //upper
                                  2, // step increment
                                  2,// page_increment,
                                  0.0);
	spin_dict_label = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_dict_label), dict_label_bytes );
	gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(spin_dict_label), TRUE);
	gtk_widget_set_usize(spin_dict_label,60,20);
	gtk_box_pack_end (GTK_BOX(hbox), spin_dict_label, FALSE, FALSE, 0);
	gtk_tooltips_set_tip(tooltip, spin_dict_label, 
			     _("Specify the number of bytes to display on top of each toggle buttons in dictionary bar."),"Private");


	vbox = gtk_vbox_new(FALSE,10);
	label = gtk_label_new(_("Selection lookup"));
	gtk_notebook_append_page(GTK_NOTEBOOK(note_book),vbox,label);

	hbox = gtk_hbox_new(FALSE,10);
	gtk_container_border_width(GTK_CONTAINER(hbox), 2);
	gtk_box_pack_start (GTK_BOX(vbox)
			    , hbox,FALSE, FALSE, 0);

	label = gtk_label_new(_("Lookup interval (ms)"));
	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
//	gtk_widget_set_usize( label, 120, 20 );
	gtk_box_pack_start (GTK_BOX(hbox), label,FALSE, FALSE, 0);
	

	adj = gtk_adjustment_new( 1000, //value
				  10, // lower
				  10000, //upper
                                  100, // step increment
                                  1000,// page_increment,
                                  (gfloat)0.0);
	spin_interval = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_interval), auto_interval );
	gtk_widget_set_usize(spin_interval,60,20);
	gtk_box_pack_end (GTK_BOX(hbox), spin_interval, FALSE, FALSE, 0);
	gtk_tooltips_set_tip(tooltip, spin_interval,
			     _("Interval to check selection. Increasing this number may eat up your CPU."), "Private");

	hbox = gtk_hbox_new(FALSE,10);
	gtk_container_border_width(GTK_CONTAINER(hbox), 2);
	gtk_box_pack_start (GTK_BOX(vbox)
			    , hbox,FALSE, FALSE, 0);

	label = gtk_label_new(_("Minimum chars for selection lookup"));
	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
//	gtk_widget_set_usize( label, 120, 20 );
	gtk_box_pack_start (GTK_BOX(hbox), label,FALSE, FALSE, 0);
	

	adj = gtk_adjustment_new( 3, //value
				  0, // lower
				  10, //upper
                                  1, // step increment
                                  5,// page_increment,
                                  (gfloat)0.0);
	spin_minchar = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_minchar), auto_minchar );
	gtk_widget_set_usize(spin_minchar,60,20);
	gtk_box_pack_end (GTK_BOX(hbox), spin_minchar, FALSE, FALSE, 0);
	gtk_tooltips_set_tip(tooltip, spin_minchar,
			     _("When the number of characters in selection is less than this number, it will not be looked up."), "Private");



	hbox = gtk_hbox_new(FALSE,10);
	gtk_container_border_width(GTK_CONTAINER(hbox), 2);
	gtk_box_pack_start (GTK_BOX(vbox)
			    , hbox,FALSE, FALSE, 0);

	label = gtk_label_new(_("Maximum chars for automatic lookup"));
	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
//	gtk_widget_set_usize( label, 120, 20 );
	gtk_box_pack_start (GTK_BOX(hbox), label,FALSE, FALSE, 0);
	

	adj = gtk_adjustment_new(100, //value
				  1, // lower
				  1000, //upper
                                  1, // step increment
                                  10,// page_increment,
                                  (gfloat)0.0);
	spin_maxchar = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_maxchar), auto_maxchar );
	gtk_widget_set_usize(spin_maxchar,60,20);
	gtk_box_pack_end (GTK_BOX(hbox), spin_maxchar, FALSE, FALSE, 0);
	gtk_tooltips_set_tip(tooltip, spin_maxchar,
			     _("When the number of characters in selection is larger than this number, it will not be looked up."), "Private");



	hbox = gtk_hbox_new(FALSE,10);
	gtk_container_border_width(GTK_CONTAINER(hbox), 2);
	gtk_box_pack_start (GTK_BOX(vbox)
			    , hbox,FALSE, FALSE, 0);

	label = gtk_label_new(_("Popup window size"));
	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
//	gtk_widget_set_usize( label, 120, 20 );
	gtk_box_pack_start (GTK_BOX(hbox), label,FALSE, FALSE, 0);


	adj = gtk_adjustment_new(100, //value
				  1, // lower
				  1024, //upper
                                  10, // step increment
                                  10,// page_increment,
                                  (gfloat)0.0);
	spin_popup_width = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_popup_width), popup_width );
	gtk_widget_set_usize(spin_popup_width,60,20);
	gtk_box_pack_start(GTK_BOX(hbox), spin_popup_width, FALSE, FALSE, 0);


	label = gtk_label_new(" x ");
	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
//	gtk_widget_set_usize( label, 120, 20 );
	gtk_box_pack_start (GTK_BOX(hbox), label,FALSE, FALSE, 0);


	adj = gtk_adjustment_new(100, //value
				  1, // lower
				  1024, //upper
                                  10, // step increment
                                  10,// page_increment,
                                  (gfloat)0.0);
	spin_popup_height = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_popup_height), popup_height );
	gtk_widget_set_usize(spin_popup_height,60,20);
	gtk_box_pack_end (GTK_BOX(hbox), spin_popup_height, FALSE, FALSE, 0);


	hbox = gtk_hbox_new(FALSE,10);
	gtk_container_border_width(GTK_CONTAINER(hbox), 2);
	gtk_box_pack_start (GTK_BOX(vbox)
			    , hbox,FALSE, FALSE, 0);

	check_popup_title = gtk_check_button_new_with_label(_("Show popup title"));
	gtk_tooltips_set_tip(tooltip, check_popup_title, 
			     _("Show title of popup window."),"Private");
	gtk_box_pack_start (GTK_BOX(hbox)
			    , check_popup_title,FALSE,FALSE, 0);
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_popup_title), bshow_popup_title);


	hbox = gtk_hbox_new(FALSE,10);
	gtk_container_border_width(GTK_CONTAINER(hbox), 2);
	gtk_box_pack_start (GTK_BOX(vbox)
			    , hbox,FALSE, FALSE, 0);

	check_beep = gtk_check_button_new_with_label(_("Beep on no hit"));
	gtk_tooltips_set_tip(tooltip, check_beep, 
			     _("Beep when no hit."),"Private");
	gtk_box_pack_start (GTK_BOX(hbox)
			    , check_beep,FALSE,FALSE, 0);
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_beep), bbeep_on_nohit);

	gtk_widget_show_all(pref_dlg);

}


#define PREF_TYPE_INTEGER  0
#define PREF_TYPE_BOOLEAN  1
#define PREF_TYPE_STRING   2
#define PREF_TYPE_FLOAT   3

struct _preferences {
	gchar *name;
	gint type;
	void *addr;
};

struct _preferences preferences[] = {
	{"max_search", PREF_TYPE_INTEGER, &max_search},
	{"max_remember_words", PREF_TYPE_INTEGER, &max_remember_words},
	{"dict_label_bytes", PREF_TYPE_INTEGER, &dict_label_bytes},
	{"auto_interval", PREF_TYPE_INTEGER, &auto_interval},
	{"auto_minchar", PREF_TYPE_INTEGER, &auto_minchar},
	{"auto_maxchar", PREF_TYPE_INTEGER, &auto_maxchar},
	{"show_menu_bar", PREF_TYPE_BOOLEAN, &bshow_menu_bar},
	{"show_status_bar", PREF_TYPE_BOOLEAN, &bshow_status_bar},
	{"show_dict_bar", PREF_TYPE_BOOLEAN, &bshow_dict_bar},
	{"show_tree_tab", PREF_TYPE_BOOLEAN, &bshow_tree_tab},
	{"auto_lookup", PREF_TYPE_BOOLEAN, &bauto_lookup},
	{"beep_on_nohit", PREF_TYPE_BOOLEAN, &bbeep_on_nohit},
	{"ignore_locks", PREF_TYPE_BOOLEAN, &bignore_locks},
	{"show_popup_title", PREF_TYPE_BOOLEAN, &bshow_popup_title},
	{"ending_correction", PREF_TYPE_BOOLEAN, &bending_correction},
	{"ending_only_nohit", PREF_TYPE_BOOLEAN, &bending_only_nohit},
	{"show_popup", PREF_TYPE_BOOLEAN, &bshow_popup},
	{"popup_width", PREF_TYPE_INTEGER, &popup_width},
	{"popup_height", PREF_TYPE_INTEGER, &popup_height},
	{"window_x", PREF_TYPE_INTEGER, &window_x},
	{"window_y", PREF_TYPE_INTEGER, &window_y},
	{"window_width", PREF_TYPE_INTEGER, &window_width},
	{"window_height", PREF_TYPE_INTEGER, &window_height},
	{"tree_width", PREF_TYPE_INTEGER, &tree_width},
	{"tree_height", PREF_TYPE_INTEGER, &tree_height},
	{"wave_template", PREF_TYPE_STRING, &wave_template},
	{"mpeg_template", PREF_TYPE_STRING, &mpeg_template},
	{"font_normal", PREF_TYPE_STRING, &fontset_normal},
	{"font_bold", PREF_TYPE_STRING, &fontset_bold},
	{"font_italic", PREF_TYPE_STRING, &fontset_italic},
	{"font_superscript", PREF_TYPE_STRING, &fontset_superscript},
#ifdef ENABLE_WEBSEARCH
	{"browser_template", PREF_TYPE_STRING, &browser_template},
#endif
	{"line_space", PREF_TYPE_FLOAT, &line_space}
};

gint load_preference()
{
	gchar filename[512];

	xmlDoc *doc;
	xmlNode *root;
	xmlNode *xpreference;
	xmlNode *xnode;

	sprintf(filename, "%s/preference.xml", package_dir);

	if(find_file(filename) == FALSE) {
		fprintf(stderr, _("Couldn't open preference. Default value will be used.\n"));
		return(1);
	}

	doc = xml_parse_file(filename);
	if(doc == NULL){
		//warning(_("Couldn't open preference. Default value will be used."));
		return(1);
	}

	root = doc->root;

	// preference
	xpreference = xml_get_child(root);
	if(strcmp(xml_get_name(xpreference), "preference") != 0){
		goto FAILED;
	}

	xnode = xml_get_child(xpreference);
	while(xnode){
		gint items;
		gint i;

		items = sizeof (preferences) / sizeof (preferences[0]);
		for(i=0 ; i<items ; i++){
			if(strcmp(xml_get_name(xnode), preferences[i].name) == 0){
				switch(preferences[i].type){
				case PREF_TYPE_INTEGER:
				case PREF_TYPE_BOOLEAN:
					*(int *)(preferences[i].addr) = atoi(xml_get_content(xnode));
					break;
				case PREF_TYPE_STRING:
					*(gchar **)(preferences[i].addr) = strdup(xml_get_content(xnode));
					break;
				case PREF_TYPE_FLOAT:
//					*(float *)(preferences[i].addr) = strtof(xml_get_content(xnode), NULL);
					sscanf(xml_get_content(xnode), "%f",(float *)(preferences[i].addr));
					break;
				default:
					break;
				}
				
			}
		}
		xnode = xml_get_next(xnode);
	}

	xml_destroy_document(doc);
	return(0);

 FAILED:
	fprintf(stderr, "preference.xml corrupt\n");
	xml_destroy_document(doc);
	return(1);

}

void load_ending()
{
	ENDING *ending;
	gchar filename[512];

	xmlDoc  *doc;
	xmlNode *root;
	xmlNode *xending;
	xmlNode *xentry;
	xmlNode *xnode;

	gchar *inflected;
	gchar *normal;

	clear_ending();

	sprintf(filename, "%s/endinglist.xml", package_dir);

	if(find_file(filename) == FALSE){
		// デフォルトのファイルをコピーする
		gchar command[512];
		sprintf(command, "cp %s/endinglist.xml %s", PACKAGEDIR, filename);
		system(command);

		// コピーしたはずなのになかったらエラー
		if(find_file(filename) == FALSE){
			fprintf(stderr, _("Couldn't open ending list. Check installation.\n"));
			return;
		}
	}

	doc = xml_parse_file(filename);
	if(doc == NULL){
		//warning(_("Couldn't open endinglist."));
		return;
	}


	root = doc->root;

	// endinglist
	xending = xml_get_child(root);
	if(strcmp(xml_get_name(xending), "endinglist") != 0){
		goto FAILED;
	}

	xentry = xml_get_child(xending);
	while(xentry){
		if(strcmp(xml_get_name(xentry), "entry") != 0){
			fprintf(stderr, "<entry> tag expected.\n");
			goto FAILED;
		}

		xnode = xml_get_child(xentry);

		inflected = NULL;
		normal=NULL;

		while(xnode){
			gchar *tagname;
			tagname = xml_get_name(xnode);
			if(strcmp(tagname, "inflected") == 0){
				inflected = xml_get_content(xnode);
			} else if(strcmp(tagname, "normal") == 0){
				normal = xml_get_content(xnode);
			} else {
				fprintf(stderr, "unknown tag name found.\n");
				goto FAILED;
			}
			xnode = xml_get_next(xnode);
		}

		if(!inflected && !normal){
			xentry = xml_get_next(xentry);
			continue;
		}

		ending = (ENDING *)calloc(sizeof(ENDING), 1);
		if(ending == NULL){
			fprintf(stderr, "No memory\n");
			exit(1);
		}
		
		ending->pattern = strdup(inflected);
		ending->normal = strdup(normal);
		add_ending(ending);
		xentry = xml_get_next(xentry);
	}

	xml_destroy_document(doc);
	return;

 FAILED:
	fprintf(stderr, "endinglist.xml corrupt\n");
	xml_destroy_document(doc);
	return;
}


void load_ending_ja()
{
	ENDING *ending;
	gchar filename[512];

	xmlDoc  *doc;
	xmlNode *root;
	xmlNode *xending;
	xmlNode *xentry;
	xmlNode *xnode;

	gchar *inflected;
	gchar *normal;

	ending_list_ja = NULL;

	sprintf(filename, "%s/endinglist-ja.xml", PACKAGEDIR);

	if(find_file(filename) == FALSE){
		fprintf(stderr, _("Couldn't open ending list (JA). Check installation.\n"));
		return;
	}

	doc = xml_parse_file(filename);
	if(doc == NULL){
		//warning(_("Couldn't open endinglist."));
		return;
	}


	root = doc->root;

	// endinglist
	xending = xml_get_child(root);
	if(strcmp(xml_get_name(xending), "endinglist") != 0){
		goto FAILED;
	}

	xentry = xml_get_child(xending);
	while(xentry){
		if(strcmp(xml_get_name(xentry), "entry") != 0){
			fprintf(stderr, "<entry> tag expected.\n");
			goto FAILED;
		}

		xnode = xml_get_child(xentry);

		inflected = NULL;
		normal=NULL;

		while(xnode){
			gchar *tagname;
			tagname = xml_get_name(xnode);
			if(strcmp(tagname, "inflected") == 0){
				inflected = xml_get_content(xnode);
			} else if(strcmp(tagname, "normal") == 0){
				normal = xml_get_content(xnode);
			} else {
				fprintf(stderr, "unknown tag name found.\n");
				goto FAILED;
			}
			xnode = xml_get_next(xnode);
		}

		if(!inflected && !normal){
			xentry = xml_get_next(xentry);
			continue;
		}

		ending = (ENDING *)calloc(sizeof(ENDING), 1);
		if(ending == NULL){
			fprintf(stderr, "No memory\n");
			exit(1);
		}
		
		ending->pattern = strdup(inflected);
		ending->normal = strdup(normal);
		ending_list_ja = g_list_append(ending_list_ja, ending);
		xentry = xml_get_next(xentry);
	}

	xml_destroy_document(doc);
	return;

 FAILED:
	fprintf(stderr, "endinglist.xml corrupt\n");
	xml_destroy_document(doc);
	return;
}



void save_ending()
{
	GList *list;
	ENDING *ending;
	gchar filename[512];
	xmlDoc *doc;
	xmlNode *xending;
	xmlNode *xentry;

	sprintf(filename, "%s/endinglist.xml", package_dir);

	doc = xml_doc_new();
	doc->encoding = strdup("euc-jp");
	doc->version = strdup("1.0");

	xending = xml_add_child(doc->root, "endinglist", NULL);

	list = g_list_first(ending_list);
	while(list){
		ending = (ENDING *)(list->data);
		xentry = xml_add_child(xending, "entry", NULL);
		xml_add_child(xentry, "inflected", ending->pattern);
		xml_add_child(xentry, "normal", ending->normal);
		list = g_list_next(list);
	}

	xml_save_file(filename, doc);

	xml_destroy_document(doc);

	return;

}

gint save_preference()
{
	gchar filename[512];
	xmlDoc *doc;
	xmlNode *xpreference;
	gint items;
	gint i;
	gchar buff[512];

	sprintf(filename, "%s/preference.xml", package_dir);

	doc = xml_doc_new();
	doc->encoding = strdup("euc-jp");
	doc->version = strdup("1.0");

	xpreference = xml_add_child(doc->root, "preference", NULL);


	items = sizeof (preferences) / sizeof (preferences[0]);
	for(i=0 ; i<items ; i++){
		switch(preferences[i].type){
		case PREF_TYPE_INTEGER:
		case PREF_TYPE_BOOLEAN:
			sprintf(buff, "%d", *((int *)preferences[i].addr));
			xml_add_child(xpreference, preferences[i].name, buff);
			break;
		case PREF_TYPE_FLOAT:
			sprintf(buff, "%f", *((float *)preferences[i].addr));
			xml_add_child(xpreference, preferences[i].name, buff);
			break;
		case PREF_TYPE_STRING:
			xml_add_child(xpreference, preferences[i].name, *((gchar **)preferences[i].addr));
			break;
		default:
			break;
		}
				
	}

	xml_save_file(filename, doc);

	xml_destroy_document(doc);

	return(0);
}

void load_weblist()
{
	char filename[512];
	char *name;
	char *home;
	char *pre;
	char *post;
	char *glue;
	char *charcode;
	WEB_GROUP *group;
        WEB_MEMBER *member;

	xmlDoc  *doc;
	xmlNode *root;
	xmlNode *xsearchengine;
	xmlNode *xgroup;
	xmlNode *xengine;
	xmlNode *xnode;


	sprintf(filename, "%s/searchengines.xml", package_dir);

	if(find_file(filename) == FALSE){
		// デフォルトのファイルをコピーする
		gchar command[512];
		sprintf(command, "cp %s/searchengines.xml %s", PACKAGEDIR, filename);
		system(command);

		// コピーしたはずなのになかったらエラー
		if(find_file(filename) == FALSE){
			fprintf(stderr, _("Couldn't open searchengine list. Check installation.\n"));
			return;
		}
	}



	doc = xml_parse_file(filename);
	if(doc == NULL){
		fprintf(stderr, "%s not found. Is this the first try ?\n", filename);
		return;
	}


	root = doc->root;

	xsearchengine = xml_get_child(root);

	if(strcmp(xml_get_name(xsearchengine), "searchengine") != 0){
		goto FAILED;
	}
	
	xgroup = xml_get_child(xsearchengine);

	while(xgroup){
		if(strcmp(xml_get_name(xgroup), "group") != 0){
			fprintf(stderr, "<group> tag expected.\n");
			goto FAILED;
		}

		group = (WEB_GROUP *)calloc(sizeof(WEB_GROUP), 1);
		group->name = strdup(xml_get_attr(xgroup, "name"));
		web_list = g_list_append(web_list, group);
		
		xengine = xml_get_child(xgroup);
		member = NULL;
		
		while(xengine){
			if(strcmp(xml_get_name(xengine), "engine") != 0){
			fprintf(stderr, "<engine> tag expected.\n");
				goto FAILED;
			}

			name = home = pre = post = glue = charcode = NULL;

			xnode = xml_get_child(xengine);
			while(xnode){
				gchar *tagname;
				tagname = xml_get_name(xnode);
				if(strcmp(tagname, "name") == 0){
					name = xml_get_content(xnode);
				} else if(strcmp(tagname, "home") == 0){
					home = xml_get_content(xnode);
				} else if(strcmp(tagname, "pre") == 0){
					pre = xml_get_content(xnode);
				} else if(strcmp(tagname, "post") == 0){
					post = xml_get_content(xnode);
				} else if(strcmp(tagname, "glue") == 0){
					glue = xml_get_content(xnode);
				} else if(strcmp(tagname, "charcode") == 0){
					charcode = xml_get_content(xnode);
				} else {
					fprintf(stderr, "unknown tag name found.\n");
					goto FAILED;
				}
				xnode = xml_get_next(xnode);
			}


			if((!name) || (!pre)) {
				fprintf(stderr, "name or pre not present.\n");
				goto FAILED;
			}
			member = (WEB_MEMBER *)calloc(sizeof(WEB_MEMBER), 1);
			member->name = strdup(name);
			if(home)
				member->home = strdup(home);
			else
				member->home = strdup("");

			member->pre = strdup(pre);

			if(post)
				member->post = strdup(post);
			else
				member->post = strdup("");

			if(glue)
				member->glue = strdup(glue);
			else
				member->glue = strdup("");

			if(charcode)
				member->charcode = strdup(charcode);
			else
				member->charcode = strdup("");

			group->member = g_list_append(group->member, member);

			xengine = xml_get_next(xengine);
		}
		xgroup = xml_get_next(xgroup);
	}
	
	xml_destroy_document(doc);

	//print_weblist();

	return;

 FAILED:
	fprintf(stderr, "dictgroup.xml corrupt\n");
	xml_destroy_document(doc);
	return;


}


void save_weblist()
{
	char filename[512];
	WEB_GROUP *group;
	WEB_MEMBER *member;
	GList *group_item;
	GList *member_item;

	xmlDoc  *doc;
	xmlNode *xsearchengine;
	xmlNode *xgroup;
	xmlNode *xengine;


	sprintf(filename, "%s/searchengines.xml", package_dir);

	doc = xml_doc_new();
	doc->encoding = strdup("euc-jp");
	doc->version = strdup("1.0");

	xsearchengine = xml_add_child(doc->root, "searchengine", NULL);

	group_item = g_list_first(web_list);
	while(group_item)
	{
		group = (WEB_GROUP *)(group_item->data);

		xgroup = xml_add_child(xsearchengine, "group", NULL);
		xml_set_attr(xgroup, "name", group->name);

		member_item = group->member;
		while(member_item != NULL){
			member = (WEB_MEMBER *)(member_item->data);

			xengine = xml_add_child(xgroup, "engine", NULL);

			xml_add_child(xengine, "name", member->name);
			xml_add_child(xengine, "home", member->home);
			xml_add_child(xengine, "pre", member->pre);
			xml_add_child(xengine, "post", member->post);
			xml_add_child(xengine, "glue", member->glue);
			xml_add_child(xengine, "charcode", member->charcode);
			member_item = g_list_next(member_item);
		}
		group_item = g_list_next(group_item);
	}

	xml_save_file(filename, doc);

	xml_destroy_document(doc);
}

extern struct _shortcuts shortcuts;
extern struct _shortcut_command commands[];

void load_shortcut()
{
	gchar filename[512];

	xmlDoc  *doc;
	xmlNode *root;
	xmlNode *xshortcutdef;
	xmlNode *xshortcut;
	xmlNode *xnode;

	gint state;
	gint keyval;
	gchar *command;

	void (* func)();

	gint count=0;
	gint i;

	sprintf(filename, "%s/shortcut.xml", package_dir);

	if(find_file(filename) == FALSE){
		// デフォルトのファイルをコピーする
		gchar command[512];
		sprintf(command, "cp %s/shortcut.xml %s", PACKAGEDIR, filename);
		system(command);

		// コピーしたはずなのになかったらエラー
		if(find_file(filename) == FALSE){
			fprintf(stderr, _("Couldn't open shortcut definition. Check installation.\n"));
			return;
		}
	}

	doc = xml_parse_file(filename);
	if(doc == NULL){
		//warning(_("Couldn't open shortcut definition."));
		return;
	}


	root = doc->root;

	// shortcut
	xshortcutdef = xml_get_child(root);
	if(strcmp(xml_get_name(xshortcutdef), "shortcutdef") != 0){
		goto FAILED;
	}

	shortcuts.count = 0;

	xshortcut = xml_get_child(xshortcutdef);
	while(xshortcut){
		if(strcmp(xml_get_name(xshortcut), "shortcut") != 0){
			fprintf(stderr, "<shortcut> tag expected.\n");
			goto FAILED;
		}

		xnode = xml_get_child(xshortcut);

		command = NULL;
		while(xnode){
			gchar *tagname;
			tagname = xml_get_name(xnode);
			if(strcmp(tagname, "modifier") == 0){
				state = strtol(xml_get_content(xnode), NULL, 16);
			} else if(strcmp(tagname, "value") == 0){
				keyval = strtol(xml_get_content(xnode), NULL, 16);
			} else if(strcmp(tagname, "command") == 0){
				command = xml_get_content(xnode);
			} else {
				fprintf(stderr, "unknown tag name found.\n");
				goto FAILED;
			}
			xnode = xml_get_next(xnode);
		}

		if((keyval == 0) || (command == NULL)) {
			xshortcut = xml_get_next(xshortcut);
			continue;
		}

		func = NULL;
		for(i=0 ; ; i ++){
			if(commands[i].description == NULL)
				break;
			if(strcmp(commands[i].description, command) == 0){
				func = commands[i].func;
				break;
			}
		}

		if(func == NULL){
			xshortcut = xml_get_next(xshortcut);
			continue;
		}

		shortcuts.shortcut[shortcuts.count].state = state;
		shortcuts.shortcut[shortcuts.count].keyval = keyval;;
		shortcuts.shortcut[shortcuts.count].command = &commands[i];
		shortcuts.count ++;
		
		xshortcut = xml_get_next(xshortcut);
	}

	xml_destroy_document(doc);
	return;

 FAILED:
	fprintf(stderr, "shortcut.xml corrupt\n");
	xml_destroy_document(doc);
	return;
}

void save_shortcut()
{
	GList *list;
	ENDING *ending;
	gchar filename[512];
	xmlDoc *doc;
	xmlNode *xshortcutdef;
	xmlNode *xshortcut;
	gint i;
	gchar buff[16];

	sprintf(filename, "%s/shortcut.xml", package_dir);

	doc = xml_doc_new();
	doc->encoding = strdup("euc-jp");
	doc->version = strdup("1.0");

	xshortcutdef = xml_add_child(doc->root, "shortcutdef", NULL);

	for(i=0; i < shortcuts.count ; i++){
		xshortcut = xml_add_child(xshortcutdef, "shortcut", NULL);
		sprintf(buff, "0x%04x", shortcuts.shortcut[i].state);
		xml_add_child(xshortcut, "modifier", buff);
		sprintf(buff, "0x%04x", shortcuts.shortcut[i].keyval);
		xml_add_child(xshortcut, "value", buff);
		xml_add_child(xshortcut, "command", shortcuts.shortcut[i].command->description);
	}

	xml_save_file(filename, doc);

	xml_destroy_document(doc);

	return;

}



syntax highlighted by Code2HTML, v. 0.9.1