#include <stdio.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>

#include "property_messages.h"
#include "property_data.h"
#include "property_window.h"
#include "palette_aux.h"

enum {
    CATEGORY_LIST_LABEL = 0,
    CATEGORY_LIST_WIDGET,
    CATEGORY_LIST_NUM_COLUMNS
};

enum {
    IME_LIST_ENABLE = 0,
    IME_LIST_NAME,
    IME_LIST_MODULE_POINTER,
    IME_LIST_INCONSISTENT,
    IME_LIST_NUM_COLUMNS
};

#define _(s)  (s)

gboolean property_window_delete_callback (GtkWidget *widget, GdkEvent *event, gpointer user_data);
void property_window_click_restore_button_callback (GtkButton *button, gpointer user_data);
void property_window_click_apply_button_callback (GtkButton *button, gpointer user_data);
void property_window_click_ok_button_callback (GtkButton *button, gpointer user_data);
void property_window_click_cancel_button_callback (GtkButton *button, gpointer user_data);

GtkTreeModel *property_window_create_category_list_model(property_window_t *property_window,
							 property_data_t *property_data);
GtkListStore *property_window_create_ime_list_model(property_window_t *property_window,
						    property_data_t *property_data);
GtkWidget *property_window_create_category_list_view();

extern palette_window_t *palette_window;

property_window_t *property_window_new()
{
    property_window_t *property_window;

    GtkWidget *main_window;
    GtkWidget *work_area;
    GtkWidget *apply_button;
    GtkWidget *restore_button;
    GtkWidget *ok_button;
    GtkWidget *cancel_button;

    GtkWidget *hpaned1;
    GtkWidget *scrolledwindow;
    GtkWidget *vbox1;
    GtkWidget *vbox2;
    GtkWidget *frame1;
    GtkWidget *hbox1;

    GtkWidget *category_list_view;

    property_window = (property_window_t *)calloc(1, sizeof(property_window_t));
    if (property_window == NULL)
        return NULL;

    // Create main window.
    main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (main_window), PROPERTY_WINDOW_TITLE);
    gtk_window_set_position (GTK_WINDOW (main_window), GTK_WIN_POS_CENTER);
    gtk_window_set_modal (GTK_WINDOW (main_window), FALSE);
    gtk_window_set_destroy_with_parent (GTK_WINDOW (main_window), TRUE);
    gtk_window_set_resizable (GTK_WINDOW (main_window), TRUE);

    vbox1 = gtk_vbox_new (FALSE, 0);
    gtk_widget_show (vbox1);
    gtk_container_add (GTK_CONTAINER (main_window), vbox1);

    // Create paned window.
    hpaned1 = gtk_hpaned_new ();
    gtk_widget_show (hpaned1);
    gtk_box_pack_start (GTK_BOX (vbox1), hpaned1, TRUE, TRUE, 0);
    gtk_container_set_border_width (GTK_CONTAINER (hpaned1), 4);

    // Create hbox for button area.
    hbox1 = gtk_hbox_new (FALSE, 0);
    gtk_widget_show (hbox1);
    gtk_box_pack_start(GTK_BOX (vbox1), hbox1, FALSE, FALSE, 8);

    ok_button = gtk_button_new_from_stock ("gtk-ok");
    gtk_widget_show (ok_button);
    gtk_box_pack_end (GTK_BOX (hbox1), ok_button, FALSE, FALSE, 4);

    cancel_button = gtk_button_new_from_stock ("gtk-cancel");
    gtk_widget_show (cancel_button);
    gtk_box_pack_end (GTK_BOX (hbox1), cancel_button, FALSE, FALSE, 4);

    apply_button = gtk_button_new_from_stock ("gtk-apply");
    gtk_widget_show (apply_button);
    gtk_box_pack_end (GTK_BOX (hbox1), apply_button, FALSE, FALSE, 4);
    GTK_WIDGET_SET_FLAGS (apply_button, GTK_CAN_DEFAULT);

    restore_button = gtk_button_new_from_stock ("gtk-revert-to-saved");
    gtk_widget_show (restore_button);
    gtk_box_pack_end (GTK_BOX (hbox1), restore_button, FALSE, FALSE, 4);

    // Create scrollwindow for module list.
    scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
    gtk_widget_show (scrolledwindow);
    gtk_paned_pack1 (GTK_PANED (hpaned1), scrolledwindow, FALSE, FALSE);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow), 
                                         GTK_SHADOW_ETCHED_IN);
    gtk_widget_set_size_request(scrolledwindow, 150, 280);

    category_list_view = (GtkWidget *)property_window_create_category_list_view();
    gtk_container_add (GTK_CONTAINER (scrolledwindow), category_list_view);

    // Create vbox for work area and button area.
    vbox2 = gtk_vbox_new (FALSE, 0);
    gtk_widget_show (vbox2);
    gtk_paned_pack2 (GTK_PANED (hpaned1), vbox2, TRUE, FALSE);

    // Create frame for work area.
    frame1 = gtk_frame_new (NULL);
    gtk_widget_show (frame1);
    gtk_widget_set_size_request(frame1, 470, 420);
    gtk_box_pack_start (GTK_BOX (vbox2), frame1, TRUE, TRUE, 0);

    work_area = gtk_vbox_new (FALSE, 0);
    gtk_widget_show (work_area);
    gtk_container_add (GTK_CONTAINER (frame1), work_area);

    property_window->main_window = main_window;
    property_window->category_list_view = category_list_view;
    property_window->work_area = work_area;
    property_window->apply_button = apply_button;
    property_window->restore_button = restore_button;
    
    g_signal_connect ((gpointer) ok_button, "clicked",
                      G_CALLBACK (property_window_click_ok_button_callback),
                      property_window);
    g_signal_connect ((gpointer) cancel_button, "clicked",
                      G_CALLBACK (property_window_click_cancel_button_callback),
                      property_window);
    g_signal_connect ((gpointer) apply_button, "clicked",
                      G_CALLBACK (property_window_click_apply_button_callback),
                      property_window);
    g_signal_connect ((gpointer) restore_button, "clicked",
                      G_CALLBACK (property_window_click_restore_button_callback),
                      property_window);
    g_signal_connect (G_OBJECT (main_window), "delete_event",
                      G_CALLBACK (property_window_delete_callback),
                      property_window);

    gtk_widget_grab_default (apply_button);

    gtk_widget_realize(main_window);

    return property_window;
}

void property_window_destroy(property_window_t *property_window)
{
    int i, j;

    if (!property_window)
        return;

    if (property_window->main_window)
        gtk_widget_destroy(property_window->main_window);

    if (property_window->ime_module_widgets) {
	for (i = 0; i < property_window->num_ime_modules; i++) {
	    ime_module_widget_t *ime_module_widget;

	    ime_module_widget = property_window->ime_module_widgets[i];
	    if (ime_module_widget == NULL)
		continue;

	    if (ime_module_widget->ime_property_widgets) {
		for (j = 0; j < ime_module_widget->num_ime_properties; j++) {
		    ime_property_widget_t *ime_property_widget;
		    ime_property_widget = ime_module_widget->ime_property_widgets[j];
		    if (ime_property_widget != NULL)
		        free ((char *) ime_property_widget);
		}
		free ((char *)ime_module_widget->ime_property_widgets);
	    }
	    free ((char *) ime_module_widget);
	}
	free ((char *)property_window->ime_module_widgets);
    }

    free ((char *)property_window);

    return;
}

void property_window_show(property_window_t *property_window)
{
    if (!property_window)
        return;

    gtk_widget_show(property_window->main_window);
    gdk_window_raise (property_window->main_window->window);

    return;
}

void property_window_hide(property_window_t *property_window)
{
    if (!property_window)
        return;

    gtk_widget_hide(property_window->main_window);
    return;
}

void property_window_set_modified_status(property_window_t *property_window,
					 int modified)
{
    if (property_window == NULL ||
	property_window->modified_status == modified)
	return;

    property_window->modified_status = modified;

    if (modified) {
	gtk_widget_set_sensitive (property_window->apply_button, TRUE);
	gtk_widget_set_sensitive (property_window->restore_button, TRUE);
    } else {
	gtk_widget_set_sensitive (property_window->apply_button, FALSE);
	gtk_widget_set_sensitive (property_window->restore_button, FALSE);
    }

    return;
}

property_window_t *property_window_new_with_property_data(property_data_t *property_data)
{
    property_window_t *property_window;
    GtkTreeModel *category_list_model;

    if (property_data == NULL)
	return NULL;

    property_window = property_window_new();
    if (property_window == NULL)
	return NULL;
    
    category_list_model = (GtkTreeModel *)property_window_create_category_list_model(property_window,
										     property_data);

    property_window->category_list_model = (GtkTreeStore *) category_list_model;

    gtk_tree_view_set_model(GTK_TREE_VIEW (property_window->category_list_view), 
			    GTK_TREE_MODEL (category_list_model));

    gtk_tree_view_expand_all (GTK_TREE_VIEW (property_window->category_list_view));

    property_window->modified_status == TRUE;

    g_object_set_data(G_OBJECT (property_window->main_window),
		      DATA_PROPERTY_DATA_INFO,
		      (gpointer) property_data);

    return property_window;
}

void property_window_restore(property_window_t *property_window)
{
    int i, j;
    property_data_t *property_data;
    int fkey_vkb_id;

    if (property_window == NULL || property_window->modified_status == FALSE)
	return;

    property_data = (property_data_t *) g_object_get_data(G_OBJECT (property_window->main_window),
							  DATA_PROPERTY_DATA_INFO);

    if (property_data == NULL)
	return;

    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (property_window->widget_show_ime_icon),
				 property_data->show_ime_button);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (property_window->widget_show_qjbj_icon),
				 property_data->show_qjbj_button);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (property_window->widget_show_punct_icon),
				 property_data->show_punct_button);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (property_window->widget_show_vkb_icon),
				 property_data->show_vkb_button);
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (property_window->widget_show_utility_icon),
				 property_data->show_utility_button);

    if (property_data->show_with_vertical) {
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (property_window->widget_direction_vertical), TRUE);
    } else {
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (property_window->widget_direction_horizontal), TRUE);
    }

    if (property_data->beep_enabled) {
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (property_window->widget_beep_enabled), TRUE);
    } else {
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (property_window->widget_beep_disabled), TRUE);
    }

    fkey_vkb_id = property_data->fkey_vkb - 'A';
    if (fkey_vkb_id < 0 || fkey_vkb_id >= 26)
	fkey_vkb_id = 'K' -'A';
    gtk_option_menu_set_history (GTK_OPTION_MENU (property_window->widget_fkey_vkb_list), fkey_vkb_id);

    if (property_window->ime_module_widgets) {
	for (i = 0; i < property_window->num_ime_modules; i++) {
	    ime_module_widget_t *ime_module_widget;

	    ime_module_widget = property_window->ime_module_widgets[i];
	    if (ime_module_widget == NULL)
		continue;

	    if (ime_module_widget->ime_property_widgets) {
		for (j = 0; j < ime_module_widget->num_ime_properties; j++) {
		    ime_property_widget_t *ime_property_widget;
		    ime_property_widget = ime_module_widget->ime_property_widgets[j];
		    if (ime_property_widget == NULL ||
			ime_property_widget->ime_property == NULL ||
			ime_property_widget->widget == NULL) 
			continue;

		    if (ime_property_widget->ime_property->type == ImeProperty_Toggle) {
			gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (ime_property_widget->widget),
						     ime_property_widget->ime_property->value.int_value);
		    } else if (ime_property_widget->ime_property->type == ImeProperty_Selection) {
			gtk_option_menu_set_history (GTK_OPTION_MENU (ime_property_widget->widget),
						     ime_property_widget->ime_property->value.int_value);
		    } else if (ime_property_widget->ime_property->type == ImeProperty_Int) {
			gtk_spin_button_set_value (GTK_SPIN_BUTTON (ime_property_widget->widget),
						   ime_property_widget->ime_property->value.int_value);
		    }
		}
	    }
	}
    }

    if (property_window->ime_list_model) {
	g_object_unref (property_window->ime_list_model);
    }

    property_window->ime_list_model = property_window_create_ime_list_model(property_window,
									    property_data);
    gtk_tree_view_set_model (GTK_TREE_VIEW (property_window->ime_list_view),
			     GTK_TREE_MODEL (property_window->ime_list_model));

    property_window_set_modified_status(property_window, FALSE);

    return;
}

void property_window_apply(property_window_t *property_window)
{
    int i, j;
    int fkey_vkb_id;
    property_data_t *property_data;
    GtkTreeModel *ime_list_model;
    gboolean have_iter;
    GtkTreeIter iter;
    gboolean enabled;

    gboolean ime_all_disabled = TRUE;

    if (property_window == NULL || property_window->modified_status == FALSE)
	return;

    property_data = (property_data_t *) g_object_get_data(G_OBJECT (property_window->main_window),
							  DATA_PROPERTY_DATA_INFO);

    if (property_data == NULL)
	return;

    ime_list_model = (GtkTreeModel *)property_window->ime_list_model;
    if (ime_list_model) {
	have_iter = gtk_tree_model_get_iter_first(ime_list_model, &iter);
	while (have_iter) {
	    gtk_tree_model_get (ime_list_model, &iter,
				IME_LIST_ENABLE, &enabled,
				-1);
	    if (enabled) {
		ime_all_disabled = FALSE;
		break;
	    }

	    have_iter = gtk_tree_model_iter_next(ime_list_model, &iter);
	}

	if (ime_all_disabled) {
	    GtkWidget *dialog;

	    dialog = gtk_message_dialog_new (GTK_WINDOW (property_window->main_window),
				   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
				   GTK_MESSAGE_WARNING,
				   GTK_BUTTONS_OK,
				   PROPERTY_WARNING_DIALOG_IME_DISABLED_STR);
	    gtk_dialog_run (GTK_DIALOG (dialog));
	    gtk_widget_destroy (dialog);
	    return;
	}
    }

    /* Apply for statusbar settings */
    property_data->show_ime_button =
	gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (property_window->widget_show_ime_icon));
    property_data->show_qjbj_button =
	gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (property_window->widget_show_qjbj_icon));
    property_data->show_punct_button =
	gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (property_window->widget_show_punct_icon));
    property_data->show_vkb_button =
	gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (property_window->widget_show_vkb_icon));
    property_data->show_utility_button =
	gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (property_window->widget_show_utility_icon));

    property_data->show_with_vertical =
	gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (property_window->widget_direction_vertical));

    property_data->beep_enabled =
	gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (property_window->widget_beep_enabled));

    /* Apply for fkey settings */
    fkey_vkb_id = gtk_option_menu_get_history (GTK_OPTION_MENU (property_window->widget_fkey_vkb_list));
    property_data->fkey_vkb = fkey_vkb_id + 'A';

    /* Apply for ime property settings */
    if (property_window->ime_module_widgets) {
	for (i = 0; i < property_window->num_ime_modules; i++) {
	    ime_module_widget_t *ime_module_widget;

	    ime_module_widget = property_window->ime_module_widgets[i];
	    if (ime_module_widget == NULL)
		continue;

	    if (ime_module_widget->ime_property_widgets) {
		for (j = 0; j < ime_module_widget->num_ime_properties; j++) {
		    ime_property_widget_t *ime_property_widget;
		    ime_property_widget = ime_module_widget->ime_property_widgets[j];
		    if (ime_property_widget == NULL ||
			ime_property_widget->ime_property == NULL ||
			ime_property_widget->widget == NULL) 
			continue;

		    if (ime_property_widget->ime_property->type == ImeProperty_Toggle) {
			ime_property_widget->ime_property->value.int_value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (ime_property_widget->widget));
		    } else if (ime_property_widget->ime_property->type == ImeProperty_Selection) {
			ime_property_widget->ime_property->value.int_value = gtk_option_menu_get_history (GTK_OPTION_MENU (ime_property_widget->widget));
		    } else if (ime_property_widget->ime_property->type == ImeProperty_Int) {
			ime_property_widget->ime_property->value.int_value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (ime_property_widget->widget));
		    }
		}
	    }
	}
    }

    /* Apply for ime enable and sequence settings */
    if (ime_list_model) {
	int current_ime_module_id = 0;

	have_iter = gtk_tree_model_get_iter_first(ime_list_model, &iter);
	while (have_iter) {
	    gpointer ime_module_ptr;
	    gtk_tree_model_get (ime_list_model, &iter,
				IME_LIST_ENABLE, &enabled,
				IME_LIST_MODULE_POINTER, &ime_module_ptr,
				-1);

	    if (ime_module_ptr != NULL) {
		
		DEBUG_printf("uuid: %s, enabled: %d\n", ((ime_module_t *)ime_module_ptr)->uuid, enabled);

		for (i = current_ime_module_id; i < property_data->num_ime_modules; i++) {
		    ime_module_t *ime_module = property_data->ime_modules[i];
		    if (ime_module == NULL)
			continue;

		    if (ime_module == ime_module_ptr) {
			for (j = i; j > current_ime_module_id; j--)
			    property_data->ime_modules[j] = property_data->ime_modules[j - 1];
			property_data->ime_modules[current_ime_module_id] = ime_module;
			current_ime_module_id ++;
			ime_module->enabled = enabled;
			break;
		    }
		}
	    }

	    have_iter = gtk_tree_model_iter_next(ime_list_model, &iter);
	}
    }

    palette_window_update_layout_with_property_data(palette_window, property_data);
    property_data_save_to_profile(property_data);

    palette_aux_Update_LE_Properties_Request();

    property_window_set_modified_status(property_window, FALSE);
    return;
}

/*************************************************************/
/*       restore/applly/cancel/ok buttons' callbacks         */
/*************************************************************/
void
property_window_set_modified_status_callback (GtkWidget *widget, gpointer user_data)
{
    property_window_t *property_window = (property_window_t *) user_data;

    DEBUG_printf("property_window_set_modified_status_callback =======\n");
    property_window_set_modified_status(property_window, TRUE);

    return;
}

void
property_window_click_restore_button_callback (GtkButton *button, gpointer user_data)
{
    property_window_t *property_window = (property_window_t *) user_data;

    property_window_restore(property_window);
}

void
property_window_click_apply_button_callback (GtkButton *button, gpointer user_data)
{
    property_window_t *property_window = (property_window_t *) user_data;

    property_window_apply(property_window);
}

void
property_window_click_ok_button_callback (GtkButton *button, gpointer user_data)
{
    property_window_t *property_window = (property_window_t *)user_data;

    property_window_apply(property_window);
    property_window_hide(property_window);

    return;
}

void
property_window_click_cancel_button_callback (GtkButton *button, gpointer user_data)
{
    property_window_t *property_window = (property_window_t *)user_data;

    property_window_hide(property_window);
    return;
}

gboolean
property_window_delete_callback (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
    property_window_t *property_window = (property_window_t *)user_data;

    property_window_hide(property_window);
    return TRUE;
}

/*************************************************************/
/*       property categories widget                          */
/*************************************************************/
static GtkWidget *
property_window_create_category_header(const char *category)
{
    GtkWidget *vbox;
    GtkWidget *label;
    GtkWidget *sep;

    char buf[128];
    
    vbox = gtk_vbox_new (FALSE, 0);
    gtk_widget_show(vbox);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 0);

    snprintf(buf, 127, "<span weight=\"bold\" size=\"large\">%s</span>", category);

    label = gtk_label_new(NULL);
    gtk_label_set_markup(GTK_LABEL(label), buf);
    gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
    gtk_widget_show(label);
    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);

    sep = gtk_hseparator_new();
    gtk_widget_show(sep);
    gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, TRUE, 4);

    return vbox;
}

static GtkWidget *
property_window_create_setting_cover(const char *category)
{
    GtkWidget *cover;
    char buf[128];

    snprintf(buf, 127, PROPERTY_SETTING_COVER_STR, category);

    cover = gtk_label_new(NULL);

    gtk_label_set_markup(GTK_LABEL(cover), buf);
    gtk_label_set_justify(GTK_LABEL(cover), GTK_JUSTIFY_CENTER);

    gtk_widget_hide(cover);

    return cover;
}

static GtkWidget *
property_window_create_candidate_style_view(property_window_t *property_window,
					    property_data_t *property_data)
{
    GtkWidget *vbox;
    GtkWidget *header;
    GtkWidget *frame;
    GtkWidget *table;
    GtkWidget *hbox;
    GtkWidget *widget_application_style;
    GtkWidget *widget_traditional_style;
    GtkWidget *widget_modern_style;
    GSList    *group;
    
    vbox = gtk_vbox_new (FALSE, 6);
    gtk_widget_show(vbox);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);

    header = property_window_create_category_header(CATEGORY_CANDIDATE_SETTING_STR);
    gtk_box_pack_start(GTK_BOX(vbox), header, FALSE, FALSE, 4);

    // Create the ToolBar setup block.
    frame = gtk_frame_new (_("Candidate Style"));
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
    gtk_container_set_border_width (GTK_CONTAINER (frame), 4);

    table = gtk_table_new (2, 2, FALSE);
    gtk_widget_show (table);
    gtk_container_add (GTK_CONTAINER (frame), table);
    gtk_table_set_row_spacings (GTK_TABLE (table), 4);
    gtk_table_set_col_spacings (GTK_TABLE (table), 8);

/*
    hbox = gtk_hbox_new(FALSE, 20);
    gtk_widget_show(hbox);
    gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
    gtk_container_add(GTK_CONTAINER (frame), hbox);
*/
    widget_traditional_style = gtk_radio_button_new_with_mnemonic (NULL, _("_Traditional mode"));
    gtk_widget_show (widget_traditional_style);
/*
    gtk_box_pack_start(GTK_BOX (hbox), widget_traditional_style, FALSE, FALSE, 5);
*/
    gtk_table_attach (GTK_TABLE (table), widget_traditional_style, 0, 1, 0, 1,
                          (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                          (GtkAttachOptions) (GTK_EXPAND), 4, 0);

    group = gtk_radio_button_get_group(GTK_RADIO_BUTTON (widget_traditional_style));
    widget_modern_style = gtk_radio_button_new_with_mnemonic (group, _("_Modern mode"));
    gtk_widget_show (widget_modern_style);
/*
    gtk_box_pack_start(GTK_BOX (hbox), widget_modern_style, FALSE, FALSE, 5);
*/
    gtk_table_attach (GTK_TABLE (table), widget_modern_style, 1, 2, 0, 1,
                          (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                          (GtkAttachOptions) (GTK_EXPAND), 4, 0);


    group = gtk_radio_button_get_group(GTK_RADIO_BUTTON (widget_modern_style));
    widget_application_style = gtk_radio_button_new_with_mnemonic (group, _("_Application mode"));
    gtk_widget_show (widget_application_style);
/*
    gtk_box_pack_start(GTK_BOX (hbox), widget_application_style, FALSE, FALSE, 5);
*/
    gtk_table_attach (GTK_TABLE (table), widget_application_style, 0, 2, 1, 2,
                          (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                          (GtkAttachOptions) (GTK_EXPAND), 4, 0);

    gtk_widget_hide(vbox);

    return vbox;
}

/*************************************************************/
/*           properties for toolbar                          */
/*************************************************************/
static void
statusbar_show_ime_button_toggled_cb(GtkWidget *button,
				     property_window_t *property_window)
{
/*
    int show_ime_button = 0;

    if (property_data == NULL)
	return;

    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) {
	show_ime_button = 1;
    }

    property_data->show_ime_button = show_ime_button;
*/

    property_window_set_modified_status(property_window, TRUE);
    return;
}

static GtkWidget *
property_window_create_statusbar_setting_view(property_window_t *property_window,
					      property_data_t *property_data)
{
    GtkWidget *vbox;
    GtkWidget *header;
    GtkWidget *widget_show_ime_icon;
    GtkWidget *widget_show_qjbj_icon;
    GtkWidget *widget_show_punct_icon;
    GtkWidget *widget_show_vkb_icon;
    GtkWidget *widget_show_utility_icon;
    GtkWidget *frame;
    GtkWidget *table;
    GtkWidget *hbox;
    GtkWidget *widget_direction_vertical;
    GtkWidget *widget_direction_horizontal;
    GSList    *group;
    
    vbox = gtk_vbox_new (FALSE, 6);
    gtk_widget_show(vbox);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);

    header = property_window_create_category_header(CATEGORY_STATUSBAR_SETTING_STR);
    gtk_box_pack_start(GTK_BOX(vbox), header, FALSE, FALSE, 4);

    // Create the ToolBar setup block.
    frame = gtk_frame_new (STATUSBAR_SHOW_HIDE_FRAME);
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
    gtk_container_set_border_width (GTK_CONTAINER (frame), 4);

    table = gtk_table_new (3, 2, FALSE);
    gtk_widget_show (table);
    gtk_container_add (GTK_CONTAINER (frame), table);
    gtk_table_set_row_spacings (GTK_TABLE (table), 4);
    gtk_table_set_col_spacings (GTK_TABLE (table), 8);

    widget_show_ime_icon = gtk_check_button_new_with_mnemonic (STATUSBAR_SHOW_IME_BUTTON);
    gtk_widget_show (widget_show_ime_icon);
    property_window->widget_show_ime_icon = widget_show_ime_icon;
    gtk_table_attach (GTK_TABLE (table), widget_show_ime_icon, 0, 1, 0, 1,
                          (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                          (GtkAttachOptions) (GTK_EXPAND), 4, 0);
    g_signal_connect (G_OBJECT (widget_show_ime_icon), "toggled",
                      G_CALLBACK (property_window_set_modified_status_callback),
                      property_window);

    widget_show_qjbj_icon = gtk_check_button_new_with_mnemonic (STATUSBAR_SHOW_QJBJ_BUTTON);
    gtk_widget_show (widget_show_qjbj_icon);
    property_window->widget_show_qjbj_icon = widget_show_qjbj_icon;
    gtk_table_attach (GTK_TABLE (table), widget_show_qjbj_icon, 0, 1, 1, 2,
                          (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                          (GtkAttachOptions) (GTK_EXPAND), 4, 0);
    g_signal_connect (G_OBJECT (widget_show_qjbj_icon), "toggled",
                      G_CALLBACK (property_window_set_modified_status_callback),
                      property_window);

    widget_show_punct_icon = gtk_check_button_new_with_mnemonic (STATUSBAR_SHOW_PUNCT_BUTTON);
    gtk_widget_show (widget_show_punct_icon);
    property_window->widget_show_punct_icon = widget_show_punct_icon;
    gtk_table_attach (GTK_TABLE (table), widget_show_punct_icon, 0, 2, 2, 3,
                          (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                          (GtkAttachOptions) (GTK_EXPAND), 4, 0);
    g_signal_connect (G_OBJECT (widget_show_punct_icon), "toggled",
                      G_CALLBACK (property_window_set_modified_status_callback),
                      property_window);

    widget_show_vkb_icon = gtk_check_button_new_with_mnemonic (STATUSBAR_SHOW_VKB_BUTTON);
    gtk_widget_show (widget_show_vkb_icon);
    property_window->widget_show_vkb_icon = widget_show_vkb_icon;
    gtk_table_attach (GTK_TABLE (table), widget_show_vkb_icon, 1, 2, 0, 1,
                          (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                          (GtkAttachOptions) (GTK_EXPAND), 4, 0);
    g_signal_connect (G_OBJECT (widget_show_vkb_icon), "toggled",
                      G_CALLBACK (property_window_set_modified_status_callback),
                      property_window);

    widget_show_utility_icon = gtk_check_button_new_with_mnemonic (STATUSBAR_SHOW_UTILITY_BUTTON);
    gtk_widget_show (widget_show_utility_icon);
    property_window->widget_show_utility_icon = widget_show_utility_icon;
    gtk_table_attach (GTK_TABLE (table), widget_show_utility_icon, 1, 2, 1, 2,
                          (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                          (GtkAttachOptions) (GTK_EXPAND), 4, 0);
    g_signal_connect (G_OBJECT (widget_show_utility_icon), "toggled",
                      G_CALLBACK (property_window_set_modified_status_callback),
                      property_window);

    // Create the ToolBar setup block.
    frame = gtk_frame_new (STATUSBAR_DIRECTION_FRAME);
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
    gtk_container_set_border_width (GTK_CONTAINER (frame), 4);

    hbox = gtk_hbox_new(FALSE, 20);
    gtk_widget_show(hbox);
    gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
    gtk_container_add(GTK_CONTAINER (frame), hbox);

    widget_direction_vertical = gtk_radio_button_new_with_mnemonic (NULL, STATUSBAR_VERTICAL_STYLE);
    gtk_widget_show (widget_direction_vertical);
    property_window->widget_direction_vertical = widget_direction_vertical;
    gtk_box_pack_start(GTK_BOX (hbox), widget_direction_vertical, FALSE, FALSE, 5);
    g_signal_connect (G_OBJECT (widget_direction_vertical), "toggled",
                      G_CALLBACK (property_window_set_modified_status_callback),
                      property_window);

    group = gtk_radio_button_get_group(GTK_RADIO_BUTTON (widget_direction_vertical));
    widget_direction_horizontal = gtk_radio_button_new_with_mnemonic (group, STATUSBAR_HORIZONTAL_STYLE);
    gtk_widget_show (widget_direction_horizontal);
    property_window->widget_direction_horizontal = widget_direction_horizontal;
    gtk_box_pack_start(GTK_BOX (hbox), widget_direction_horizontal, FALSE, FALSE, 5);
    g_signal_connect (G_OBJECT (widget_direction_horizontal), "toggled",
                      G_CALLBACK (property_window_set_modified_status_callback),
                      property_window);

    gtk_widget_hide(vbox);

    return vbox;
}

/*************************************************************/
/*           properties for shortcut keys                    */
/*************************************************************/
static GtkWidget *
property_window_create_fkey_setting_view(property_window_t *property_window,
					 property_data_t *property_data)
{
    GtkWidget *vbox;
    GtkWidget *label;
    GtkWidget *header;
    GtkWidget *frame;
    GtkWidget *table;
    GtkWidget *hbox;
/*
    GtkWidget *toggle_ctrl;
    GtkWidget *toggle_alt;
    GtkWidget *toggle_shift;
*/

    GtkWidget *option_menu, *menu, *menu_item;
    int i;
    char buf[4];

    vbox = gtk_vbox_new (FALSE, 6);
    gtk_widget_show(vbox);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);

    header = property_window_create_category_header(CATEGORY_FKEY_SETTING_STR);
    gtk_box_pack_start(GTK_BOX(vbox), header, FALSE, FALSE, 4);

    // Create the ToolBar setup block.
    frame = gtk_frame_new (FKEY_SETTING_VKB_FRAME);
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);

    table = gtk_table_new (1, 2, FALSE);
    gtk_widget_show (table);
    gtk_container_set_border_width (GTK_CONTAINER (table), 8);
    gtk_container_add (GTK_CONTAINER (frame), table);
    gtk_table_set_row_spacings (GTK_TABLE (table), 4);
    gtk_table_set_col_spacings (GTK_TABLE (table), 8);

    label = gtk_label_new (FKEY_VKB_LABEL);
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
                          (GtkAttachOptions) (GTK_FILL),
                          (GtkAttachOptions) (0), 4, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

    hbox = gtk_hbox_new (FALSE, 0);
    gtk_widget_show (hbox);
    gtk_table_attach (GTK_TABLE (table), hbox, 1, 2, 0, 1,
                      (GtkAttachOptions) (GTK_FILL),
                      (GtkAttachOptions) (0), 4, 4);

#if 0
    toggle_ctrl = gtk_check_button_new_with_mnemonic (_("_Ctrl"));
    gtk_widget_show (toggle_ctrl);
    gtk_box_pack_start (GTK_BOX (hbox), toggle_ctrl, TRUE, TRUE, 2);

    toggle_alt = gtk_check_button_new_with_mnemonic (_("A_lt"));
    gtk_widget_show (toggle_alt);
    gtk_box_pack_start (GTK_BOX (hbox), toggle_alt, TRUE, TRUE, 2);

    toggle_shift = gtk_check_button_new_with_mnemonic (_("_Shift"));
    gtk_widget_show (toggle_shift);
    gtk_box_pack_start (GTK_BOX (hbox), toggle_shift, TRUE, TRUE, 2);
#endif

    option_menu = gtk_option_menu_new();
    gtk_widget_show (option_menu);
    g_signal_connect (G_OBJECT (option_menu), "changed",
		      G_CALLBACK (property_window_set_modified_status_callback),
		      property_window);

    menu = gtk_menu_new();
    gtk_widget_show (menu);
    buf[0] = ' ';
    buf[2] = ' ';
    buf[3] = '\0';
    for (i = 0; i < 26; i++) {
        buf[1] = 'A'+ i;
	menu_item = gtk_menu_item_new_with_label (buf);
	gtk_widget_show (menu_item);
	gtk_menu_shell_append (GTK_MENU_SHELL (menu),
			       menu_item);
    }
    gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
    property_window->widget_fkey_vkb_list = option_menu;

    gtk_box_pack_start (GTK_BOX (hbox), option_menu, FALSE, FALSE, 2);
    gtk_widget_hide(vbox);

    return vbox;
}

static GtkWidget *
property_window_create_beep_setting_view(property_window_t *property_window,
					 property_data_t *property_data)
{
    GtkWidget *vbox;
    GtkWidget *header;
    GtkWidget *frame;
    GtkWidget *hbox;
    GtkWidget *widget_beep_enabled;
    GtkWidget *widget_beep_disabled;
    GSList    *group;
    
    vbox = gtk_vbox_new (FALSE, 6);
    gtk_widget_show(vbox);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);

    header = property_window_create_category_header(CATEGORY_BEEP_SETTING_STR);
    gtk_box_pack_start(GTK_BOX(vbox), header, FALSE, FALSE, 4);

    // Create the ToolBar setup block.
    frame = gtk_frame_new (BEEP_SETTING_FRAME);
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
    gtk_container_set_border_width (GTK_CONTAINER (frame), 4);

    hbox = gtk_hbox_new(FALSE, 20);
    gtk_widget_show(hbox);
    gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
    gtk_container_add(GTK_CONTAINER (frame), hbox);

    widget_beep_enabled = gtk_radio_button_new_with_mnemonic (NULL, BEEP_ENABLE_STYLE);
    gtk_widget_show (widget_beep_enabled);
    property_window->widget_beep_enabled = widget_beep_enabled;
    gtk_box_pack_start(GTK_BOX (hbox), widget_beep_enabled, FALSE, FALSE, 5);
    g_signal_connect (G_OBJECT (widget_beep_enabled), "toggled",
                      G_CALLBACK (property_window_set_modified_status_callback),
                      property_window);

    group = gtk_radio_button_get_group(GTK_RADIO_BUTTON (widget_beep_enabled));
    widget_beep_disabled = gtk_radio_button_new_with_mnemonic (group, BEEP_DISABLE_STYLE);
    gtk_widget_show (widget_beep_disabled);
    property_window->widget_beep_disabled = widget_beep_disabled;
    gtk_box_pack_start(GTK_BOX (hbox), widget_beep_disabled, FALSE, FALSE, 5);
    g_signal_connect (G_OBJECT (widget_beep_disabled), "toggled",
                      G_CALLBACK (property_window_set_modified_status_callback),
                      property_window);

    gtk_widget_hide(vbox);

    return vbox;
}

/*************************************************************/
/*           properties for IMEs' status                     */
/*************************************************************/
GtkListStore *property_window_create_ime_list_model(property_window_t *property_window,
						    property_data_t *property_data)
{
    int i;
    GtkListStore *model;
    GtkTreeIter iter;

    model = gtk_list_store_new(IME_LIST_NUM_COLUMNS,
			       G_TYPE_BOOLEAN,
			       G_TYPE_STRING,
			       G_TYPE_POINTER,
			       G_TYPE_BOOLEAN);

    if (property_data == NULL)
        return model;

    for (i = 0; i < property_data->num_ime_modules; i++) {
        ime_module_t *ime_module = property_data->ime_modules[i];

        if (ime_module == NULL || 
	    ime_module->name == NULL)
            continue;

	gtk_list_store_append(model, &iter);
	gtk_list_store_set(model, &iter,
			   IME_LIST_ENABLE, ime_module->enabled,
			   IME_LIST_NAME, ime_module->name,
			   IME_LIST_MODULE_POINTER, ime_module,
			   IME_LIST_INCONSISTENT, FALSE,
			   -1);
    }

    return model;
}


void property_window_ime_set_as_default_cb(GtkWidget *widget, gpointer user_data)
{
    GtkWidget *ime_list_view;
    GtkTreeSelection *selection;
    GtkTreeModel *model;
    GtkTreeIter iter;

    property_window_t *property_window = (property_window_t *) user_data;

    if (property_window == NULL)
	return;

    ime_list_view = property_window->ime_list_view;
    if (ime_list_view == NULL)
	return;

    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ime_list_view));

    if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
        GtkTreePath* first_path = gtk_tree_path_new_first();
        GtkTreePath* now_path = gtk_tree_model_get_path(model, &iter);
	if (gtk_tree_path_compare(first_path, now_path)!=0) {
	    gtk_list_store_move_after(GTK_LIST_STORE(model), &iter, NULL);
	    gtk_tree_selection_select_path(selection, first_path);
	    gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW (ime_list_view), first_path, NULL, FALSE, 0, 0);
        }
        gtk_tree_path_free(first_path);
        gtk_tree_path_free(now_path);
    }

    property_window_set_modified_status(property_window, TRUE);
}

void property_window_ime_move_up_cb(GtkWidget *widget, gpointer user_data)
{
    GtkWidget *ime_list_view;
    GtkTreeSelection *selection;
    GtkTreeModel *model;
    GtkTreeIter iter;

    property_window_t *property_window = (property_window_t *) user_data;

    if (property_window == NULL)
	return;

    ime_list_view = property_window->ime_list_view;
    if (ime_list_view == NULL)
	return;

    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ime_list_view));

    if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
        GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
        if (gtk_tree_path_prev(path)) {
	    GtkTreeIter prev;

	    gtk_tree_model_get_iter(model, &prev, path);
	    gtk_list_store_swap(GTK_LIST_STORE(model), &iter, &prev);
	    gtk_tree_selection_select_path(selection, path);

	    gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW (ime_list_view), path, NULL, FALSE, 0, 0);
        }
        gtk_tree_path_free(path);
    }

    property_window_set_modified_status(property_window, TRUE);
}

void property_window_ime_move_down_cb(GtkWidget *widget, gpointer user_data)
{
    GtkWidget *ime_list_view;
    GtkTreeSelection *selection;
    GtkTreeModel *model;
    GtkTreeIter iter;

    property_window_t *property_window = (property_window_t *) user_data;

    if (property_window == NULL)
	return;

    ime_list_view = property_window->ime_list_view;
    if (ime_list_view == NULL)
	return;

    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ime_list_view));

    if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
        GtkTreeIter next;
        GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
        gtk_tree_path_next(path);
        if (gtk_tree_model_get_iter(model, &next, path)) {
	    gtk_list_store_swap(GTK_LIST_STORE(model), &iter, &next);
	    gtk_tree_selection_select_path(selection, path);
	    gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW (ime_list_view), path, NULL, FALSE, 0, 0);
        }
        gtk_tree_path_free(path);
    }

    property_window_set_modified_status(property_window, TRUE);
}

void property_window_ime_enable_toggled_cb (GtkCellRendererToggle *cell,
					    gchar *path_str,
					    gpointer user_data)
{
    GtkTreeModel *ime_list_model;
    GtkTreeIter  iter;
    GtkTreePath  *path = gtk_tree_path_new_from_string (path_str);
    gboolean enabled;

    property_window_t *property_window = (property_window_t *) user_data;

    if (property_window == NULL)
	return;

    ime_list_model = (GtkTreeModel *)property_window->ime_list_model;
    if (ime_list_model == NULL)
	return;

    gtk_tree_model_get_iter (ime_list_model, &iter, path);
    gtk_tree_model_get (ime_list_model, &iter, IME_LIST_ENABLE, &enabled, -1);

    enabled = !enabled;

    DEBUG_printf("enabled: %d\n", enabled);
    gtk_list_store_set (GTK_LIST_STORE (ime_list_model), &iter, IME_LIST_ENABLE, enabled, -1);

    gtk_tree_path_free (path);

    property_window_set_modified_status(property_window, TRUE);
}

GtkWidget *property_window_create_ime_list_view(property_window_t *property_window)
{
    GtkWidget *vbox;
    GtkWidget *scrolledwindow;
    GtkWidget *header;
    GtkWidget *frame;
    GtkWidget *hbox1, *vbox1;
    GtkWidget *up_button, *down_button;
    GtkWidget *default_button;

    GtkWidget *ime_list_view;
    GtkTreeModel *model;
    GtkCellRenderer *renderer;
    GtkTreeViewColumn *column;
    GtkTreeSelection *selection;

    vbox = gtk_vbox_new(FALSE, 4);
    gtk_widget_show(vbox);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);

    header = property_window_create_category_header(CATEGORY_IMESTATUS_SETTING_STR);
    gtk_box_pack_start(GTK_BOX(vbox), header, FALSE, FALSE, 4);

    hbox1 = gtk_hbox_new(FALSE, 4);
    gtk_widget_show(hbox1);
    gtk_box_pack_start(GTK_BOX(vbox), hbox1, TRUE, TRUE, 4);

    scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
    gtk_widget_show(scrolledwindow);
    gtk_box_pack_start(GTK_BOX(hbox1), scrolledwindow, TRUE, TRUE, 4);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolledwindow),
				   GTK_POLICY_AUTOMATIC,
				   GTK_POLICY_AUTOMATIC);
    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolledwindow),
					GTK_SHADOW_NONE);

    ime_list_view = gtk_tree_view_new ();
    gtk_widget_show(ime_list_view);
    property_window->ime_list_view = ime_list_view;
    gtk_container_add(GTK_CONTAINER (scrolledwindow), ime_list_view);
    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW (ime_list_view), TRUE);
    gtk_tree_view_set_rules_hint(GTK_TREE_VIEW (ime_list_view), TRUE);

    // Enable column
    column = gtk_tree_view_column_new();
    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
    gtk_tree_view_column_set_resizable(column, FALSE);
    gtk_tree_view_column_set_title(column, IME_COLUMN_ENABLE_STR);

    renderer = gtk_cell_renderer_toggle_new();
    gtk_cell_renderer_toggle_set_radio(GTK_CELL_RENDERER_TOGGLE (renderer), FALSE);
    gtk_tree_view_column_pack_start(column, renderer, FALSE);
    gtk_tree_view_column_set_attributes(column, renderer,
					"active", IME_LIST_ENABLE,
					"inconsistent", IME_LIST_INCONSISTENT,
					NULL);
    g_signal_connect (G_OBJECT (renderer), "toggled",
                      G_CALLBACK (property_window_ime_enable_toggled_cb),
                      property_window);

    gtk_tree_view_append_column(GTK_TREE_VIEW (ime_list_view), column);

    // Name column
    column = gtk_tree_view_column_new();
    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
    gtk_tree_view_column_set_resizable(column, FALSE);

    gtk_tree_view_column_set_title(column, IME_COLUMN_NAME_STR);

    renderer = gtk_cell_renderer_text_new();
    gtk_tree_view_column_pack_start(column, renderer, TRUE);
    gtk_tree_view_column_set_attributes(column, renderer,
					"text", IME_LIST_NAME, NULL);

    gtk_tree_view_append_column(GTK_TREE_VIEW (ime_list_view), column);

    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW (ime_list_view));
    gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);

    vbox1 = gtk_vbox_new(FALSE, 4);
    gtk_widget_show(vbox1);
    gtk_box_pack_start(GTK_BOX (hbox1), vbox1, FALSE, FALSE, 4);

    default_button = gtk_button_new_from_stock(GTK_STOCK_GOTO_TOP);
    gtk_widget_show(default_button);
    gtk_box_pack_start(GTK_BOX (vbox1), default_button, FALSE, FALSE, 4);
    g_signal_connect(G_OBJECT (default_button),"clicked", 
		     G_CALLBACK (property_window_ime_set_as_default_cb),
		     property_window);

    up_button = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
    gtk_widget_show(up_button);
    gtk_box_pack_start(GTK_BOX (vbox1), up_button, FALSE, FALSE, 4);
    g_signal_connect(G_OBJECT (up_button),"clicked", 
		     G_CALLBACK (property_window_ime_move_up_cb),
		     property_window);

    down_button = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
    gtk_widget_show(down_button);
    gtk_box_pack_start(GTK_BOX (vbox1), down_button, FALSE, FALSE, 4);
    g_signal_connect(G_OBJECT (down_button),"clicked", 
		     G_CALLBACK (property_window_ime_move_down_cb),
		     property_window);

    gtk_widget_hide(vbox);

    return vbox;
}

/*************************************************************/
/*           properties for IMEs                             */
/*************************************************************/
GtkWidget *property_window_create_ime_property_view(property_window_t *property_window,
						    ime_module_t *ime_module,
						    ime_module_widget_t *ime_module_widget)
{
    GtkWidget *vbox;
    GtkWidget *header;
    GtkWidget *scrolledwindow;
    GtkWidget *vbox1;
    GtkWidget *check;
    GtkWidget *table;
    GtkWidget *label;
    GtkWidget *combo;
    char buf[128];
    int i;

    ImePropertyListRec *property_list;

    if (ime_module == NULL ||
	ime_module->property_list == NULL ||
	ime_module_widget == NULL)
	return NULL;

    property_list = ime_module->property_list;

    vbox = gtk_vbox_new(FALSE, 4);
    gtk_widget_show(vbox);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);

    snprintf(buf, 127, "%s - %s", CATEGORY_IME_SETTING_STR, ime_module->name);
    header = property_window_create_category_header(buf);
    gtk_box_pack_start(GTK_BOX(vbox), header, FALSE, FALSE, 4);

/*
    scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
    gtk_widget_show(scrolledwindow);
    gtk_box_pack_start(GTK_BOX(vbox), scrolledwindow, TRUE, TRUE, 4);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow),
				   GTK_POLICY_AUTOMATIC,
				   GTK_POLICY_AUTOMATIC);
    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolledwindow),
                                        GTK_SHADOW_NONE);
*/

    table= gtk_table_new(0, 2, FALSE);
    gtk_widget_show(table);
    gtk_table_set_row_spacings (GTK_TABLE (table), 2);
    gtk_table_set_col_spacings (GTK_TABLE (table), 12);
    gtk_container_set_border_width (GTK_CONTAINER (table), 2);
/*
    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW (scrolledwindow),
					  GTK_WIDGET(table));
*/
    gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);

    ime_module_widget->num_ime_properties = property_list->count;
    ime_module_widget->ime_property_widgets = (ime_property_widget_t **)calloc(property_list->count,
									sizeof(ime_property_widget_t *));

    if (ime_module_widget->ime_property_widgets == NULL)
	return vbox;

    for (i = 0; i < property_list->count; i ++) {
	ImePropertyRec *ime_property = &(property_list->properties[i]);

	ime_module_widget->ime_property_widgets[i] = (ime_property_widget_t *)calloc(1,
								sizeof (ime_property_widget_t));
	if (ime_module_widget->ime_property_widgets[i] == NULL)
	    continue;

	ime_module_widget->ime_property_widgets[i]->ime_property = ime_property;

	if (ime_property->type == ImeProperty_Toggle) {
	    gtk_table_resize(GTK_TABLE(table), i+1, 2);
	    check = gtk_check_button_new_with_label(ime_property->name);
	    gtk_widget_show(check);
	    g_signal_connect (G_OBJECT (check), "toggled",
			      G_CALLBACK (property_window_set_modified_status_callback),
			      property_window);

	    gtk_table_attach (GTK_TABLE (table), check, 0, 1, i, i + 1,
                          (GtkAttachOptions) (GTK_FILL),
                          (GtkAttachOptions) (0), 0, 0);

	    ime_module_widget->ime_property_widgets[i]->widget = check;

	} else if (ime_property->type == ImeProperty_Selection) {
	    int j;
	    char **value_ptr;
	    GtkWidget *alignment;
	    GtkWidget *option_menu, *menu, *menu_item;

	    gtk_table_resize(GTK_TABLE(table), i+1, 2);
	    label = gtk_label_new(ime_property->name);
	    gtk_widget_show(label);

	    gtk_table_attach (GTK_TABLE (table), label, 0, 1, i, i + 1,
                          (GtkAttachOptions) (GTK_FILL),
                          (GtkAttachOptions) (0), 0, 0);
	    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

	    alignment = gtk_alignment_new (0, 0.5, 0, 1);
	    gtk_widget_show (alignment);
	    gtk_table_attach (GTK_TABLE (table), alignment, 1, 2, i, i + 1,
			      (GtkAttachOptions) (GTK_FILL),
			      (GtkAttachOptions) (0), 0, 0);

	    option_menu = gtk_option_menu_new();
	    gtk_widget_show (option_menu);
	    g_signal_connect (G_OBJECT (option_menu), "changed",
			      G_CALLBACK (property_window_set_modified_status_callback),
			      property_window);

	    menu = gtk_menu_new();
	    gtk_widget_show (menu);
	    value_ptr = ime_property->range.multiString_range;
	    if (value_ptr != NULL) {
	        for (j = 0; value_ptr[j]; j++) {
		     menu_item = gtk_menu_item_new_with_label (value_ptr[j]);
		     gtk_widget_show (menu_item);
		     gtk_menu_shell_append (GTK_MENU_SHELL (menu),
					    menu_item);
	        }
	    }
	    gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);

	    gtk_container_add (GTK_CONTAINER (alignment), option_menu);

	    ime_module_widget->ime_property_widgets[i]->widget = option_menu;

	} else if (ime_property->type == ImeProperty_Int) {
	    GtkWidget *alignment;
	    GtkWidget *spin_button;
	    int value_min, value_max;

	    gtk_table_resize(GTK_TABLE(table), i+1, 2);
	    label = gtk_label_new(ime_property->name);
	    gtk_widget_show(label);

	    gtk_table_attach (GTK_TABLE (table), label, 0, 1, i, i + 1,
                          (GtkAttachOptions) (GTK_FILL),
                          (GtkAttachOptions) (0), 0, 0);
	    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

	    alignment = gtk_alignment_new (0, 0.5, 0, 1);
	    gtk_widget_show (alignment);
	    gtk_table_attach (GTK_TABLE (table), alignment, 1, 2, i, i + 1,
			      (GtkAttachOptions) (GTK_FILL),
			      (GtkAttachOptions) (0), 0, 0);

	    value_min = ime_property->range.int_range.min;
	    value_max = ime_property->range.int_range.max;
	    spin_button = gtk_spin_button_new_with_range (value_min, value_max, value_min);
	    gtk_widget_show (spin_button);
	    gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), 1);
	    g_signal_connect (G_OBJECT (spin_button), "value_changed",
			      G_CALLBACK (property_window_set_modified_status_callback),
			      property_window);

	    gtk_container_add (GTK_CONTAINER (alignment), spin_button);

	    ime_module_widget->ime_property_widgets[i]->widget = spin_button;
	}
    }

    gtk_widget_hide(vbox);

    return vbox;
}

/*************************************************************/
/*           Version/Copyright Info                          */
/*************************************************************/
/* create copyright view */
static GtkWidget *
property_window_create_copyright_view()
{
    GtkWidget *vbox;
    GtkWidget *header;
    GtkWidget *hbox1;
    GtkWidget *label_title;
    GtkWidget *label_space;
    GtkWidget *label_info;
    GtkWidget *vbox_category;
    GtkWidget *vbox_info;

    vbox = gtk_vbox_new(FALSE, 10);
    gtk_widget_show(vbox);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);

    header = property_window_create_category_header(CATEGORY_COPYRIGHT_STR);
    gtk_box_pack_start(GTK_BOX(vbox), header, FALSE, FALSE, 4);

    /* for copyright category */
    vbox_category = gtk_vbox_new (FALSE, 6);
    gtk_widget_show (vbox_category);
    gtk_box_pack_start (GTK_BOX (vbox), vbox_category, FALSE, FALSE, 0);

    label_title = gtk_label_new (INFO_COPYRIGHT_STR);
    gtk_widget_show (label_title);
    gtk_box_pack_start (GTK_BOX (vbox_category), label_title, FALSE, FALSE, 0);
    gtk_label_set_use_markup (GTK_LABEL (label_title), TRUE);
    gtk_misc_set_alignment (GTK_MISC (label_title), 0, 0.5);

    hbox1 = gtk_hbox_new (FALSE, 0);
    gtk_widget_show (hbox1);
    gtk_box_pack_start (GTK_BOX (vbox_category), hbox1, FALSE, FALSE, 0);

    label_space = gtk_label_new (INFO_INDENT_STR);
    gtk_widget_show (label_space);
    gtk_box_pack_start (GTK_BOX (hbox1), label_space, FALSE, FALSE, 0);

    vbox_info = gtk_vbox_new (FALSE, 6);
    gtk_widget_show (vbox_info);
    gtk_box_pack_start (GTK_BOX (hbox1), vbox_info, FALSE, FALSE, 0);

    label_info = gtk_label_new (INFO_LANGUAGE_ENGINE_STR);
    gtk_widget_show (label_info);
    gtk_box_pack_start (GTK_BOX (vbox_info), label_info, FALSE, FALSE, 0);
    gtk_label_set_use_markup (GTK_LABEL (label_info), TRUE);
    gtk_misc_set_alignment (GTK_MISC (label_info), 0, 0.5);

    /* for Internet category */
    vbox_category = gtk_vbox_new (FALSE, 6);
    gtk_widget_show (vbox_category);
    gtk_box_pack_start (GTK_BOX (vbox), vbox_category, FALSE, FALSE, 0);

    label_title = gtk_label_new (INFO_INTERNET_STR);
    gtk_widget_show (label_title);
    gtk_box_pack_start (GTK_BOX (vbox_category), label_title, FALSE, FALSE, 0);
    gtk_label_set_use_markup (GTK_LABEL (label_title), TRUE);
    gtk_misc_set_alignment (GTK_MISC (label_title), 0, 0.5);

    hbox1 = gtk_hbox_new (FALSE, 0);
    gtk_widget_show (hbox1);
    gtk_box_pack_start (GTK_BOX (vbox_category), hbox1, FALSE, FALSE, 0);

    label_space = gtk_label_new (INFO_INDENT_STR);
    gtk_widget_show (label_space);
    gtk_box_pack_start (GTK_BOX (hbox1), label_space, FALSE, FALSE, 0);
  
    label_info = gtk_label_new (_("http://www.openi18n.org"));
    gtk_widget_show (label_info);
    gtk_box_pack_start (GTK_BOX (hbox1), label_info, FALSE, FALSE, 0);
    gtk_label_set_use_markup (GTK_LABEL (label_info), TRUE);
    gtk_misc_set_alignment (GTK_MISC (label_info), 0, 0.5);

    /* for Developers category */
    vbox_category = gtk_vbox_new (FALSE, 6);
    gtk_widget_show (vbox_category);
    gtk_box_pack_start (GTK_BOX (vbox), vbox_category, FALSE, FALSE, 0);

    label_title = gtk_label_new (INFO_DEVELOPERS_STR);
    gtk_widget_show (label_title);
    gtk_box_pack_start (GTK_BOX (vbox_category), label_title, FALSE, FALSE, 0);
    gtk_label_set_use_markup (GTK_LABEL (label_title), TRUE);
    gtk_misc_set_alignment (GTK_MISC (label_title), 0, 0.5);

    hbox1 = gtk_hbox_new (FALSE, 0);
    gtk_widget_show (hbox1);
    gtk_box_pack_start (GTK_BOX (vbox_category), hbox1, TRUE, TRUE, 0);

    label_space = gtk_label_new (INFO_INDENT_STR);
    gtk_widget_show (label_space);
    gtk_box_pack_start (GTK_BOX (hbox1), label_space, FALSE, FALSE, 0);

    vbox_info = gtk_vbox_new (FALSE, 6);
    gtk_widget_show (vbox_info);
    gtk_box_pack_start (GTK_BOX (hbox1), vbox_info, FALSE, FALSE, 0);

    label_info = gtk_label_new (INFO_DEVELOPER_NAMES_STR);
    gtk_widget_show (label_info);
    gtk_box_pack_start (GTK_BOX (vbox_info), label_info, FALSE, FALSE, 0);
    gtk_label_set_use_markup (GTK_LABEL (label_info), TRUE);
    gtk_misc_set_alignment (GTK_MISC (label_info), 0, 0.5);

    /* for Acknowledgement category */
    vbox_category = gtk_vbox_new (FALSE, 6);
    gtk_widget_show (vbox_category);
    gtk_box_pack_start (GTK_BOX (vbox), vbox_category, FALSE, FALSE, 0);

    label_title = gtk_label_new (INFO_THANKS_STR);
    gtk_widget_show (label_title);
    gtk_box_pack_start (GTK_BOX (vbox_category), label_title, FALSE, FALSE, 0);
    gtk_label_set_use_markup (GTK_LABEL (label_title), TRUE);
    gtk_misc_set_alignment (GTK_MISC (label_title), 0, 0.5);

    hbox1 = gtk_hbox_new (FALSE, 0);
    gtk_widget_show (hbox1);
    gtk_box_pack_start (GTK_BOX (vbox_category), hbox1, TRUE, TRUE, 0);

    label_space = gtk_label_new (INFO_INDENT_STR);
    gtk_widget_show (label_space);
    gtk_box_pack_start (GTK_BOX (hbox1), label_space, FALSE, FALSE, 0);

    vbox_info = gtk_vbox_new (FALSE, 6);
    gtk_widget_show (vbox_info);
    gtk_box_pack_start (GTK_BOX (hbox1), vbox_info, FALSE, FALSE, 0);

    label_info = gtk_label_new (INFO_THANK_NAMES_STR);
    gtk_widget_show (label_info);
    gtk_box_pack_start (GTK_BOX (vbox_info), label_info, FALSE, FALSE, 0);
    gtk_label_set_use_markup (GTK_LABEL (label_info), TRUE);
    gtk_misc_set_alignment (GTK_MISC (label_info), 0, 0.5);

    gtk_widget_hide(vbox);

    return vbox;
}

/*************************************************************/
/*           Categories List Treeview                        */
/*************************************************************/
GtkTreeModel *
property_window_create_category_list_model(property_window_t *property_window,
					   property_data_t *property_data)
{
    GtkTreeStore *category_list_model;
    GtkTreeIter iter, parent;
    GtkWidget *widget;

    int i, num_ime_modules;

    category_list_model = gtk_tree_store_new(CATEGORY_LIST_NUM_COLUMNS,
					     G_TYPE_STRING,
					     GTK_TYPE_WIDGET);

    /* Add system_setting catogory */
    widget = property_window_create_setting_cover(CATEGORY_SYSTEM_SETTING_STR);
    gtk_box_pack_start(GTK_BOX(property_window->work_area), widget, TRUE,
		       TRUE, 0);

    gtk_tree_store_append(category_list_model, &parent, NULL);
    gtk_tree_store_set(category_list_model, &parent,
		       CATEGORY_LIST_LABEL, CATEGORY_SYSTEM_SETTING_STR,
		       CATEGORY_LIST_WIDGET, widget,
		       -1);
               
    /* Add system_setting/imestatus_setting */
    widget = property_window_create_ime_list_view(property_window);
    gtk_box_pack_start(GTK_BOX(property_window->work_area), widget, TRUE,
		       TRUE, 0);

    gtk_tree_store_append(category_list_model, &iter, &parent);
    gtk_tree_store_set(category_list_model, &iter,
		       CATEGORY_LIST_LABEL, CATEGORY_IMESTATUS_SETTING_STR,
		       CATEGORY_LIST_WIDGET, widget,
		       -1);

    /* Add system_setting/fkey_setting */
    widget = property_window_create_fkey_setting_view(property_window, property_data);
    gtk_box_pack_start(GTK_BOX(property_window->work_area), widget, TRUE,
		       TRUE, 0);

    gtk_tree_store_append(category_list_model, &iter, &parent);
    gtk_tree_store_set(category_list_model, &iter,
		       CATEGORY_LIST_LABEL, CATEGORY_FKEY_SETTING_STR,
		       CATEGORY_LIST_WIDGET, widget,
		       -1);

#if 0
    /* Add system_setting/candidate_setting */
    widget = property_window_create_candidate_style_view(property_window, property_data);
    gtk_box_pack_start(GTK_BOX(property_window->work_area), widget, TRUE,
		       TRUE, 0);

    gtk_tree_store_append(category_list_model, &iter, &parent);
    gtk_tree_store_set(category_list_model, &iter,
		       CATEGORY_LIST_LABEL, CATEGORY_CANDIDATE_SETTING_STR,
		       CATEGORY_LIST_WIDGET, widget,
		       -1);
#endif

    /* Add system_setting/statusbar_setting */
    widget = property_window_create_statusbar_setting_view(property_window, property_data);
    gtk_box_pack_start(GTK_BOX(property_window->work_area), widget, TRUE,
		       TRUE, 0);

    gtk_tree_store_append(category_list_model, &iter, &parent);
    gtk_tree_store_set(category_list_model, &iter,
		       CATEGORY_LIST_LABEL, CATEGORY_STATUSBAR_SETTING_STR,
		       CATEGORY_LIST_WIDGET, widget,
		       -1);

    /* Add system_setting/beep_setting */
    widget = property_window_create_beep_setting_view(property_window, property_data);
    gtk_box_pack_start(GTK_BOX(property_window->work_area), widget, TRUE,
		       TRUE, 0);

    gtk_tree_store_append(category_list_model, &iter, &parent);
    gtk_tree_store_set(category_list_model, &iter,
		       CATEGORY_LIST_LABEL, CATEGORY_BEEP_SETTING_STR,
		       CATEGORY_LIST_WIDGET, widget,
		       -1);

    /* Add IME properties setting catogory */
    widget = property_window_create_setting_cover(CATEGORY_IME_SETTING_STR);
    gtk_box_pack_start(GTK_BOX(property_window->work_area), widget, TRUE,
		       TRUE, 0);

    gtk_tree_store_append(category_list_model, &parent, NULL);
    gtk_tree_store_set(category_list_model, &parent,
		       CATEGORY_LIST_LABEL, CATEGORY_IME_SETTING_STR,
		       CATEGORY_LIST_WIDGET, widget,
		       -1);

    /* Add IME_Setting/property_setting */
    num_ime_modules = property_data->num_ime_modules;
    property_window->num_ime_modules = num_ime_modules;
    property_window->ime_module_widgets = (ime_module_widget_t **) calloc (num_ime_modules,
									   sizeof (ime_module_widget_t *));
    if (property_window->ime_module_widgets == NULL)
    	return GTK_TREE_MODEL(category_list_model);

    for (i = 0; i < num_ime_modules; i++) {
	ime_module_t *ime_module = property_data->ime_modules[i];
	ime_module_widget_t *ime_module_widget;

        if (ime_module == NULL || 
	    ime_module->property_list == NULL)
            continue;

	ime_module_widget = (ime_module_widget_t *) calloc(1, sizeof (ime_module_widget_t));
	if (ime_module_widget == NULL)
	    continue;

	ime_module_widget->num_ime_properties = 0;
	ime_module_widget->ime_property_widgets = NULL;

	property_window->ime_module_widgets[i] = ime_module_widget;

	widget = property_window_create_ime_property_view(property_window, ime_module, ime_module_widget);
	gtk_box_pack_start(GTK_BOX(property_window->work_area), widget, TRUE,
		           TRUE, 0);

	gtk_tree_store_append(category_list_model, &iter, &parent);
	gtk_tree_store_set(category_list_model, &iter,
		           CATEGORY_LIST_LABEL, ime_module->name,
		           CATEGORY_LIST_WIDGET, widget,
		           -1);
    }

    /* Add Copyright catogory */
    widget = property_window_create_copyright_view();
    gtk_box_pack_start(GTK_BOX(property_window->work_area), widget, TRUE,
		       TRUE, 0);

    gtk_tree_store_append(category_list_model, &parent, NULL);
    gtk_tree_store_set(category_list_model, &parent,
		       CATEGORY_LIST_LABEL, CATEGORY_COPYRIGHT_STR,
		       CATEGORY_LIST_WIDGET, widget,
		       -1);

    return GTK_TREE_MODEL(category_list_model);
}

void property_window_realize_tree(GtkWidget * widget, gpointer * data)
{
    gtk_tree_view_expand_all(GTK_TREE_VIEW(widget));
}

gboolean
property_window_hide_widget_iter_func(GtkTreeModel * model,
					GtkTreePath * path,
					GtkTreeIter * iter, gpointer data)
{
    GtkWidget *widget;
    gtk_tree_model_get(model, iter, CATEGORY_LIST_WIDGET, &widget, -1);

    if (widget) {
	gtk_widget_hide(widget);
	g_object_unref(widget);
    }

    return FALSE;
}

void
property_window_selection_changed_cb(GtkTreeSelection * selection,
				       gpointer user_data)
{
    GtkTreeModel *model;
    GtkTreeIter iter;
    GtkWidget *widget;
    gchar *label;

    DEBUG_printf("property_window_selection_changed_cb \n");
    if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
	gtk_tree_model_get(model, &iter,
			   CATEGORY_LIST_LABEL, &label,
			   CATEGORY_LIST_WIDGET, &widget, -1);

	if (widget != NULL) {
	    gtk_tree_model_foreach(model,
				   property_window_hide_widget_iter_func,
				   NULL);
	    gtk_widget_show(widget);
	    g_object_unref(widget);
	}

	if (label) {
	    DEBUG_printf("label: %s\n", label);
	    g_free(label);
	}
    }
}

GtkWidget *property_window_create_category_list_view()
{
    GtkWidget *treeview;
    GtkCellRenderer *renderer;
    GtkTreeSelection *selection;
    GtkTreeViewColumn *column;
    gint col_offset;

    treeview = gtk_tree_view_new();
    gtk_widget_show(treeview);
    gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
    gtk_tree_view_set_enable_search(GTK_TREE_VIEW(treeview), FALSE);

    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
    gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);

    /* add column for category */
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes (NULL, renderer,
						       "text", CATEGORY_LIST_LABEL, NULL);

    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
    gtk_tree_view_column_set_clickable(GTK_TREE_VIEW_COLUMN(column), FALSE);

    g_signal_connect(selection, "changed",
		     G_CALLBACK(property_window_selection_changed_cb),
		     selection);

    g_signal_connect(G_OBJECT(treeview), "realize",
		     G_CALLBACK(property_window_realize_tree), treeview);

    return treeview;
}
