diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/aspell/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/plugins/aspell/Makefile.am | 6 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-command.c | 410 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-command.h | 25 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-completion.c | 106 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-completion.h | 25 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-config.c | 40 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-info.c | 89 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-info.h | 25 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-speller.c | 333 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell-speller.h | 25 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell.c | 669 | ||||
-rw-r--r-- | src/plugins/aspell/weechat-aspell.h | 5 |
13 files changed, 1110 insertions, 651 deletions
diff --git a/src/plugins/aspell/CMakeLists.txt b/src/plugins/aspell/CMakeLists.txt index 6b5248ecb..eadb701e1 100644 --- a/src/plugins/aspell/CMakeLists.txt +++ b/src/plugins/aspell/CMakeLists.txt @@ -21,7 +21,10 @@ ADD_LIBRARY(aspell MODULE weechat-aspell.c weechat-aspell.h weechat-aspell-bar-item.c weechat-aspell-bar-item.h +weechat-aspell-command.c weechat-aspell-command.h +weechat-aspell-completion.c weechat-aspell-completion.h weechat-aspell-config.c weechat-aspell-config.h +weechat-aspell-info.c weechat-aspell-info.h weechat-aspell-speller.c weechat-aspell-speller.h) SET_TARGET_PROPERTIES(aspell PROPERTIES PREFIX "") diff --git a/src/plugins/aspell/Makefile.am b/src/plugins/aspell/Makefile.am index 41679833f..c101d05a0 100644 --- a/src/plugins/aspell/Makefile.am +++ b/src/plugins/aspell/Makefile.am @@ -28,8 +28,14 @@ aspell_la_SOURCES = weechat-aspell.c \ weechat-aspell.h \ weechat-aspell-bar-item.c \ weechat-aspell-bar-item.h \ + weechat-aspell-command.c \ + weechat-aspell-command.h \ + weechat-aspell-completion.c \ + weechat-aspell-completion.h \ weechat-aspell-config.c \ weechat-aspell-config.h \ + weechat-aspell-info.c \ + weechat-aspell-info.h \ weechat-aspell-speller.c \ weechat-aspell-speller.h aspell_la_LDFLAGS = -module diff --git a/src/plugins/aspell/weechat-aspell-command.c b/src/plugins/aspell/weechat-aspell-command.c new file mode 100644 index 000000000..9ef908776 --- /dev/null +++ b/src/plugins/aspell/weechat-aspell-command.c @@ -0,0 +1,410 @@ +/* + * weechat-aspell-command.c - aspell commands + * + * Copyright (C) 2013 Sebastien 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 <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "weechat-aspell.h" +#include "weechat-aspell-config.h" +#include "weechat-aspell-speller.h" + + +/* + * Converts an aspell ISO lang code in its English full name. + * + * Note: result must be freed after use. + */ + +char * +weechat_aspell_command_iso_to_lang (const char *code) +{ + int i; + + for (i = 0; aspell_langs[i].code; i++) + { + if (strcmp (aspell_langs[i].code, code) == 0) + return strdup (aspell_langs[i].name); + } + + /* lang code not found */ + return strdup ("Unknown"); +} + +/* + * Converts an aspell ISO country code in its English full name. + * + * Note: result must be freed after use. + */ + +char * +weechat_aspell_command_iso_to_country (const char *code) +{ + int i; + + for (i = 0; aspell_countries[i].code; i++) + { + if (strcmp (aspell_countries[i].code, code) == 0) + return strdup (aspell_countries[i].name); + } + + /* country code not found */ + return strdup ("Unknown"); +} + +/* + * Displays list of aspell dictionaries installed on system. + */ + +void +weechat_aspell_command_speller_list_dicts () +{ + char *country, *lang, *pos; + char str_dict[256], str_country[128]; + struct AspellConfig *config; + AspellDictInfoList *list; + AspellDictInfoEnumeration *elements; + const AspellDictInfo *dict; + + config = new_aspell_config(); + list = get_aspell_dict_info_list (config); + elements = aspell_dict_info_list_elements (list); + + weechat_printf (NULL, ""); + weechat_printf (NULL, + /* TRANSLATORS: "%s" is "aspell" */ + _( "%s dictionaries list:"), + ASPELL_PLUGIN_NAME); + + while ((dict = aspell_dict_info_enumeration_next (elements)) != NULL) + { + country = NULL; + pos = strchr (dict->code, '_'); + + if (pos) + { + pos[0] = '\0'; + lang = weechat_aspell_command_iso_to_lang ((char*)dict->code); + pos[0] = '_'; + country = weechat_aspell_command_iso_to_country (pos + 1); + } + else + lang = weechat_aspell_command_iso_to_lang ((char*)dict->code); + + str_country[0] = '\0'; + if (country || dict->jargon[0]) + { + snprintf (str_country, sizeof (str_country), " (%s%s%s)", + (country) ? country : dict->jargon, + (country && dict->jargon[0]) ? " - " : "", + (country && dict->jargon[0]) ? ((dict->jargon[0]) ? dict->jargon : country) : ""); + } + + snprintf (str_dict, sizeof (str_dict), "%-22s %s%s", + dict->name, lang, str_country); + + weechat_printf (NULL, " %s", str_dict); + + if (lang) + free (lang); + if (country) + free (country); + } + + delete_aspell_dict_info_enumeration (elements); + delete_aspell_config (config); +} + +/* + * Sets a list of dictionaries for a buffer. + */ + +void +weechat_aspell_command_set_dict (struct t_gui_buffer *buffer, const char *value) +{ + char *name; + + name = weechat_aspell_build_option_name (buffer); + if (!name) + return; + + if (weechat_aspell_config_set_dict (name, value) > 0) + { + if (value && value[0]) + weechat_printf (NULL, "%s: \"%s\" => %s", + ASPELL_PLUGIN_NAME, name, value); + else + weechat_printf (NULL, _("%s: \"%s\" removed"), + ASPELL_PLUGIN_NAME, name); + } + + free (name); +} + +/* + * Adds a word in personal dictionary. + */ + +void +weechat_aspell_command_add_word (struct t_gui_buffer *buffer, const char *dict, + const char *word) +{ + struct t_aspell_speller_buffer *ptr_speller_buffer; + AspellSpeller *new_speller, *ptr_speller; + + new_speller = NULL; + + if (dict) + { + ptr_speller = weechat_hashtable_get (weechat_aspell_spellers, dict); + if (!ptr_speller) + { + if (!weechat_aspell_speller_dict_supported (dict)) + { + weechat_printf (NULL, + _("%s: error: dictionary \"%s\" is not " + "available on your system"), + ASPELL_PLUGIN_NAME, dict); + return; + } + new_speller = weechat_aspell_speller_new (dict); + if (!new_speller) + return; + ptr_speller = new_speller; + } + } + else + { + ptr_speller_buffer = weechat_hashtable_get (weechat_aspell_speller_buffer, + buffer); + if (!ptr_speller_buffer) + ptr_speller_buffer = weechat_aspell_speller_buffer_new (buffer); + if (!ptr_speller_buffer) + goto error; + if (!ptr_speller_buffer->spellers || !ptr_speller_buffer->spellers[0]) + { + weechat_printf (NULL, + _("%s%s: no dictionary on this buffer for " + "adding word"), + weechat_prefix ("error"), + ASPELL_PLUGIN_NAME); + return; + } + else if (ptr_speller_buffer->spellers[1]) + { + weechat_printf (NULL, + _("%s%s: many dictionaries are defined for " + "this buffer, please specify dictionary"), + weechat_prefix ("error"), + ASPELL_PLUGIN_NAME); + return; + } + ptr_speller = ptr_speller_buffer->spellers[0]; + } + + if (aspell_speller_add_to_personal (ptr_speller, + word, + strlen (word)) == 1) + { + weechat_printf (NULL, + _("%s: word \"%s\" added to personal dictionary"), + ASPELL_PLUGIN_NAME, word); + } + else + goto error; + + goto end; + +error: + weechat_printf (NULL, + _("%s%s: failed to add word to personal " + "dictionary"), + weechat_prefix ("error"), ASPELL_PLUGIN_NAME); + +end: + if (new_speller) + weechat_hashtable_remove (weechat_aspell_spellers, dict); +} + +/* + * Callback for command "/aspell". + */ + +int +weechat_aspell_command_cb (void *data, struct t_gui_buffer *buffer, + int argc, char **argv, char **argv_eol) +{ + char *dicts; + const char *default_dict; + struct t_infolist *infolist; + int number; + + /* make C compiler happy */ + (void) data; + + if (argc == 1) + { + /* display aspell status */ + weechat_printf (NULL, ""); + weechat_printf (NULL, "%s", + (aspell_enabled) ? + _("Aspell is enabled") : _("Aspell is disabled")); + default_dict = weechat_config_string (weechat_aspell_config_check_default_dict); + weechat_printf (NULL, + _("Default dictionary: %s"), + (default_dict && default_dict[0]) ? + default_dict : _("(not set)")); + number = 0; + infolist = weechat_infolist_get ("option", NULL, "aspell.dict.*"); + if (infolist) + { + while (weechat_infolist_next (infolist)) + { + if (number == 0) + weechat_printf (NULL, _("Specific dictionaries on buffers:")); + number++; + weechat_printf (NULL, " %s: %s", + weechat_infolist_string (infolist, "option_name"), + weechat_infolist_string (infolist, "value")); + } + weechat_infolist_free (infolist); + } + return WEECHAT_RC_OK; + } + + /* enable aspell */ + if (weechat_strcasecmp (argv[1], "enable") == 0) + { + weechat_config_option_set (weechat_aspell_config_check_enabled, "1", 1); + weechat_printf (NULL, _("Aspell enabled")); + return WEECHAT_RC_OK; + } + + /* disable aspell */ + if (weechat_strcasecmp (argv[1], "disable") == 0) + { + weechat_config_option_set (weechat_aspell_config_check_enabled, "0", 1); + weechat_printf (NULL, _("Aspell disabled")); + return WEECHAT_RC_OK; + } + + /* toggle aspell */ + if (weechat_strcasecmp (argv[1], "toggle") == 0) + { + if (aspell_enabled) + { + weechat_config_option_set (weechat_aspell_config_check_enabled, "0", 1); + weechat_printf (NULL, _("Aspell disabled")); + } + else + { + weechat_config_option_set (weechat_aspell_config_check_enabled, "1", 1); + weechat_printf (NULL, _("Aspell enabled")); + } + return WEECHAT_RC_OK; + } + + /* list of dictionaries */ + if (weechat_strcasecmp (argv[1], "listdict") == 0) + { + weechat_aspell_command_speller_list_dicts (); + return WEECHAT_RC_OK; + } + + /* set dictionary for current buffer */ + if (weechat_strcasecmp (argv[1], "setdict") == 0) + { + if (argc > 2) + { + dicts = weechat_string_replace (argv_eol[2], " ", ""); + weechat_aspell_command_set_dict (buffer, + (dicts) ? dicts : argv[2]); + if (dicts) + free (dicts); + } + return WEECHAT_RC_OK; + } + + /* delete dictionary used on current buffer */ + if (weechat_strcasecmp (argv[1], "deldict") == 0) + { + weechat_aspell_command_set_dict (buffer, NULL); + return WEECHAT_RC_OK; + } + + /* add word to personal dictionary */ + if (weechat_strcasecmp (argv[1], "addword") == 0) + { + if (argc > 3) + weechat_aspell_command_add_word (buffer, argv[2], argv_eol[3]); + else + weechat_aspell_command_add_word (buffer, NULL, argv_eol[2]); + return WEECHAT_RC_OK; + } + + return WEECHAT_RC_ERROR; +} + +/* + * Hooks aspell command. + */ + +void +weechat_aspell_command_init () +{ + weechat_hook_command ("aspell", + N_("aspell plugin configuration"), + N_("enable|disable|toggle" + " || listdict" + " || setdict <dict>[,<dict>...]" + " || deldict" + " || addword [<dict>] <word>"), + N_(" enable: enable aspell\n" + " disable: disable aspell\n" + " toggle: toggle aspell\n" + "listdict: show installed dictionaries\n" + " setdict: set dictionary for current buffer " + "(multiple dictionaries can be separated by a " + "comma)\n" + " deldict: delete dictionary used on current " + "buffer\n" + " addword: add a word in personal aspell " + "dictionary\n" + "\n" + "Input line beginning with a '/' is not checked, " + "except for some commands (see /set " + "aspell.check.commands).\n\n" + "To enable aspell on all buffers, use option " + "\"default_dict\", then enable aspell, for " + "example:\n" + " /set aspell.check.default_dict \"en\"\n" + " /aspell enable\n\n" + "Default key to toggle aspell is alt-s."), + "enable" + " || disable" + " || toggle" + " || listdict" + " || setdict %(aspell_dicts)" + " || deldict" + " || addword", + &weechat_aspell_command_cb, NULL); +} diff --git a/src/plugins/aspell/weechat-aspell-command.h b/src/plugins/aspell/weechat-aspell-command.h new file mode 100644 index 000000000..f24bc7790 --- /dev/null +++ b/src/plugins/aspell/weechat-aspell-command.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2013 Sebastien 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef __WEECHAT_ASPELL_COMMAND_H +#define __WEECHAT_ASPELL_COMMAND_H 1 + +extern void weechat_aspell_command_init (); + +#endif /* __WEECHAT_ASPELL_COMMAND_H */ diff --git a/src/plugins/aspell/weechat-aspell-completion.c b/src/plugins/aspell/weechat-aspell-completion.c new file mode 100644 index 000000000..36ccf24f6 --- /dev/null +++ b/src/plugins/aspell/weechat-aspell-completion.c @@ -0,0 +1,106 @@ +/* + * weechat-aspell-completion.c - completion for aspell commands + * + * Copyright (C) 2013 Sebastien 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 <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "weechat-aspell.h" + + +/* + * Adds aspell langs (all langs, even for dictionaries not installed) to + * completion list. + */ + +int +weechat_aspell_completion_langs_cb (void *data, const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + int i; + + /* make C compiler happy */ + (void) data; + (void) completion_item; + (void) buffer; + + for (i = 0; aspell_langs[i].code; i++) + { + weechat_hook_completion_list_add (completion, + aspell_langs[i].code, + 0, WEECHAT_LIST_POS_SORT); + } + + return WEECHAT_RC_OK; +} + +/* + * Adds aspell dictionaries (only installed dictionaries) to completion list. + */ + +int +weechat_aspell_completion_dicts_cb (void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + struct AspellConfig *config; + AspellDictInfoList *list; + AspellDictInfoEnumeration *elements; + const AspellDictInfo *dict; + + /* make C compiler happy */ + (void) data; + (void) completion_item; + (void) buffer; + + 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) + { + weechat_hook_completion_list_add (completion, dict->name, + 0, WEECHAT_LIST_POS_SORT); + } + + delete_aspell_dict_info_enumeration (elements); + delete_aspell_config (config); + + return WEECHAT_RC_OK; +} + +/* + * Hooks completion. + */ + +void +weechat_aspell_completion_init () +{ + weechat_hook_completion ("aspell_langs", + N_("list of all languages supported by aspell"), + &weechat_aspell_completion_langs_cb, NULL); + weechat_hook_completion ("aspell_dicts", + N_("list of aspell installed dictionaries"), + &weechat_aspell_completion_dicts_cb, NULL); +} diff --git a/src/plugins/aspell/weechat-aspell-completion.h b/src/plugins/aspell/weechat-aspell-completion.h new file mode 100644 index 000000000..96010a5aa --- /dev/null +++ b/src/plugins/aspell/weechat-aspell-completion.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2013 Sebastien 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef __WEECHAT_ASPELL_COMPLETION_H +#define __WEECHAT_ASPELL_COMPLETION_H 1 + +extern void weechat_aspell_completion_init (); + +#endif /* __WEECHAT_ASPELL_COMPLETION_H */ diff --git a/src/plugins/aspell/weechat-aspell-config.c b/src/plugins/aspell/weechat-aspell-config.c index c7a6e9a6a..2301f91a5 100644 --- a/src/plugins/aspell/weechat-aspell-config.c +++ b/src/plugins/aspell/weechat-aspell-config.c @@ -33,6 +33,8 @@ struct t_config_file *weechat_aspell_config_file = NULL; struct t_config_section *weechat_aspell_config_section_dict = NULL; +int weechat_aspell_config_loading = 0; + /* aspell config, look section */ struct t_config_option *weechat_aspell_config_look_color; @@ -110,7 +112,9 @@ weechat_aspell_config_change_default_dict (void *data, (void) data; (void) option; - weechat_aspell_create_spellers (weechat_current_buffer ()); + weechat_hashtable_remove_all (weechat_aspell_speller_buffer); + if (!weechat_aspell_config_loading) + weechat_aspell_speller_remove_unused (); } /* @@ -157,7 +161,9 @@ weechat_aspell_config_dict_change (void *data, (void) data; (void) option; - weechat_aspell_create_spellers (weechat_current_buffer ()); + weechat_hashtable_remove_all (weechat_aspell_speller_buffer); + if (!weechat_aspell_config_loading) + weechat_aspell_speller_remove_unused (); } /* @@ -177,7 +183,9 @@ weechat_aspell_config_dict_delete_option (void *data, weechat_config_option_free (option); - weechat_aspell_create_spellers (weechat_current_buffer ()); + weechat_hashtable_remove_all (weechat_aspell_speller_buffer); + if (!weechat_aspell_config_loading) + weechat_aspell_speller_remove_unused (); return WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED; } @@ -211,7 +219,7 @@ weechat_aspell_config_dict_create_option (void *data, if (ptr_option) { if (value && value[0]) - rc = weechat_config_option_set (ptr_option, value, 1); + rc = weechat_config_option_set (ptr_option, value, 0); else { weechat_config_option_free (ptr_option); @@ -246,7 +254,11 @@ weechat_aspell_config_dict_create_option (void *data, option_name, value); } else - weechat_aspell_create_spellers (weechat_current_buffer ()); + { + weechat_hashtable_remove_all (weechat_aspell_speller_buffer); + if (!weechat_aspell_config_loading) + weechat_aspell_speller_remove_unused (); + } return rc; } @@ -263,8 +275,9 @@ weechat_aspell_config_option_change (void *data, (void) data; (void) option; - weechat_aspell_speller_free_all (); - weechat_aspell_create_spellers (weechat_current_buffer ()); + weechat_hashtable_remove_all (weechat_aspell_speller_buffer); + if (!weechat_aspell_config_loading) + weechat_aspell_speller_remove_unused (); } /* @@ -284,8 +297,9 @@ weechat_aspell_config_option_delete_option (void *data, weechat_config_option_free (option); - weechat_aspell_speller_free_all (); - weechat_aspell_create_spellers (weechat_current_buffer ()); + weechat_hashtable_remove_all (weechat_aspell_speller_buffer); + if (!weechat_aspell_config_loading) + weechat_aspell_speller_remove_unused (); return WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED; } @@ -353,8 +367,9 @@ weechat_aspell_config_option_create_option (void *data, } else { - weechat_aspell_speller_free_all (); - weechat_aspell_create_spellers (weechat_current_buffer ()); + weechat_hashtable_remove_all (weechat_aspell_speller_buffer); + if (!weechat_aspell_config_loading) + weechat_aspell_speller_remove_unused (); } return rc; @@ -525,12 +540,15 @@ weechat_aspell_config_read () { int rc; + weechat_aspell_config_loading = 1; rc = weechat_config_read (weechat_aspell_config_file); + weechat_aspell_config_loading = 0; if (rc == WEECHAT_CONFIG_READ_OK) { weechat_aspell_config_change_commands (NULL, weechat_aspell_config_check_commands); } + weechat_aspell_speller_remove_unused (); return rc; } diff --git a/src/plugins/aspell/weechat-aspell-info.c b/src/plugins/aspell/weechat-aspell-info.c new file mode 100644 index 000000000..5b3614aa6 --- /dev/null +++ b/src/plugins/aspell/weechat-aspell-info.c @@ -0,0 +1,89 @@ +/* + * weechat-aspell-info.c - info for aspell plugin + * + * Copyright (C) 2013 Sebastien 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 <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "weechat-aspell.h" + + +/* + * Returns aspell info. + */ + +const char * +weechat_aspell_info_get_info_cb (void *data, const char *info_name, + const char *arguments) +{ + int rc; + long unsigned int value; + struct t_gui_buffer *buffer; + const char *buffer_full_name; + + /* make C compiler happy */ + (void) data; + + if (weechat_strcasecmp (info_name, "aspell_dict") == 0) + { + if (arguments) + { + buffer_full_name = NULL; + if (strncmp (arguments, "0x", 2) == 0) + { + rc = sscanf (arguments, "%lx", &value); + if ((rc != EOF) && (rc != 0)) + { + buffer = (struct t_gui_buffer *)value; + if (buffer) + { + buffer_full_name = weechat_buffer_get_string (buffer, + "full_name"); + } + } + } + else + buffer_full_name = arguments; + + if (buffer_full_name) + return weechat_aspell_get_dict_with_buffer_name (buffer_full_name); + } + return NULL; + } + + return NULL; +} + +/* + * Hooks info for aspell plugin. + */ + +void +weechat_aspell_info_init () +{ + /* info hooks */ + weechat_hook_info ("aspell_dict", + N_("comma-separated list of dictionaries used in buffer"), + N_("buffer pointer (\"0x12345678\") or buffer full name " + "(\"irc.freenode.#weechat\")"), + &weechat_aspell_info_get_info_cb, NULL); +} diff --git a/src/plugins/aspell/weechat-aspell-info.h b/src/plugins/aspell/weechat-aspell-info.h new file mode 100644 index 000000000..aa0bcdf9c --- /dev/null +++ b/src/plugins/aspell/weechat-aspell-info.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2013 Sebastien 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef __WEECHAT_ASPELL_INFO_H +#define __WEECHAT_ASPELL_INFO_H 1 + +extern void weechat_aspell_info_init (); + +#endif /* __WEECHAT_ASPELL_INFO_H */ diff --git a/src/plugins/aspell/weechat-aspell-speller.c b/src/plugins/aspell/weechat-aspell-speller.c index bb12d9745..0b674b4b8 100644 --- a/src/plugins/aspell/weechat-aspell-speller.c +++ b/src/plugins/aspell/weechat-aspell-speller.c @@ -26,22 +26,32 @@ #include "../weechat-plugin.h" #include "weechat-aspell.h" #include "weechat-aspell-speller.h" +#include "weechat-aspell-config.h" -struct t_aspell_speller *weechat_aspell_spellers = NULL; -struct t_aspell_speller *last_weechat_aspell_speller = NULL; +/* + * spellers: one by dictionary (key is name of dictionary (eg: "fr"), value is + * pointer on AspellSpeller) + */ +struct t_hashtable *weechat_aspell_spellers = NULL; + +/* + * spellers by buffer (key is buffer pointer, value is pointer on + * struct t_aspell_speller_buffer) + */ +struct t_hashtable *weechat_aspell_speller_buffer = NULL; /* - * Checks if an aspell dictionary exists for a lang. + * Checks if an aspell dictionary is supported (installed on system). * * Returns: - * 1: aspell dict exists for the lang - * 0: aspell dict does not exist for the lang + * 1: aspell dict is supported + * 0: aspell dict is NOT supported */ int -weechat_aspell_speller_exists (const char *lang) +weechat_aspell_speller_dict_supported (const char *lang) { struct AspellConfig *config; AspellDictInfoList *list; @@ -90,7 +100,7 @@ weechat_aspell_speller_check_dictionaries (const char *dict_list) { for (i = 0; i < argc; i++) { - if (!weechat_aspell_speller_exists (argv[i])) + if (!weechat_aspell_speller_dict_supported (argv[i])) { weechat_printf (NULL, _("%s: warning: dictionary \"%s\" is not " @@ -104,39 +114,17 @@ weechat_aspell_speller_check_dictionaries (const char *dict_list) } /* - * Searches for a speller by lang. - * - * Returns pointer to speller found, NULL if not found. - */ - -struct t_aspell_speller * -weechat_aspell_speller_search (const char *lang) -{ - struct t_aspell_speller *ptr_speller; - - for (ptr_speller = weechat_aspell_spellers; ptr_speller; - ptr_speller = ptr_speller->next_speller) - { - if (strcmp (ptr_speller->lang, lang) == 0) - return ptr_speller; - } - - /* no speller found */ - return NULL; -} - -/* - * Creates and adds a new speller instance. + * Creates and adds a new speller instance in the hashtable. * - * Returns pointer to new speller, NULL if error. + * Returns pointer to new aspell speller, NULL if error. */ -struct t_aspell_speller * +AspellSpeller * weechat_aspell_speller_new (const char *lang) { - struct t_aspell_speller *new_speller; AspellConfig *config; AspellCanHaveError *ret; + AspellSpeller *new_speller; struct t_infolist *infolist; if (!lang) @@ -179,82 +167,269 @@ weechat_aspell_speller_new (const char *lang) return NULL; } - /* create and add a new speller cell */ - new_speller = malloc (sizeof (*new_speller)); - if (!new_speller) + new_speller = to_aspell_speller (ret); + weechat_hashtable_set (weechat_aspell_spellers, lang, new_speller); + + /* free configuration */ + delete_aspell_config (config); + + return new_speller; +} + +void +weechat_aspell_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) { - weechat_printf (NULL, - _("%s%s: not enough memory to create new speller"), - weechat_prefix ("error"), ASPELL_PLUGIN_NAME); - return NULL; + 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". + */ - new_speller->speller = to_aspell_speller (ret); - new_speller->lang = strdup (lang); +void +weechat_aspell_speller_remove_unused_cb (void *data, + struct t_hashtable *hashtable, + const void *key, const void *value) +{ + struct t_hashtable *used_spellers; - /* add speller to list */ - new_speller->prev_speller = last_weechat_aspell_speller; - new_speller->next_speller = NULL; - if (weechat_aspell_spellers) - last_weechat_aspell_speller->next_speller = new_speller; - else - weechat_aspell_spellers = new_speller; - last_weechat_aspell_speller = new_speller; + /* make C compiler happy */ + (void) value; - /* free configuration */ - delete_aspell_config (config); + used_spellers = (struct t_hashtable *)data; - return new_speller; + /* 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 a speller instance. + * Removes unused spellers from hashtable "weechat_aspell_spellers". */ void -weechat_aspell_speller_free (struct t_aspell_speller *speller) +weechat_aspell_speller_remove_unused () { - if (!speller) + struct t_hashtable *used_spellers; + struct t_infolist *infolist; + + if (weechat_aspell_plugin->debug) + { + weechat_printf (NULL, + "%s: removing unused spellers", + ASPELL_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" */ + weechat_aspell_speller_add_dicts_to_hash (used_spellers, + weechat_config_string (weechat_aspell_config_check_default_dict)); + infolist = weechat_infolist_get ("option", NULL, "aspell.dict.*"); + if (infolist) + { + while (weechat_infolist_next (infolist)) + { + weechat_aspell_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 (weechat_aspell_spellers, + &weechat_aspell_speller_remove_unused_cb, + used_spellers); + + weechat_hashtable_free (used_spellers); +} + +/* + * Callback called when a key is removed in hashtable "weechat_aspell_spellers". + */ + +void +weechat_aspell_speller_free_value_cb (struct t_hashtable *hashtable, + const void *key, void *value) +{ + AspellSpeller *ptr_speller; + + /* make C compiler happy */ + (void) hashtable; + if (weechat_aspell_plugin->debug) { weechat_printf (NULL, "%s: removing speller for lang \"%s\"", - ASPELL_PLUGIN_NAME, speller->lang); + ASPELL_PLUGIN_NAME, (const char *)key); } - /* free data */ - if (speller->speller) + /* free aspell data */ + ptr_speller = (AspellSpeller *)value; + aspell_speller_save_all_word_lists (ptr_speller); + delete_aspell_speller (ptr_speller); +} + +/* + * Creates a structure for buffer speller info in hashtable + * "weechat_aspell_buffer_spellers". + */ + +struct t_aspell_speller_buffer * +weechat_aspell_speller_buffer_new (struct t_gui_buffer *buffer) +{ + const char *buffer_dicts; + char **dicts; + int num_dicts, i; + struct t_aspell_speller_buffer *new_speller_buffer; + AspellSpeller *ptr_speller; + + if (!buffer) + return NULL; + + weechat_hashtable_remove (weechat_aspell_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 = weechat_aspell_get_dict (buffer); + if (buffer_dicts) { - aspell_speller_save_all_word_lists (speller->speller); - delete_aspell_speller (speller->speller); + dicts = weechat_string_split (buffer_dicts, ",", 0, 0, &num_dicts); + if (dicts && (num_dicts > 0)) + { + new_speller_buffer->spellers = + malloc ((num_dicts + 1) * sizeof (AspellSpeller *)); + if (new_speller_buffer->spellers) + { + for (i = 0; i < num_dicts; i++) + { + ptr_speller = weechat_hashtable_get (weechat_aspell_spellers, + dicts[i]); + if (!ptr_speller) + ptr_speller = weechat_aspell_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); } - if (speller->lang) - free (speller->lang); - - /* remove speller from list */ - if (speller->prev_speller) - (speller->prev_speller)->next_speller = speller->next_speller; - if (speller->next_speller) - (speller->next_speller)->prev_speller = speller->prev_speller; - if (weechat_aspell_spellers == speller) - weechat_aspell_spellers = speller->next_speller; - if (last_weechat_aspell_speller == speller) - last_weechat_aspell_speller = speller->prev_speller; - - free (speller); + + weechat_hashtable_set (weechat_aspell_speller_buffer, + buffer, + new_speller_buffer); + + weechat_bar_item_update ("aspell_dict"); + + return new_speller_buffer; } /* - * Frees all spellers. + * Callback called when a key is removed in hashtable + * "weechat_aspell_speller_buffer". */ void -weechat_aspell_speller_free_all () +weechat_aspell_speller_buffer_free_value_cb (struct t_hashtable *hashtable, + const void *key, void *value) { - while (weechat_aspell_spellers) + struct t_aspell_speller_buffer *ptr_speller_buffer; + + /* make C compiler happy */ + (void) hashtable; + (void) key; + + ptr_speller_buffer = (struct t_aspell_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 +weechat_aspell_speller_init () +{ + weechat_aspell_spellers = weechat_hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, + NULL); + if (!weechat_aspell_spellers) + return 0; + weechat_hashtable_set_pointer (weechat_aspell_spellers, + "callback_free_value", + &weechat_aspell_speller_free_value_cb); + + weechat_aspell_speller_buffer = weechat_hashtable_new (32, + WEECHAT_HASHTABLE_POINTER, + WEECHAT_HASHTABLE_POINTER, + NULL, + NULL); + if (!weechat_aspell_speller_buffer) { - weechat_aspell_speller_free (weechat_aspell_spellers); + weechat_hashtable_free (weechat_aspell_spellers); + return 0; } + weechat_hashtable_set_pointer (weechat_aspell_speller_buffer, + "callback_free_value", + &weechat_aspell_speller_buffer_free_value_cb); + + return 1; +} + +/* + * Ends spellers (removes hashtables). + */ + +void +weechat_aspell_speller_end () +{ + weechat_hashtable_free (weechat_aspell_spellers); + weechat_hashtable_free (weechat_aspell_speller_buffer); } diff --git a/src/plugins/aspell/weechat-aspell-speller.h b/src/plugins/aspell/weechat-aspell-speller.h index 212be88b0..15c67564a 100644 --- a/src/plugins/aspell/weechat-aspell-speller.h +++ b/src/plugins/aspell/weechat-aspell-speller.h @@ -21,22 +21,23 @@ #ifndef __WEECHAT_ASPELL_SPELLER_H #define __WEECHAT_ASPELL_SPELLER_H 1 -struct t_aspell_speller +struct t_aspell_speller_buffer { - AspellSpeller *speller; /* aspell speller */ - char *lang; /* language */ - - struct t_aspell_speller *prev_speller; /* pointer to next speller */ - struct t_aspell_speller *next_speller; /* pointer to previous speller */ + AspellSpeller **spellers; /* pointer to spellers for buf. */ + char *modifier_string; /* last modifier string */ + int input_pos; /* position of cursor in input */ + char *modifier_result; /* last modifier result */ }; -extern struct t_aspell_speller *weechat_aspell_spellers; +extern struct t_hashtable *weechat_aspell_spellers; +extern struct t_hashtable *weechat_aspell_speller_buffer; -extern int weechat_aspell_speller_exists (const char *lang); -extern struct t_aspell_speller *weechat_aspell_speller_search (const char *lang); +extern int weechat_aspell_speller_dict_supported (const char *lang); extern void weechat_aspell_speller_check_dictionaries (const char *dict_list); -extern struct t_aspell_speller *weechat_aspell_speller_new (const char *lang); -extern void weechat_aspell_speller_free (struct t_aspell_speller *speller); -extern void weechat_aspell_speller_free_all (); +extern AspellSpeller *weechat_aspell_speller_new (const char *lang); +extern void weechat_aspell_speller_remove_unused (); +extern struct t_aspell_speller_buffer *weechat_aspell_speller_buffer_new (struct t_gui_buffer *buffer); +extern int weechat_aspell_speller_init (); +extern void weechat_aspell_speller_end (); #endif /* __WEECHAT_ASPELL_SPELLER_H */ diff --git a/src/plugins/aspell/weechat-aspell.c b/src/plugins/aspell/weechat-aspell.c index 9dd03f3a0..df50ffd92 100644 --- a/src/plugins/aspell/weechat-aspell.c +++ b/src/plugins/aspell/weechat-aspell.c @@ -30,7 +30,10 @@ #include "../weechat-plugin.h" #include "weechat-aspell.h" #include "weechat-aspell-bar-item.h" +#include "weechat-aspell-command.h" +#include "weechat-aspell-completion.h" #include "weechat-aspell-config.h" +#include "weechat-aspell-info.h" #include "weechat-aspell-speller.h" @@ -43,18 +46,13 @@ WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); struct t_weechat_plugin *weechat_aspell_plugin = NULL; int aspell_enabled = 0; -struct t_gui_buffer *aspell_buffer_spellers = NULL; - -char *aspell_last_modifier_string = NULL; /* last str. received by modifier */ -int aspell_last_buffer_input_pos = -1; /* last cursor position */ -char *aspell_last_modifier_result = NULL; /* last str. built by modifier */ /* - * aspell supported langs, updated on 2012-07-05 + * aspell supported languages, updated on 2012-07-05 * URL: ftp://ftp.gnu.org/gnu/aspell/dict/0index.html */ -struct t_aspell_code aspell_langs_avail[] = +struct t_aspell_code aspell_langs[] = { { "af", "Afrikaans" }, { "am", "Amharic" }, @@ -150,7 +148,7 @@ struct t_aspell_code aspell_langs_avail[] = { NULL, NULL} }; -struct t_aspell_code aspell_countries_avail[] = +struct t_aspell_code aspell_countries[] = { { "AT", "Austria" }, { "BR", "Brazil" }, @@ -201,19 +199,18 @@ weechat_aspell_build_option_name (struct t_gui_buffer *buffer) } /* - * Gets dictionary list for a buffer. + * Gets dictionary list for a name of buffer. * * First tries with all arguments, then removes one by one to find dict (from * specific to general dict). */ const char * -weechat_aspell_get_dict (struct t_gui_buffer *buffer) +weechat_aspell_get_dict_with_buffer_name (const char *name) { - char *name, *option_name, *ptr_end; + char *option_name, *ptr_end; struct t_config_option *ptr_option; - name = weechat_aspell_build_option_name (buffer); if (!name) return NULL; @@ -227,7 +224,6 @@ weechat_aspell_get_dict (struct t_gui_buffer *buffer) if (ptr_option) { free (option_name); - free (name); return weechat_config_string (ptr_option); } ptr_end--; @@ -241,297 +237,44 @@ weechat_aspell_get_dict (struct t_gui_buffer *buffer) ptr_option = weechat_aspell_config_get_dict (option_name); free (option_name); - free (name); if (ptr_option) return weechat_config_string (ptr_option); } - else - free (name); /* nothing found => return default dictionary (if set) */ if (weechat_config_string (weechat_aspell_config_check_default_dict) && weechat_config_string (weechat_aspell_config_check_default_dict)[0]) + { return weechat_config_string (weechat_aspell_config_check_default_dict); + } /* no default dictionary set */ return NULL; } /* - * Sets a list of dictionaries for a buffer. + * Gets dictionary list for a buffer. + * + * First tries with all arguments, then removes one by one to find dict (from + * specific to general dict). */ -void -weechat_aspell_set_dict (struct t_gui_buffer *buffer, const char *value) +const char * +weechat_aspell_get_dict (struct t_gui_buffer *buffer) { char *name; + const char *dict; name = weechat_aspell_build_option_name (buffer); if (!name) - return; + return NULL; - if (weechat_aspell_config_set_dict (name, value) > 0) - { - if (value && value[0]) - weechat_printf (NULL, "%s: \"%s\" => %s", - ASPELL_PLUGIN_NAME, name, value); - else - weechat_printf (NULL, _("%s: \"%s\" removed"), - ASPELL_PLUGIN_NAME, name); - } + dict = weechat_aspell_get_dict_with_buffer_name (name); free (name); -} - -/* - * Checks if current spellers are already OK. - * - * Returns: - * 1: already OK - * 0: spellers must be changed - */ - -int -weechat_aspell_spellers_already_ok (const char *dict_list) -{ - char **argv; - int argc, rc, i; - struct t_aspell_speller *ptr_speller; - - if (!dict_list && !weechat_aspell_spellers) - return 1; - - if (!dict_list || !weechat_aspell_spellers) - return 0; - - rc = 1; - - argv = weechat_string_split (dict_list, ",", 0, 0, &argc); - if (argv) - { - ptr_speller = weechat_aspell_spellers; - for (i = 0; i < argc; i++) - { - if (!ptr_speller) - { - rc = 0; - break; - } - if (strcmp (ptr_speller->lang, argv[i]) != 0) - { - rc = 0; - break; - } - ptr_speller = ptr_speller->next_speller; - } - if (ptr_speller) - rc = 0; - weechat_string_free_split (argv); - } - - return rc; -} - -/* - * Creates spellers for a buffer. - */ - -void -weechat_aspell_create_spellers (struct t_gui_buffer *buffer) -{ - const char *dict_list; - char **argv; - int argc, i; - - if (!buffer) - return; - - dict_list = weechat_aspell_get_dict (buffer); - if (!weechat_aspell_spellers_already_ok (dict_list)) - { - weechat_aspell_speller_free_all (); - if (dict_list) - { - argv = weechat_string_split (dict_list, ",", 0, 0, &argc); - if (argv) - { - for (i = 0; i < argc; i++) - { - weechat_aspell_speller_new (argv[i]); - } - weechat_string_free_split (argv); - } - } - weechat_bar_item_update ("aspell_dict"); - } -} - -/* - * Converts an aspell ISO lang code in its English full name. - * - * Note: result must be freed after use. - */ - -char * -weechat_aspell_iso_to_lang (const char *code) -{ - int i; - - for (i = 0; aspell_langs_avail[i].code; i++) - { - if (strcmp (aspell_langs_avail[i].code, code) == 0) - return strdup (aspell_langs_avail[i].name); - } - - /* lang code not found */ - return strdup ("Unknown"); -} - -/* - * Converts an aspell ISO country code in its English full name. - * - * Note: result must be freed after use. - */ - -char * -weechat_aspell_iso_to_country (const char *code) -{ - int i; - - for (i = 0; aspell_countries_avail[i].code; i++) - { - if (strcmp (aspell_countries_avail[i].code, code) == 0) - return strdup (aspell_countries_avail[i].name); - } - - /* country code not found */ - return strdup ("Unknown"); -} - -/* - * Displays list of aspell dictionaries installed on system. - */ - -void -weechat_aspell_speller_list_dicts () -{ - char *country, *lang, *pos; - char buffer[192]; - struct AspellConfig *config; - AspellDictInfoList *list; - AspellDictInfoEnumeration *elements; - const AspellDictInfo *dict; - - config = new_aspell_config(); - list = get_aspell_dict_info_list (config); - elements = aspell_dict_info_list_elements (list); - - weechat_printf (NULL, ""); - weechat_printf (NULL, - /* TRANSLATORS: "%s" is "aspell" */ - _( "%s dictionaries list:"), - ASPELL_PLUGIN_NAME); - - while ((dict = aspell_dict_info_enumeration_next (elements)) != NULL) - { - country = NULL; - pos = strchr (dict->code, '_'); - - if (pos) - { - pos[0] = '\0'; - lang = weechat_aspell_iso_to_lang ((char*)dict->code); - pos[0] = '_'; - country = weechat_aspell_iso_to_country (pos + 1); - } - else - lang = weechat_aspell_iso_to_lang ((char*)dict->code); - - if (strlen (dict->jargon) == 0) - { - if (pos) - { - snprintf (buffer, sizeof (buffer), "%-22s %s (%s)", - dict->name, lang, country); - } - else - { - snprintf (buffer, sizeof (buffer), "%-22s %s", - dict->name, lang); - } - } - else - { - if (pos) - { - snprintf (buffer, sizeof (buffer), "%-22s %s (%s - %s)", - dict->name, lang, country, dict->jargon); - } - else - { - snprintf (buffer, sizeof (buffer), "%-22s %s (%s)", - dict->name, lang, dict->jargon); - } - } - - weechat_printf (NULL, " %s", buffer); - - if (lang) - free (lang); - if (country) - free (country); - } - delete_aspell_dict_info_enumeration (elements); - delete_aspell_config (config); -} - -/* - * Adds a word in personal dictionary. - */ - -void -weechat_aspell_add_word (const char *lang, const char *word) -{ - struct t_aspell_speller *new_speller, *ptr_speller; - - new_speller = NULL; - ptr_speller = weechat_aspell_speller_search (lang); - if (!ptr_speller) - { - if (!weechat_aspell_speller_exists (lang)) - { - weechat_printf (NULL, - _("%s: error: dictionary \"%s\" is not " - "available on your system"), - ASPELL_PLUGIN_NAME, lang); - return; - } - new_speller = weechat_aspell_speller_new (lang); - if (!new_speller) - return; - ptr_speller = new_speller; - } - - if (aspell_speller_add_to_personal (ptr_speller->speller, - word, - strlen (word)) == 1) - { - weechat_printf (NULL, - _("%s: word \"%s\" added to personal dictionary"), - ASPELL_PLUGIN_NAME, word); - } - else - { - weechat_printf (NULL, - _("%s%s: failed to add word to personal " - "dictionary"), - weechat_prefix ("error"), ASPELL_PLUGIN_NAME); - } - - if (new_speller) - weechat_aspell_speller_free (new_speller); + return dict; } /* @@ -628,10 +371,12 @@ weechat_aspell_string_is_simili_number (const char *word) */ int -weechat_aspell_check_word (struct t_gui_buffer *buffer, const char *word) +weechat_aspell_check_word (struct t_gui_buffer *buffer, + struct t_aspell_speller_buffer *speller_buffer, + const char *word) { const char *buffer_type, *buffer_nick, *buffer_channel; - struct t_aspell_speller *ptr_speller; + int i; /* word too small? then do not check word */ if ((weechat_config_integer (weechat_aspell_config_check_word_min_length) > 0) @@ -661,12 +406,12 @@ weechat_aspell_check_word (struct t_gui_buffer *buffer, const char *word) } /* check word with all spellers for this buffer (order is important) */ - for (ptr_speller = weechat_aspell_spellers; ptr_speller; - ptr_speller = ptr_speller->next_speller) + if (speller_buffer->spellers) { - if (aspell_speller_check (ptr_speller->speller, word, -1) == 1) + for (i = 0; speller_buffer->spellers[i]; i++) { - return 1; + if (aspell_speller_check (speller_buffer->spellers[i], word, -1) == 1) + return 1; } } @@ -683,10 +428,10 @@ weechat_aspell_check_word (struct t_gui_buffer *buffer, const char *word) */ char * -weechat_aspell_get_suggestions (const char *word) +weechat_aspell_get_suggestions (struct t_aspell_speller_buffer *speller_buffer, + const char *word) { - struct t_aspell_speller *ptr_speller; - int size, max_suggestions, num_suggestions; + int i, size, max_suggestions, num_suggestions; char *suggestions, *suggestions2; const char *ptr_word; const AspellWordList *list; @@ -702,33 +447,35 @@ weechat_aspell_get_suggestions (const char *word) return NULL; suggestions[0] = '\0'; - for (ptr_speller = weechat_aspell_spellers; ptr_speller; - ptr_speller = ptr_speller->next_speller) + if (speller_buffer->spellers) { - list = aspell_speller_suggest (ptr_speller->speller, word, -1); - if (list) + for (i = 0; speller_buffer->spellers[i]; i++) { - elements = aspell_word_list_elements (list); - num_suggestions = 0; - while ((ptr_word = aspell_string_enumeration_next (elements)) != NULL) + list = aspell_speller_suggest (speller_buffer->spellers[i], word, -1); + if (list) { - size += strlen (ptr_word) + ((suggestions[0]) ? 1 : 0); - suggestions2 = realloc (suggestions, size); - if (!suggestions2) + elements = aspell_word_list_elements (list); + num_suggestions = 0; + while ((ptr_word = aspell_string_enumeration_next (elements)) != NULL) { - free (suggestions); - delete_aspell_string_enumeration (elements); - return NULL; + size += strlen (ptr_word) + ((suggestions[0]) ? 1 : 0); + suggestions2 = realloc (suggestions, size); + if (!suggestions2) + { + free (suggestions); + delete_aspell_string_enumeration (elements); + return NULL; + } + suggestions = suggestions2; + if (suggestions[0]) + strcat (suggestions, (num_suggestions == 0) ? "/" : ","); + strcat (suggestions, ptr_word); + num_suggestions++; + if ((max_suggestions >= 0) && (num_suggestions == max_suggestions)) + break; } - suggestions = suggestions2; - if (suggestions[0]) - strcat (suggestions, (num_suggestions == 0) ? "/" : ","); - strcat (suggestions, ptr_word); - num_suggestions++; - if ((max_suggestions >= 0) && (num_suggestions == max_suggestions)) - break; + delete_aspell_string_enumeration (elements); } - delete_aspell_string_enumeration (elements); } } @@ -752,11 +499,12 @@ weechat_aspell_modifier_cb (void *data, const char *modifier, { long unsigned int value; struct t_gui_buffer *buffer; + struct t_aspell_speller_buffer *ptr_speller_buffer; char *result, *ptr_string, *pos_space, *ptr_end, save_end; char *word_for_suggestions, *old_suggestions, *suggestions; char *word_and_suggestions; const char *color_normal, *color_error, *ptr_suggestions; - int buffer_has_changed, utf8_char_int, char_size; + int utf8_char_int, char_size; int length, index_result, length_word, word_ok; int length_color_normal, length_color_error, rc; int input_pos, current_pos, word_start_pos, word_end_pos; @@ -777,54 +525,54 @@ weechat_aspell_modifier_cb (void *data, const char *modifier, buffer = (struct t_gui_buffer *)value; - buffer_has_changed = 0; - if (buffer != aspell_buffer_spellers) - { - weechat_aspell_create_spellers (buffer); - aspell_buffer_spellers = buffer; - buffer_has_changed = 1; - } - - if (!weechat_aspell_spellers) - return NULL; - - /* check text search only if option is enabled */ + /* check text during search only if option is enabled */ if (weechat_buffer_get_integer (buffer, "text_search") && !weechat_config_boolean (weechat_aspell_config_check_during_search)) return NULL; + /* get structure with speller info for buffer */ + ptr_speller_buffer = weechat_hashtable_get (weechat_aspell_speller_buffer, + buffer); + if (!ptr_speller_buffer) + { + ptr_speller_buffer = weechat_aspell_speller_buffer_new (buffer); + if (!ptr_speller_buffer) + return NULL; + } + if (!ptr_speller_buffer->spellers) + return NULL; + /* * for performance: return last string built if input string is the - * same and cursor position is the same (only if suggestions are enabled) + * same (and cursor position is the same, if suggestions are enabled) */ input_pos = weechat_buffer_get_integer (buffer, "input_pos"); - if (!buffer_has_changed - && aspell_last_modifier_string - && (strcmp (string, aspell_last_modifier_string) == 0) + if (ptr_speller_buffer->modifier_string + && (strcmp (string, ptr_speller_buffer->modifier_string) == 0) && ((weechat_config_integer (weechat_aspell_config_check_suggestions) < 0) - || (input_pos == aspell_last_buffer_input_pos))) + || (input_pos == ptr_speller_buffer->input_pos))) { - return (aspell_last_modifier_result) ? - strdup (aspell_last_modifier_result) : NULL; + return (ptr_speller_buffer->modifier_result) ? + strdup (ptr_speller_buffer->modifier_result) : NULL; } /* free last modifier string and result */ - if (aspell_last_modifier_string) + if (ptr_speller_buffer->modifier_string) { - free (aspell_last_modifier_string); - aspell_last_modifier_string = NULL; + free (ptr_speller_buffer->modifier_string); + ptr_speller_buffer->modifier_string = NULL; } - if (aspell_last_modifier_result) + if (ptr_speller_buffer->modifier_result) { - free (aspell_last_modifier_result); - aspell_last_modifier_result = NULL; + free (ptr_speller_buffer->modifier_result); + ptr_speller_buffer->modifier_result = NULL; } word_for_suggestions = NULL; /* save last modifier string received */ - aspell_last_modifier_string = strdup (string); - aspell_last_buffer_input_pos = input_pos; + ptr_speller_buffer->modifier_string = strdup (string); + ptr_speller_buffer->input_pos = input_pos; color_normal = weechat_color ("bar_fg"); length_color_normal = strlen (color_normal); @@ -838,7 +586,7 @@ weechat_aspell_modifier_cb (void *data, const char *modifier, { result[0] = '\0'; - ptr_string = aspell_last_modifier_string; + ptr_string = ptr_speller_buffer->modifier_string; index_result = 0; /* check if string is a command */ @@ -865,7 +613,9 @@ weechat_aspell_modifier_cb (void *data, const char *modifier, free (result); return NULL; } - memcpy (result + index_result, aspell_last_modifier_string, char_size); + memcpy (result + index_result, + ptr_speller_buffer->modifier_string, + char_size); index_result += char_size; strcpy (result + index_result, ptr_string); index_result += strlen (ptr_string); @@ -939,7 +689,9 @@ weechat_aspell_modifier_cb (void *data, const char *modifier, if ((save_end != '\0') || (weechat_config_integer (weechat_aspell_config_check_real_time))) { - word_ok = weechat_aspell_check_word (buffer, ptr_string); + word_ok = weechat_aspell_check_word (buffer, + ptr_speller_buffer, + ptr_string); if (!word_ok && (input_pos >= word_start_pos)) { /* @@ -992,7 +744,8 @@ weechat_aspell_modifier_cb (void *data, const char *modifier, /* if there is a misspelled word, get suggestions and set them in buffer */ if (word_for_suggestions) { - suggestions = weechat_aspell_get_suggestions (word_for_suggestions); + suggestions = weechat_aspell_get_suggestions (ptr_speller_buffer, + word_for_suggestions); if (suggestions) { length = strlen (word_for_suggestions) + 1 /* ":" */ @@ -1044,182 +797,38 @@ weechat_aspell_modifier_cb (void *data, const char *modifier, if (!result) return NULL; - aspell_last_modifier_result = strdup (result); + ptr_speller_buffer->modifier_result = strdup (result); return result; } /* - * Callback for command "/aspell". - */ - -int -weechat_aspell_command_cb (void *data, struct t_gui_buffer *buffer, - int argc, char **argv, char **argv_eol) -{ - char *dicts; - const char *default_dict; - struct t_infolist *infolist; - int number; - - /* make C compiler happy */ - (void) data; - - if (argc == 1) - { - /* display aspell status */ - weechat_printf (NULL, ""); - weechat_printf (NULL, "%s", - (aspell_enabled) ? - _("Aspell is enabled") : _("Aspell is disabled")); - default_dict = weechat_config_string (weechat_aspell_config_check_default_dict); - weechat_printf (NULL, - _("Default dictionary: %s"), - (default_dict && default_dict[0]) ? - default_dict : _("(not set)")); - number = 0; - infolist = weechat_infolist_get ("option", NULL, "aspell.dict.*"); - if (infolist) - { - while (weechat_infolist_next (infolist)) - { - if (number == 0) - weechat_printf (NULL, _("Specific dictionaries on buffers:")); - number++; - weechat_printf (NULL, " %s: %s", - weechat_infolist_string (infolist, "option_name"), - weechat_infolist_string (infolist, "value")); - } - weechat_infolist_free (infolist); - } - return WEECHAT_RC_OK; - } - - /* enable aspell */ - if (weechat_strcasecmp (argv[1], "enable") == 0) - { - weechat_config_option_set (weechat_aspell_config_check_enabled, "1", 1); - weechat_printf (NULL, _("Aspell enabled")); - return WEECHAT_RC_OK; - } - - /* disable aspell */ - if (weechat_strcasecmp (argv[1], "disable") == 0) - { - weechat_config_option_set (weechat_aspell_config_check_enabled, "0", 1); - weechat_printf (NULL, _("Aspell disabled")); - return WEECHAT_RC_OK; - } - - /* toggle aspell */ - if (weechat_strcasecmp (argv[1], "toggle") == 0) - { - if (aspell_enabled) - { - weechat_config_option_set (weechat_aspell_config_check_enabled, "0", 1); - weechat_printf (NULL, _("Aspell disabled")); - } - else - { - weechat_config_option_set (weechat_aspell_config_check_enabled, "1", 1); - weechat_printf (NULL, _("Aspell enabled")); - } - return WEECHAT_RC_OK; - } - - /* list of dictionaries */ - if (weechat_strcasecmp (argv[1], "listdict") == 0) - { - weechat_aspell_speller_list_dicts (); - return WEECHAT_RC_OK; - } - - /* set dictionary for current buffer */ - if (weechat_strcasecmp (argv[1], "setdict") == 0) - { - if (argc > 2) - { - dicts = weechat_string_replace (argv_eol[2], " ", ""); - weechat_aspell_set_dict (buffer, - (dicts) ? dicts : argv[2]); - if (dicts) - free (dicts); - } - return WEECHAT_RC_OK; - } - - /* delete dictionary used on current buffer */ - if (weechat_strcasecmp (argv[1], "deldict") == 0) - { - weechat_aspell_set_dict (buffer, NULL); - return WEECHAT_RC_OK; - } - - /* add word to personal dictionary */ - if (weechat_strcasecmp (argv[1], "addword") == 0) - { - if (argc > 3) - weechat_aspell_add_word (argv[2], argv_eol[3]); - else - { - if (!weechat_aspell_spellers) - { - weechat_printf (NULL, - _("%s%s: no dictionary on this buffer for " - "adding word"), - weechat_prefix ("error"), - ASPELL_PLUGIN_NAME); - } - else if (weechat_aspell_spellers->next_speller) - { - weechat_printf (NULL, - _("%s%s: many dictionaries are defined for " - "this buffer, please specify dictionary"), - weechat_prefix ("error"), - ASPELL_PLUGIN_NAME); - } - else - weechat_aspell_add_word (weechat_aspell_spellers->lang, - argv_eol[2]); - } - return WEECHAT_RC_OK; - } - - return WEECHAT_RC_ERROR; -} - -/* - * Adds aspell langs to completion list. + * Refreshes bar items on signal "buffer_switch". */ int -weechat_aspell_completion_langs_cb (void *data, const char *completion_item, - struct t_gui_buffer *buffer, - struct t_gui_completion *completion) +weechat_aspell_buffer_switch_cb (void *data, const char *signal, + const char *type_data, void *signal_data) { - int i; - /* make C compiler happy */ (void) data; - (void) completion_item; - (void) buffer; + (void) signal; + (void) type_data; + (void) signal_data; - for (i = 0; aspell_langs_avail[i].code; i++) - { - weechat_hook_completion_list_add (completion, - aspell_langs_avail[i].code, - 0, WEECHAT_LIST_POS_SORT); - } + /* refresh bar items (for root bars) */ + weechat_bar_item_update ("aspell_dict"); + weechat_bar_item_update ("aspell_suggest"); return WEECHAT_RC_OK; } /* - * Refreshes bar items on signal "buffer_switch". + * Refreshes bar items on signal "window_switch". */ int -weechat_aspell_buffer_switch_cb (void *data, const char *signal, +weechat_aspell_window_switch_cb (void *data, const char *signal, const char *type_data, void *signal_data) { /* make C compiler happy */ @@ -1236,22 +845,20 @@ weechat_aspell_buffer_switch_cb (void *data, const char *signal, } /* - * Refreshes bar items on signal "window_switch". + * Removes struct for buffer in hashtable "weechat_aspell_speller_buffer" on + * signal "buffer_closed". */ int -weechat_aspell_window_switch_cb (void *data, const char *signal, +weechat_aspell_buffer_closed_cb (void *data, const char *signal, const char *type_data, void *signal_data) { /* make C compiler happy */ (void) data; (void) signal; (void) type_data; - (void) signal_data; - /* refresh bar items (for root bars) */ - weechat_bar_item_update ("aspell_dict"); - weechat_bar_item_update ("aspell_suggest"); + weechat_hashtable_remove (weechat_aspell_speller_buffer, signal_data); return WEECHAT_RC_OK; } @@ -1269,50 +876,18 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) weechat_plugin = plugin; + if (!weechat_aspell_speller_init ()) + return WEECHAT_RC_ERROR; + if (!weechat_aspell_config_init ()) return WEECHAT_RC_ERROR; if (weechat_aspell_config_read () < 0) return WEECHAT_RC_ERROR; - /* command /aspell */ - weechat_hook_command ("aspell", - N_("aspell plugin configuration"), - N_("enable|disable|toggle" - " || listdict" - " || setdict <lang>" - " || deldict" - " || addword [<lang>] <word>"), - N_(" enable: enable aspell\n" - " disable: disable aspell\n" - " toggle: toggle aspell\n" - "listdict: show installed dictionaries\n" - " setdict: set dictionary for current buffer\n" - " deldict: delete dictionary used on current " - "buffer\n" - " addword: add a word in personal aspell " - "dictionary\n" - "\n" - "Input line beginning with a '/' is not checked, " - "except for some commands (see /set " - "aspell.check.commands).\n\n" - "To enable aspell on all buffers, use option " - "\"default_dict\", then enable aspell, for " - "example:\n" - " /set aspell.check.default_dict \"en\"\n" - " /aspell enable\n\n" - "Default key to toggle aspell is alt-s."), - "enable" - " || disable" - " || toggle" - " || listdict" - " || setdict %(aspell_langs)" - " || deldict" - " || addword", - &weechat_aspell_command_cb, NULL); - weechat_hook_completion ("aspell_langs", - N_("list of supported langs for aspell"), - &weechat_aspell_completion_langs_cb, NULL); + weechat_aspell_command_init (); + + weechat_aspell_completion_init (); /* * callback for spell checking input text @@ -1324,10 +899,14 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) weechat_aspell_bar_item_init (); + weechat_aspell_info_init (); + weechat_hook_signal ("buffer_switch", &weechat_aspell_buffer_switch_cb, NULL); weechat_hook_signal ("window_switch", &weechat_aspell_window_switch_cb, NULL); + weechat_hook_signal ("buffer_closed", + &weechat_aspell_buffer_closed_cb, NULL); return WEECHAT_RC_OK; } @@ -1343,15 +922,9 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) (void) plugin; weechat_aspell_config_write (); - - weechat_aspell_speller_free_all (); - - if (aspell_last_modifier_string) - free (aspell_last_modifier_string); - if (aspell_last_modifier_result) - free (aspell_last_modifier_result); - weechat_aspell_config_free (); + weechat_aspell_speller_end (); + return WEECHAT_RC_OK; } diff --git a/src/plugins/aspell/weechat-aspell.h b/src/plugins/aspell/weechat-aspell.h index 072818103..7f26608fd 100644 --- a/src/plugins/aspell/weechat-aspell.h +++ b/src/plugins/aspell/weechat-aspell.h @@ -34,8 +34,11 @@ struct t_aspell_code extern struct t_weechat_plugin *weechat_aspell_plugin; extern int aspell_enabled; +extern struct t_aspell_code aspell_langs[]; +extern struct t_aspell_code aspell_countries[]; -extern void weechat_aspell_create_spellers (struct t_gui_buffer *buffer); +extern char *weechat_aspell_build_option_name (struct t_gui_buffer *buffer); +extern const char *weechat_aspell_get_dict_with_buffer_name (const char *name); extern const char *weechat_aspell_get_dict (struct t_gui_buffer *buffer); #endif /* __WEECHAT_ASPELL_H */ |