From b4678b289948de74d8b7473c15354b85ed88e752 Mon Sep 17 00:00:00 2001 From: Aleteoryx Date: Thu, 24 Jul 2025 22:26:34 -0400 Subject: [PATCH] added spellcheck lang multiselect this took so long, and was a good way to learn gtk. jesus though lmao Implements: https://todo.amehut.dev/~aleteoryx/sexchat/11 --- src/fe-gtk/enchant.c | 134 ++++++++++++++++++++ src/fe-gtk/enchant.h | 47 +++++++ src/fe-gtk/meson.build | 1 + src/fe-gtk/setup.c | 223 ++++++++++++++++++++++++++++++++-- src/fe-gtk/sexy-spell-entry.c | 164 ++++--------------------- 5 files changed, 416 insertions(+), 153 deletions(-) create mode 100644 src/fe-gtk/enchant.c create mode 100644 src/fe-gtk/enchant.h diff --git a/src/fe-gtk/enchant.c b/src/fe-gtk/enchant.c new file mode 100644 index 0000000000000000000000000000000000000000..80a102e50e8a24668e5e212f24727c2d4d5fa040 --- /dev/null +++ b/src/fe-gtk/enchant.c @@ -0,0 +1,134 @@ +/* + * common/enchant.c - Enchant Library Runtime Loading + * + * Copyright (C) 2004-2006 Christian Hammond. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include "enchant.h" + +struct EnchantBroker * (*enchant_broker_init) (void); +void (*enchant_broker_free) (struct EnchantBroker * broker); +void (*enchant_broker_free_dict) (struct EnchantBroker * broker, struct EnchantDict * dict); +void (*enchant_broker_list_dicts) (struct EnchantBroker * broker, EnchantDictDescribeFn fn, void * user_data); +struct EnchantDict * (*enchant_broker_request_dict) (struct EnchantBroker * broker, const char *const tag); + +void (*enchant_dict_add_to_personal) (struct EnchantDict * dict, const char *const word, ssize_t len); +void (*enchant_dict_add_to_session) (struct EnchantDict * dict, const char *const word, ssize_t len); +int (*enchant_dict_check) (struct EnchantDict * dict, const char *const word, ssize_t len); +void (*enchant_dict_describe) (struct EnchantDict * dict, EnchantDictDescribeFn fn, void * user_data); +void (*enchant_dict_free_suggestions) (struct EnchantDict * dict, char **suggestions); +void (*enchant_dict_store_replacement) (struct EnchantDict * dict, const char *const mis, ssize_t mis_len, const char *const cor, ssize_t cor_len); +char ** (*enchant_dict_suggest) (struct EnchantDict * dict, const char *const word, ssize_t len, size_t * out_n_suggs); + +static gboolean _have_enchant = FALSE; + +void +initialize_enchant (void) +{ + GModule *enchant; + gpointer funcptr; + gsize i; + const char * const libnames[] = { +#ifdef G_OS_WIN32 + "libenchant.dll", +#endif +#ifdef G_OS_UNIX + "libenchant.so.1", + "libenchant.so.2", + "libenchant-2.so.2", +#endif +#ifdef __APPLE__ + "libenchant.dylib", +#endif + }; + + if (_have_enchant) + return; + + for (i = 0; i < G_N_ELEMENTS(libnames); ++i) + { + enchant = g_module_open(libnames[i], 0); + if (enchant) + { + g_info ("Loaded %s", libnames[i]); + _have_enchant = TRUE; + break; + } + } + + if (!_have_enchant) + return; + +#define MODULE_SYMBOL(name, func, alt_name) G_STMT_START { \ + const char *funcname = name; \ + gboolean ret = g_module_symbol(enchant, funcname, &funcptr); \ + if (alt_name) { \ + funcname = alt_name; \ + ret = g_module_symbol(enchant, funcname, &funcptr); \ + } \ + if (ret == FALSE) { \ + g_warning ("Failed to find enchant symbol %s", funcname); \ + _have_enchant = FALSE; \ + return; \ + } \ + (func) = funcptr; \ +} G_STMT_END; + + MODULE_SYMBOL("enchant_broker_init", enchant_broker_init, NULL) + MODULE_SYMBOL("enchant_broker_free", enchant_broker_free, NULL) + MODULE_SYMBOL("enchant_broker_free_dict", enchant_broker_free_dict, NULL) + MODULE_SYMBOL("enchant_broker_list_dicts", enchant_broker_list_dicts, NULL) + MODULE_SYMBOL("enchant_broker_request_dict", enchant_broker_request_dict, NULL) + + MODULE_SYMBOL("enchant_dict_add_to_personal", enchant_dict_add_to_personal, "enchant_dict_add") + MODULE_SYMBOL("enchant_dict_add_to_session", enchant_dict_add_to_session, NULL) + MODULE_SYMBOL("enchant_dict_check", enchant_dict_check, NULL) + MODULE_SYMBOL("enchant_dict_describe", enchant_dict_describe, NULL) + MODULE_SYMBOL("enchant_dict_free_suggestions", enchant_dict_free_suggestions, "enchant_dict_free_string_list") + MODULE_SYMBOL("enchant_dict_store_replacement", enchant_dict_store_replacement, NULL) + MODULE_SYMBOL("enchant_dict_suggest", enchant_dict_suggest, NULL) +} + +gboolean +have_enchant (void) +{ + return _have_enchant; +} + + +static void +get_lang_from_dict_cb (const char * const lang_tag, + const char * const provider_name, + const char * const provider_desc, + const char * const provider_file, + void * user_data) { + gchar **lang = (gchar **)user_data; + *lang = g_strdup(lang_tag); +} + +gchar * +enchant_get_lang_from_dict (struct EnchantDict *dict) +{ + gchar *lang; + + if (!_have_enchant) + return NULL; + + enchant_dict_describe(dict, get_lang_from_dict_cb, &lang); + return lang; +} diff --git a/src/fe-gtk/enchant.h b/src/fe-gtk/enchant.h new file mode 100644 index 0000000000000000000000000000000000000000..3931f5291bcbe3ef4e8d5bd25c17b0539ed53381 --- /dev/null +++ b/src/fe-gtk/enchant.h @@ -0,0 +1,47 @@ +/* + * common/enchant.h - Enchant Library Runtime Loading + * + * Copyright (C) 2004-2006 Christian Hammond. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +struct EnchantDict; +struct EnchantBroker; + +typedef void (*EnchantDictDescribeFn) (const char * const lang_tag, + const char * const provider_name, + const char * const provider_desc, + const char * const provider_file, + void * user_data); + + +extern struct EnchantBroker * (*enchant_broker_init) (void); +extern void (*enchant_broker_free) (struct EnchantBroker * broker); +extern void (*enchant_broker_free_dict) (struct EnchantBroker * broker, struct EnchantDict * dict); +extern void (*enchant_broker_list_dicts) (struct EnchantBroker * broker, EnchantDictDescribeFn fn, void * user_data); +extern struct EnchantDict * (*enchant_broker_request_dict) (struct EnchantBroker * broker, const char *const tag); + +extern void (*enchant_dict_add_to_personal) (struct EnchantDict * dict, const char *const word, ssize_t len); +extern void (*enchant_dict_add_to_session) (struct EnchantDict * dict, const char *const word, ssize_t len); +extern int (*enchant_dict_check) (struct EnchantDict * dict, const char *const word, ssize_t len); +extern void (*enchant_dict_describe) (struct EnchantDict * dict, EnchantDictDescribeFn fn, void * user_data); +extern void (*enchant_dict_free_suggestions) (struct EnchantDict * dict, char **suggestions); +extern void (*enchant_dict_store_replacement) (struct EnchantDict * dict, const char *const mis, ssize_t mis_len, const char *const cor, ssize_t cor_len); +extern char ** (*enchant_dict_suggest) (struct EnchantDict * dict, const char *const word, ssize_t len, size_t * out_n_suggs); + +gboolean have_enchant (void); +void initialize_enchant (void); +gchar *enchant_get_lang_from_dict (struct EnchantDict *dict); diff --git a/src/fe-gtk/meson.build b/src/fe-gtk/meson.build index d07514db7ad10333f5a915e14b7bb49621effa57..49ec2c517eda470cb06993259b048b10d4abb074 100644 --- a/src/fe-gtk/meson.build +++ b/src/fe-gtk/meson.build @@ -6,6 +6,7 @@ hexchat_gtk_sources = [ 'custom-list.c', 'dccgui.c', 'editlist.c', + 'enchant.c', 'fe-gtk.c', 'fkeys.c', 'gtkutil.c', diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c index 2c557e67acfbe4dc4279e9a3d67be34d1411d0f6..2e24781d23a92a079185fd730eaeb2191e09d8eb 100644 --- a/src/fe-gtk/setup.c +++ b/src/fe-gtk/setup.c @@ -38,11 +38,13 @@ #include "menu.h" #include "plugin-tray.h" #include "notifications/notification-backend.h" +#include "enchant.h" #ifdef WIN32 #include "../common/fe.h" #endif #include "sexy-spell-entry.h" +#include "sexy-iso-codes.h" GtkStyle *create_input_style (GtkStyle *); @@ -56,6 +58,7 @@ static struct hexchatprefs setup_prefs; static GtkWidget *cancel_button; static GtkWidget *font_dialog = NULL; + enum { ST_END, @@ -72,7 +75,8 @@ enum ST_HSCALE, ST_HEADER, ST_LABEL, - ST_ALERTHEAD + ST_ALERTHEAD, + ST_MULTISEL }; typedef struct @@ -181,6 +185,8 @@ static const setting appearance_settings[] = {ST_END, 0, 0, 0, 0, 0} }; +static const char **spelllangs = NULL; + static const char *const tabcompmenu[] = { N_("A-Z"), @@ -196,12 +202,8 @@ static const setting inputbox_settings[] = {ST_TOGGLE, N_("Show nick box"), P_OFFINTNL(hex_gui_input_nick),0,0,1}, {ST_TOGGLE, N_("Show user mode icon in nick box"), P_OFFINTNL(hex_gui_input_icon),0,0,0}, {ST_TOGGLE, N_("Spell checking"), P_OFFINTNL(hex_gui_input_spell),0,0,1}, - {ST_ENTRY, N_("Dictionaries to use:"), P_OFFSETNL(hex_text_spell_langs),0,0,sizeof prefs.hex_text_spell_langs}, -#ifdef WIN32 - {ST_LABEL, N_("Use language codes (as in \"%LOCALAPPDATA%\\enchant\\myspell\\dicts\").\nSeparate multiple entries with commas.")}, -#else - {ST_LABEL, N_("Use language codes. Separate multiple entries with commas.")}, -#endif + {ST_MULTISEL, N_("Dictionaries to use:"), P_OFFSETNL(hex_text_spell_langs),0,(void *)&spelllangs,sizeof prefs.hex_text_spell_langs}, + {ST_LABEL, N_("If no dictionary is selected, English will be used."), 0, 0, 0, 1}, {ST_HEADER, N_("Nick Completion"),0,0,0}, {ST_ENTRY, N_("Nick completion suffix:"), P_OFFSETNL(hex_completion_suffix),0,0,sizeof prefs.hex_completion_suffix}, @@ -1287,8 +1289,144 @@ setup_create_header (GtkWidget *table, int row, char *labeltext) label = gtk_label_new (NULL); gtk_label_set_markup (GTK_LABEL (label), buf); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, 0, 4, row, row + 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 5); + gtk_table_attach (GTK_TABLE (table), label, 1, 4, row, row + 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 5); +} + +struct multi_select_info { + GtkListStore *store; + const setting *set; +}; + +static void +setup_multi_select_info_free_cb (gpointer data, + GClosure * closure) +{ + g_free (data); +} + +static void +setup_multi_select_cb (GtkCellRendererToggle *cell_renderer, + char *path, + gpointer user_data) +{ + struct multi_select_info *info = (struct multi_select_info *) user_data; + GtkTreeIter row; + gboolean cellstate, hasnext; + char *cellslug, *dest = setup_get_str(&setup_prefs, info->set); + int val_len = 0; + + gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (info->store), &row, path); + gtk_tree_model_get (GTK_TREE_MODEL (info->store), &row, 2, &cellstate, -1); + gtk_list_store_set (info->store, &row, 2, !cellstate, -1); + + setup_prefs.hex_text_spell_langs[0] = '\0'; + hasnext = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (info->store), &row); + while (hasnext) + { + gtk_tree_model_get (GTK_TREE_MODEL (info->store), &row, + 1, &cellslug, + 2, &cellstate, + -1); + + if (cellstate) + { + if (!val_len) + { + val_len = strlen (cellslug); + strcpy (dest, cellslug); + } else if (strlen (cellslug) + 2 < (info->set->extra - val_len)) + { + dest[val_len++] = ','; + dest[val_len] = '\0'; + strcat (dest, cellslug); + val_len += strlen (cellslug); + } else + { + g_free (cellslug); + break; + } + } + + g_free (cellslug); + hasnext = gtk_tree_model_iter_next (GTK_TREE_MODEL (info->store), &row); + } +} + +static GtkWidget * +setup_create_multi_select (GtkWidget *table, int row, const setting *set) +{ + GtkWidget *select, *scrollbox, *label; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + GtkListStore *store; + GtkTreeIter iter; + struct multi_select_info *user_data; + char **entries = *((char ***)set->list), **entry, **enabled, **i; + gboolean entry_enabled; + + label = gtk_label_new (set->label); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_table_attach (GTK_TABLE (table), label, 2, 3, row, row + 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, LABEL_INDENT, 5); + + enabled = g_strsplit_set (setup_get_str(&setup_prefs, set), ", \t", 0); + + /* human name slug enabled? */ + store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN); + + for (entry = entries; *entry; entry += 2) + { + entry_enabled = FALSE; + for (i = enabled; *i; i++) + { + if (strcmp (*i, entry[1]) == 0) + { + entry_enabled = TRUE; + break; + } + } + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, entry[0], + 1, entry[1], + 2, entry_enabled, + -1); + } + + g_strfreev (enabled); + + select = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (select), FALSE); + g_object_unref (store); + + // first column + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes (set->label, renderer, + "text", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (select), column); + + // second column + user_data = g_new0 (struct multi_select_info, 1); + user_data->store = store; + user_data->set = set; + renderer = gtk_cell_renderer_toggle_new (); + column = gtk_tree_view_column_new_with_attributes ("", renderer, + "active", 2, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (select), column); + g_signal_connect_data (G_OBJECT (renderer), "toggled", G_CALLBACK (setup_multi_select_cb), user_data, + (GClosureNotify) (setup_multi_select_info_free_cb), (GConnectFlags) 0); + + scrollbox = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbox), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollbox), GTK_SHADOW_ETCHED_IN); + gtk_container_add(GTK_CONTAINER (scrollbox), select); + + gtk_table_attach (GTK_TABLE (table), scrollbox, 2, 3, row + 1, row + 2, + GTK_SHRINK | GTK_FILL, GTK_FILL, LABEL_INDENT, 0); + + return scrollbox; } static void @@ -1296,7 +1434,7 @@ setup_create_button (GtkWidget *table, int row, char *label, GCallback callback) { GtkWidget *but = gtk_button_new_with_label (label); gtk_table_attach (GTK_TABLE (table), but, 2, 3, row, row + 1, - GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 5); + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 5); g_signal_connect (G_OBJECT (but), "clicked", callback, NULL); } @@ -1372,6 +1510,10 @@ setup_create_page (const setting *set) break; case ST_ALERTHEAD: setup_create_alert_header (tab, row, &set[i]); + break; + case ST_MULTISEL: + wid = setup_create_multi_select (tab, row, &set[i]); + row++; } if (do_disable) @@ -2334,9 +2476,67 @@ setup_close_cb (GtkWidget *win, GtkWidget **swin) } } +static void +setup_load_spellangs_cb (const char * const lang_tag, + const char * const provider_name, + const char * const provider_desc, + const char * const provider_file, + void * user_data) +{ + GSList **langs = (GSList **)user_data; + + *langs = g_slist_prepend(*langs, (gpointer)g_strdup(lang_tag)); +} + +static void +setup_load_spelllangs (void) +{ + struct EnchantBroker *broker; + GSList *langs = NULL, *lang; + guint num_langs; + const char **ptr; + const char *lang_code, *lang_name, *lang_country; + + if (spelllangs) + return; + + broker = enchant_broker_init (); + enchant_broker_list_dicts (broker, setup_load_spellangs_cb, &langs); + enchant_broker_free (broker); + + num_langs = g_slist_length (langs); + spelllangs = ptr = g_new0 (const char *, (num_langs * 2) + 1); + + codetable_init (); + + for (lang = langs; lang; lang = lang->next) + { + lang_name = lang_country = NULL; + lang_code = (const char *) lang->data; + + if (num_langs > 1 && strcmp(lang_code, "en") == 0) + continue; + + codetable_lookup (lang_code, &lang_name, &lang_country); + + if (lang_country == NULL || lang_country[0] == '\0') + *(ptr++) = g_strdup (lang_name); + else + *(ptr++) = g_strdup_printf ("%s (%s)", lang_name, lang_country); + + *(ptr++) = lang_code; + } + + *ptr = NULL; + + g_slist_free(langs); +} + void setup_open (void) { + setup_load_spelllangs (); + if (setup_window) { gtk_window_present (GTK_WINDOW (setup_window)); @@ -2348,6 +2548,5 @@ setup_open (void) color_change = FALSE; setup_window = setup_window_open (); - g_signal_connect (G_OBJECT (setup_window), "destroy", - G_CALLBACK (setup_close_cb), &setup_window); + g_signal_connect (G_OBJECT (setup_window), "destroy", G_CALLBACK (setup_close_cb), &setup_window); } diff --git a/src/fe-gtk/sexy-spell-entry.c b/src/fe-gtk/sexy-spell-entry.c index a304278310acc7f062cc071856b27e052fb1e4f3..baaa7ca30f3e85f0f851bfde9082906492b57967 100644 --- a/src/fe-gtk/sexy-spell-entry.c +++ b/src/fe-gtk/sexy-spell-entry.c @@ -31,6 +31,7 @@ #include #include #include "sexy-iso-codes.h" +#include "enchant.h" #ifdef WIN32 #include "marshal.h" @@ -50,35 +51,6 @@ #include "palette.h" #include "xtext.h" -/* - * Bunch of poop to make enchant into a runtime dependency rather than a - * compile-time dependency. This makes it so I don't have to hear the - * complaints from people with binary distributions who don't get spell - * checking because they didn't check their configure output. - */ -struct EnchantDict; -struct EnchantBroker; - -typedef void (*EnchantDictDescribeFn) (const char * const lang_tag, - const char * const provider_name, - const char * const provider_desc, - const char * const provider_file, - void * user_data); - -static struct EnchantBroker * (*enchant_broker_init) (void); -static void (*enchant_broker_free) (struct EnchantBroker * broker); -static void (*enchant_broker_free_dict) (struct EnchantBroker * broker, struct EnchantDict * dict); -static void (*enchant_broker_list_dicts) (struct EnchantBroker * broker, EnchantDictDescribeFn fn, void * user_data); -static struct EnchantDict * (*enchant_broker_request_dict) (struct EnchantBroker * broker, const char *const tag); - -static void (*enchant_dict_add_to_personal) (struct EnchantDict * dict, const char *const word, ssize_t len); -static void (*enchant_dict_add_to_session) (struct EnchantDict * dict, const char *const word, ssize_t len); -static int (*enchant_dict_check) (struct EnchantDict * dict, const char *const word, ssize_t len); -static void (*enchant_dict_describe) (struct EnchantDict * dict, EnchantDictDescribeFn fn, void * user_data); -static void (*enchant_dict_free_suggestions) (struct EnchantDict * dict, char **suggestions); -static void (*enchant_dict_store_replacement) (struct EnchantDict * dict, const char *const mis, ssize_t mis_len, const char *const cor, ssize_t cor_len); -static char ** (*enchant_dict_suggest) (struct EnchantDict * dict, const char *const word, ssize_t len, size_t * out_n_suggs); -static gboolean have_enchant = FALSE; struct _SexySpellEntryPriv { @@ -119,7 +91,6 @@ static gboolean default_word_check (SexySpellEntry static gboolean sexy_spell_entry_activate_language_internal (SexySpellEntry *entry, const gchar *lang, GError **error); -static gchar *get_lang_from_dict (struct EnchantDict *dict); static void sexy_spell_entry_recheck_all (SexySpellEntry *entry); static void entry_strsplit_utf8 (GtkEntry *entry, gchar ***set, @@ -154,73 +125,6 @@ spell_accumulator(GSignalInvocationHint *hint, GValue *return_accu, const GValue return ret; } -static void -initialize_enchant (void) -{ - GModule *enchant; - gpointer funcptr; - gsize i; - const char * const libnames[] = { -#ifdef G_OS_WIN32 - "libenchant.dll", -#endif -#ifdef G_OS_UNIX - "libenchant.so.1", - "libenchant.so.2", - "libenchant-2.so.2", -#endif -#ifdef __APPLE__ - "libenchant.dylib", -#endif - }; - - for (i = 0; i < G_N_ELEMENTS(libnames); ++i) - { - enchant = g_module_open(libnames[i], 0); - if (enchant) - { - g_info ("Loaded %s", libnames[i]); - have_enchant = TRUE; - break; - } - } - - if (!have_enchant) - return; - -#define MODULE_SYMBOL(name, func, alt_name) G_STMT_START { \ - const char *funcname = name; \ - gboolean ret = g_module_symbol(enchant, funcname, &funcptr); \ - if (alt_name) { \ - funcname = alt_name; \ - ret = g_module_symbol(enchant, funcname, &funcptr); \ - } \ - if (ret == FALSE) { \ - g_warning ("Failed to find enchant symbol %s", funcname); \ - have_enchant = FALSE; \ - return; \ - } \ - (func) = funcptr; \ -} G_STMT_END; - - MODULE_SYMBOL("enchant_broker_init", enchant_broker_init, NULL) - MODULE_SYMBOL("enchant_broker_free", enchant_broker_free, NULL) - MODULE_SYMBOL("enchant_broker_free_dict", enchant_broker_free_dict, NULL) - MODULE_SYMBOL("enchant_broker_list_dicts", enchant_broker_list_dicts, NULL) - MODULE_SYMBOL("enchant_broker_request_dict", enchant_broker_request_dict, NULL) - - MODULE_SYMBOL("enchant_dict_add_to_personal", enchant_dict_add_to_personal, - "enchant_dict_add") - MODULE_SYMBOL("enchant_dict_add_to_session", enchant_dict_add_to_session, NULL) - MODULE_SYMBOL("enchant_dict_check", enchant_dict_check, NULL) - MODULE_SYMBOL("enchant_dict_describe", enchant_dict_describe, NULL) - MODULE_SYMBOL("enchant_dict_free_suggestions", - enchant_dict_free_suggestions, "enchant_dict_free_string_list") - MODULE_SYMBOL("enchant_dict_store_replacement", - enchant_dict_store_replacement, NULL) - MODULE_SYMBOL("enchant_dict_suggest", enchant_dict_suggest, NULL) -} - static void sexy_spell_entry_class_init(SexySpellEntryClass *klass) { @@ -236,7 +140,7 @@ sexy_spell_entry_class_init(SexySpellEntryClass *klass) object_class = G_OBJECT_CLASS(klass); widget_class = GTK_WIDGET_CLASS(klass); - if (have_enchant) + if (have_enchant()) klass->word_check = default_word_check; gobject_class->finalize = sexy_spell_entry_finalize; @@ -476,7 +380,7 @@ add_to_dictionary(GtkWidget *menuitem, SexySpellEntry *entry) gint start, end; struct EnchantDict *dict; - if (!have_enchant) + if (!have_enchant()) return; get_word_extents_from_position(entry, &start, &end, entry->priv->mark_character); @@ -504,7 +408,7 @@ ignore_all(GtkWidget *menuitem, SexySpellEntry *entry) gint start, end; GSList *li; - if (!have_enchant) + if (!have_enchant()) return; get_word_extents_from_position(entry, &start, &end, entry->priv->mark_character); @@ -535,7 +439,7 @@ replace_word(GtkWidget *menuitem, SexySpellEntry *entry) gint cursor; struct EnchantDict *dict; - if (!have_enchant) + if (!have_enchant()) return; get_word_extents_from_position(entry, &start, &end, entry->priv->mark_character); @@ -572,7 +476,7 @@ build_suggestion_menu(SexySpellEntry *entry, GtkWidget *menu, struct EnchantDict gchar **suggestions; size_t n_suggestions, i; - if (!have_enchant) + if (!have_enchant()) return; suggestions = enchant_dict_suggest(dict, word, -1, &n_suggestions); @@ -620,7 +524,7 @@ build_spelling_menu(SexySpellEntry *entry, const gchar *word) GtkWidget *topmenu, *mi; gchar *label; - if (!have_enchant) + if (!have_enchant()) return NULL; topmenu = gtk_menu_new(); @@ -639,7 +543,7 @@ build_spelling_menu(SexySpellEntry *entry, const gchar *word) for (li = entry->priv->dict_list; li; li = g_slist_next (li)) { dict = (struct EnchantDict *) li->data; - lang = get_lang_from_dict(dict); + lang = enchant_get_lang_from_dict(dict); lang_name = sexy_spell_entry_get_language_name (entry, lang); if (lang_name) { @@ -686,7 +590,7 @@ build_spelling_menu(SexySpellEntry *entry, const gchar *word) for (li = entry->priv->dict_list; li; li = g_slist_next(li)) { dict = (struct EnchantDict *)li->data; - lang = get_lang_from_dict(dict); + lang = enchant_get_lang_from_dict(dict); lang_name = sexy_spell_entry_get_language_name (entry, lang); if (lang_name) { @@ -727,7 +631,7 @@ sexy_spell_entry_populate_popup(SexySpellEntry *entry, GtkMenu *menu, gpointer d gint start, end; gchar *word; - if ((have_enchant == FALSE) || (entry->priv->checked == FALSE)) + if ((have_enchant() == FALSE) || (entry->priv->checked == FALSE)) return; if (g_slist_length(entry->priv->dict_list) == 0) @@ -765,7 +669,7 @@ sexy_spell_entry_init(SexySpellEntry *entry) entry->priv->dict_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); - if (have_enchant) + if (have_enchant()) { #ifdef HAVE_ISO_CODES if (codetable_ref == 0) @@ -803,7 +707,7 @@ sexy_spell_entry_finalize(GObject *obj) g_free(entry->priv->word_starts); g_free(entry->priv->word_ends); - if (have_enchant) { + if (have_enchant()) { if (entry->priv->broker) { GSList *li; for (li = entry->priv->dict_list; li; li = g_slist_next(li)) { @@ -862,7 +766,7 @@ default_word_check(SexySpellEntry *entry, const gchar *word) gboolean result = TRUE; GSList *li; - if (!have_enchant) + if (!have_enchant()) return result; if (g_unichar_isalpha(*word) == FALSE) { @@ -1088,7 +992,7 @@ sexy_spell_entry_recheck_all(SexySpellEntry *entry) check_attributes (entry, text, text_len); } - if (have_enchant && entry->priv->checked + if (have_enchant() && entry->priv->checked && g_slist_length (entry->priv->dict_list) != 0) { /* Loop through words */ @@ -1257,7 +1161,7 @@ sexy_spell_entry_activate_default_languages(SexySpellEntry *entry) GSList *enchant_langs; char *lang, **i, **langs; - if (!have_enchant) + if (!have_enchant()) return; if (!entry->priv->broker) @@ -1288,34 +1192,12 @@ sexy_spell_entry_activate_default_languages(SexySpellEntry *entry) sexy_spell_entry_recheck_all (entry); } -static void -get_lang_from_dict_cb(const char * const lang_tag, - const char * const provider_name, - const char * const provider_desc, - const char * const provider_file, - void * user_data) { - gchar **lang = (gchar **)user_data; - *lang = g_strdup(lang_tag); -} - -static gchar * -get_lang_from_dict(struct EnchantDict *dict) -{ - gchar *lang; - - if (!have_enchant) - return NULL; - - enchant_dict_describe(dict, get_lang_from_dict_cb, &lang); - return lang; -} - static gboolean sexy_spell_entry_activate_language_internal(SexySpellEntry *entry, const gchar *lang, GError **error) { struct EnchantDict *dict; - if (!have_enchant) + if (!have_enchant()) return FALSE; if (!entry->priv->broker) @@ -1333,7 +1215,7 @@ sexy_spell_entry_activate_language_internal(SexySpellEntry *entry, const gchar * enchant_dict_add_to_session (dict, "HexChat", strlen("HexChat")); entry->priv->dict_list = g_slist_append(entry->priv->dict_list, (gpointer) dict); - g_hash_table_insert(entry->priv->dict_hash, get_lang_from_dict(dict), (gpointer) dict); + g_hash_table_insert(entry->priv->dict_hash, enchant_get_lang_from_dict(dict), (gpointer) dict); return TRUE; } @@ -1394,7 +1276,7 @@ sexy_spell_entry_get_language_name(const SexySpellEntry *entry, const gchar *lang_name = ""; const gchar *country_name = ""; - g_return_val_if_fail (have_enchant, NULL); + g_return_val_if_fail (have_enchant(), NULL); if (codetable_ref == 0) codetable_init (); @@ -1449,7 +1331,7 @@ sexy_spell_entry_activate_language(SexySpellEntry *entry, const gchar *lang, GEr g_return_val_if_fail(SEXY_IS_SPELL_ENTRY(entry), FALSE); g_return_val_if_fail(lang != NULL && *lang != '\0', FALSE); - if (!have_enchant) + if (!have_enchant()) return FALSE; if (error) @@ -1484,7 +1366,7 @@ sexy_spell_entry_deactivate_language(SexySpellEntry *entry, const gchar *lang) g_return_if_fail(entry != NULL); g_return_if_fail(SEXY_IS_SPELL_ENTRY(entry)); - if (!have_enchant) + if (!have_enchant()) return; if (!entry->priv->dict_list) @@ -1545,7 +1427,7 @@ sexy_spell_entry_set_active_languages(SexySpellEntry *entry, GSList *langs, GErr g_return_val_if_fail(SEXY_IS_SPELL_ENTRY(entry), FALSE); g_return_val_if_fail(langs != NULL, FALSE); - if (!have_enchant) + if (!have_enchant()) return FALSE; /* deactivate all languages first */ @@ -1585,12 +1467,12 @@ sexy_spell_entry_get_active_languages(SexySpellEntry *entry) g_return_val_if_fail(entry != NULL, NULL); g_return_val_if_fail(SEXY_IS_SPELL_ENTRY(entry), NULL); - if (!have_enchant) + if (!have_enchant()) return NULL; for (li = entry->priv->dict_list; li; li = g_slist_next(li)) { dict = (struct EnchantDict *) li->data; - lang = get_lang_from_dict(dict); + lang = enchant_get_lang_from_dict(dict); ret = g_slist_append(ret, lang); } return ret;