#include <m17n.h>
#include <m17n-misc.h>
#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
#include <config.h>
#include "m17n-im-config.h"
#define CONFIG_CALLBACK_DATA " config-callback-data"
#define CONFIG_STATUS_DATA " config-status-data"
-#define CONFIG_TREE_VIEW " config-tree-view"
+#define CONFIG_TREE_VIEW " config-tree-view"
typedef void (*MimConfigCallbackFunc) (GtkWidget *widget, gpointer data);
}
}
-extern GtkWidget *create_variable_list (MSymbol lang, MSymbol name);
-extern GtkWidget *create_command_list (MSymbol lang, MSymbol name);
-
-static void
-edit_im (GtkTreeView *tree, MSymbol lang, MSymbol name)
-{
- GtkWidget *dialog, *notebook, *scrolled, *vbox, *label;
- gint response;
- MPlist *plist;
-
- dialog = (gtk_dialog_new_with_buttons
- (name == Mnil ? "global" : msymbol_name (name),
- GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tree))),
- GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
- GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
- NULL));
- gtk_widget_set_size_request (dialog, 500, 300);
-
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_container_set_border_width (GTK_CONTAINER(vbox), 10);
- gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
-
- notebook = gtk_notebook_new ();
- gtk_container_add (GTK_CONTAINER (vbox), notebook);
-
- /* Variables' page */
- scrolled = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- label = gtk_label_new_with_mnemonic (_("_Variables"));
- gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled, label);
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
- vbox);
- gtk_box_pack_start (GTK_BOX (vbox),
- create_variable_list (lang, name),
- FALSE, FALSE, 0);
-
- /* Commands' pages */
- scrolled = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- label = gtk_label_new_with_mnemonic (_("Co_mmands"));
- gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled, label);
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
- vbox);
- gtk_box_pack_start (GTK_BOX (vbox),
- create_command_list (lang, name),
- FALSE, FALSE, 0);
-
- gtk_widget_show_all (dialog);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-}
+static void config_im (GtkTreeView *tree, MSymbol lang, MSymbol name);
static void
update_child_row (GtkTreeModel *model, GtkTreeIter *iter,
enum MimStatus old, new;
old = get_mim_status (lang, name);
- edit_im (tree, lang, name);
+ config_im (tree, lang, name);
new = get_mim_status (lang, name);
if (old != new)
update_child_row (model, &iter, new, NULL, tree);
imtable[i].lang = msymbol_name (language);
else
/* `~' is for putting this element at the tail by sort. */
- imtable[i].lang = "~other";
+ imtable[i].lang = _("~other");
imtable[i].name = msymbol_name (tag[2]);
imtable[i].symlang = tag[1];
imtable[i].symname = tag[2];
&& fmt != MTEXT_FORMAT_UTF_8)
native = 0;
}
- if (native)
+ if (0 && native)
{
name = alloca (strlen (lang) + nbytes + 4);
sprintf (name, "%s (%s)", lang, native);
destroy_cb (GtkWidget *widget, gpointer data)
{
M17N_FINI ();
+ initialized = 0;
+}
+
+\f
+/****************************************************/
+/* Configuration of a specific variable or command. */
+/****************************************************/
+
+/* Common staffs to variable and command */
+
+struct ConfigControl
+{
+ /* Data type name ("Value" or "Key bindings"). */
+ gchar *data_type_name;
+ MSymbol lang, name, item;
+ /* Fill in widgets in DIALOG for configuring a specific variable or
+ command. */
+ void (*setup_dialog) (GtkWidget *dialog, struct ConfigControl *control);
+ /* Update the contents of DATA widget. */
+ void (*update_data) (struct ConfigControl *control);
+ /* Convert PLIST to string. PLIST is a variable value or command
+ key sequeneses. */
+ GString *(*data_string) (MPlist *plist);
+ /* minput_get_variable or minput_get_command. */
+ MPlist *(*get) (MSymbol, MSymbol, MSymbol);
+ /* minput_config_variable or minput_config_command. */
+ int (*config) (MSymbol, MSymbol, MSymbol, MPlist *);
+ /* If non-NULL, a function to call before finishing a dialog. */
+ int (*config_on_ok) (struct ConfigControl *control);
+
+ /* Widget showing the current data (value or key bindings) */
+ GtkWidget *data;
+
+ /* Button widget to configure the data to the default. */
+ GtkWidget *default_;
+
+ /* Button widget to cancel the configuration. */
+ GtkWidget *revert;
+
+ /* Label widget showing the current status. */
+ GtkWidget *status;
+};
+
+struct CommandControl
+{
+ struct ConfigControl control;
+ GtkWidget *entry;
+ GtkWidget *clear;
+ GtkWidget *add;
+ GtkWidget *delete;
+};
+
+enum WidgetType
+ {
+ ENTRY_WIDGET,
+ COMBO_BOX_WIDGET,
+ SPIN_BUTTON_WIDGET
+ };
+
+struct VariableControl
+{
+ struct ConfigControl control;
+
+ /* type of current variable: Minteger, Msymbol, or Mtext */
+ MSymbol vtype;
+
+ /* type of widget */
+ enum WidgetType wtype;
+};
+
+#define CONFIG_CONTROL(control) ((struct ConfigControl *) (control))
+#define COMMAND_CONTROL(control) ((struct CommandControl *) (control))
+#define VARIABLE_CONTROL(control) ((struct VariableControl *) (control))
+
+#define CURRENT_DATA \
+ (mplist_next \
+ (mplist_next \
+ (mplist_next \
+ (mplist_value \
+ (control->get (control->lang, control->name, control->item))))))
+
+#define CURRENT_STATUS \
+ (mplist_value \
+ (mplist_next \
+ (mplist_next \
+ (mplist_value \
+ (control->get (control->lang, control->name, control->item))))))
+
+#define CURRENT_DESCRIPTION \
+ (mtext_data \
+ (mplist_value \
+ (mplist_next \
+ (mplist_value \
+ (control->get (control->lang, control->name, control->item)))), \
+ NULL, NULL, NULL, NULL))
+
+#define CONFIG_DATA(plist) \
+ control->config (control->lang, control->name, control->item, \
+ (plist))
+
+static void
+update_widgets (struct ConfigControl *control)
+{
+ MSymbol status = CURRENT_STATUS;
+
+ if (status == Mconfigured)
+ {
+ gtk_widget_set_sensitive (control->default_, TRUE);
+ gtk_widget_set_sensitive (control->revert, TRUE);
+ gtk_label_set_text (GTK_LABEL (control->status),
+ mim_status_str[MIM_STATUS_MODIFIED]);
+ }
+ else if (status == Mcustomized)
+ {
+ gtk_widget_set_sensitive (control->default_, TRUE);
+ gtk_widget_set_sensitive (control->revert, FALSE);
+ gtk_label_set_text (GTK_LABEL (control->status),
+ mim_status_str[MIM_STATUS_CUSTOMIZED]);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (control->default_, FALSE);
+ gtk_widget_set_sensitive (control->revert, FALSE);
+ gtk_label_set_text (GTK_LABEL (control->status),
+ mim_status_str[MIM_STATUS_DEFAULT]);
+ }
+}
+
+static void
+help_cb (GtkButton *button, gpointer data)
+{
+ struct ConfigControl *control = data;
+ GtkWidget *msg;
+
+ msg = gtk_message_dialog_new (GTK_WINDOW
+ (gtk_widget_get_toplevel (GTK_WIDGET (button))),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE,
+ CURRENT_DESCRIPTION);
+ gtk_dialog_run (GTK_DIALOG (msg));
+ gtk_widget_destroy (msg);
+}
+
+static void
+default_cb (GtkButton *button, gpointer data)
+{
+ MPlist *empty = mplist ();
+ struct ConfigControl *control = data;
+
+ CONFIG_DATA (empty);
+ m17n_object_unref (empty);
+ control->update_data (control);
+ update_widgets (control);
+ control->config_on_ok = NULL;
+}
+
+static void
+revert_cb (GtkButton *button, gpointer data)
+{
+ struct ConfigControl *control = data;
+
+ CONFIG_DATA (NULL);
+ control->update_data (control);
+ update_widgets (control);
+ control->config_on_ok = NULL;
+}
+
+static void
+ok_cb (GtkButton *button, gpointer data)
+{
+ struct ConfigControl *control = data;
+
+ if (control->config_on_ok)
+ {
+ if (! control->config_on_ok (control))
+ {
+ revert_cb (NULL, control);
+ return;
+ }
+ control->config_on_ok = NULL;
+ }
+ gtk_dialog_response (GTK_DIALOG
+ (gtk_widget_get_toplevel (GTK_WIDGET (button))),
+ GTK_RESPONSE_OK);
+}
+
+enum
+ {
+ /* Variable or command name */
+ CONFIG_COL_ITEM,
+ /* Status (default, modified, or customized). */
+ CONFIG_COL_STATUS,
+ /* Variable value or command key bindings. */
+ CONFIG_COL_DATA,
+ /* Number of columns of list store. */
+ NUM_CONFIG_COLS
+ };
+
+
+static void
+set_list_element (GtkListStore *store, GtkTreeIter *iter,
+ struct ConfigControl *control, MPlist *plist)
+{
+ MSymbol status;
+ gchar *status_str;
+
+ if (! plist)
+ plist = mplist_value (control->get (control->lang, control->name,
+ control->item));
+ plist = mplist_next (mplist_next (plist));
+
+ status = mplist_value (plist);
+ if (status == Mconfigured)
+ status_str = mim_status_str[MIM_STATUS_MODIFIED];
+ else if (status == Mcustomized)
+ status_str = mim_status_str[MIM_STATUS_CUSTOMIZED];
+ else
+ status_str = mim_status_str[MIM_STATUS_DEFAULT];
+ plist = mplist_next (plist);
+ gtk_list_store_set (store, iter,
+ CONFIG_COL_ITEM, msymbol_name (control->item),
+ CONFIG_COL_STATUS, status_str,
+ CONFIG_COL_DATA, control->data_string (plist)->str,
+ -1);
+}
+
+/* Called when an item (command or variable) name is activated.
+ Create a dialog widget to config that itme. */
+
+static void
+item_activated_cb (GtkTreeView *parent, GtkTreePath *path,
+ GtkTreeViewColumn *col, gpointer data)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkWidget *dialog, *label, *help, *hbox, *ok;
+ gchar *item;
+ struct ConfigControl *control = CONFIG_CONTROL (data);
+
+ model = gtk_tree_view_get_model (parent);
+ if (! gtk_tree_model_get_iter (model, &iter, path))
+ return;
+ gtk_tree_model_get (model, &iter, CONFIG_COL_ITEM, &item, -1);
+ control->item = msymbol (item);
+
+ dialog = gtk_dialog_new ();
+ gtk_window_set_title (GTK_WINDOW (dialog), msymbol_name (control->item));
+ gtk_window_set_transient_for
+ (GTK_WINDOW (dialog),
+ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (parent))));
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area),
+ GTK_BUTTONBOX_EDGE);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 12);
+ label = gtk_label_new (_("Status"));
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ label = gtk_label_new (": ");
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ control->status = gtk_label_new (NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), control->status, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+ hbox, FALSE, FALSE, 0);
+
+ help = gtk_button_new_from_stock (GTK_STOCK_HELP);
+ g_signal_connect (G_OBJECT (help), "clicked",
+ G_CALLBACK (help_cb), control);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
+ help, FALSE, FALSE, 0);
+ ok = gtk_button_new_from_stock (GTK_STOCK_OK);
+ g_signal_connect (G_OBJECT (ok), "clicked",
+ G_CALLBACK (ok_cb), control);
+ gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area),
+ ok, FALSE, FALSE, 0);
+
+ control->setup_dialog (dialog, control);
+
+ update_widgets (control);
+ gtk_widget_show_all (dialog);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_tree_model_get_iter (model, &iter, path);
+ set_list_element (GTK_LIST_STORE (model), &iter, control, NULL);
+ gtk_widget_destroy (dialog);
+ /*m17n_object_unref (entry_keyseq);*/
+}
+
+
+/* Create a list view widget listing variable or command names with
+ their current status and data. */
+
+GtkWidget *
+create_item_list (MSymbol lang, MSymbol name, struct ConfigControl *control)
+{
+ GtkListStore *store;
+ GtkWidget *view;
+ MPlist *plist;
+
+ plist = control->get (lang, name, Mnil);
+ /* plist == ((command/variable description status data ...) ...) */
+ if (! plist)
+ return gtk_label_new (_("No customizable item."));
+ store = gtk_list_store_new (NUM_CONFIG_COLS,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+ for (; plist && mplist_key (plist) == Mplist; plist = mplist_next (plist))
+ {
+ GtkTreeIter iter;
+ MPlist *pl;
+
+ pl = mplist_value (plist);
+ /* pl == (command/variable description status data ...) */
+ control->item = mplist_value (pl);
+ gtk_list_store_append (store, &iter);
+ set_list_element (store, &iter, control, pl);
+ }
+
+ view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+ g_object_unref (G_OBJECT (store));
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW (view), -1, _("Name"), gtk_cell_renderer_text_new (),
+ "text", CONFIG_COL_ITEM, NULL);
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW (view), -1, _("Status"), gtk_cell_renderer_text_new (),
+ "text", CONFIG_COL_STATUS, NULL);
+ gtk_tree_view_insert_column_with_attributes
+ (GTK_TREE_VIEW (view), -1, control->data_type_name,
+ gtk_cell_renderer_text_new (),
+ "text", CONFIG_COL_DATA, NULL);
+ g_signal_connect (G_OBJECT (view), "row-activated",
+ G_CALLBACK (item_activated_cb), control);
+
+ return view;
+}
+
+static struct VariableControl var;
+static struct CommandControl cmd;
+
+static void
+config_im (GtkTreeView *tree, MSymbol lang, MSymbol name)
+{
+ GtkWidget *dialog, *notebook, *scrolled, *vbox, *label;
+
+ var.control.lang = cmd.control.lang = lang;
+ var.control.name = cmd.control.name = name;
+ var.control.config_on_ok = cmd.control.config_on_ok = NULL;
+
+ dialog = (gtk_dialog_new_with_buttons
+ (name == Mnil ? "global" : msymbol_name (name),
+ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tree))),
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+ NULL));
+ gtk_widget_set_size_request (dialog, 500, 300);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER(vbox), 10);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
+
+ notebook = gtk_notebook_new ();
+ gtk_container_add (GTK_CONTAINER (vbox), notebook);
+
+ /* Variables' page */
+ scrolled = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ label = gtk_label_new_with_mnemonic (_("_Variables"));
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled, label);
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
+ vbox);
+ gtk_box_pack_start (GTK_BOX (vbox),
+ create_item_list (lang, name, CONFIG_CONTROL (&var)),
+ FALSE, FALSE, 0);
+
+ /* Commands' pages */
+ scrolled = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ label = gtk_label_new_with_mnemonic (_("Co_mmands"));
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled, label);
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
+ vbox);
+ gtk_box_pack_start (GTK_BOX (vbox),
+ create_item_list (lang, name, CONFIG_CONTROL (&cmd)),
+ FALSE, FALSE, 0);
+
+ gtk_widget_show_all (dialog);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+\f
+/* Staffs for variable configuration. */
+
+void
+variable_update_data (struct ConfigControl *control)
+{
+ MPlist *plist;
+ MSymbol key;
+ void *value;
+
+ plist = CURRENT_DATA;
+ /* plist == (value [valid-value ...]) */
+ key = mplist_key (plist);
+ value = mplist_value (plist);
+
+ if (VARIABLE_CONTROL (control)->wtype == ENTRY_WIDGET)
+ {
+ if (key == Msymbol)
+ gtk_entry_set_text (GTK_ENTRY (control->data),
+ msymbol_name ((MSymbol) value));
+ else if (key == Mtext)
+ /* Fixme : Assuming the return value is in UTF-8 */
+ gtk_entry_set_text (GTK_ENTRY (control->data),
+ mtext_data ((MText *) value,
+ NULL, NULL, NULL, NULL));
+ else /* key == Minteger */
+ {
+ gchar buf[32];
+ g_snprintf (buf, sizeof (buf), "%d", (gint) value);
+ gtk_entry_set_text (GTK_ENTRY (control->data), buf);
+ }
+ }
+ else if (VARIABLE_CONTROL (control)->wtype == COMBO_BOX_WIDGET)
+ {
+ gint i;
+
+ for (i = 0, plist = mplist_next (plist);
+ plist && mplist_key (plist) == key;
+ i++, plist = mplist_next (plist))
+ if (mplist_value (plist) == value)
+ break;
+ gtk_combo_box_set_active (GTK_COMBO_BOX (control->data), i);
+ }
+ else /* ci->wtype == SPIN_BUTTON_WIDGET */
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (control->data),
+ (gdouble) (int) value);
+}
+
+static gboolean
+config_with_entry (struct ConfigControl *control)
+{
+ const gchar *text = gtk_entry_get_text (GTK_ENTRY (control->data));
+ MPlist *plist = mplist ();
+ gboolean ret = TRUE;
+
+ if (VARIABLE_CONTROL (control)->vtype == Msymbol)
+ {
+ mplist_add (plist, Msymbol, msymbol (text));
+ CONFIG_DATA (plist);
+ }
+ else if (VARIABLE_CONTROL (control)->vtype == Mtext)
+ {
+ MText *mt;
+
+ mt = mconv_decode_buffer (Mcoding_utf_8, (guchar *) text, strlen (text));
+ mplist_add (plist, Mtext, mt);
+ CONFIG_DATA (plist);
+ m17n_object_unref (mt);
+ }
+ else /* VARIABLE_CONTROL (control)->vtype == Minteger */
+ {
+ int i;
+
+ if (sscanf (text, "%d", &i) == 1)
+ {
+ mplist_add (plist, Minteger, (void *) i);
+ CONFIG_DATA (plist);
+ }
+ else
+ {
+ GtkWidget *msg;
+
+ msg = gtk_message_dialog_new (GTK_WINDOW
+ (gtk_widget_get_toplevel (control->data)),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("The value must be an integer."));
+ gtk_dialog_run (GTK_DIALOG (msg));
+ gtk_widget_destroy (msg);
+ ret = FALSE;
+ }
+ }
+
+ m17n_object_unref (plist);
+ return ret;
+}
+
+static gboolean
+config_with_combo (struct ConfigControl *control)
+{
+ gchar *text = gtk_combo_box_get_active_text (GTK_COMBO_BOX (control->data));
+ MPlist *plist = mplist ();
+
+ if (VARIABLE_CONTROL (control)->vtype == Msymbol)
+ {
+ mplist_add (plist, Msymbol, msymbol (text));
+ CONFIG_DATA (plist);
+ }
+ else if (VARIABLE_CONTROL (control)->vtype == Mtext)
+ {
+ MText *mt;
+
+ mt = mconv_decode_buffer (Mcoding_utf_8, (guchar *) text, strlen (text));
+ mplist_add (plist, Mtext, mt);
+ CONFIG_DATA (plist);
+ m17n_object_unref (mt);
+ }
+ else /* VARIABLE_CONTROL (control)->vtype == Minteger */
+ {
+ int i;
+
+ sscanf (text, "%d", &i);
+ mplist_add (plist, Minteger, (void *) i);
+ CONFIG_DATA (plist);
+ }
+ m17n_object_unref (plist);
+ return TRUE;
+}
+
+static gboolean
+config_with_spin (struct ConfigControl *control)
+{
+ gint i = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (control->data));
+ MPlist *plist = mplist ();
+
+ mplist_add (plist, Minteger, (void *) i);
+ CONFIG_DATA (plist);
+ m17n_object_unref (plist);
+ return TRUE;
+}
+
+static void
+changed_cb (GtkEntry *entry, gpointer data)
+{
+ struct ConfigControl *control = data;
+
+ gtk_widget_set_sensitive (control->default_, TRUE);
+ gtk_widget_set_sensitive (control->revert, TRUE);
+ gtk_label_set_text (GTK_LABEL (control->status), _("modified"));
+ if (VARIABLE_CONTROL (control)->wtype == ENTRY_WIDGET)
+ control->config_on_ok = config_with_entry;
+ else if (VARIABLE_CONTROL (control)->wtype == COMBO_BOX_WIDGET)
+ control->config_on_ok = config_with_combo;
+ else
+ control->config_on_ok = config_with_spin;
+}
+
+static GString *
+variable_data_string (MPlist *plist)
+{
+ static GString *str;
+
+ if (! str)
+ str = g_string_sized_new (80);
+ else
+ g_string_truncate (str, 0);
+
+ if (mplist_key (plist) == Msymbol)
+ g_string_append (str, msymbol_name ((MSymbol) mplist_value (plist)));
+ else if (mplist_key (plist) == Mtext)
+ /* Fixme : Assuming the return value is in UTF-8 */
+ g_string_append (str, mtext_data ((MText *) mplist_value (plist),
+ NULL, NULL, NULL, NULL));
+ else /* mplist_key (plist) == Minteger */
+ g_string_append_printf (str, "%d", (gint) mplist_value (plist));
+ return str;
+}
+
+static void
+variable_setup_dialog (GtkWidget *dialog, struct ConfigControl *control)
+{
+ MPlist *plist;
+ void *value;
+ GtkWidget *hbox;
+
+ plist = CURRENT_DATA;
+ VARIABLE_CONTROL (control)->vtype = mplist_key (plist);
+ value = mplist_value (plist);
+ plist = mplist_next (plist);
+
+ if (VARIABLE_CONTROL (control)->vtype == Msymbol)
+ {
+ if (mplist_key (plist) == Msymbol)
+ {
+ gint i, nth;
+
+ control->data = gtk_combo_box_new_text ();
+ g_signal_connect (GTK_OBJECT (control->data), "changed",
+ G_CALLBACK (changed_cb), control);
+ VARIABLE_CONTROL (control)->wtype = COMBO_BOX_WIDGET;
+ for (i = 0; mplist_key (plist) == Msymbol;
+ plist = mplist_next (plist), i++)
+ {
+ if (mplist_value (plist) == value)
+ nth = i;
+ gtk_combo_box_append_text
+ (GTK_COMBO_BOX (control->data),
+ msymbol_name ((MSymbol) mplist_value (plist)));
+ }
+ gtk_combo_box_set_active (GTK_COMBO_BOX (control->data), nth);
+ }
+ else
+ {
+ control->data = gtk_entry_new ();
+ g_signal_connect (GTK_OBJECT (control->data), "changed",
+ G_CALLBACK (changed_cb), control);
+ g_signal_connect (GTK_OBJECT (control->data), "activate",
+ G_CALLBACK (ok_cb), control);
+ VARIABLE_CONTROL (control)->wtype = ENTRY_WIDGET;
+ gtk_entry_set_text (GTK_ENTRY (control->data), msymbol_name (value));
+ gtk_editable_set_editable (GTK_EDITABLE (control->data), TRUE);
+ }
+ }
+ else if (VARIABLE_CONTROL (control)->vtype == Mtext)
+ {
+ if (plist && mplist_key (plist) == Mtext)
+ {
+ gint i, nth;
+
+ control->data = gtk_combo_box_new_text ();
+ VARIABLE_CONTROL (control)->wtype = COMBO_BOX_WIDGET;
+ for (i = 0; plist && mplist_key (plist) == Mtext;
+ plist = mplist_next (plist), i++)
+ {
+ if (! mtext_cmp ((MText *) mplist_value (plist),
+ (MText *) value))
+ nth = i;
+ /* Fixme : Assuming the return value is in UTF-8 */
+ gtk_combo_box_append_text
+ (GTK_COMBO_BOX (control->data),
+ mtext_data ((MText *) mplist_value (plist),
+ NULL, NULL, NULL, NULL));
+ }
+ gtk_combo_box_set_active (GTK_COMBO_BOX (control->data), nth);
+ g_signal_connect (GTK_OBJECT (control->data), "changed",
+ G_CALLBACK (changed_cb), control);
+ }
+ else
+ {
+ control->data = gtk_entry_new ();
+ VARIABLE_CONTROL (control)->wtype = ENTRY_WIDGET;
+ /* Fixme : Assuming the return value is in UTF-8 */
+ gtk_entry_set_text (GTK_ENTRY (control->data),
+ mtext_data (value, NULL, NULL, NULL, NULL));
+ gtk_editable_set_editable (GTK_EDITABLE (control->data), TRUE);
+ g_signal_connect (GTK_OBJECT (control->data), "changed",
+ G_CALLBACK (changed_cb), control);
+ g_signal_connect (GTK_OBJECT (control->data), "activate",
+ G_CALLBACK (ok_cb), control);
+ }
+ }
+ else /* control->vtype == Minteger */
+ {
+ if (plist && mplist_key (plist) == Minteger)
+ {
+ gint i, nth;
+
+ control->data = gtk_combo_box_new_text ();
+ VARIABLE_CONTROL (control)->wtype = COMBO_BOX_WIDGET;
+ for (i = 0; plist && mplist_key (plist) == Minteger;
+ plist = mplist_next (plist), i++)
+ {
+ gchar buf[32];
+
+ if (mplist_value (plist) == value)
+ nth = i;
+ g_snprintf (buf, sizeof (buf), "%d",
+ (gint) mplist_value (plist));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (control->data), buf);
+ }
+ gtk_combo_box_set_active (GTK_COMBO_BOX (control->data), nth);
+ g_signal_connect (GTK_OBJECT (control->data), "changed",
+ G_CALLBACK (changed_cb), control);
+ }
+ else if (plist && mplist_key (plist) == Mplist)
+ {
+ GtkObject *adj;
+ gdouble lower, upper;
+
+ plist = mplist_value (plist);
+ lower = (gdouble) (int) mplist_value (plist);
+ upper = (gdouble) (int) mplist_value (mplist_next (plist));
+ adj = gtk_adjustment_new ((gdouble) (int) value, lower, upper,
+ 1.0, 10.0, 0);
+ control->data = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 0, 0);
+ VARIABLE_CONTROL (control)->wtype = SPIN_BUTTON_WIDGET;
+ gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (control->data), TRUE);
+ gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (control->data),
+ GTK_UPDATE_ALWAYS);
+ g_signal_connect (GTK_OBJECT (control->data), "changed",
+ G_CALLBACK (changed_cb), control);
+ }
+ else
+ {
+ gchar buf[32];
+
+ control->data = gtk_entry_new ();
+ VARIABLE_CONTROL (control)->wtype = ENTRY_WIDGET;
+ g_snprintf (buf, sizeof (buf), "%d", (gint) value);
+ gtk_entry_set_text (GTK_ENTRY (control->data), buf);
+ gtk_editable_set_editable (GTK_EDITABLE (control->data), TRUE);
+ g_signal_connect (GTK_OBJECT (control->data), "changed",
+ G_CALLBACK (changed_cb), control);
+ g_signal_connect (GTK_OBJECT (control->data), "activate",
+ G_CALLBACK (ok_cb), control);
+ }
+ }
+
+ control->default_ = gtk_button_new_from_stock (_("_Default"));
+ g_signal_connect (G_OBJECT (control->default_), "clicked",
+ G_CALLBACK (default_cb), control);
+
+ control->revert = gtk_button_new_from_stock (GTK_STOCK_REVERT_TO_SAVED);
+ g_signal_connect (G_OBJECT (control->revert), "clicked",
+ G_CALLBACK (revert_cb), control);
+
+ hbox = gtk_hbutton_box_new ();
+ gtk_box_set_spacing (GTK_BOX (hbox), 6);
+ gtk_container_add (GTK_CONTAINER (hbox), control->default_);
+ gtk_container_add (GTK_CONTAINER (hbox), control->revert);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+ control->data, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+ hbox, FALSE, FALSE, 0);
+}
+
+\f
+/* Staffs for command configuration. */
+
+static void
+selection_cb (GtkTreeSelection *selection, gpointer data)
+{
+ gtk_widget_set_sensitive
+ (COMMAND_CONTROL (data)->delete,
+ gtk_tree_selection_count_selected_rows (selection) ? TRUE : FALSE);
+}
+
+static void
+delete_cb (GtkButton *button, gpointer data)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ MPlist *pl, *new;
+ struct ConfigControl *control = data;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (control->data));
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (control->data));
+
+ if (! gtk_tree_model_get_iter_first (model, &iter))
+ return;
+
+ new = mplist ();
+ for (pl = CURRENT_DATA; mplist_key (pl) != Mnil; pl = mplist_next (pl))
+ {
+ if (! gtk_tree_selection_iter_is_selected (selection, &iter))
+ mplist_add (new, Mplist, mplist_value (pl));
+ gtk_tree_model_iter_next (model, &iter);
+ }
+ CONFIG_DATA (new);
+ m17n_object_unref (new);
+ control->update_data (control);
+ update_widgets (control);
+}
+
+static GtkWidget *
+create_deleting_section (struct ConfigControl *control)
+{
+ struct CommandControl *cmd_control = COMMAND_CONTROL (control);
+ GtkListStore *store;
+ GtkWidget *label, *scrolled, *hbox, *vbox;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *selection;
+
+ label = gtk_label_new (_("Current key bindings:"));
+
+ store = gtk_list_store_new (1, G_TYPE_STRING);
+ control->data = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+ g_object_unref (G_OBJECT (store));
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (control->data), FALSE);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (control->data));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (selection_cb), control);
+
+ scrolled = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
+ control->data);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_append_column (GTK_TREE_VIEW (control->data), column);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer, "text", 0, NULL);
+
+ control->update_data (control);
+
+ control->default_ = gtk_button_new_from_stock (_("_Default"));
+ g_signal_connect (G_OBJECT (control->default_), "clicked",
+ G_CALLBACK (default_cb), control);
+
+ control->revert = gtk_button_new_from_stock (GTK_STOCK_REVERT_TO_SAVED);
+ g_signal_connect (G_OBJECT (control->revert), "clicked",
+ G_CALLBACK (revert_cb), control);
+
+ cmd_control->delete = gtk_button_new_from_stock (GTK_STOCK_DELETE);
+ gtk_widget_set_sensitive (cmd_control->delete, FALSE);
+ g_signal_connect (G_OBJECT (cmd_control->delete), "clicked",
+ G_CALLBACK (delete_cb), control);
+
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (vbox), hbox);
+
+ gtk_container_add (GTK_CONTAINER (vbox), scrolled);
+
+ hbox = gtk_hbutton_box_new ();
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing (GTK_BOX (hbox), 6);
+ gtk_container_add (GTK_CONTAINER (hbox), control->default_);
+ gtk_container_add (GTK_CONTAINER (hbox), control->revert);
+ gtk_container_add (GTK_CONTAINER (hbox), cmd_control->delete);
+ gtk_container_add (GTK_CONTAINER (vbox), hbox);
+
+ return vbox;
+}
+
+static unsigned modifier_state = 0;
+static MPlist *entry_keyseq;
+
+enum KeyMaskBit {
+ META_MASK_BIT = 1,
+ ALT_MASK_BIT = META_MASK_BIT << 1,
+ SUPER_MASK_BIT = ALT_MASK_BIT << 1,
+ HYPER_MASK_BIT = SUPER_MASK_BIT << 1
+};
+
+static void
+update_entry (GtkEntry *entry)
+{
+ if (mplist_key (entry_keyseq) == Mnil)
+ gtk_entry_set_text (entry, "");
+ else
+ {
+ MPlist *p;
+ gchar *name;
+
+ name = msymbol_name ((MSymbol) mplist_value (entry_keyseq));
+ gtk_entry_set_text (entry, name);
+ for (p = mplist_next (entry_keyseq); mplist_key (p) != Mnil;
+ p = mplist_next (p))
+ {
+ name = msymbol_name ((MSymbol) mplist_value (p));
+ gtk_entry_append_text (entry, " ");
+ gtk_entry_append_text (entry, name);
+ }
+ gtk_editable_set_position (GTK_EDITABLE (entry), -1);
+ }
+}
+
+static gboolean
+key_pressed_cb (GtkEntry *entry, GdkEventKey *event, gpointer data)
+{
+ guint c;
+ MText *mt;
+ char buf[32];
+ char *name;
+ int nbytes, i;
+ struct CommandControl *cmd_control = data;
+
+ c = gdk_keyval_to_unicode (event->keyval);
+ if (c == 0)
+ {
+ switch (event->keyval)
+ {
+ case GDK_Meta_L: case GDK_Meta_R:
+ modifier_state |= META_MASK_BIT; return TRUE;
+ case GDK_Alt_L: case GDK_Alt_R:
+ modifier_state |= ALT_MASK_BIT; return TRUE;
+ case GDK_Super_L: case GDK_Super_R:
+ modifier_state |= SUPER_MASK_BIT; return TRUE;
+ case GDK_Hyper_L: case GDK_Hyper_R:
+ modifier_state |= HYPER_MASK_BIT; return TRUE;
+ default:
+ if (event->keyval >= GDK_Shift_L && event->keyval <= GDK_Shift_Lock)
+ return TRUE;
+ }
+ name = gdk_keyval_name (event->keyval);
+ if (! name)
+ return TRUE;
+ nbytes = strlen (name);
+ }
+ else
+ {
+ name = alloca (8);
+ mt = mtext ();
+ mtext_cat_char (mt, c);
+ nbytes = mconv_encode_buffer (msymbol ("utf-8"), mt,
+ (unsigned char *) name, 32);
+ m17n_object_unref (mt);
+ }
+ i = 0;
+ if (c == 0 && event->state & GDK_SHIFT_MASK)
+ buf[i++] = 'S', buf[i++] = '-';
+ if (event->state & GDK_CONTROL_MASK)
+ buf[i++] = 'C', buf[i++] = '-';
+ if (modifier_state & META_MASK_BIT)
+ buf[i++] = 'M', buf[i++] = '-';
+ if (modifier_state & ALT_MASK_BIT)
+ buf[i++] = 'A', buf[i++] = '-';
+ if (modifier_state & SUPER_MASK_BIT)
+ buf[i++] = 's', buf[i++] = '-';
+ if (modifier_state & HYPER_MASK_BIT)
+ buf[i++] = 'H', buf[i++] = '-';
+ strncpy (buf + i, name, nbytes);
+ buf[i + nbytes] = 0;
+ mplist_add (entry_keyseq, Msymbol, msymbol (buf));
+ update_entry (entry);
+ gtk_widget_set_sensitive (cmd_control->clear, TRUE);
+ gtk_widget_set_sensitive (cmd_control->add, TRUE);
+ return TRUE;
+}
+
+static gboolean
+key_released_cb (GtkEntry *entry, GdkEventKey *event, gpointer data)
+{
+ guint c;
+
+ c = gdk_keyval_to_unicode (event->keyval);
+ if (c == 0)
+ {
+ switch (event->keyval)
+ {
+ case GDK_Meta_L: case GDK_Meta_R:
+ modifier_state &= ~META_MASK_BIT; break;
+ case GDK_Alt_L: case GDK_Alt_R:
+ modifier_state &= ~ALT_MASK_BIT; break;
+ case GDK_Super_L: case GDK_Super_R:
+ modifier_state &= ~SUPER_MASK_BIT; break;
+ case GDK_Hyper_L: case GDK_Hyper_R:
+ modifier_state &= ~HYPER_MASK_BIT; break;
+ }
+ }
+ return FALSE;
+}
+
+static void
+clear_cb (GtkButton *button, gpointer data)
+{
+ struct CommandControl *cmd_control = data;
+
+ mplist_set (entry_keyseq, Mnil, NULL);
+ gtk_widget_grab_focus (cmd_control->entry);
+ update_entry (GTK_ENTRY (cmd_control->entry));
+ gtk_widget_set_sensitive (cmd_control->clear, FALSE);
+ gtk_widget_set_sensitive (cmd_control->add, FALSE);
+}
+
+static void
+add_cb (GtkButton *button, gpointer data)
+{
+ MPlist *new;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ struct ConfigControl *control = data;
+
+ if (mplist_length (entry_keyseq) == 0)
+ return;
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (control->data));
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ {
+ gchar *keyseq = control->data_string (entry_keyseq)->str;
+ gchar *str;
+
+ do {
+ gtk_tree_model_get (model, &iter, 0, &str, -1);
+ if (strcmp (keyseq, str) == 0)
+ /* entry_keyseq is already registered. */
+ return;
+ } while (gtk_tree_model_iter_next (model, &iter));
+ }
+ new = mplist_copy (CURRENT_DATA);
+ mplist_add (new, Mplist, entry_keyseq);
+ CONFIG_DATA (new);
+ m17n_object_unref (new);
+ control->update_data (control);
+ update_widgets (control);
+}
+
+static GtkWidget *
+create_adding_section (struct ConfigControl *control)
+{
+ struct CommandControl *cmd_control = COMMAND_CONTROL (control);
+ GtkWidget *label, *hbox, *vbox;
+
+ label = gtk_label_new (_("New key binding:"));
+
+ entry_keyseq = mplist ();
+ cmd_control->entry = gtk_entry_new ();
+ g_signal_connect (G_OBJECT (cmd_control->entry), "key-press-event",
+ G_CALLBACK (key_pressed_cb), cmd_control);
+ g_signal_connect (G_OBJECT (cmd_control->entry), "key-release-event",
+ G_CALLBACK (key_released_cb), cmd_control);
+
+ cmd_control->clear = gtk_button_new_from_stock (GTK_STOCK_CLEAR);
+ gtk_widget_set_sensitive (cmd_control->clear, FALSE);
+ g_signal_connect (G_OBJECT (cmd_control->clear), "clicked",
+ G_CALLBACK (clear_cb), cmd_control);
+
+ cmd_control->add = gtk_button_new_from_stock (GTK_STOCK_ADD);
+ gtk_widget_set_sensitive (cmd_control->add, FALSE);
+ g_signal_connect (G_OBJECT (cmd_control->add), "clicked",
+ G_CALLBACK (add_cb), cmd_control);
+
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (vbox), hbox);
+
+ gtk_container_add (GTK_CONTAINER (vbox), cmd_control->entry);
+
+ hbox = gtk_hbutton_box_new ();
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing (GTK_BOX (hbox), 6);
+ gtk_container_add (GTK_CONTAINER (hbox), cmd_control->clear);
+ gtk_container_add (GTK_CONTAINER (hbox), cmd_control->add);
+ gtk_container_add (GTK_CONTAINER (vbox), hbox);
+
+ return vbox;
+}
+
+static void
+append_key_sequence (GString *str, MPlist *keyseq)
+{
+ static MSymbol space_symbol;
+ MPlist *p;
+
+ if (! space_symbol)
+ space_symbol = msymbol (" ");
+
+ for (p = keyseq ; mplist_key (p) != Mnil; p = mplist_next (p))
+ {
+ MSymbol key = (MSymbol) mplist_value (p);
+
+ if (p != keyseq)
+ g_string_append_c (str, ' ');
+ if (key == space_symbol)
+ g_string_append (str, "Space");
+ else
+ g_string_append (str, msymbol_name (key));
+ }
+}
+
+static GString *
+command_data_string (MPlist *plist)
+{
+ static GString *str;
+
+ if (! str)
+ str = g_string_sized_new (80);
+ else
+ g_string_truncate (str, 0);
+
+ if (mplist_key (plist) == Mplist)
+ {
+ MPlist *pl;
+
+ /* PLIST == ((KEY KEY ...) ...) */
+ for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
+ {
+ if (pl != plist)
+ g_string_append (str, ", ");
+ append_key_sequence (str, mplist_value (pl));
+ }
+ }
+ else
+ {
+ /* PLIST == (KEY KEY ...) */
+ append_key_sequence (str, plist);
+ }
+ return str;
+}
+
+static void
+command_update_data (struct ConfigControl *control)
+{
+ GtkTreeView *tree = GTK_TREE_VIEW (control->data);
+ GtkListStore *store = GTK_LIST_STORE (gtk_tree_view_get_model (tree));
+ GtkTreeIter iter;
+ MPlist *pl;
+
+ gtk_list_store_clear (store);
+ for (pl = CURRENT_DATA; mplist_key (pl) != Mnil; pl = mplist_next (pl))
+ {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ 0, control->data_string (mplist_value (pl))->str,
+ -1);
+ }
+}
+
+static void
+command_setup_dialog (GtkWidget *dialog, struct ConfigControl *control)
+{
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+ create_deleting_section (control), FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
+ create_adding_section (control), FALSE, FALSE, 0);
}
\f
if (merror_code < 0)
return NULL;
+ initialized = 1;
+
#if ENABLE_NLS
bindtextdomain ("m17n-im-config", GETTEXTDIR);
bind_textdomain_codeset ("m17n-im-config", "UTF-8");
mim_status_str[MIM_STATUS_MODIFIED] = _("modified");
mim_status_str[MIM_STATUS_NO] = _("uncustomizable");
+ var.control.data_type_name = _("Value");
+ var.control.setup_dialog = variable_setup_dialog;
+ var.control.update_data = variable_update_data;
+ var.control.data_string = variable_data_string;
+ var.control.get = minput_get_variable;
+ var.control.config = minput_config_variable;
+
+ cmd.control.data_type_name = _("Key Bindings");
+ cmd.control.setup_dialog = command_setup_dialog;
+ cmd.control.update_data = command_update_data;
+ cmd.control.data_string = command_data_string;
+ cmd.control.get = minput_get_command;
+ cmd.control.config = minput_config_command;
+
store = make_store_for_input_methods ();
tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
g_object_unref (G_OBJECT (store));