/* GIMLET: GNOME Input Method Language Enabing Tool
 *
 * Copyright (C) 2001, 2002 Havoc Pennington
 * Copyright (C) 2002 Red Hat, Inc.
 * Copyright (C) 2003 Sun Microsystems
 * Copyright (C) 2003 Mariano Suarez-Alvarez
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <config.h>

#include <gtk/gtkmain.h>
#include <gtk/gtkdrawingarea.h>
#include <gtk/gtkbutton.h>
#include <gtk/gtksignal.h>
#include <panel-applet.h>
#include <panel-applet-gconf.h>
#include <gnome.h>

#include "gnome-im-switcher.h"
#include "language.h"
#include "utils.h"

#include <gconf/gconf-client.h>
#include <gtk/gtktreeview.h>
#include <gtk/gtkmessagedialog.h>
#include <gtk/gtktreestore.h>

#include <string.h>

#include "gimlet-lang-data.h"

static GConfClient *default_client = NULL;

enum
{
  COLUMN_NAME,
  COLUMN_DESCRIPTION,
  N_COLUMNS
};

/*
 * Utility stuff
 */


static GSList *active_languages = NULL;

static void
update_single_tree_model (GtkListStore *store)
{
  GSList *tmp;
  GtkTreeIter parent_iter;

  gtk_list_store_clear (store);
  
  tmp = active_languages;
  while (tmp != NULL)
    {
      GimletLanguage *e = tmp->data;
      
      if (strcmp (e->iiim_lang_name, "ASCII") != 0)
	{
	  gtk_list_store_append (store, &parent_iter);
	  gtk_list_store_set (store, &parent_iter,
			      COLUMN_DESCRIPTION,
			      e->description,
			      COLUMN_NAME,
			      e->name,
			      -1);
	}
      tmp = tmp->next;
    }
}

static GSList *stores = NULL;

static void
unregister_store (void    *data,
                  GObject *where_object_was)
{
  stores = g_slist_remove (stores, where_object_was);
}

static void
update_active_language_tree_models (void)
{
  GSList *tmp;
  tmp = stores;
  while (tmp != NULL)
    {
      update_single_tree_model (tmp->data);
      tmp = tmp->next;
    }
}

static void
register_active_language_tree_model (GtkListStore *store)
{
  update_single_tree_model (store);
  stores = g_slist_prepend (stores, store);
  g_object_weak_ref (G_OBJECT (store), unregister_store, NULL);
}

static void update_active_languages_from_string_list (GSList *strings);

static void
languages_change_notify (GConfClient *client,
                         guint        cnxn_id,
                         GConfEntry  *entry,
                         gpointer     user_data)
{
  GConfValue *val;
  GSList *strings;
  
  /* FIXME handle whether the entry is writable
   */

  val = gconf_entry_get_value (entry);
  if (val == NULL || val->type != GCONF_VALUE_LIST ||
      gconf_value_get_list_type (val) != GCONF_VALUE_STRING)
    strings = NULL;
  else
    {
      GSList *tmp;

      strings = NULL;
      tmp = gconf_value_get_list (val);
      while (tmp != NULL)
        {
          GConfValue *v = tmp->data;
          g_assert (v->type == GCONF_VALUE_STRING);

          if (gconf_value_get_string (v))
            {
              strings = g_slist_prepend (strings,
					 (gchar*) gconf_value_get_string (v));
            }
          
          tmp = tmp->next;
        }
    }

  update_active_languages_from_string_list (strings);

  /* note we didn't copy the strings themselves, so don't free them */
  g_slist_free (strings);
}

static GimletLanguage*
find_language_by_description (const char *description)
{
  int i = 0;
  int n_elements = G_N_ELEMENTS (g_languages);

  while (i < n_elements)
    {
      if (strcmp (description, g_languages[i].description) == 0)
        return &g_languages[i];

      ++i;
    }

  return NULL;
}

static const GimletLanguage*
find_language_by_iiim_lang_name (const char *iiim_lang_name)
{
  int i = 0;
  int n_elements = G_N_ELEMENTS (g_languages);

  while (i < n_elements)
    {
      if (strcmp (iiim_lang_name, g_languages[i].iiim_lang_name) == 0)
        return &g_languages[i];

      ++i;
    }

  return NULL;
}

gchar *
gimlet_language_find_name (char *iiim_lang_name)
{
  const GimletLanguage *ilname = find_language_by_iiim_lang_name (iiim_lang_name);
  if (ilname)
    return ilname->name;
  else
    return NULL;
}

gchar *
gimlet_language_find_description (char *iiim_lang_name)
{
  const GimletLanguage *ilname = find_language_by_iiim_lang_name (iiim_lang_name);
  if (ilname)
    return ilname->description;
  else
    return NULL;
}

gchar *
gimlet_language_find_short (char *ilname)
{
  if (find_language_by_iiim_lang_name (ilname))
    {
      /* treat Chinese specially */
      if (strlen (ilname) == 5 &&
	  ilname[0] == 'z' &&
	  ilname[1] == 'h')
	{
	  if (strcmp (ilname, "zh_CN") == 0)
	    return (g_strdup ("SC"));
	  else
	    return (g_strdup ("TC"));
	}    
      else
	{
	  gchar *ll = g_strndup (ilname, 2);
	  ll[0] = g_ascii_toupper (ll[0]);
	  return ll;
	}
    }
  else
    return NULL;
}

static GimletLanguage*
gimlet_language_copy (const GimletLanguage *src)
{
  GimletLanguage *c;

  c = g_new (GimletLanguage, 1);
  c->idx = src->idx;
  c->valid = src->valid;
  c->conversion_on = src->conversion_on;
  c->name = g_strdup (src->name);
  c->description = g_strdup (src->description);
  c->iiim_lang_name = g_strdup (src->iiim_lang_name);
  
  return c;
}

static void
update_active_languages_from_string_list (GSList *strings)
{
  GSList *tmp;
  GHashTable *table;
  const char *description;

  table = g_hash_table_new (g_direct_hash, g_direct_equal);
  
  g_slist_foreach (active_languages, (GFunc) gimlet_language_free,
		   NULL);
  g_slist_free (active_languages);
  active_languages = NULL;

  /* First add the ASCII . */
  description = g_languages[ASCII].description;
  if (g_hash_table_lookup (table, GINT_TO_POINTER (g_quark_from_string (description))) == NULL)
    {
      active_languages = g_slist_prepend (active_languages,
					  gimlet_language_copy (&g_languages[ASCII]));
      g_hash_table_insert (table,
			   GINT_TO_POINTER (g_quark_from_string (description)),
			   GINT_TO_POINTER (g_quark_from_string (description)));
    }

  for (tmp = strings; tmp != NULL; tmp = tmp->next)
    {
      const GimletLanguage *l;
      GimletLanguage *language;
      const char *iiim_lang_name = tmp->data;
      
      l = find_language_by_iiim_lang_name (iiim_lang_name);
      if (l == NULL)
	continue;		/* this can happen e.g client locale is "C" */

      if (g_hash_table_lookup (table, GINT_TO_POINTER (g_quark_from_string (l->description))) != NULL)
	continue;
      g_hash_table_insert (table,
			   GINT_TO_POINTER (g_quark_from_string (l->description)),
			   GINT_TO_POINTER (g_quark_from_string (l->description)));
      language = l->valid ? gimlet_language_copy (l) : NULL;

      if (language != NULL)
	active_languages = g_slist_append (active_languages, language);
    }

  g_hash_table_destroy (table);
  
  update_active_language_tree_models ();
}

static void
response_callback (GtkWidget *window,
                   int        id,
                   void      *data)
{
  if (id == GTK_RESPONSE_HELP)
    gimlet_util_show_help ("imswitcher-usage-add", GTK_WINDOW (window));
  else
    gtk_widget_destroy (GTK_WIDGET (window));
}

static void
count_selected_items_func (GtkTreeModel      *model,
                           GtkTreePath       *path,
                           GtkTreeIter       *iter,
                           gpointer           data)
{
  int *count = data;

  *count += 1;
}

static void
available_selection_changed_callback (GtkTreeSelection *selection,
                                      void             *data)
{
  int count;
  GtkWidget *add_button;
  GtkWidget *dialog;

  dialog = data;
  
  count = 0;
  gtk_tree_selection_selected_foreach (selection,
                                       count_selected_items_func,
                                       &count);

  add_button = g_object_get_data (G_OBJECT (dialog), "language-dialog-add");
  
  gtk_widget_set_sensitive (add_button, count > 0);
}

static void
displayed_selection_changed_callback (GtkTreeSelection *selection,
                                      void             *data)
{
  int count;
  GtkWidget *remove_button;
  GtkWidget *dialog;

  dialog = data;
  
  count = 0;
  gtk_tree_selection_selected_foreach (selection,
                                       count_selected_items_func,
                                       &count);

  remove_button = g_object_get_data (G_OBJECT (dialog), "language-dialog-remove");
  
  gtk_widget_set_sensitive (remove_button, count > 0);
}

static void
get_selected_languages_func (GtkTreeModel      *model,
                             GtkTreePath       *path,
                             GtkTreeIter       *iter,
                             gpointer           data)
{
  GSList **list = data;
  char *description;

  description = NULL;
  gtk_tree_model_get (model,
                      iter,
                      COLUMN_DESCRIPTION,
                      &description,
                      -1);

  *list = g_slist_prepend (*list, description);
}

static gboolean
description_in_language_list (GSList     *list,
			      const char *str)
{
  GSList *tmp;

  tmp = list;
  while (tmp != NULL)
    {
      const GimletLanguage *lang = tmp->data;
      
      if (strcmp (lang->description, str) == 0)
        return TRUE;

      tmp = tmp->next;
    }

  return FALSE;
}

static GSList*
remove_iiim_lang_from_list (GSList     *list,
			    const char *str)
{
  GSList *tmp;

  tmp = list;
  while (tmp != NULL)
    {
      if (strcmp (tmp->data, str) == 0)
        break;

      tmp = tmp->next;
    }

  if (tmp != NULL)
    {
      list = g_slist_remove (list, tmp->data);
      g_free (tmp->data);
    }
  return list;
}

/* static GSList*
 * remove_string_from_list (GSList     *list,
 *                          const char *str)
 * {
 *   GSList *tmp;
 * 
 *   tmp = list;
 *   while (tmp != NULL)
 *     {
 *       if (strcmp (tmp->data, str) == 0)
 *         break;
 * 
 *       tmp = tmp->next;
 *     }
 * 
 *   if (tmp != NULL)
 *     {
 *       list = g_slist_remove (list, tmp->data);
 *       g_free (tmp->data);
 *     }
 *   return list;
 * }
 */

/* static GSList*
 * language_list_to_description_list (GSList *src)
 * {
 *   GSList *list;
 *   GSList *tmp;
 *   
 *   list = NULL;
 *   tmp = src;
 *   while (tmp != NULL)
 *     {
 *       const GimletLanguage *lang = tmp->data;
 *       
 *       list = g_slist_append (list, g_strdup (lang->description));
 *       tmp = tmp->next;
 *     }
 * 
 *   return list;
 * }
 */

static GSList*
language_list_to_iiim_lang_list (GSList *src)
{
  GSList *list;
  GSList *tmp;
  
  list = NULL;
  tmp = src;
  while (tmp != NULL)
    {
      const GimletLanguage *lang = tmp->data;
      
      list = g_slist_append (list, g_strdup (lang->iiim_lang_name));
      tmp = tmp->next;
    }

  return list;
}

static void
gconf_set_active_languages (GtkWidget *gimlet_applet, GSList *strings)
{
  gchar *key;

  key = panel_applet_gconf_get_full_key (PANEL_APPLET (gimlet_applet),
					 (const gchar*)"active_languages");
  gconf_client_set_list (default_client, key, 
                         GCONF_VALUE_STRING,
                         strings,
                         NULL);
  g_free (key);
}

static GSList *
gconf_get_active_languages (GimletWindow *gimlet)
{
  gchar *key;
  GSList *strings = NULL;

  key = panel_applet_gconf_get_full_key (PANEL_APPLET (gimlet->applet),
					 "active_languages");
  if (default_client == NULL)
    {
      GError *err;

      default_client = gconf_client_get_default ();
      g_object_ref (G_OBJECT (default_client));

      err = NULL;
      gconf_client_notify_add (default_client, key, 
			       languages_change_notify,
			       NULL, /* user_data */
			       NULL, &err);
    }
  strings = gconf_client_get_list (default_client,
				   key,
				   GCONF_VALUE_STRING, NULL);
  g_free (key);
  return strings;
}

static void
add_button_clicked_callback (GtkWidget *button,
                             void      *data)
{
  GtkWidget *dialog;
  GtkWidget *treeview;
  GtkWidget *gimlet_applet;
  GtkTreeSelection *selection;
  GSList *languages;
  GSList *tmp;
  GSList *active_iiim_lang_list;

  dialog = data;

  treeview = g_object_get_data (G_OBJECT (dialog),
                                "language-dialog-available-treeview");
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));

  languages = NULL;
  gtk_tree_selection_selected_foreach (selection,
                                       get_selected_languages_func,
                                       &languages);

  active_iiim_lang_list = language_list_to_iiim_lang_list (active_languages);

  tmp = languages;
  while (tmp != NULL)
    {
      /* appending is less efficient but produces user-expected
       * result
       */
      if (!description_in_language_list (active_languages, tmp->data))
	{
	  GimletLanguage *l;

	  l = find_language_by_description ((const char*)tmp->data);
#if 0
	  if (l == NULL)
	    continue;		/* this should not happen */
#endif
	  active_iiim_lang_list = g_slist_append (active_iiim_lang_list,
						  g_strdup (l->iiim_lang_name));
	}
      tmp = tmp->next;
    }

  /* this is reentrant, but only after it's done using the list
   * values, so should be safe
   */
  gimlet_applet = g_object_get_data (G_OBJECT (dialog),
				     "gimlet-applet");

  gconf_set_active_languages (gimlet_applet, active_iiim_lang_list);

  g_slist_foreach (active_iiim_lang_list, (GFunc) g_free, NULL);
  g_slist_free (active_iiim_lang_list);
  
  g_slist_foreach (languages, (GFunc) g_free, NULL);
  g_slist_free (languages);
}

static void
remove_button_clicked_callback (GtkWidget *button,
                                void      *data)
{
  GtkWidget *dialog;
  GtkWidget *treeview;
  GtkWidget *gimlet_applet;
  GtkTreeSelection *selection;
  GSList *languages;
  GSList *tmp;
  GSList *active_iiim_lang_list;

  dialog = data;

  treeview = g_object_get_data (G_OBJECT (dialog),
                                "language-dialog-displayed-treeview");
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));

  languages = NULL;
  gtk_tree_selection_selected_foreach (selection,
                                       get_selected_languages_func,
                                       &languages);

  active_iiim_lang_list = language_list_to_iiim_lang_list (active_languages);

  tmp = languages;
  while (tmp != NULL)
    {
      GimletLanguage *l;

      /* appending is less efficient but produces user-expected
       * result
       */
      l = find_language_by_description (tmp->data);
#if 0
      if (l == NULL)
	continue;		/* this should not happen */
#endif
      active_iiim_lang_list =
	remove_iiim_lang_from_list (active_iiim_lang_list, l->iiim_lang_name);

      tmp = tmp->next;
    }

  /* this is reentrant, but only after it's done using the list
   * values, so should be safe
   */
  gimlet_applet = g_object_get_data (G_OBJECT (dialog),
				     "gimlet-applet");

  gconf_set_active_languages (gimlet_applet, active_iiim_lang_list);

  g_slist_foreach (active_iiim_lang_list, (GFunc) g_free, NULL);
  g_slist_free (active_iiim_lang_list);

  g_slist_foreach (languages, (GFunc) g_free, NULL);
  g_slist_free (languages);
}

GtkWidget*
gimlet_langmenu_dialog_new (GtkWindow *transient_parent,
			    GimletWindow *gimlet)
{
  GladeXML *xml;
  GtkWidget *w;
  GtkCellRenderer *cell_renderer;
  int i;
  GtkTreeModel *sort_model;
  GtkListStore *tree;
  GtkTreeViewColumn *column;
  GtkTreeIter parent_iter;
  GtkTreeSelection *selection;
  GtkWidget *dialog;

  xml = gimlet_util_load_glade_file (GIMLET_GLADE_FILE,
				     "languages-dialog",
				     transient_parent);
  if (xml == NULL)
    return NULL;

  /* The dialog itself */
  dialog = glade_xml_get_widget (xml, "languages-dialog");

  gimlet_util_set_unique_role (GTK_WINDOW (dialog), "gimlet-languages");

  g_signal_connect (G_OBJECT (dialog), "response",
                    G_CALLBACK (response_callback),
                    NULL);

  /* buttons */
  w = glade_xml_get_widget (xml, "add-button");
  g_object_set_data (G_OBJECT (dialog),
                     "language-dialog-add",
                     w);

  g_object_set_data (G_OBJECT (dialog),
                     "gimlet-applet",
                     gimlet->applet);
  g_signal_connect (G_OBJECT (w), "clicked",
                    G_CALLBACK (add_button_clicked_callback),
                    dialog);

  w = glade_xml_get_widget (xml, "remove-button");
  g_object_set_data (G_OBJECT (dialog),
                     "language-dialog-remove",
                     w);

  g_signal_connect (G_OBJECT (w), "clicked",
                    G_CALLBACK (remove_button_clicked_callback),
                    dialog);
  
  /* Tree view of available languages */
  
  w = glade_xml_get_widget (xml, "available-treeview");
  g_object_set_data (G_OBJECT (dialog),
                     "language-dialog-available-treeview",
                     w);
  
  tree = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);

  /* Column 1 */
  cell_renderer = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes (_("_Language"),
						     cell_renderer,
						     "text", COLUMN_NAME,
						     NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW (w), column);
  gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
  
  /* Column 2 */
  cell_renderer = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes (_("_Description"),
						     cell_renderer,
						     "text", COLUMN_DESCRIPTION,
						     NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW (w), column);
  gtk_tree_view_column_set_sort_column_id (column, COLUMN_DESCRIPTION);  

  /* Add the data */

  i = 0;
  while (i < (int) G_N_ELEMENTS (g_languages))
    {
      if (g_languages[i].valid && (strcmp (g_languages[i].iiim_lang_name,
					   "ASCII") != 0))
        {
          gtk_list_store_append (tree, &parent_iter);
          gtk_list_store_set (tree, &parent_iter,
                              COLUMN_DESCRIPTION,
                              g_languages[i].description,
                              COLUMN_NAME,
                              g_languages[i].name,
                              -1);
        }
      ++i;
    }

  /* Sort model */
  sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
  
  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
                                        COLUMN_NAME,
                                        GTK_SORT_ASCENDING);
  
  gtk_tree_view_set_model (GTK_TREE_VIEW (w), sort_model);
  g_object_unref (G_OBJECT (tree));

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (w));    
  gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection),
			       GTK_SELECTION_MULTIPLE);

  available_selection_changed_callback (selection, dialog);
  g_signal_connect (G_OBJECT (selection), "changed",                    
                    G_CALLBACK (available_selection_changed_callback),
                    dialog);

  /* Tree view of selected languages */
  
  w = glade_xml_get_widget (xml, "displayed-treeview");
  g_object_set_data (G_OBJECT (dialog),
                     "language-dialog-displayed-treeview",
                     w);
  
  tree = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);

  /* Column 1 */
  cell_renderer = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes (_("_Language"),
						     cell_renderer,
						     "text", COLUMN_NAME,
						     NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW (w), column);
  gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
  
  /* Column 2 */
  cell_renderer = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes (_("_Description"),
						     cell_renderer,
						     "text", COLUMN_DESCRIPTION,
						     NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW (w), column);
  gtk_tree_view_column_set_sort_column_id (column, COLUMN_DESCRIPTION);  

  /* Add the data */
  register_active_language_tree_model (tree);

  /* Sort model */
  sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
  
  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
                                        COLUMN_NAME,
                                        GTK_SORT_ASCENDING);
  
  gtk_tree_view_set_model (GTK_TREE_VIEW (w), sort_model);
  g_object_unref (G_OBJECT (tree));  

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (w));    
  gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection),
			       GTK_SELECTION_MULTIPLE);

  displayed_selection_changed_callback (selection, dialog);
  g_signal_connect (G_OBJECT (selection), "changed",
                    G_CALLBACK (displayed_selection_changed_callback),
                    dialog);

  g_object_unref (G_OBJECT (xml));
  
  return dialog;
}

void
gimlet_language_init (GimletWindow *gimlet)
{
  int i;
  int n_elements;
  gchar **p;
  GSList *strings = NULL;

  n_elements = G_N_ELEMENTS (g_languages);

  if (gimlet->client_lang_list != NULL)
    {
      for (p = gimlet->client_lang_list; *p; p++)
	for (i = 0; i < n_elements; i++)
	  {
	    /* Translate the description */
	    g_languages[i].description = _(g_languages[i].description);

	    if (g_languages[i].iiim_lang_name != NULL)
	      {
		guint len = strlen (g_languages[i].iiim_lang_name);
		if (strncmp (g_languages[i].iiim_lang_name, *p, len) == 0)
		  g_languages[i].valid = TRUE;
	      }
	  }
    }

  strings = gconf_get_active_languages (gimlet);

  update_active_languages_from_string_list (strings);

  g_slist_foreach (strings, (GFunc) g_free, NULL);
  g_slist_free (strings);
}

char*
gimlet_language_get_name (GimletLanguage *data)
{
  return data->name;
}

char*
gimlet_language_get_iiim_lang_name (GimletLanguage *data)
{
  /* avoid returning NULL */
  return data->iiim_lang_name ? data->iiim_lang_name : DEFAULT_LANG;
}

char *
gimlet_language_get_conversion_mode (char *iiim_lang_name)
{
  GSList *tmp;
  tmp = active_languages;
  GimletLanguage *lang;

  while (tmp != NULL)
    {
      lang = tmp->data;
      if (strcmp (lang->iiim_lang_name, iiim_lang_name) == 0)
	break;
      tmp = tmp->next;
    }
  return (lang->conversion_on ? "on" : "off");
}

GSList*
gimlet_language_get_active_languages (void)
{
  GSList *copy;
  GSList *tmp;

  copy = NULL;
  tmp = active_languages;
  while (tmp != NULL)
    {
      copy = g_slist_append (copy,
                              gimlet_language_copy (tmp->data));
      
      tmp = tmp->next;
    }

  return copy;
}

/*
  add an active language from the iiiim input language which
  client has set.
*/
void
gimlet_language_add_active_language (GimletWindow *gimlet,
				     char *iiim_lang_name)
{
  GtkWidget *gimlet_applet = GTK_WIDGET (gimlet->applet);
  GSList *active_iiim_lang_list;
  GSList *tmp;

  active_iiim_lang_list = language_list_to_iiim_lang_list (active_languages);

  tmp = active_iiim_lang_list;
  while (tmp != NULL)
    {
      if (strcmp (tmp->data, iiim_lang_name) == 0)
	return;
      tmp = tmp->next;
    }
  active_iiim_lang_list = g_slist_prepend (active_iiim_lang_list,
					   g_strdup (iiim_lang_name));
  gconf_set_active_languages (gimlet_applet, active_iiim_lang_list);

  g_slist_foreach (active_iiim_lang_list, (GFunc) g_free, NULL);
  g_slist_free (active_iiim_lang_list);
}

void
gimlet_language_free (GimletLanguage *language)
{
  g_free (language->name);
  g_free (language->description);
  g_free (language->iiim_lang_name);
  g_free (language);
}
