diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2019-01-27 14:59:22 +0100 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2019-02-19 21:15:56 +0100 |
commit | 57aa9e060ef7214f8b822fa32b40bb728482adce (patch) | |
tree | 5721144252be73832b937bade4520b3de7e735bb /src/plugins/spell/spell-speller.c | |
parent | e8159298ad4b607e8daee89406de2434ee9c22e4 (diff) | |
download | weechat-57aa9e060ef7214f8b822fa32b40bb728482adce.zip |
spell: rename "aspell" plugin to "spell" (issue #1299)
The following things have been renamed:
- file aspell.conf -> spell.conf
- options aspell.* -> spell.*
- bar item aspell_dict -> spell_dict
- bar item and local variable aspell_suggest -> spell_suggest
- info aspell_dict -> spell_dict
Diffstat (limited to 'src/plugins/spell/spell-speller.c')
-rw-r--r-- | src/plugins/spell/spell-speller.c | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/src/plugins/spell/spell-speller.c b/src/plugins/spell/spell-speller.c new file mode 100644 index 000000000..0b0ac5492 --- /dev/null +++ b/src/plugins/spell/spell-speller.c @@ -0,0 +1,486 @@ +/* + * spell-speller.c - speller management for spell checker plugin + * + * Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org> + * Copyright (C) 2006-2019 Sébastien Helleu <flashcode@flashtux.org> + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat 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 3 of the License, or + * (at your option) any later version. + * + * WeeChat 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 WeeChat. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "spell.h" +#include "spell-speller.h" +#include "spell-config.h" + + +/* + * spellers: one by dictionary (key is name of dictionary (eg: "fr"), value is + * pointer on AspellSpeller) + */ +struct t_hashtable *spell_spellers = NULL; + +/* + * spellers by buffer (key is buffer pointer, value is pointer on + * struct t_spell_speller_buffer) + */ +struct t_hashtable *spell_speller_buffer = NULL; + + +/* + * Checks if a spelling dictionary is supported (installed on system). + * + * Returns: + * 1: spell dict is supported + * 0: spell dict is NOT supported + */ + +int +spell_speller_dict_supported (const char *lang) +{ +#ifdef USE_ENCHANT + return enchant_broker_dict_exists (broker, lang); +#else + struct AspellConfig *config; + AspellDictInfoList *list; + AspellDictInfoEnumeration *elements; + const AspellDictInfo *dict; + int rc; + + rc = 0; + + config = new_aspell_config (); + list = get_aspell_dict_info_list (config); + elements = aspell_dict_info_list_elements (list); + + while ((dict = aspell_dict_info_enumeration_next (elements)) != NULL) + { + if (strcmp (dict->name, lang) == 0) + { + rc = 1; + break; + } + } + + delete_aspell_dict_info_enumeration (elements); + delete_aspell_config (config); + + return rc; +#endif /* USE_ENCHANT */ +} + +/* + * Checks if dictionaries are valid (called when user creates/changes + * dictionaries for a buffer). + * + * An error is displayed for each invalid dictionary found. + */ + +void +spell_speller_check_dictionaries (const char *dict_list) +{ + char **argv; + int argc, i; + + if (dict_list) + { + argv = weechat_string_split (dict_list, ",", 0, 0, &argc); + if (argv) + { + for (i = 0; i < argc; i++) + { + if (!spell_speller_dict_supported (argv[i])) + { + weechat_printf (NULL, + _("%s: warning: dictionary \"%s\" is not " + "available on your system"), + SPELL_PLUGIN_NAME, argv[i]); + } + } + weechat_string_free_split (argv); + } + } +} + +/* + * Creates and adds a new speller instance in the hashtable. + * + * Returns pointer to new speller, NULL if error. + */ + +#ifdef USE_ENCHANT +EnchantDict * +#else +AspellSpeller * +#endif /* USE_ENCHANT */ +spell_speller_new (const char *lang) +{ +#ifdef USE_ENCHANT + EnchantDict *new_speller; +#else + AspellConfig *config; + AspellCanHaveError *ret; + AspellSpeller *new_speller; +#endif /* USE_ENCHANT */ + struct t_infolist *infolist; + + if (!lang) + return NULL; + + if (weechat_spell_plugin->debug) + { + weechat_printf (NULL, + "%s: creating new speller for lang \"%s\"", + SPELL_PLUGIN_NAME, lang); + } + +#ifdef USE_ENCHANT + new_speller = enchant_broker_request_dict (broker, lang); + if (!new_speller) + { + weechat_printf (NULL, + _("%s%s: error: unable to create speller for lang \"%s\""), + weechat_prefix ("error"), SPELL_PLUGIN_NAME, + lang); + return NULL; + } +#else + /* create a speller instance for the newly created cell */ + config = new_aspell_config (); + aspell_config_replace (config, "lang", lang); +#endif /* USE_ENCHANT */ + + /* apply all options */ + infolist = weechat_infolist_get ("option", NULL, "spell.option.*"); + if (infolist) + { + while (weechat_infolist_next (infolist)) + { +#ifdef USE_ENCHANT + /* TODO: set option with enchant */ +#else + aspell_config_replace (config, + weechat_infolist_string (infolist, "option_name"), + weechat_infolist_string (infolist, "value")); +#endif /* USE_ENCHANT */ + } + weechat_infolist_free (infolist); + } + +#ifndef USE_ENCHANT + ret = new_aspell_speller (config); + + if (aspell_error (ret) != 0) + { + weechat_printf (NULL, + "%s%s: error: %s", + weechat_prefix ("error"), SPELL_PLUGIN_NAME, + aspell_error_message (ret)); + delete_aspell_config (config); + delete_aspell_can_have_error (ret); + return NULL; + } + + new_speller = to_aspell_speller (ret); +#endif /* USE_ENCHANT */ + + weechat_hashtable_set (spell_spellers, lang, new_speller); + +#ifndef USE_ENCHANT + /* free configuration */ + delete_aspell_config (config); +#endif /* USE_ENCHANT */ + + return new_speller; +} + +/* + * Creates hashtable entries with a string containing a list of dicts. + */ + +void +spell_speller_add_dicts_to_hash (struct t_hashtable *hashtable, + const char *dict) +{ + char **dicts; + int num_dicts, i; + + if (!dict || !dict[0]) + return; + + dicts = weechat_string_split (dict, ",", 0, 0, &num_dicts); + if (dicts) + { + for (i = 0; i < num_dicts; i++) + { + weechat_hashtable_set (hashtable, dicts[i], NULL); + } + weechat_string_free_split (dicts); + } +} + +/* + * Removes a speller if it is NOT in hashtable "used_spellers". + */ + +void +spell_speller_remove_unused_cb (void *data, + struct t_hashtable *hashtable, + const void *key, const void *value) +{ + struct t_hashtable *used_spellers; + + /* make C compiler happy */ + (void) value; + + used_spellers = (struct t_hashtable *)data; + + /* if speller is not in "used_spellers", remove it (not used any more) */ + if (!weechat_hashtable_has_key (used_spellers, key)) + weechat_hashtable_remove (hashtable, key); +} + +/* + * Removes unused spellers from hashtable "spell_spellers". + */ + +void +spell_speller_remove_unused () +{ + struct t_hashtable *used_spellers; + struct t_infolist *infolist; + + if (weechat_spell_plugin->debug) + { + weechat_printf (NULL, + "%s: removing unused spellers", + SPELL_PLUGIN_NAME); + } + + /* create a hashtable that will contain all used spellers */ + used_spellers = weechat_hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + if (!used_spellers) + return; + + /* collect used spellers and store them in hashtable "used_spellers" */ + spell_speller_add_dicts_to_hash (used_spellers, + weechat_config_string (spell_config_check_default_dict)); + infolist = weechat_infolist_get ("option", NULL, "spell.dict.*"); + if (infolist) + { + while (weechat_infolist_next (infolist)) + { + spell_speller_add_dicts_to_hash (used_spellers, + weechat_infolist_string (infolist, "value")); + } + weechat_infolist_free (infolist); + } + + /* + * look at current spellers, and remove spellers that are not in hashtable + * "used_spellers" + */ + weechat_hashtable_map (spell_spellers, + &spell_speller_remove_unused_cb, + used_spellers); + + weechat_hashtable_free (used_spellers); +} + +/* + * Callback called when a key is removed in hashtable "spell_spellers". + */ + +void +spell_speller_free_value_cb (struct t_hashtable *hashtable, + const void *key, void *value) +{ +#ifdef USE_ENCHANT + EnchantDict *ptr_speller; +#else + AspellSpeller *ptr_speller; +#endif /* USE_ENCHANT */ + + /* make C compiler happy */ + (void) hashtable; + + if (weechat_spell_plugin->debug) + { + weechat_printf (NULL, + "%s: removing speller for lang \"%s\"", + SPELL_PLUGIN_NAME, (const char *)key); + } + + /* free speller */ +#ifdef USE_ENCHANT + ptr_speller = (EnchantDict *)value; + enchant_broker_free_dict (broker, ptr_speller); +#else + ptr_speller = (AspellSpeller *)value; + aspell_speller_save_all_word_lists (ptr_speller); + delete_aspell_speller (ptr_speller); +#endif /* USE_ENCHANT */ +} + +/* + * Creates a structure for buffer speller info in hashtable + * "spell_buffer_spellers". + */ + +struct t_spell_speller_buffer * +spell_speller_buffer_new (struct t_gui_buffer *buffer) +{ + const char *buffer_dicts; + char **dicts; + int num_dicts, i; + struct t_spell_speller_buffer *new_speller_buffer; +#ifdef USE_ENCHANT + EnchantDict *ptr_speller; +#else + AspellSpeller *ptr_speller; +#endif /* USE_ENCHANT */ + + if (!buffer) + return NULL; + + weechat_hashtable_remove (spell_speller_buffer, buffer); + + new_speller_buffer = malloc (sizeof (*new_speller_buffer)); + if (!new_speller_buffer) + return NULL; + + new_speller_buffer->spellers = NULL; + new_speller_buffer->modifier_string = NULL; + new_speller_buffer->input_pos = -1; + new_speller_buffer->modifier_result = NULL; + + buffer_dicts = spell_get_dict (buffer); + if (buffer_dicts) + { + dicts = weechat_string_split (buffer_dicts, ",", 0, 0, &num_dicts); + if (dicts && (num_dicts > 0)) + { + new_speller_buffer->spellers = +#ifdef USE_ENCHANT + malloc ((num_dicts + 1) * sizeof (EnchantDict *)); +#else + malloc ((num_dicts + 1) * sizeof (AspellSpeller *)); +#endif /* USE_ENCHANT */ + if (new_speller_buffer->spellers) + { + for (i = 0; i < num_dicts; i++) + { + ptr_speller = weechat_hashtable_get (spell_spellers, + dicts[i]); + if (!ptr_speller) + ptr_speller = spell_speller_new (dicts[i]); + new_speller_buffer->spellers[i] = ptr_speller; + } + new_speller_buffer->spellers[num_dicts] = NULL; + } + } + if (dicts) + weechat_string_free_split (dicts); + } + + weechat_hashtable_set (spell_speller_buffer, + buffer, + new_speller_buffer); + + weechat_bar_item_update ("spell_dict"); + + return new_speller_buffer; +} + +/* + * Callback called when a key is removed in hashtable + * "spell_speller_buffer". + */ + +void +spell_speller_buffer_free_value_cb (struct t_hashtable *hashtable, + const void *key, void *value) +{ + struct t_spell_speller_buffer *ptr_speller_buffer; + + /* make C compiler happy */ + (void) hashtable; + (void) key; + + ptr_speller_buffer = (struct t_spell_speller_buffer *)value; + + if (ptr_speller_buffer->spellers) + free (ptr_speller_buffer->spellers); + if (ptr_speller_buffer->modifier_string) + free (ptr_speller_buffer->modifier_string); + if (ptr_speller_buffer->modifier_result) + free (ptr_speller_buffer->modifier_result); + + free (ptr_speller_buffer); +} + +/* + * Initializes spellers (creates hashtables). + * + * Returns: + * 1: OK (hashtables created) + * 0: error (not enough memory) + */ + +int +spell_speller_init () +{ + spell_spellers = weechat_hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + if (!spell_spellers) + return 0; + weechat_hashtable_set_pointer (spell_spellers, + "callback_free_value", + &spell_speller_free_value_cb); + + spell_speller_buffer = weechat_hashtable_new (32, + WEECHAT_HASHTABLE_POINTER, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + if (!spell_speller_buffer) + { + weechat_hashtable_free (spell_spellers); + return 0; + } + weechat_hashtable_set_pointer (spell_speller_buffer, + "callback_free_value", + &spell_speller_buffer_free_value_cb); + + return 1; +} + +/* + * Ends spellers (removes hashtables). + */ + +void +spell_speller_end () +{ + weechat_hashtable_free (spell_spellers); + weechat_hashtable_free (spell_speller_buffer); +} |