Fixed bugs:
[claws.git] / src / gtkspell.c
index 6880a7878b466e7dd6da88e71265e2beea26bb22..d4b1838b7dbe10981ace1492f8d7ba78c1a79911 100644 (file)
@@ -58,7 +58,6 @@
 #include "gtkspell.h"
 
 #include <pspell/pspell.h>
-#include <pspell/string_list.h>
 /* size of the text buffer used in various word-processing routines. */
 #define BUFSIZE 1024
 
@@ -78,16 +77,16 @@ static void menu_change_dict                (GtkWidget *w, GtkPspell *gtkpspell);
 static void entry_insert_cb            (GtkXText *gtktext, gchar *newtext, 
                                         guint len, guint *ppos, 
                                         GtkPspell *gtkpspell);
+static void entry_delete_cb            (GtkXText *gtktext, gint start, gint end, 
+                                        GtkPspell *gtkpspell);
 static gint compare_dict               (Dictionary *a, Dictionary *b);
 guchar *convert_to_pspell_encoding     (const guchar *encoding);
 
+static void allocate_color(GtkPspell *gtkpspell);
 
 /* gtkspellconfig - only one config per session */
 GtkPspellConfig * gtkpspellconfig;
 
-/* TODO: configurable */
-static GdkColor highlight = { 0, 255 * 256, 0, 0 };
-
 /******************************************************************************/
 
 /* gtkspell_init() - run the first pspell_config from which every
@@ -152,6 +151,7 @@ GtkPspell * gtkpspell_new(GtkPspellConfig *gtkpspellconfig)
        gtkpspell->mode            = PSPELL_FASTMODE;
        gtkpspell->learn           = TRUE;
        gtkpspell->gtktext         = NULL;
+
        return gtkpspell;
 }
 
@@ -179,7 +179,7 @@ GtkPspell *gtkpspell_new_with_config(GtkPspellConfig *gtkpspellconfig,
        gtkpspell->gtktext         = NULL;
   
        gtkpspell->config          = pspell_config_clone(gtkpspellconfig);
-       gtkpspell->mode            = PSPELL_FASTMODE;
+       gtkpspell->mode            = mode;
        gtkpspell->learn           = TRUE;
        
        if (!set_path_and_dict(gtkpspell, gtkpspell->config, path, dict)) {
@@ -212,6 +212,7 @@ GtkPspell *gtkpspell_new_with_config(GtkPspellConfig *gtkpspellconfig,
        else {
                gtkpspell->checker = to_pspell_manager( gtkpspell->possible_err );
        }
+
        return gtkpspell;
 }
 
@@ -325,12 +326,11 @@ int set_path_and_dict(GtkPspell *gtkpspell, PspellConfig *config,
        if (temppath[strlen(temppath)-1] == G_DIR_SEPARATOR) 
                temppath[strlen(temppath)-1]= 0;
        if (temppath) {
-               pspell_config_replace(config, "rem-word-list-path", temppath);
                pspell_config_replace(config, "add-word-list-path", temppath);
+               debug_print(_("Pspell config: added path %s\n"), pspell_config_retrieve(config, "word-list-path"));
+               if (pspell_config_error_number(config))
+                       debug_print(_("Pspell config: %s\n"), pspell_config_error_message(config));
        }
-       debug_print(_("Pspell config: added path %s\n"), pspell_config_retrieve(config, "word-list-path"));
-       if (pspell_config_error_number(config))
-               debug_print(_("Pspell config: %s\n"), pspell_config_error_message(config));
        if (language) 
                pspell_config_replace(config, "language-tag", language);
        if (spelling) 
@@ -342,13 +342,13 @@ int set_path_and_dict(GtkPspell *gtkpspell, PspellConfig *config,
 
        switch(gtkpspell->mode) {
        case PSPELL_FASTMODE: 
-               pspell_config_replace(config, "sug_mode", "fast");
+               pspell_config_replace(config, "sug-mode", "fast");
                break;
        case PSPELL_NORMALMODE: 
-               pspell_config_replace(config, "sug_mode", "normal");
+               pspell_config_replace(config, "sug-mode", "normal");
                break;
        case PSPELL_BADSPELLERMODE: 
-               pspell_config_replace(config, "sug_mode", "bad-spellers");
+               pspell_config_replace(config, "sug-mode", "bad-spellers");
                break;
        }
   
@@ -410,6 +410,11 @@ int gtkpspell_set_path_and_dict(GtkPspell * gtkpspell, guchar * path,
 /* Returns an allocated string */  
 guchar *gtkpspell_get_dict(GtkPspell *gtkpspell)
 {
+/* Number of dashes in a dictionary name + 1 (for trailing null)
+ * needed when rebuilding dictionary name 
+ */
+#define DASHES_IN_DICTNAME 3+1
+
        guchar *dict;
        guchar *language;
        guchar *spelling;
@@ -423,8 +428,8 @@ guchar *gtkpspell_get_dict(GtkPspell *gtkpspell)
        jargon   = g_strdup(pspell_config_retrieve(gtkpspell->config, "jargon"  ));
        len      = strlen(language) + strlen(spelling) + strlen(jargon);
 
-       if (len < BUFSIZE) {
-               dict = g_new(char,len + 4);
+       if (len + DASHES_IN_DICTNAME < BUFSIZE) {
+               dict = g_new(char,len + DASHES_IN_DICTNAME);
                strcpy(dict, language);
                if (spelling) {
                        strcat(dict, "-");
@@ -465,10 +470,19 @@ static void menu_change_dict(GtkWidget *w, GtkPspell *gtkpspell)
        /* Dict is simply the menu label */
 
        gtk_label_get(GTK_LABEL(GTK_BIN(w)->child), (gchar **) &thelabel);
+
+       if (!strcmp2(thelabel, _("None")))
+                       return;
+
        thedict = g_strdup(thelabel);
 
        /* Set path, dict, (and sug_mode ?) */
-       gtkpspell_set_path_and_dict(gtkpspell, gtkpspell->path, thedict);
+       if(!gtkpspell_set_path_and_dict(gtkpspell, gtkpspell->path, thedict)) {
+               /* FIXME : try to handle this very special case */
+               debug_print("Pspell: Attempt to change to a non existant dict. I will crash after closing compose window.\n");
+               gtkpspell_detach(gtkpspell);
+               gtkpspell = gtkpspell_delete(gtkpspell);
+       }
        g_free(thedict);
 }
 
@@ -686,16 +700,11 @@ static void change_color(GtkPspell * gtkpspell,
        gtk_xtext_freeze(gtktext);
        newtext = gtk_editable_get_chars(GTK_EDITABLE(gtktext), start, end);
        if (newtext) {
-               gtk_signal_handler_block_by_func(GTK_OBJECT(gtktext),
-                                                GTK_SIGNAL_FUNC(entry_insert_cb), 
-                                                gtkpspell);
                gtk_xtext_set_point(gtktext, start);
                gtk_xtext_forward_delete(gtktext, end - start);
 
                gtk_xtext_insert(gtktext, NULL, color, NULL, newtext, end - start);
-               gtk_signal_handler_unblock_by_func(GTK_OBJECT(gtktext),
-                                                  GTK_SIGNAL_FUNC(entry_insert_cb), 
-                                                  gtkpspell);
+               g_free(newtext);
        }
        gtk_xtext_thaw(gtktext);
 }
@@ -717,16 +726,10 @@ static gboolean check_at(GtkPspell *gtkpspell, int from_pos)
        gtkpspell->theword[BUFSIZE - 1] = 0;
 
        if (misspelled_test(gtkpspell, buf)) {
-               if (highlight.pixel == 0) {
-                       /* add an entry for the highlight in the color map. */
-                       GdkColormap *gc = gtk_widget_get_colormap(GTK_WIDGET(gtktext));
-                       gdk_colormap_alloc_color(gc, &highlight, FALSE, TRUE);
-               }
-               change_color(gtkpspell, start, end, &highlight);
+                       change_color(gtkpspell, start, end, &(gtkpspell->highlight));
                return TRUE;
        } else {
-               change_color(gtkpspell, start, end,
-                            &(GTK_WIDGET(gtktext)->style->fg[0]));
+               change_color(gtkpspell, start, end, NULL);
                return FALSE;
        }
 }
@@ -782,8 +785,7 @@ static void entry_insert_cb(GtkXText *gtktext, gchar *newtext,
        /* Never mess with set_insertion when frozen */
        gtk_xtext_freeze(gtktext);
        gtk_xtext_backward_delete(GTK_XTEXT(gtktext), len);
-       gtk_xtext_insert(GTK_XTEXT(gtktext), NULL,
-                        &(GTK_WIDGET(gtktext)->style->fg[0]), NULL, newtext, len);
+       gtk_xtext_insert(GTK_XTEXT(gtktext), NULL, NULL, NULL, newtext, len);
        *ppos = gtk_xtext_get_point(GTK_XTEXT(gtktext));
               
        if (iswordsep(newtext[0])) {
@@ -821,6 +823,7 @@ static void entry_delete_cb(GtkXText *gtktext, gint start, gint end,
        }
 
        gtk_editable_set_position(GTK_EDITABLE(gtktext), origpos);
+       gtk_xtext_set_point(gtktext, origpos);
        gtk_editable_select_region(GTK_EDITABLE(gtktext), origpos, origpos);
        /* this is to *UNDO* the selection, in case they were holding shift
          * while hitting backspace. */
@@ -848,9 +851,22 @@ static void replace_word(GtkWidget *w, GtkPspell *gtkpspell)
        oldlen = end - start;
 
        gtk_xtext_set_point(GTK_XTEXT(gtktext), end);
-       gtk_xtext_backward_delete(GTK_XTEXT(gtktext), end - start);
-       gtk_xtext_insert(GTK_XTEXT(gtktext), NULL, NULL, NULL, newword, strlen(newword));
+       gtk_signal_handler_block_by_func(GTK_OBJECT(gtktext),
+                       GTK_SIGNAL_FUNC(entry_insert_cb), 
+                       gtkpspell);
+       gtk_signal_handler_block_by_func(GTK_OBJECT(gtktext),
+                       GTK_SIGNAL_FUNC(entry_delete_cb), 
+                       gtkpspell);
+       gtk_xtext_set_point(gtktext, start);
+       gtk_signal_emit_by_name(GTK_OBJECT(gtktext), "delete-text", start, end);
+       gtk_signal_emit_by_name(GTK_OBJECT(gtktext), "insert-text", newword, strlen(newword), &start);
     
+       gtk_signal_handler_unblock_by_func(GTK_OBJECT(gtktext),
+                       GTK_SIGNAL_FUNC(entry_insert_cb), 
+                       gtkpspell);
+       gtk_signal_handler_unblock_by_func(GTK_OBJECT(gtktext),
+                       GTK_SIGNAL_FUNC(entry_delete_cb), 
+                       gtkpspell);
        if (end-start > 0 && gtkpspell->learn) { 
                /* Just be sure the buffer ends somewhere... */
                buf[end-start] = 0; 
@@ -1222,7 +1238,7 @@ void gtkpspell_uncheck_all(GtkPspell * gtkpspell)
 
 void gtkpspell_attach(GtkPspell *gtkpspell, GtkXText *gtktext) 
 {
-       gtkpspell->gtktext=gtktext;
+       gtkpspell->gtktext = gtktext;
        gtk_signal_connect_after(GTK_OBJECT(gtktext), "insert-text",
                           GTK_SIGNAL_FUNC(entry_insert_cb), gtkpspell);
        gtk_signal_connect_after(GTK_OBJECT(gtktext), "delete-text",
@@ -1230,6 +1246,8 @@ void gtkpspell_attach(GtkPspell *gtkpspell, GtkXText *gtktext)
        gtk_signal_connect(GTK_OBJECT(gtktext), "button-press-event",
                           GTK_SIGNAL_FUNC(button_press_intercept_cb), gtkpspell);
 
+       allocate_color(gtkpspell);
+       
 }
 
 void gtkpspell_detach(GtkPspell * gtkpspell) 
@@ -1403,6 +1421,59 @@ gchar *gtkpspell_get_dictionary_menu_active_item(GtkWidget *menu)
   
 }
 
+GtkWidget *gtkpspell_sugmode_option_menu_new(gint sugmode)
+{
+       GtkWidget *menu;
+       GtkWidget *item;
+
+
+       menu = gtk_menu_new();
+       gtk_widget_show(menu);
+
+       item = gtk_menu_item_new_with_label(_("Fast Mode"));
+        gtk_widget_show(item);
+       gtk_menu_append(GTK_MENU(menu), item);
+       gtk_object_set_data(GTK_OBJECT(item), "sugmode", GINT_TO_POINTER(PSPELL_FASTMODE));
+
+       item = gtk_menu_item_new_with_label(_("Normal Mode"));
+        gtk_widget_show(item);
+       gtk_menu_append(GTK_MENU(menu), item);
+       gtk_object_set_data(GTK_OBJECT(item), "sugmode", GINT_TO_POINTER(PSPELL_NORMALMODE));
+       
+       item = gtk_menu_item_new_with_label(_("Bad Spellers Mode"));
+        gtk_widget_show(item);
+       gtk_menu_append(GTK_MENU(menu), item);
+       gtk_object_set_data(GTK_OBJECT(item), "sugmode", GINT_TO_POINTER(PSPELL_BADSPELLERMODE));
+
+       return menu;
+}
+       
+void gtkpspell_sugmode_option_menu_set(GtkOptionMenu *optmenu, gint sugmode)
+{
+       g_return_if_fail(GTK_IS_OPTION_MENU(optmenu));
+
+       g_return_if_fail(sugmode == PSPELL_FASTMODE ||
+                        sugmode == PSPELL_NORMALMODE ||
+                        sugmode == PSPELL_BADSPELLERMODE);
+
+       gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), sugmode - 1);
+}
+
+gint gtkpspell_get_sugmode_from_option_menu(GtkOptionMenu *optmenu)
+{
+       gint sugmode;
+       GtkWidget *item;
+       
+       g_return_val_if_fail(GTK_IS_OPTION_MENU(optmenu), -1);
+
+       item = gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(optmenu)));
+       
+       sugmode = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(item), "sugmode"));
+
+       return sugmode;
+       
+}
+               
 /* convert_to_pspell_encoding () - converts ISO-8859-* strings to iso8859-* 
  * as needed by pspell. Returns an allocated string.
  */
@@ -1410,8 +1481,8 @@ gchar *gtkpspell_get_dictionary_menu_active_item(GtkWidget *menu)
 guchar *convert_to_pspell_encoding (const guchar *encoding)
 {
        guchar * pspell_encoding;
-       /* Beware, strstr2 returns 0 if string is found -1 if not */
-       if (!strstr2(encoding, "ISO-8859-")) {
+
+       if (strstr2(encoding, "ISO-8859-")) {
                pspell_encoding = g_strdup_printf("iso8859%s", encoding+8);
        }
        else
@@ -1423,6 +1494,21 @@ guchar *convert_to_pspell_encoding (const guchar *encoding)
        
 }
 
-               
-               
+static void allocate_color(GtkPspell *gtkpspell)
+{
+
+       GdkColormap *gc;
+       /* Color allocation */
+       gc = gtk_widget_get_colormap(GTK_WIDGET(gtkpspell->gtktext));
+
+       if (gtkpspell->highlight.pixel)
+               gdk_colormap_free_colors(gc, &(gtkpspell->highlight), 1);
+
+       gtkut_convert_int_to_gdk_color(prefs_common.misspelled_col,
+                       &(gtkpspell->highlight));
+
+       /* add an entry for the highlight in the color map. */
+       gdk_colormap_alloc_color(gc, &(gtkpspell->highlight), FALSE, TRUE);
+}
+
 #endif