summaryrefslogtreecommitdiff
path: root/src/plugins/spell/spell-config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/spell/spell-config.c')
-rw-r--r--src/plugins/spell/spell-config.c676
1 files changed, 676 insertions, 0 deletions
diff --git a/src/plugins/spell/spell-config.c b/src/plugins/spell/spell-config.c
new file mode 100644
index 000000000..cc24efc35
--- /dev/null
+++ b/src/plugins/spell/spell-config.c
@@ -0,0 +1,676 @@
+/*
+ * spell-config.c - spell checker configuration options (file spell.conf)
+ *
+ * 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 <limits.h>
+
+#include "../weechat-plugin.h"
+#include "spell.h"
+#include "spell-config.h"
+#include "spell-speller.h"
+
+
+struct t_config_file *spell_config_file = NULL;
+struct t_config_section *spell_config_section_dict = NULL;
+
+int spell_config_loading = 0;
+
+/* spell config, color section */
+
+struct t_config_option *spell_config_color_misspelled;
+struct t_config_option *spell_config_color_suggestion;
+struct t_config_option *spell_config_color_suggestion_delimiter_dict;
+struct t_config_option *spell_config_color_suggestion_delimiter_word;
+
+/* spell config, check section */
+
+struct t_config_option *spell_config_check_commands;
+struct t_config_option *spell_config_check_default_dict;
+struct t_config_option *spell_config_check_during_search;
+struct t_config_option *spell_config_check_enabled;
+struct t_config_option *spell_config_check_real_time;
+struct t_config_option *spell_config_check_suggestions;
+struct t_config_option *spell_config_check_word_min_length;
+
+/* spell config, look section */
+
+struct t_config_option *spell_config_look_suggestion_delimiter_dict;
+struct t_config_option *spell_config_look_suggestion_delimiter_word;
+
+
+char **spell_commands_to_check = NULL;
+int spell_count_commands_to_check = 0;
+int *spell_length_commands_to_check = NULL;
+
+
+/*
+ * Callback for changes on option "spell.check.commands".
+ */
+
+void
+spell_config_change_commands (const void *pointer, void *data,
+ struct t_config_option *option)
+{
+ const char *value;
+ int i;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+
+ if (spell_commands_to_check)
+ {
+ weechat_string_free_split (spell_commands_to_check);
+ spell_commands_to_check = NULL;
+ spell_count_commands_to_check = 0;
+ }
+
+ if (spell_length_commands_to_check)
+ {
+ free (spell_length_commands_to_check);
+ spell_length_commands_to_check = NULL;
+ }
+
+ value = weechat_config_string (option);
+ if (value && value[0])
+ {
+ spell_commands_to_check = weechat_string_split (value,
+ ",", 0, 0,
+ &spell_count_commands_to_check);
+ if (spell_count_commands_to_check > 0)
+ {
+ spell_length_commands_to_check = malloc (spell_count_commands_to_check *
+ sizeof (int));
+ for (i = 0; i < spell_count_commands_to_check; i++)
+ {
+ spell_length_commands_to_check[i] = strlen (spell_commands_to_check[i]);
+ }
+ }
+ }
+}
+
+/*
+ * Callback for changes on option "spell.check.default_dict".
+ */
+
+void
+spell_config_change_default_dict (const void *pointer, void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) option;
+
+ weechat_hashtable_remove_all (spell_speller_buffer);
+ if (!spell_config_loading)
+ spell_speller_remove_unused ();
+}
+
+/*
+ * Callback for changes on option "spell.check.enabled".
+ */
+
+void
+spell_config_change_enabled (const void *pointer, void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+
+ spell_enabled = weechat_config_boolean (option);
+
+ /* refresh input and spell suggestions */
+ weechat_bar_item_update ("input_text");
+ weechat_bar_item_update ("spell_suggest");
+}
+
+/*
+ * Callback for changes on option "spell.check.suggestions".
+ */
+
+void
+spell_config_change_suggestions (const void *pointer, void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) option;
+
+ weechat_bar_item_update ("spell_suggest");
+}
+
+/*
+ * Callback for changes on a dictionary.
+ */
+
+void
+spell_config_dict_change (const void *pointer, void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) option;
+
+ weechat_hashtable_remove_all (spell_speller_buffer);
+ if (!spell_config_loading)
+ spell_speller_remove_unused ();
+}
+
+/*
+ * Callback called when an option is deleted in section "dict".
+ */
+
+int
+spell_config_dict_delete_option (const void *pointer, void *data,
+ struct t_config_file *config_file,
+ struct t_config_section *section,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) config_file;
+ (void) section;
+
+ weechat_config_option_free (option);
+
+ weechat_hashtable_remove_all (spell_speller_buffer);
+ if (!spell_config_loading)
+ spell_speller_remove_unused ();
+
+ return WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED;
+}
+
+/*
+ * Creates an option in section "dict".
+ */
+
+int
+spell_config_dict_create_option (const void *pointer, void *data,
+ struct t_config_file *config_file,
+ struct t_config_section *section,
+ const char *option_name,
+ const char *value)
+{
+ struct t_config_option *ptr_option;
+ int rc;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+
+ rc = WEECHAT_CONFIG_OPTION_SET_ERROR;
+
+ if (value && value[0])
+ spell_speller_check_dictionaries (value);
+
+ if (option_name)
+ {
+ ptr_option = weechat_config_search_option (config_file, section,
+ option_name);
+ if (ptr_option)
+ {
+ if (value && value[0])
+ rc = weechat_config_option_set (ptr_option, value, 0);
+ else
+ {
+ weechat_config_option_free (ptr_option);
+ rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+ }
+ }
+ else
+ {
+ if (value && value[0])
+ {
+ ptr_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "string",
+ _("comma separated list of dictionaries to use on this buffer"),
+ NULL, 0, 0, "", value, 0,
+ NULL, NULL, NULL,
+ &spell_config_dict_change, NULL, NULL,
+ NULL, NULL, NULL);
+ rc = (ptr_option) ?
+ WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE : WEECHAT_CONFIG_OPTION_SET_ERROR;
+ }
+ else
+ rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+ }
+ }
+
+ if (rc == WEECHAT_CONFIG_OPTION_SET_ERROR)
+ {
+ weechat_printf (NULL,
+ _("%s%s: error creating spell dictionary \"%s\" => \"%s\""),
+ weechat_prefix ("error"), SPELL_PLUGIN_NAME,
+ option_name, value);
+ }
+ else
+ {
+ weechat_hashtable_remove_all (spell_speller_buffer);
+ if (!spell_config_loading)
+ spell_speller_remove_unused ();
+ }
+
+ return rc;
+}
+
+/*
+ * Callback for changes on an spell option.
+ */
+
+void
+spell_config_option_change (const void *pointer, void *data,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) option;
+
+ weechat_hashtable_remove_all (spell_speller_buffer);
+ if (!spell_config_loading)
+ spell_speller_remove_unused ();
+}
+
+/*
+ * Callback called when an option is deleted in section "option".
+ */
+
+int
+spell_config_option_delete_option (const void *pointer, void *data,
+ struct t_config_file *config_file,
+ struct t_config_section *section,
+ struct t_config_option *option)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) config_file;
+ (void) section;
+
+ weechat_config_option_free (option);
+
+ weechat_hashtable_remove_all (spell_speller_buffer);
+ if (!spell_config_loading)
+ spell_speller_remove_unused ();
+
+ return WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED;
+}
+
+/*
+ * Callback called when an option is created in section "option".
+ */
+
+int
+spell_config_option_create_option (const void *pointer, void *data,
+ struct t_config_file *config_file,
+ struct t_config_section *section,
+ const char *option_name,
+ const char *value)
+{
+ struct t_config_option *ptr_option;
+ int rc;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+
+ rc = WEECHAT_CONFIG_OPTION_SET_ERROR;
+
+ if (option_name)
+ {
+ ptr_option = weechat_config_search_option (config_file, section,
+ option_name);
+ if (ptr_option)
+ {
+ if (value && value[0])
+ rc = weechat_config_option_set (ptr_option, value, 1);
+ else
+ {
+ weechat_config_option_free (ptr_option);
+ rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+ }
+ }
+ else
+ {
+ if (value && value[0])
+ {
+ ptr_option = weechat_config_new_option (
+ config_file, section,
+ option_name, "string",
+ _("option for aspell (for list of available options and "
+ "format, run command \"aspell config\" in a shell)"),
+ NULL, 0, 0, "", value, 0,
+ NULL, NULL, NULL,
+ &spell_config_option_change, NULL, NULL,
+ NULL, NULL, NULL);
+ rc = (ptr_option) ?
+ WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE : WEECHAT_CONFIG_OPTION_SET_ERROR;
+ }
+ else
+ rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+ }
+ }
+
+ if (rc == WEECHAT_CONFIG_OPTION_SET_ERROR)
+ {
+ weechat_printf (NULL,
+ _("%s%s: error creating spell option \"%s\" => \"%s\""),
+ weechat_prefix ("error"), SPELL_PLUGIN_NAME,
+ option_name, value);
+ }
+ else
+ {
+ weechat_hashtable_remove_all (spell_speller_buffer);
+ if (!spell_config_loading)
+ spell_speller_remove_unused ();
+ }
+
+ return rc;
+}
+
+/*
+ * Gets a list of dictionaries for a buffer.
+ */
+
+struct t_config_option *
+spell_config_get_dict (const char *name)
+{
+ return weechat_config_search_option (spell_config_file,
+ spell_config_section_dict,
+ name);
+}
+
+/*
+ * Sets a list of dictionaries for a buffer.
+ */
+
+int
+spell_config_set_dict (const char *name, const char *value)
+{
+ return spell_config_dict_create_option (NULL, NULL,
+ spell_config_file,
+ spell_config_section_dict,
+ name,
+ value);
+}
+
+/*
+ * Initializes spell configuration file.
+ *
+ * Returns:
+ * 1: OK
+ * 0: error
+ */
+
+int
+spell_config_init ()
+{
+ struct t_config_section *ptr_section;
+
+ spell_config_file = weechat_config_new (SPELL_CONFIG_NAME,
+ NULL, NULL, NULL);
+ if (!spell_config_file)
+ return 0;
+
+ /* color */
+ ptr_section = weechat_config_new_section (
+ spell_config_file, "color",
+ 0, 0,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (spell_config_file);
+ spell_config_file = NULL;
+ return 0;
+ }
+
+ spell_config_color_misspelled = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "misspelled", "color",
+ N_("text color for misspelled words (input bar)"),
+ NULL, 0, 0, "lightred", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ spell_config_color_suggestion = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "suggestion", "color",
+ N_("text color for suggestion on a misspelled word in bar item "
+ "\"spell_suggest\""),
+ NULL, 0, 0, "default", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ spell_config_color_suggestion_delimiter_dict = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "suggestion_delimiter_dict", "color",
+ N_("text color for delimiters displayed between two dictionaries "
+ "in bar item \"spell_suggest\""),
+ NULL, 0, 0, "cyan", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ spell_config_color_suggestion_delimiter_word = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "suggestion_delimiter_word", "color",
+ N_("text color for delimiters displayed between two words in bar item "
+ "\"spell_suggest\""),
+ NULL, 0, 0, "cyan", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ /* check */
+ ptr_section = weechat_config_new_section (
+ spell_config_file, "check",
+ 0, 0,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (spell_config_file);
+ spell_config_file = NULL;
+ return 0;
+ }
+
+ spell_config_check_commands = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "commands", "string",
+ N_("comma separated list of commands for which spell checking is "
+ "enabled (spell checking is disabled for all other commands)"),
+ NULL, 0, 0,
+ "ame,amsg,away,command,cycle,kick,kickban,me,msg,notice,part,query,"
+ "quit,topic", NULL, 0,
+ NULL, NULL, NULL,
+ &spell_config_change_commands, NULL, NULL,
+ NULL, NULL, NULL);
+ spell_config_check_default_dict = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "default_dict", "string",
+ N_("default dictionary (or comma separated list of dictionaries) to "
+ "use when buffer has no dictionary defined (leave blank to disable "
+ "spell checker on buffers for which you didn't explicitly "
+ "enabled it)"),
+ NULL, 0, 0, "", NULL, 0,
+ NULL, NULL, NULL,
+ &spell_config_change_default_dict, NULL, NULL,
+ NULL, NULL, NULL);
+ spell_config_check_during_search = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "during_search", "boolean",
+ N_("check words during text search in buffer"),
+ NULL, 0, 0, "off", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ spell_config_check_enabled = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "enabled", "boolean",
+ N_("enable spell checker for command line"),
+ NULL, 0, 0, "off", NULL, 0,
+ NULL, NULL, NULL,
+ &spell_config_change_enabled, NULL, NULL,
+ NULL, NULL, NULL);
+ spell_config_check_real_time = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "real_time", "boolean",
+ N_("real-time spell checking of words (slower, disabled by default: "
+ "words are checked only if there's delimiter after)"),
+ NULL, 0, 0, "off", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ spell_config_check_suggestions = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "suggestions", "integer",
+ N_("number of suggestions to display in bar item \"spell_suggest\" "
+ "for each dictionary set in buffer (-1 = disable suggestions, "
+ "0 = display all possible suggestions in all languages)"),
+ NULL, -1, INT_MAX, "-1", NULL, 0,
+ NULL, NULL, NULL,
+ &spell_config_change_suggestions, NULL, NULL,
+ NULL, NULL, NULL);
+ spell_config_check_word_min_length = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "word_min_length", "integer",
+ N_("minimum length for a word to be spell checked (use 0 to check all "
+ "words)"),
+ NULL, 0, INT_MAX, "2", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ /* dict */
+ ptr_section = weechat_config_new_section (
+ spell_config_file, "dict",
+ 1, 1,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ &spell_config_dict_create_option, NULL, NULL,
+ &spell_config_dict_delete_option, NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (spell_config_file);
+ spell_config_file = NULL;
+ return 0;
+ }
+
+ spell_config_section_dict = ptr_section;
+
+ /* look */
+ ptr_section = weechat_config_new_section (
+ spell_config_file, "look",
+ 0, 0,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (spell_config_file);
+ spell_config_file = NULL;
+ return 0;
+ }
+
+ spell_config_look_suggestion_delimiter_dict = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "suggestion_delimiter_dict", "string",
+ N_("delimiter displayed between two dictionaries in bar item "
+ "\"spell_suggest\""),
+ NULL, 0, 0, " / ", NULL, 0,
+ NULL, NULL, NULL,
+ &spell_config_change_suggestions, NULL, NULL,
+ NULL, NULL, NULL);
+ spell_config_look_suggestion_delimiter_word = weechat_config_new_option (
+ spell_config_file, ptr_section,
+ "suggestion_delimiter_word", "string",
+ N_("delimiter displayed between two words in bar item "
+ "\"spell_suggest\""),
+ NULL, 0, 0, ",", NULL, 0,
+ NULL, NULL, NULL,
+ &spell_config_change_suggestions, NULL, NULL,
+ NULL, NULL, NULL);
+
+ /* option */
+ ptr_section = weechat_config_new_section (
+ spell_config_file, "option",
+ 1, 1,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ &spell_config_option_create_option, NULL, NULL,
+ &spell_config_option_delete_option, NULL, NULL);
+ if (!ptr_section)
+ {
+ weechat_config_free (spell_config_file);
+ spell_config_file = NULL;
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Reads spell configuration file.
+ */
+
+int
+spell_config_read ()
+{
+ int rc;
+
+ spell_config_loading = 1;
+ rc = weechat_config_read (spell_config_file);
+ spell_config_loading = 0;
+ if (rc == WEECHAT_CONFIG_READ_OK)
+ spell_config_change_commands (NULL, NULL, spell_config_check_commands);
+ spell_speller_remove_unused ();
+
+ return rc;
+}
+
+/*
+ * Writes spell configuration file.
+ */
+
+int
+spell_config_write ()
+{
+ return weechat_config_write (spell_config_file);
+}
+
+/*
+ * Frees spell configuration.
+ */
+
+void
+spell_config_free ()
+{
+ weechat_config_free (spell_config_file);
+
+ if (spell_commands_to_check)
+ weechat_string_free_split (spell_commands_to_check);
+ if (spell_length_commands_to_check)
+ free (spell_length_commands_to_check);
+}