/* charset.c
 * Copyright (C) 2005 Sylvain Cresto <scresto@gmail.com>
 * 
 * This file is part of graveman!
 *
 * graveman! 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, or
 * (at your option) any later version.
 * 
 * graveman! 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 program; see the file COPYING. If not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA 02111-1307, USA. 
 * 
 * URL: http://www.nongnu.org/graveman/
 *
 */

/* definition des fenetres */

#include "graveman.h"

GSList *Gcharsetlist = NULL;

/* table de correspondance pour l'autodetection des charsets */
Tdata Gautoconvcharset[] = {
  /* iso */
  { "iso8859-1", N_("Latin/Occidental alphabet (ISO 8859-1)") },
  { "iso8859-2", N_("Latin alphabet No. 2 (ISO 8859-2)") },
  { "iso8859-3", N_("Latin alphabet No. 3 (ISO 8859-3)") },
  { "iso8859-4", N_("Latin alphabet No. 4 (ISO 8859-4)") },
  { "iso8859-5", N_("Latin/Cyrillic alphabet (ISO 8859-5)") },
  { "iso8859-6", N_("Latin/Arabic alphabet (ISO 8859-6)") },
  { "iso8859-7", N_("Latin/Greek alphabet (ISO 8859-7)") },
  { "iso8859-8", N_("Latin/Hebrew alphabet (ISO 8859-8)") },
  { "iso8859-9", N_("Latin alphabet No. 5 (ISO 8859-9)") },
  { "iso8859-10", N_("Latin alphabet No. 6 (ISO 8859-10)") },
  { "iso8859-11", N_("Latin/Thai alphabet (ISO 8859-11)") },
  { "iso8859-13", N_("Latin alphabet No. 7 (ISO 8859-13)") },
  { "iso8859-14", N_("Latin/Celtic alphabet (ISO 8859-14)") },
  { "iso8859-15", N_("Latin/Occidental+euro alphabet (ISO 8859-15)") },

  /* koi8 ukraine + russie */
  { "koi8-u", N_("Ukrainian (KOI8-U)") },
  { "koi8-r", N_("Russian (KOI8-R)") },

  /* windows */
  { "cp1250", N_("Windows Central European (CP1250)") },
  { "cp1251", N_("Windows Cyrillic (CP1251)") },
  { "cp1252", N_("Windows US ANSI (CP1252)") },
  { "cp1254", N_("Windows Turkish (CP1254)") },
  { "cp1257", N_("Windows Baltic (CP1257)") },
  
  /* ms dos */
  { "cp437",  N_("MS-DOS US (CP437)") },
  { "cp737",  N_("MS-DOS Greek (CP737)") },
  { "cp775",  N_("MS-DOS Baltic (CP774)") },
  { "cp850",  N_("MS-DOS Multilingual Latin1 (CP852)") },
  { "cp852",  N_("MS-DOS Slavic (CP852)") },
  { "cp855",  N_("MS-DOS Cyrillic (CP855)") },
  { "cp857",  N_("MS-DOS Turkish (CP857)") },
  { "cp860",  N_("MS-DOS Portugese (CP860)") },
  { "cp861",  N_("MS-DOS Icelandic (CP861)") },
  { "cp862",  N_("MS-DOS Hebrew (CP862)") },
  { "cp863",  N_("MS-DOS Canadian French (CP863)") },
  { "cp864",  N_("MS-DOS Arabic (CP864)") },
  { "cp865",  N_("MS-DOS Nordic (CP865)") },
  { "cp866",  N_("MS-DOS Russian (CP866)") },
  { "cp869",  N_("MS-DOS Modern Greek (CP869)") },
  { "cp874",  N_("MS-DOS Thai (CP874)") },

  /* macintosh */
  { "cp10000", N_("Macintosh Roman (CP10000)") },
  { "cp10004", N_("Macintosh Arabic (CP10004)") },
  { "cp10006", N_("Macintosh Greek (CP10006)") },
  { "cp10007", N_("Macintosh Cyrillic (CP10007)") },
  { "cp10029", N_("Macintosh Central European (CP10029)") },
  { "cp10079", N_("Macintosh Icelandic (CP10079)") },
  { "cp10081", N_("Macintosh Turkish (CP10081)") },
  { NULL, NULL },
};


const char *charset_code_to_label(gchar *Acode)
{
  gint i;
  
  for (i=0; Gautoconvcharset[i].data; i++) {
    if (!strcmp(Gautoconvcharset[i].data, Acode)) {
      return _(Gautoconvcharset[i].label);
    }
  }

  return Acode;
}

/* initialisation treeview contenant la liste des charsets */
void prepare_properties_charsettreeview(GtkTreeView *Atreeview)
{
  GtkListStore *Lmodel = gtk_list_store_new(4, G_TYPE_INT, GDK_TYPE_PIXBUF, G_TYPE_STRING,
                G_TYPE_STRING);
  GtkCellRenderer *Lcellrender;
  GtkTreeViewColumn *Lcell;

  gtk_tree_view_set_model(Atreeview, GTK_TREE_MODEL(Lmodel));

  /* creation colonnes */
  Lcellrender = gtk_cell_renderer_pixbuf_new();
  Lcell = gtk_tree_view_column_new_with_attributes("", Lcellrender, "pixbuf", 1, NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(Atreeview), Lcell);
  gtk_tree_view_column_set_resizable(Lcell, TRUE);

  Lcellrender = gtk_cell_renderer_text_new();
  Lcell = gtk_tree_view_column_new_with_attributes(_("Code / Location"), Lcellrender, "text", 2, NULL);
  gtk_tree_view_column_set_resizable(Lcell, TRUE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(Atreeview), Lcell);

  Lcellrender = gtk_cell_renderer_text_new();
  Lcell = gtk_tree_view_column_new_with_attributes(_("Label"), Lcellrender, "text", 3, NULL);
  gtk_tree_view_column_set_resizable(Lcell, TRUE);
  gtk_tree_view_append_column(GTK_TREE_VIEW(Atreeview), Lcell);
}

/* boite de dialogue "selection d'un fichier charset" */
GtkWidget* create_charsetselection (GtkWindow *AParent)
{
  GtkWidget *Lfileselection;

  GtkFileFilter *filterall;

  /* filtres pour la selection de fichiers */
  filterall = gtk_file_filter_new ();
  gtk_file_filter_set_name (filterall, _("All files (*.*)"));
  gtk_file_filter_add_pattern(filterall, "*");

  Lfileselection = gtk_file_chooser_dialog_new(_("Select file containing character set table"),
                        AParent, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
				      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
				      NULL);

  gtk_dialog_set_default_response (GTK_DIALOG (Lfileselection), GTK_RESPONSE_ACCEPT);
  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (Lfileselection), filterall);

  return Lfileselection;
}


/* selection d'un fichier charset */
void gtk_charset_sel(GtkWidget *Abtn, gpointer Adata)
{
  Tgrave *Lg = (Tgrave *)Adata;
  GtkWidget *Ltextdest = (GtkWidget *) sc_grave_get_widget(Lg, "charsetlocation");
  gint Lresp;
  GtkWidget *Lfilesel;

  Lfilesel = create_charsetselection(sc_grave_get_data(Lg, "window"));
  use_last_dir(GTK_FILE_CHOOSER(Lfilesel));
  Lresp=gtk_dialog_run(GTK_DIALOG(Lfilesel));
  gtk_widget_hide (Lfilesel);
  while (gtk_events_pending())
    gtk_main_iteration();

  if (Lresp == GTK_RESPONSE_ACCEPT) {
    gchar *Lfilenamebrut = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER ( Lfilesel));
    gchar *Lfilename = _FILENAME(Lfilenamebrut);
    save_last_dir(GTK_FILE_CHOOSER(Lfilesel));
    gtk_entry_set_text(GTK_ENTRY(Ltextdest), Lfilename);
    g_free(Lfilename);
    g_free(Lfilenamebrut);
  }

  gtk_widget_destroy(Lfilesel);
}

/* ajouter manuelement une definition de charset */
void gtk_charset_add(GtkWidget *Abtn, gpointer Adata)
{
  Tgrave *Lg = (Tgrave *) Adata;
  GtkWidget *Lparent = GTK_WIDGET(sc_grave_get_data(Lg, "window"));
  Tgrave *Ldialoghash = create_dialog_add_charset(Lparent);
  GtkWidget *Lwinaddcharset = sc_grave_get_data(Ldialoghash, "window");
  GtkWidget *Lmessage;
  gboolean Lcontinue = TRUE;

  while (Lcontinue) {
    if (gtk_dialog_run(GTK_DIALOG(Lwinaddcharset)) != GTK_RESPONSE_CANCEL) {
      GtkEntry *Lcharsetlabel = GTK_ENTRY(sc_grave_get_widget(Ldialoghash, "charsetlabel"));
      gchar *Lfilename = _FILENAME(gtk_entry_get_text(GTK_ENTRY(sc_grave_get_widget(Ldialoghash, "charsetlocation"))));
      
      if (*Lfilename && g_file_test(Lfilename, G_FILE_TEST_EXISTS)) {
        config_append_charset(Lfilename, (gchar *)gtk_entry_get_text(Lcharsetlabel));

        /* mise a jour de la liste des peripheriques */
        update_charsets(Lg);

        Lmessage = gtk_message_dialog_new(GTK_WINDOW(Lparent),
                                     GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
                                     _("Charset succesfully added !"));
        Lcontinue = FALSE;
      } else if (*Lfilename) {
        gchar *Lmsg = g_strdup_printf(_("Cannot add this charset, file '%s' doesn't exist !"), Lfilename);

        Lmessage = gtk_message_dialog_new(GTK_WINDOW(Lparent),
                                     GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, Lmsg);
        g_free(Lmsg);
      } else {
        break;
      }
      
      gtk_dialog_run(GTK_DIALOG(Lmessage));
      gtk_widget_destroy(Lmessage);

      g_free(Lfilename);

    } else {
      Lcontinue = FALSE;
    }
  }
  gtk_widget_destroy(Lwinaddcharset);
  sc_grave_destroy(Ldialoghash);
}

void gtk_charset_edit(GtkWidget *Abtn, gpointer Adata)
{
  Tgrave *Lg = (Tgrave *) Adata;
  GtkWidget *Lparent = GTK_WIDGET(sc_grave_get_data(Lg, "window"));
  GtkTreeView *Lliste = GTK_TREE_VIEW(sc_grave_get_widget(Lg, "charsetdata"));
  GtkTreeSelection *Lselection = gtk_tree_view_get_selection(GTK_TREE_VIEW(Lliste));
  GtkTreeIter Liter;
  GtkTreeModel *Ltreemodel;

  if (gtk_tree_selection_get_selected(Lselection, &Ltreemodel, &Liter)) {
    Tgrave *Ldialoghash;
    GtkWidget *Lwineditcharset;
    Tdata *Lcharset;
    gint Lnum;
    
    gtk_tree_model_get(Ltreemodel, &Liter, 0, &Lnum, -1);
    Lcharset = (Tdata *)g_slist_nth_data(Gcharsetlist, Lnum);
    Ldialoghash = create_dialog_edit_charset(Lparent, Lcharset);
    Lwineditcharset = sc_grave_get_data(Ldialoghash, "window");

    if (gtk_dialog_run(GTK_DIALOG(Lwineditcharset)) != GTK_RESPONSE_CANCEL) {
      GtkEntry *Lcharsetlabel = GTK_ENTRY(sc_grave_get_widget(Ldialoghash, "charsetlabel"));

      /* on remplace le nom dans la liste des lecteurs */
      g_free(Lcharset->label);
      Lcharset->label = g_strdup(gtk_entry_get_text(Lcharsetlabel));
      /* ainsi que dans la liste affichée */
      gtk_list_store_set(GTK_LIST_STORE(Ltreemodel), &Liter, 3, Lcharset->label, -1);
    }
    gtk_widget_destroy(Lwineditcharset);
    sc_grave_destroy(Ldialoghash);
  }


}

/* l'utilisateur a cliquer sur supprimer un charset */
void gtk_charset_remove(GtkWidget *Abtn, gpointer Adata)
{
  Tgrave *Lg = (Tgrave *)Adata;
  GtkWidget *Lwindow1 = GTK_WIDGET(sc_grave_get_widget(Lg, "topwindow"));
  GtkWidget *Lconfirm;
  gint Lrep;
  
  /* confirmation debut de l'operation */ 
  Lconfirm = gtk_message_dialog_new(GTK_WINDOW(Lwindow1),
                      GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
                      GTK_BUTTONS_YES_NO,
                      _("Do you really want to remove this character set ?"));
  Lrep = gtk_dialog_run(GTK_DIALOG(Lconfirm));
  gtk_widget_destroy(Lconfirm);

  if (Lrep == GTK_RESPONSE_YES) {
    /* oui on supprime un charsets */
    GtkTreeView *Lliste = GTK_TREE_VIEW(sc_grave_get_widget(Lg, "charsetdata"));
    GtkTreeSelection *Lselection = gtk_tree_view_get_selection(GTK_TREE_VIEW(Lliste));
    GtkTreeIter Liter;
    GtkTreeModel *Ltreemodel;
    gint Lnum;

    if (gtk_tree_selection_get_selected(Lselection, &Ltreemodel, &Liter)) {
      gtk_tree_model_get(Ltreemodel, &Liter, 0, &Lnum, -1);

      _DEB("ON SUPRIMME LE CHARSET = %d\n", Lnum);
      Gcharsetlist = g_slist_remove(Gcharsetlist, g_slist_nth_data(Gcharsetlist, Lnum));
      gtk_list_store_remove(GTK_LIST_STORE(Ltreemodel), &Liter);
    } 

    update_charsets(Lg);
  }
}

/* boite de dialogue "ajouter un charset" */
Tgrave *create_dialog_add_charset(GtkWidget *Aparent)
{
  Tgrave *Lg = sc_grave_load("dialog_add_charset.glade");
  GtkWidget *Ldialog;

  g_assert(Lg);

  Ldialog = sc_grave_get_widget(Lg, "dialog_add_charset");
  gtk_window_set_transient_for(GTK_WINDOW(Ldialog), GTK_WINDOW(Aparent));
  sc_grave_ref_wtd(Lg, "dialog_add_charset", "window");

  gtk_dialog_set_default_response(GTK_DIALOG(Ldialog), GTK_RESPONSE_OK);

  gtk_entry_set_text(GTK_ENTRY(sc_grave_get_widget(Lg, "charsetlabel")), _("New charset"));

  g_signal_connect(G_OBJECT(sc_grave_get_widget(Lg, "btnbrowse")), "clicked", G_CALLBACK(gtk_charset_sel), Lg);


  return Lg;
}

/* boite de dialogue "editer un charset" */
Tgrave *create_dialog_edit_charset(GtkWidget *Aparent, Tdata *Adata)
{
  Tgrave *Lg = sc_grave_load("dialog_charset.glade");
  GtkWidget *Ldialog;
  GtkEntry *Lentry;

  g_assert(Lg);

  Ldialog = sc_grave_get_widget(Lg, "dialog_charset");
  gtk_window_set_transient_for(GTK_WINDOW(Ldialog), GTK_WINDOW(Aparent));
  sc_grave_ref_wtd(Lg, "dialog_charset", "window");
  gtk_dialog_set_default_response(GTK_DIALOG(Ldialog), GTK_RESPONSE_OK);

  Lentry = GTK_ENTRY(sc_grave_get_widget(Lg, "charsetlabel"));
  gtk_entry_set_text(Lentry, Adata->label);
  gtk_label_set_text(GTK_LABEL(sc_grave_get_widget(Lg, "charsetcode")), Adata->data);

  g_signal_connect(G_OBJECT(Lentry), "key-release-event", G_CALLBACK(callback_simpledialog_eventkeyrelease), Ldialog);

  return Lg;
}

void remplirelistecharset(GtkListStore *Adata, gboolean Aadddef)
{
  GtkTreeIter Liter;
  gint i;
  GSList *Lcur;
  Tdata *Lptr;

  gtk_list_store_clear(Adata);

  if (Aadddef) {
    /* ajout premiere ligne "default" */
    gtk_list_store_append(Adata, &Liter);

    gtk_list_store_set(Adata, &Liter, 0, -1, 1, get_image("CharsetSmallIcon"), 2,
          "DEFAULT", 3, _("Use default character set"), -1);
  }

  for (Lcur = Gcharsetlist, i=0; Lcur; Lcur = g_slist_next(Lcur), i++) {
    Lptr = (Tdata *)Lcur->data;

    gtk_list_store_append(Adata, &Liter);

    gtk_list_store_set(Adata, &Liter, 0, i, 1, get_image("CharsetSmallIcon"), 2,
          Lptr->data, 3, Lptr->label, -1);
  }
}

void selectcombocharset(GtkComboBox *Acombo, gchar *Avalue)
{
  GtkTreeModel *Lmodel = gtk_combo_box_get_model(Acombo);
  gboolean Lselect = FALSE;
  GtkTreeIter Liter;
  gboolean Lstatus;
  gchar *Lcode;

  if (Avalue) {
    for (Lstatus = gtk_tree_model_get_iter_first(Lmodel, &Liter); Lstatus == TRUE && Lselect == FALSE;
        Lstatus = gtk_tree_model_iter_next(Lmodel, &Liter)) {
      gtk_tree_model_get(Lmodel, &Liter, 2, &Lcode, -1);
      if (!strcmp(Lcode, Avalue)) {
        gtk_combo_box_set_active_iter(Acombo, &Liter);
        Lselect = TRUE;
      }
      g_free(Lcode);
    }
  }

  if (Lselect == FALSE) {
    gtk_combo_box_set_active(Acombo, 0);
  }
}

void update_charsets(Tgrave *Ag)
{
  GtkComboBox *Lcombo = GTK_COMBO_BOX(sc_grave_get_widget(Ag, "inputcharset"));

  charset_sort_list();
  remplirelistecharset(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sc_grave_get_widget(Ag, "charsetdata")))), FALSE);
  remplirelistecharset(GTK_LIST_STORE(gtk_combo_box_get_model(Lcombo)), TRUE);
  selectcombocharset(Lcombo, conf_get_string("charsetdata"));
}

/* operation de recherche des charsets */
void cherchecharset(GtkWidget *Aobj, gpointer Adata)
{
  Tgrave *Lg = (Tgrave *)Adata;
  GtkWidget *Lwindow1 = sc_grave_get_data(Lg, "window");
  GtkWidget *Lstatusbox;

  if (get_builtin_charset(Lg, NULL) == TRUE && GTK_IS_WIDGET(Aobj)) {
    update_charsets(Lg);

    /* boite de dialoge operation terminee */
    Lstatusbox = gtk_message_dialog_new(GTK_WINDOW(Lwindow1), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
        _("configuration updated."));
    gtk_dialog_run(GTK_DIALOG(Lstatusbox));
    gtk_widget_destroy(Lstatusbox);
  }
}

gint charset_sort_callback(gconstpointer Ad1, gconstpointer Ad2)
{
  Tdata *Ld1 = (Tdata *) Ad1;
  Tdata *Ld2 = (Tdata *) Ad2;
  return g_utf8_collate(Ld1->label, Ld2->label);
}

/* tri pour afficher la liste des charsets dans le bon ordre */
void charset_sort_list()
{
  if (g_slist_length(Gcharsetlist))
   Gcharsetlist = g_slist_sort(Gcharsetlist, charset_sort_callback);
}

/*
 * vim:et:ts=8:sts=2:sw=2
 */
