Logo Search packages:      
Sourcecode: katoob version File versions  Download package

emulator.c

/* 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 <config.h>
#endif

#include "katoob.h"
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>           /* strlen() */
#include <assert.h>
#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 gchar *katoob_emulator_get_pressed_key (gint keyval);

void
katoob_emulator_init ()
{
  FILE *fp;
  GDir *dir;
  const gchar *file;
  GError *err = NULL;
  gchar *_tmp;
/* FIXME: This may lead to a buffer overflow :-( */
  gchar *buff = (gchar *) g_malloc (sizeof (gunichar) * 20);
  gchar *a = (gchar *) g_malloc (sizeof (gunichar) * 3);
  gchar *b = (gchar *) g_malloc (sizeof (gunichar) * 5);
  EMU *emu = NULL;

#warning FIXME ABOVE!

  KATOOB_DEBUG_FUNCTION;
  _tmp =
    g_strdup_printf ("%s%semulator", PACKAGE_DATA_DIR, G_DIR_SEPARATOR_S);
  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%semulator%s%s", PACKAGE_DATA_DIR,
                   G_DIR_SEPARATOR_S, G_DIR_SEPARATOR_S, file);
      katoob_debug ("Attempting to open the following file:");
      katoob_debug (_tmp);
      fp = fopen (_tmp, "r");
      g_free (_tmp);
      _tmp = NULL;
      if (!fp)
      {
        g_warning ("Failed to open emulator file %s", file);
        continue;
      }
      else
      {
        emu = g_new (EMU, 1);
        emu->syms =
          g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
        while ((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;

  katoob_debug("switched to the following emulator file:");
  katoob_debug(tmp->name);
  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;
  gchar *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, 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;
  gchar *ch;
  GtkEditable *editable = GTK_EDITABLE (entry);
  static gboolean immediate_return;

  KATOOB_DEBUG_FUNCTION;

  if (!katoob->emulator)
    {
      return FALSE;
    }

  if (immediate_return)
    {
      katoob_debug ("Immediate return!");
      immediate_return = FALSE;
      return FALSE;
    }

  i = strlen (text);

  if (i > 1)
    {
      katoob_debug ("strlen > 1");
      return FALSE;
    }

  ch = katoob_emulator_get_pressed_key (*text);

  if (!ch)
    {
      katoob_debug ("Couldn't find a corresponding emulator entry!");
      return FALSE;
    }

  immediate_return = TRUE;
  g_signal_stop_emission_by_name (G_OBJECT (editable), "insert_text");
  gtk_editable_insert_text (GTK_EDITABLE (entry), ch, strlen ((gchar *) ch),
                      position);
  immediate_return = FALSE;
  g_free (ch);
  return TRUE;
}

static gchar *
katoob_emulator_get_pressed_key (gint keyval)
{
/* FIXME: Security */
/* We are passed a gint, but we are assigning it to a char, if the int is > 256, then we are exceeding the storage limit of the char */
  gchar keystroke[2];
  gchar *tmp;
#if 0
  assert (keyval >= 0 && keyval < 256);
#endif
  keystroke[0] = (gchar) keyval;
  keystroke[1] = '\0';
#warning assertion
  tmp = (gchar *) g_hash_table_lookup (active, keystroke);
  return g_strdup (tmp);
}

GtkWidget *
katoob_emulator_build_menu ()
{
  gint x;
  extern UI *katoob;
#ifndef _WIN32
  extern conf *config;
#endif /* _WIN32 */
  GtkWidget *menu, *_menu, *__menu, *item;
  GSList *tmp = NULL;

  KATOOB_DEBUG_FUNCTION;

  if ((!emus)
#ifndef _WIN32
      && (!katoob->xkb_grps)
#endif /* _WIN32 */
    )
    {
      katoob_debug("Returning!");
      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);

#ifndef _WIN32
  if ((config->xkb) && (katoob->xkb_grps))
    {
      katoob_debug("Keyboard layouts found, Adding them...");
      x = 0;
      while (katoob->xkb_grps[x])
      {
        katoob_debug(katoob->xkb_grps[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;
      }
    }
#endif /* _WIN32 */

  if (emus)
    {
      katoob_debug("Emulator layouts found, Adding them...");
      tmp = emus;
      while (tmp)
      {
        EMU *emu = (EMU *) tmp->data;
        katoob_debug(emu->name);
        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);
        tmp = g_slist_next (tmp);
      }
    }

/* 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 = 0;
  gboolean emulator = (gboolean) emu;
  EMU *tmp;
  GSList *list = NULL;

  KATOOB_DEBUG_FUNCTION;

  if (emulator)
    {
      list = emus;
      while (list)
      {
        tmp = (EMU *) list->data;
        if (!strcmp
            (tmp->name,
             gtk_label_get_text (GTK_LABEL (GTK_BIN (menuitem)->child))))
          {
            katoob_emulator_switch_xkb (x);
            return;
          }
        ++x;
        list = g_slist_next (list);
      }
    }
#ifndef _WIN32
  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);
            return;
          }
        ++x;
      }
    }
#endif /* _WIN32 */
  katoob_document_grab_focus (katoob_get_active_doc ());
}

void
katoob_emulator_free ()
{
  EMU *tmp;
  GSList *list = NULL;

  KATOOB_DEBUG_FUNCTION;

  if (!emus)
    {
      return;
    }

  list = emus;
  while (list)
    {
      tmp = (EMU *) list->data;
      g_free (tmp->name);
      g_hash_table_destroy (tmp->syms);
      list = g_slist_next (list);
    }
  g_slist_free (emus);
}

Generated by  Doxygen 1.6.0   Back to index