/* Katoob * Copyright (c) 2002,2003 Arabeyes, Mohammed Sameer. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "katoob.h" #include #include /* for GDK_DISPLAY() */ #include #include #include /* strlen() */ #include "emulator.h" #include "search.h" /* filter_text() */ #include "katoobdocument.h" #include "mdi.h" #include "misc.h" GSList *emus = NULL; GHashTable *active = NULL; /* Always point to the active emulator hash table */ typedef struct _EMU { gchar *name; GHashTable *syms; } EMU; static gunichar *katoob_emulator_get_pressed_key (gint keyval); void katoob_emulator_init () { extern UI *katoob; FILE *fp; GDir *dir; const gchar *file; GError *err = NULL; gchar *_tmp; gchar *buff = g_malloc (sizeof (gunichar) * 20); gchar *a = g_malloc (sizeof (gunichar) * 3); gchar *b = g_malloc (sizeof (gunichar) * 5); EMU *emu = NULL; katoob->emulatorno = 0; katoob_debug (__FUNCTION__); _tmp = g_strdup_printf ("%s/emulator", PACKAGE_DATA_DIR); dir = g_dir_open (_tmp, 0, &err); g_free (_tmp); if (!dir) { g_warning (err->message); g_error_free (err); g_free (buff); g_free (a); g_free (b); return; } /************************************************************************ * g_dir_read_name(): The return value is owned by GLib and must not be * * modified or freed. * ************************************************************************/ while ((file = g_dir_read_name (dir)) != NULL) { _tmp = g_strdup_printf ("%s/emulator/%s", PACKAGE_DATA_DIR, file); fp = fopen (_tmp, "r"); g_free (_tmp); if (!fp) { _tmp = g_strdup_printf ("Failed to open emulator file %s", file); g_warning (_tmp); g_free (_tmp); continue; } ++katoob->emulatorno; emu = g_new (EMU, 1); emu->syms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); while ((buff = fgets (buff, 19, fp)) != NULL) { sscanf (buff, "%s %s\n", a, b); g_hash_table_insert (emu->syms, g_strdup (a), g_strdup (b)); } emu->name = g_strdup (file); emus = g_slist_append (emus, emu); fclose (fp); } g_dir_close (dir); g_free (buff); g_free (a); g_free (b); return; } void katoob_emulator_switch_xkb (gint n) { extern UI *katoob; EMU *tmp; katoob_debug (__FUNCTION__); tmp = (EMU *) g_slist_nth_data (emus, n); active = tmp->syms; if (!active) { katoob_error (_ ("Couldn't find an emulator entry for the selected item")); return; } gtk_button_set_label (GTK_BUTTON (katoob->xkb), tmp->name); katoob->emulator = TRUE; } gboolean katoob_text_view_emulator_insert (GtkWidget * widget, GdkEventKey * event) { extern UI *katoob; GtkTextIter iter; gunichar *ch; KatoobDocument *doc = katoob_get_active_doc (); katoob_debug (__FUNCTION__); if (!doc) { return FALSE; } if (!katoob_document_has_focus (doc)) { katoob_debug ("No focused documents."); return FALSE; } if (!katoob->emulator) { katoob_debug ("Emulator is disabled."); return FALSE; } if (event->length != 1) { return FALSE; } ch = katoob_emulator_get_pressed_key (event->keyval); if (!ch) { katoob_debug ("Didn't find an equivalent word."); return FALSE; } iter = katoob_document_get_iter_at_insertion_mark (doc); katoob_document_insert_text (doc, iter, (gchar *) ch, -1); g_free (ch); return TRUE; } gboolean katoob_emulator_text_entry_insert (GtkEntry * entry, const gchar * text, gint length, gint * position, gpointer data) { extern UI *katoob; gint i; gunichar *ch; GtkEditable *editable = GTK_EDITABLE (entry); katoob_debug (__FUNCTION__); if (!katoob->emulator) { return FALSE; } i = strlen (text); if (i > 1) { return FALSE; } ch = katoob_emulator_get_pressed_key (*text); if (!ch) { return FALSE; } g_signal_handlers_disconnect_by_func (G_OBJECT (entry), G_CALLBACK (katoob_emulator_text_entry_insert), NULL); gtk_editable_insert_text (editable, (gchar *) ch, strlen ((gchar *) ch), position); g_signal_connect (G_OBJECT (entry), "insert_text", G_CALLBACK (katoob_emulator_text_entry_insert), NULL); g_signal_stop_emission_by_name (G_OBJECT (editable), "insert_text"); g_free (ch); return TRUE; } #if 0 gboolean katoob_emulator_entry_insert (GtkEntry * entry1, const gchar * text, gint length, gint * position, gpointer data) { extern UI *katoob; gint i; gunichar *ch; extern GtkWidget *findb; extern GtkWidget *entry; GtkEditable *editable = GTK_EDITABLE (entry1); katoob_debug (__FUNCTION__); if (katoob->xkb_grp == 0) { return FALSE; } i = strlen (text); if (i > 1) { return FALSE; } ch = katoob_emulator_get_pressed_key (*text); if (!ch) { return FALSE; } g_signal_handlers_disconnect_by_func (G_OBJECT (entry), G_CALLBACK (filter_text), NULL); g_signal_handlers_disconnect_by_func (G_OBJECT (entry), G_CALLBACK (katoob_emulator_entry_insert), NULL); gtk_editable_insert_text (editable, (gchar *) ch, strlen ((gchar *) ch), position); g_signal_connect (G_OBJECT (entry), "insert_text", G_CALLBACK (filter_text), NULL); g_signal_connect (G_OBJECT (entry), "delete_text", G_CALLBACK (filter_text), NULL); g_signal_connect (G_OBJECT (entry), "insert_text", G_CALLBACK (katoob_emulator_entry_insert), NULL); g_signal_stop_emission_by_name (G_OBJECT (editable), "insert_text"); gtk_widget_set_sensitive (findb, TRUE); g_free (ch); return TRUE; } #endif /* 0 */ static gunichar * katoob_emulator_get_pressed_key (gint keyval) { gunichar *ch; gchar *keystroke = g_malloc (2 * sizeof (gchar)); keystroke[0] = keyval; keystroke[1] = '\0'; (gchar *) ch = g_strdup (g_hash_table_lookup (active, keystroke)); return ch; } GtkWidget * katoob_emulator_build_menu () { gint x; extern UI *katoob; extern conf *config; GtkWidget *menu, *_menu, *__menu, *item; katoob_debug (__FUNCTION__); if ((!emus) && (!katoob->xkb_grps)) { return NULL; } menu = gtk_menu_new (); _menu = gtk_menu_new (); __menu = gtk_menu_item_new_with_mnemonic (_("Keyboard Emulator")); gtk_menu_item_set_submenu (GTK_MENU_ITEM (__menu), _menu); if ((config->xkb) && (katoob->xkb_grps)) { x = 0; while (katoob->xkb_grps[x]) /* for (x = 0; x < XkbNumKbdGroups; x++) */ { item = gtk_menu_item_new_with_label (katoob->xkb_grps[x]); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (katoob_handle_xkb_menu), (gpointer) FALSE); ++x; } } if (emus) { for (x = 0; x < katoob->emulatorno; x++) { EMU *emu = (EMU *) g_slist_nth_data (emus, x); item = gtk_menu_item_new_with_label (emu->name); gtk_menu_shell_append (GTK_MENU_SHELL (_menu), item); g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (katoob_handle_xkb_menu), (gpointer) TRUE); } } /* This is added at the end so the emulator submenu'll be the last entry. */ gtk_container_add (GTK_CONTAINER (menu), __menu); gtk_widget_show_all (menu); return menu; } void katoob_handle_xkb_button (GtkButton * button, GtkMenu * menu) { gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, 0); } void katoob_handle_xkb_menu (GtkMenuItem * menuitem, gpointer emu) { extern UI *katoob; gint x; gboolean emulator = (gboolean) emu; EMU *tmp; katoob_debug (__FUNCTION__); if (emulator) { for (x = 0; x < katoob->emulatorno; x++) { tmp = g_slist_nth_data (emus, x); if (!strcmp (tmp->name, gtk_label_get_text (GTK_LABEL (GTK_BIN (menuitem)->child)))) { katoob_emulator_switch_xkb (x); } } } else { x = 0; while (katoob->xkb_grps[x]) /* for (x = 0; x < XkbNumKbdGroups; x++) */ { if (!strcmp (katoob->xkb_grps[x], gtk_label_get_text (GTK_LABEL (GTK_BIN (menuitem)->child)))) { katoob_switch_xkb (x); } ++x; } } katoob_document_grab_focus (katoob_get_active_doc ()); } void katoob_emulator_free () { EMU *tmp; gint x, i = 0; katoob_debug (__FUNCTION__); if (!emus) { return; } x = g_slist_length (emus); for (i = 0; i < x; i++) { tmp = (EMU *) g_slist_nth_data (emus, i); g_free (tmp->name); g_hash_table_destroy (tmp->syms); } g_slist_free (emus); }