summaryrefslogtreecommitdiff
path: root/src/plugins/aspell/weechat-aspell.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/aspell/weechat-aspell.c')
-rw-r--r--src/plugins/aspell/weechat-aspell.c1176
1 files changed, 1176 insertions, 0 deletions
diff --git a/src/plugins/aspell/weechat-aspell.c b/src/plugins/aspell/weechat-aspell.c
new file mode 100644
index 000000000..9cba2b1e3
--- /dev/null
+++ b/src/plugins/aspell/weechat-aspell.c
@@ -0,0 +1,1176 @@
+/*
+ * Copyright (c) 2003-2006 by FlashCode <flashcode@flashtux.org>
+ * See README for License detail, AUTHORS for developers list.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* weechat-aspell.c: Aspell plugin support for WeeChat */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <ctype.h>
+
+#include "../weechat-plugin.h"
+#include "weechat-aspell.h"
+
+speller_t *plugin_speller = NULL;
+config_t *plugin_config = NULL;
+options_t plugin_options;
+
+t_weechat_plugin *plugin = NULL;
+
+/*
+ * new_speller : create a new speller cell
+ */
+speller_t *new_speller (void)
+{
+ speller_t *s;
+
+ s = (speller_t *) malloc (sizeof (speller_t));
+ if (!s)
+ {
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [ERROR] : unable to alloc memory.", plugin_name);
+ return NULL;
+ }
+
+ s->speller= NULL;
+ s->lang = NULL;
+ s->refs = 0;
+ s->prev_speller = NULL;
+ s->next_speller = NULL;
+
+ return s;
+}
+
+/*
+ * free_speller : free a speller cell
+ */
+void free_speller (speller_t *s)
+{
+ if (s)
+ {
+ if (s->speller)
+ {
+ aspell_speller_save_all_word_lists (s->speller);
+ delete_aspell_speller (s->speller);
+ }
+ if (s->lang)
+ free(s->lang);
+ free(s);
+ }
+}
+
+/*
+ * speller_list_search : search a speller cell
+ */
+speller_t *speller_list_search (char *lang)
+{
+ speller_t *p, *r = NULL;
+
+ for(p = plugin_speller; p; p = p->next_speller)
+ {
+ if (strcmp(p->lang, lang) == 0)
+ {
+ r = p;
+ break;
+ }
+ }
+
+ return r;
+}
+
+/*
+ * speller_list_add : create and add a new speller instance
+ */
+int speller_list_add (char *lang)
+{
+ speller_t *s;
+ AspellConfig *config;
+ AspellCanHaveError *ret;
+
+ /* create a speller instance for the newly created cell */
+ config = new_aspell_config();
+ aspell_config_replace (config, "lang", lang);
+
+ ret = new_aspell_speller (config);
+
+ if (aspell_error (ret) != 0)
+ {
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [ERROR] : %s",
+ plugin_name, aspell_error_message (ret));
+ delete_aspell_config (config);
+ delete_aspell_can_have_error (ret);
+ return 0;
+ }
+
+ /* create and add a new speller cell */
+ s = new_speller();
+ if (!s)
+ return 0;
+
+ s->next_speller = plugin_speller;
+ if (plugin_speller)
+ plugin_speller->prev_speller = s;
+ plugin_speller = s;
+
+ s->lang = strdup (lang);
+ s->refs = 1;
+ s->speller = to_aspell_speller (ret);
+
+ delete_aspell_config (config);
+
+ return 1;
+}
+
+/*
+ * speller_list_remove : remove a speller instance
+ */
+int speller_list_remove(char *lang)
+{
+ speller_t *p;
+ int r = 0;
+
+ if (!plugin_speller || !lang)
+ return 0;
+
+ if (!plugin_speller->prev_speller
+ && !plugin_speller->next_speller)
+ {
+ free_speller (plugin_speller);
+ plugin_speller = NULL;
+ return 1;
+ }
+
+ for(p = plugin_speller; p; p = p->next_speller)
+ {
+ if (strcmp(p->lang, lang) == 0)
+ {
+ if (p->prev_speller)
+ p->prev_speller->next_speller = p->next_speller;
+ else
+ plugin_speller = p->next_speller;
+
+ if (p->next_speller)
+ p->next_speller->prev_speller = p->prev_speller;
+
+ free_speller (p);
+ r = 1;
+ break;
+ }
+ }
+
+ return r;
+}
+
+/*
+ * new_config : create a new config cell
+ */
+config_t *new_config (void)
+{
+ config_t *c;
+
+ c = (config_t *) malloc (sizeof (config_t));
+ if (!c)
+ {
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [ERROR] : unable to alloc memory.", plugin_name);
+ return NULL;
+ }
+
+ c->server = NULL;
+ c->channel = NULL;
+ c->speller = NULL;
+ c->prev_config = NULL;
+ c->next_config = NULL;
+
+ return c;
+}
+
+/*
+ * free_config : free a config cell
+ */
+void free_config (config_t *c)
+{
+ if (c)
+ {
+ if (c->server)
+ free(c->server);
+ if (c->channel)
+ free(c->channel);
+
+ free(c);
+ }
+}
+
+/*
+ * config_list_search : search a config cell
+ */
+config_t *config_list_search (char *server, char *channel)
+{
+ config_t *p, *r = NULL;
+
+ if (!server || !channel)
+ return NULL;
+
+ for(p = plugin_config; p; p = p->next_config)
+ {
+ if (strcmp(p->server, server) == 0
+ && strcmp(p->channel, channel) == 0)
+ {
+ r = p;
+ break;
+ }
+ }
+
+ return r;
+}
+
+/*
+ * config_list_add : create and add a new config
+ */
+int config_list_add (char *server, char *channel)
+{
+ config_t *c;
+
+ c = new_config();
+ if (!c)
+ return 0;
+
+ c->channel = strdup (channel);
+ c->server = strdup (server);
+
+ c->next_config = plugin_config;
+ if (plugin_config)
+ plugin_config->prev_config = c;
+ plugin_config = c;
+
+ return 1;
+}
+
+/*
+ * config_list_remove : remove a speller config
+ */
+int config_list_remove(char *server, char *channel)
+{
+ config_t *p;
+ int r = 0;
+
+ if (!plugin_config || !server || !channel)
+ return 0;
+
+ if (!plugin_config->prev_config
+ && !plugin_config)
+ {
+ free_config (plugin_config);
+ plugin_config = NULL;
+ return 1;
+ }
+
+ for(p = plugin_config; p; p = p->next_config)
+ {
+ if (strcmp(p->server, server) == 0
+ && strcmp(p->channel, channel) == 0)
+ {
+ if (p->prev_config)
+ p->prev_config->next_config = p->next_config;
+ else
+ plugin_config = p->next_config;
+
+ if (p->next_config)
+ p->next_config->prev_config = p->prev_config;
+ free_config (p);
+ r = 1;
+ break;
+ }
+ }
+
+ return r;
+}
+
+/*
+ * iso_to_lang : convert an aspell iso lang code
+ * in its english full name
+ *
+ */
+char *iso_to_lang (char *code)
+{
+ iso_langs_t *p;
+ char *l;
+
+ l = NULL;
+
+ for(p = langs_avail; p->code; ++p)
+ {
+ if (strcmp(p->code, code) == 0)
+ {
+ l = strdup(p->name);
+ break;
+ }
+ }
+
+ if (!l)
+ l = strdup ("Unknown");
+
+ return l;
+}
+
+
+/*
+ * iso_to_country : convert an aspell iso country
+ * code in its english full name
+ */
+char *iso_to_country (char *code)
+{
+ iso_countries_t *p;
+ char *c;
+
+ c = NULL;
+
+ for(p = countries_avail; p->code; ++p)
+ {
+ if (strcmp(p->code, code) == 0)
+ {
+ c = strdup(p->name);
+ break;
+ }
+ }
+
+ if (!c)
+ c = strdup ("Unknown");
+
+ return c;
+}
+
+/*
+ * speller_exists : return 1 if an aspell dict exists
+ * for a lang, 0 otherwise
+ */
+int speller_exists (char *lang)
+{
+ struct AspellConfig *config;
+ AspellDictInfoList *l;
+ AspellDictInfoEnumeration *el;
+ const AspellDictInfo *di;
+ int r;
+
+ r = 0;
+ config = new_aspell_config();
+ l = get_aspell_dict_info_list (config);
+ el = aspell_dict_info_list_elements (l);
+
+ di = NULL;
+ while (( di = aspell_dict_info_enumeration_next (el)))
+ {
+ if (strcmp(di->name, lang) == 0)
+ {
+ r = 1;
+ break;
+ }
+ }
+
+ delete_aspell_dict_info_enumeration (el);
+ delete_aspell_config (config);
+
+ return r;
+}
+
+/*
+ * speller_list_dicts : list all aspell dict installed on system and display them
+ */
+void speller_list_dicts (void)
+{
+ char *country, *lang, *p;
+ char buffer[192];
+ struct AspellConfig *config;
+ AspellDictInfoList *l;
+ AspellDictInfoEnumeration *el;
+ const AspellDictInfo *di;
+
+ config = new_aspell_config();
+ l = get_aspell_dict_info_list (config);
+ el = aspell_dict_info_list_elements (l);
+ di = NULL;
+
+ plugin->print (plugin, NULL, NULL, "[%s] *** dictionnaries list :", plugin_name);
+
+ while (( di = aspell_dict_info_enumeration_next (el)))
+ {
+ country = NULL;
+ p = strchr (di->code, '_');
+
+ if (p)
+ {
+ *p = '\0';
+ lang = iso_to_lang ((char*) di->code);
+ *p = '_';
+ country = iso_to_country (p+1);
+ }
+ else
+ lang = iso_to_lang ((char*) di->code);
+
+ if (strlen (di->jargon) == 0)
+ {
+ if (p)
+ snprintf (buffer, sizeof(buffer), "%-22s %s (%s)", di->name, lang, country);
+ else
+ snprintf (buffer, sizeof(buffer), "%-22s %s", di->name, lang);
+ }
+ else
+ {
+ if (p)
+ snprintf (buffer, sizeof(buffer), "%-22s %s (%s - %s)", di->name, lang, country, di->jargon);
+ else
+ snprintf (buffer, sizeof(buffer), "%-22s %s (%s)", di->name, lang, di->jargon);
+ }
+
+ plugin->print (plugin, NULL, NULL, "[%s] - %s", plugin_name, buffer);
+
+ if (lang)
+ free (lang);
+ if (country)
+ free (country);
+ }
+
+ delete_aspell_dict_info_enumeration (el);
+ delete_aspell_config (config);
+}
+
+/*
+ * config_show : display plugin settings
+ */
+void config_show (void)
+{
+ config_t *p;
+
+ if (!plugin_config)
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [SHOW] *** No buffers with spellchecking enable",
+ plugin_name);
+ else
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [SHOW] *** Spellchecking is active on the following buffers :",
+ plugin_name);
+
+ for(p = plugin_config; p; p = p->next_config)
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [SHOW] -> %s@%s with lang '%s'",
+ plugin_name, p->channel, p->server, p->speller->lang);
+
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [SHOW] *** plugin options :", plugin_name);
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [SHOW] -> word-size = %d",
+ plugin_name, plugin_options.word_size);
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [SHOW] -> color = %s",
+ plugin_name, plugin_options.color_name);
+ plugin->print (plugin, NULL, NULL,
+ plugin_options.check_sync == 1
+ ? "[%s] [SHOW] -> realtime spellchecking is enable"
+ : "[%s] [SHOW] -> asynchronous spellchecking is enable"
+ ,
+ plugin_name);
+}
+
+/*
+ * config_addword : adding a word in personnal dictionaries
+ */
+int config_addword(char *word)
+{
+ char *server, *channel;
+ config_t *c;
+ int ret;
+
+ ret = 0;
+ channel = plugin->get_info (plugin, "channel", NULL);
+ server = plugin->get_info (plugin, "server", NULL);
+
+ if (!server || !channel)
+ return 0;
+
+ c = config_list_search (server, channel);
+ if (c) {
+ if (aspell_speller_add_to_personal (
+ c->speller->speller, (const char *) word, strlen(word)) == 1)
+ ret = 1;
+ }
+
+ if (ret)
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [ADD-WORD] word '%s' successfully added in your personnal dictionnary",
+ plugin_name, word);
+ else
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [ADD-WORD] an error occured while adding word '%s' in your personnal dict",
+ plugin_name, word);
+
+ if (server)
+ free (server);
+ if (channel)
+ free (channel);
+
+ return ret;
+}
+
+/*
+ * config_dump : display debug infos
+ */
+void config_dump (void)
+{
+ config_t *p;
+ speller_t *s;
+
+ if (!plugin_config)
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [DEBUG] [CONFIG] no config",
+ plugin_name);
+
+ for(p = plugin_config; p; p = p->next_config)
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [DEBUG] [CONFIG] @%p server='%s' channel='%s' @speller=%p lang='%s' @p=%p @n=%p",
+ plugin_name, p, p->server, p->channel, p->speller, p->speller->lang, p->prev_config, p->next_config);
+
+ if (!plugin_speller)
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [DEBUG] [SPELLER] no speller",
+ plugin_name);
+
+ for(s = plugin_speller; s; s = s->next_speller)
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [DEBUG] [SPELLER] @%p lang='%s' refs=%d @engine=%p @p=%p @n=%p",
+ plugin_name, s, s->lang, s->refs, s->speller, s->prev_speller, s->next_speller);
+}
+
+/*
+ * config_enable_for : internal subroutine
+ */
+void config_enable_for (char *server, char *channel, char *lang)
+{
+ config_t *c;
+ speller_t *s;
+
+ if (!speller_exists (lang))
+ {
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [WARN] '%s' dictionary doesn't seems to be available on your system",
+ plugin_name, lang);
+ return;
+ }
+
+ c = config_list_search (server, channel);
+ if (c)
+ {
+ c->speller->refs--;
+ if (c->speller->refs == 0)
+ speller_list_remove (c->speller->lang);
+ config_list_remove (server, channel);
+ }
+
+ if (!config_list_add (server, channel))
+ {
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [ERROR] enabling spell checking on %s@%s failed",
+ plugin_name, channel, server);
+ return;
+ }
+
+ s = speller_list_search (lang);
+
+ if (!s) {
+ speller_list_add (lang);
+ s = plugin_speller;
+ }
+ else
+ s->refs++;
+
+ plugin_config->speller = s;
+
+}
+
+/*
+ * config_enable : enabling given lang spell checking on current server/channel
+ */
+void config_enable (char *lang)
+{
+ char *channel, *server;
+
+ channel = plugin->get_info (plugin, "channel", NULL);
+ server = plugin->get_info (plugin, "server", NULL);
+
+ if (!server || !channel)
+ {
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [WARN] you are not in a channel",
+ plugin_name);
+ return;
+ }
+
+ config_enable_for (server, channel, lang);
+
+ plugin->print (plugin, NULL, NULL,
+ "[%s] spell checking '%s' is now active on %s@%s",
+ plugin_name, lang, channel, server);
+
+ if (channel)
+ free (channel);
+ if (server)
+ free (server);
+}
+
+/*
+ * config_disable : disabling spell checking on current server/channel
+ */
+void config_disable (void)
+{
+ config_t *c;
+ char *channel, *server;
+
+ channel = plugin->get_info (plugin, "channel", NULL);
+ server = plugin->get_info (plugin, "server", NULL);
+
+ if (!server || !channel)
+ {
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [WARN] you are not in a channel",
+ plugin_name, NULL, NULL);
+ return;
+ }
+
+ c = config_list_search (server, channel);
+ if (!c)
+ {
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [WARN] spell checking is not active on %s@%s",
+ plugin_name, channel, server);
+ if (channel)
+ free (channel);
+ if (server)
+ free (server);
+ return;
+ }
+
+ c->speller->refs--;
+ if (c->speller->refs == 0)
+ speller_list_remove (c->speller->lang);
+
+ config_list_remove (server, channel);
+
+ plugin->print (plugin, NULL, NULL,
+ "[%s] spell checking is now inactive on %s@%s",
+ plugin_name, channel, server);
+
+ if (channel)
+ free (channel);
+ if (server)
+ free (server);
+}
+
+/*
+ * config_set : setting options values
+ */
+int config_set(char *option, char *value)
+{
+ int c;
+
+ if (strcmp (option, "word-size") == 0)
+ {
+ plugin_options.word_size = atoi ((value == NULL) ? "" : value);
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [SET] setting %s = %d",
+ plugin_name, option, plugin_options.word_size);
+ }
+ else if (strcmp (option, "toggle-check-mode") == 0)
+ {
+ plugin_options.check_sync = plugin_options.check_sync == 1 ? 0 : 1;
+ plugin->print (plugin, NULL, NULL,
+ plugin_options.check_sync == 1
+ ? "[%s] [SET] spellchecking is now set in realtime mode"
+ : "[%s] [SET] spellchecking is now set in asynchronous mode",
+ plugin_name, option);
+ }
+ else if (strcmp (option, "color") == 0)
+ {
+ c = plugin->get_irc_color (plugin, (value == NULL) ? "" : value);
+ if (c == -1)
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [SET] setting %s = %s failed : color '%s' is unknown",
+ plugin_name, option,
+ (value == NULL) ? "" : value,
+ (value == NULL) ? "" : value);
+ else
+ {
+ plugin_options.color = c;
+ if (plugin_options.color_name)
+ free (plugin_options.color_name);
+ plugin_options.color_name = strdup (value);
+ plugin->print (plugin, NULL, NULL,
+ "[%s] [SET] setting %s = %s",
+ plugin_name, option, plugin_options.color_name);
+ }
+ }
+ else
+ return 0;
+
+ return 1;
+}
+
+/*
+ * config_save : saving plugin config
+ */
+int config_save (void)
+{
+ config_t *p, *q;
+ char *servers, *channels, *option;
+ int n;
+
+ servers = NULL;
+
+ plugin->set_plugin_config (plugin, "servers", "");
+
+ for(p = plugin_config; p; p = p->next_config)
+ {
+ servers = plugin->get_plugin_config (plugin, "servers");
+
+ if (!servers)
+ plugin->set_plugin_config (plugin, "servers", p->server);
+ else if (strlen (servers) == 0)
+ {
+ plugin->set_plugin_config (plugin, "servers", p->server);
+ free (servers);
+ }
+ else
+ {
+ if (!strstr (servers, p->server))
+ {
+ n = strlen (servers) + strlen (p->server) + 2;
+ servers = (char *) realloc (servers, n * sizeof (char));
+ strcat (servers, " ");
+ strcat (servers, p->server);
+ plugin->set_plugin_config (plugin, "servers", servers);
+ }
+ free (servers);
+ }
+
+ channels = NULL;
+ for(q = plugin_config; q; q = q->next_config)
+ {
+ if (strcmp (p->server, q->server) == 0)
+ {
+ if (!channels)
+ channels = strdup (q->channel);
+ else
+ {
+ if (!strstr (channels, q->channel))
+ {
+ n = strlen (channels) + strlen (q->channel) + 2;
+ channels = (char *) realloc (channels, n * sizeof (char));
+ strcat (channels, " ");
+ strcat (channels, q->channel);
+ }
+ }
+
+ n = 7 + strlen (p->server) + strlen (q->channel);
+ option = (char *) malloc ( n * sizeof (char));
+ snprintf (option, n, "lang_%s_%s", p->server, q->channel);
+ plugin->set_plugin_config (plugin, option, q->speller->lang);
+ free (option);
+ }
+ }
+
+ if (channels)
+ {
+ n = 10 + strlen (p->server);
+ option = (char *) malloc ( n * sizeof (char));
+ snprintf (option, n, "channels_%s", p->server);
+ plugin->set_plugin_config (plugin, option, channels);
+ free (option);
+ free (channels);
+ }
+ }
+
+ plugin->print (plugin, NULL, NULL, "[%s] [SAVE] configuration saved", plugin_name);
+ return 1;
+}
+
+/*
+ * config_load : loading plugin config
+ */
+int config_load(void)
+{
+ char *servers, *channels, *lang;
+ char *option_s, *option_l;
+ char **servers_list, **channels_list;
+ int i, j, s, c, n;
+
+ servers = plugin->get_plugin_config (plugin, "servers");
+ if (!servers)
+ return 0;
+
+ servers_list = plugin->explode_string (plugin, servers, " ", 0, &s);
+
+ if (servers_list)
+ {
+ for (i=0; i<s; i++)
+ {
+ n = 10 + strlen (servers_list[i]);
+ option_s = (char *) malloc (n * sizeof (char));
+ snprintf (option_s, n, "channels_%s", servers_list[i]);
+
+ channels = plugin->get_plugin_config (plugin, option_s);
+ if (channels)
+ {
+ channels_list = plugin->explode_string (plugin, channels, " ", 0, &c);
+ if (channels_list)
+ {
+ for (j=0; j<c; j++)
+ {
+ n = 7 + strlen (servers_list[i]) + strlen (channels_list[j]);
+ option_l = (char *) malloc (n * sizeof (char));
+ snprintf (option_l, n, "lang_%s_%s", servers_list[i], channels_list[j]);
+
+ lang = plugin->get_plugin_config (plugin, option_l);
+ if (lang)
+ {
+ config_enable_for (servers_list[i], channels_list[j], lang);
+ free (lang);
+ }
+ free (option_l);
+ }
+ plugin->free_exploded_string (plugin, channels_list);
+ }
+ free (channels);
+ }
+ free (option_s);
+ }
+
+ plugin->free_exploded_string (plugin, servers_list);
+ }
+
+ plugin->print (plugin, NULL, NULL, "[%s] [LOAD] configuration loaded", plugin_name);
+ return 1;
+}
+
+/*
+ * options_save : saving plugin options
+ */
+int options_save(void)
+{
+ char buf[8];
+
+ snprintf (buf, sizeof(buf), "%d", plugin_options.word_size);
+ plugin->set_plugin_config (plugin, "word-size", buf);
+
+ snprintf (buf, sizeof(buf), "%d", plugin_options.check_sync);
+ plugin->set_plugin_config (plugin, "check-sync", buf);
+
+ plugin->set_plugin_config (plugin, "color", plugin_options.color_name);
+
+ plugin->print (plugin, NULL, NULL, "[%s] [SAVE] options saved", plugin_name);
+ return 1;
+}
+
+/*
+ * options_load : loading plugin options
+ */
+int options_load(void)
+{
+ char *buffer;
+ int n;
+
+ buffer = plugin->get_plugin_config (plugin, "word-size");
+ if (buffer)
+ {
+ plugin_options.word_size = atoi (buffer);
+ free (buffer);
+ }
+ else
+ plugin_options.word_size = _OPTION_WORD_SIZE;
+
+ buffer = plugin->get_plugin_config (plugin, "check-sync");
+ if (buffer)
+ {
+ plugin_options.check_sync = atoi (buffer);
+ if (plugin_options.check_sync != 0 && plugin_options.check_sync != 1)
+ plugin_options.check_sync = _OPTION_CHECK_SYNC;
+ free (buffer);
+ }
+ else
+ plugin_options.check_sync = _OPTION_CHECK_SYNC;
+
+
+ buffer = plugin->get_plugin_config (plugin, "color");
+ if (buffer)
+ {
+ n = plugin->get_irc_color (plugin, buffer);
+ if (n == -1)
+ {
+ plugin_options.color = plugin->get_irc_color (plugin, _OPTION_COLOR);
+ plugin_options.color_name = strdup (_OPTION_COLOR);
+ }
+ else
+ {
+ plugin_options.color = n;
+ plugin_options.color_name = strdup (buffer);
+ }
+ free (buffer);
+ }
+ else {
+ plugin_options.color = plugin->get_irc_color (plugin, _OPTION_COLOR);
+ plugin_options.color_name = strdup (_OPTION_COLOR);
+ }
+
+ plugin->print (plugin, NULL, NULL, "[%s] [LOAD] options loaded", plugin_name);
+ return 1;
+}
+
+/*
+ * speller_command : manage "/aspell" uses
+ */
+int speller_command (t_weechat_plugin *p,
+ int argc, char **argv,
+ char *handler_args,
+ void *handler_pointer)
+{
+ /* make gcc happy */
+ (void) p;
+ (void) handler_args;
+ (void) handler_pointer;
+
+ char helpcmd[32];
+ char **args;
+ int c, r;
+
+ snprintf(helpcmd, sizeof(helpcmd), "/help %s", plugin_command);
+ r = 0;
+
+ if ((argc == 3) && argv[1] && argv[2])
+ {
+ args = plugin->explode_string (plugin, argv[2], " ", 0, &c);
+ if (args)
+ {
+ if (c >= 1)
+ {
+ if (strcmp (args[0], "dictlist") == 0)
+ {
+ speller_list_dicts (); r = 1;
+ }
+ else if (strcmp (args[0], "show") == 0)
+ {
+ config_show (); r = 1;
+ }
+ else if (strcmp (args[0], "save") == 0)
+ {
+ config_save (); options_save(); r = 1;
+ }
+ else if (strcmp (args[0], "dump") == 0)
+ {
+ config_dump (); r = 1;
+ }
+ else if (strcmp (args[0], "enable") == 0)
+ {
+ if (c >= 2) { config_enable (args[1]); r = 1; }
+ }
+ else if (strcmp (args[0], "disable") == 0)
+ config_disable ();
+ else if (strcmp (args[0], "set") == 0)
+ {
+ if (c >= 2) { r = config_set (args[1], args[2]); }
+ }
+ else if (strcmp (args[0], "add-word") == 0)
+ {
+ if (c >= 2) { config_addword (args[1]); r = 1; }
+ }
+
+ }
+ plugin->free_exploded_string (plugin, args);
+ }
+ }
+
+ if (r == 0)
+ plugin->exec_command (plugin, NULL, NULL, helpcmd);
+
+ return PLUGIN_RC_OK;
+}
+
+/*
+ * keyb_check : handler to check spelling on input line
+ */
+int keyb_check (t_weechat_plugin *p, int argc, char **argv,
+ char *handler_args, void *handler_pointer)
+{
+ /* make gcc happy */
+ (void) p;
+ (void) handler_args;
+ (void) handler_pointer;
+
+ char *server, *channel;
+ config_t *c;
+ char *input, *ptr_input, *pos_space;
+ int count;
+
+ channel = plugin->get_info (plugin, "channel", NULL);
+ server = plugin->get_info (plugin, "server", NULL);
+
+ if (!server || !channel)
+ return PLUGIN_RC_OK;
+
+ c = config_list_search (server, channel);
+ if (!c)
+ return PLUGIN_RC_OK;
+
+ if (plugin_options.check_sync == 0 && argv[0] && argv[0][0])
+ {
+ /* FIXME : using isalpha(), can make problem with UTF-8 encodings */
+ if (argv[0][0] == '*' && isalpha (argv[0][1]))
+ return PLUGIN_RC_OK;
+ }
+
+ if (!(argc == 3 && argv[1] && argv[2]))
+ return PLUGIN_RC_OK;
+
+ if (strcmp (argv[1], argv[2]) == 0)
+ return PLUGIN_RC_OK;
+
+ input = plugin->get_info (plugin, "input", NULL);
+ if (!input)
+ return PLUGIN_RC_OK;
+
+ if (!input[0])
+ return PLUGIN_RC_OK;
+
+ if (input[0] == '/')
+ return PLUGIN_RC_OK;
+
+ count = 0;
+ ptr_input = input;
+ plugin->input_color (plugin, 0, 0, 0);
+ while (ptr_input && ptr_input[0])
+ {
+ pos_space = strchr (ptr_input, ' ');
+ if (pos_space)
+ pos_space[0] = '\0';
+
+ if ( (int) strlen (ptr_input) >= plugin_options.word_size)
+ {
+ if (aspell_speller_check (c->speller->speller, ptr_input, -1) != 1)
+ {
+ if (count == 0)
+ plugin->input_color (plugin, 0, 0, 0);
+ plugin->input_color (plugin, plugin_options.color,
+ ptr_input - input, strlen (ptr_input));
+ count++;
+ }
+ }
+
+ if (pos_space)
+ {
+ pos_space[0] = ' ';
+ ptr_input = pos_space + 1;
+ while (ptr_input[0] == ' ')
+ ptr_input++;
+ }
+ else
+ ptr_input = NULL;
+ }
+ plugin->input_color (plugin, -1, 0, 0);
+
+ free (input);
+
+ return PLUGIN_RC_OK;
+}
+
+/*
+ * weechat_plugin_init : init function, called when plugin is loaded
+ */
+int weechat_plugin_init (t_weechat_plugin *p)
+{
+ char help[1024];
+ plugin_speller = NULL;
+ plugin_config = NULL;
+ plugin = p;
+
+ snprintf (help, sizeof(help),
+ " show : show plugin configuration\n"
+ "dictlist : show installed dictionnaries\n"
+ " save : save plugin configuration\n"
+ " enable : enable aspell on current channel/server\n"
+ " disable : disable aspell on current channel/server\n"
+ "add-word : add a word in your personnal aspell dict\n"
+ " dump : show plugins internals (usefull for debug)\n"
+ " set : setting options\n"
+ " OPTION := { word-size SIZE | toogle-check-mode | color COLOR }\n"
+ " word-size : minimum size for a word to be checked (default : %d)\n"
+ " toggle-check-mode : switch between a realtime or an asynchronous checking\n"
+ " color : color of the mispelled words\n",
+ _OPTION_WORD_SIZE);
+
+ plugin->cmd_handler_add (plugin, "aspell",
+ "Aspell Plugin configuration",
+ "{ show | save | dictlist | set [OPTION [VALUE]] | add-word WORD | enable LANG | disable | dump }",
+ help,
+ "show|dictlist|save|enable|disable|set|add-word|dump word-size|toggle-check-mode|color",
+ &speller_command, NULL, NULL);
+
+ plugin->keyboard_handler_add (plugin, &keyb_check, NULL, NULL);
+
+ options_load ();
+ config_load ();
+
+ return PLUGIN_RC_OK;
+}
+
+/*
+ * weechat_plugin_end : end function, called when plugin is unloaded
+ */
+void weechat_plugin_end (t_weechat_plugin *p)
+{
+ /* make gcc happy */
+ (void) p;
+
+ speller_t *s, *t;
+ config_t *c, *d;
+
+ options_save ();
+ config_save ();
+
+ /* freeing memory */
+
+ /* options */
+ if (plugin_options.color_name)
+ free (plugin_options.color_name);
+
+ /* spellers */
+ s = plugin_speller;
+ while ( s != NULL)
+ {
+ t = s;
+ s = s->next_speller;
+ free_speller (t);
+ }
+
+ /* config */
+ c = plugin_config;
+ while ( c != NULL)
+ {
+ d = c;
+ c = c->next_config;
+ free_config (c);
+ }
+}