mirror of
https://github.com/weechat/weechat.git
synced 2026-07-08 10:43:13 +02:00
spell: rename "aspell" plugin to "spell" (issue #1299)
The following things have been renamed: - file aspell.conf -> spell.conf - options aspell.* -> spell.* - bar item aspell_dict -> spell_dict - bar item and local variable aspell_suggest -> spell_suggest - info aspell_dict -> spell_dict
This commit is contained in:
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* spell-speller.c - speller management for spell checker plugin
|
||||
*
|
||||
* Copyright (C) 2006 Emmanuel Bouthenot <kolter@openics.org>
|
||||
* Copyright (C) 2006-2019 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* WeeChat is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "spell.h"
|
||||
#include "spell-speller.h"
|
||||
#include "spell-config.h"
|
||||
|
||||
|
||||
/*
|
||||
* spellers: one by dictionary (key is name of dictionary (eg: "fr"), value is
|
||||
* pointer on AspellSpeller)
|
||||
*/
|
||||
struct t_hashtable *spell_spellers = NULL;
|
||||
|
||||
/*
|
||||
* spellers by buffer (key is buffer pointer, value is pointer on
|
||||
* struct t_spell_speller_buffer)
|
||||
*/
|
||||
struct t_hashtable *spell_speller_buffer = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Checks if a spelling dictionary is supported (installed on system).
|
||||
*
|
||||
* Returns:
|
||||
* 1: spell dict is supported
|
||||
* 0: spell dict is NOT supported
|
||||
*/
|
||||
|
||||
int
|
||||
spell_speller_dict_supported (const char *lang)
|
||||
{
|
||||
#ifdef USE_ENCHANT
|
||||
return enchant_broker_dict_exists (broker, lang);
|
||||
#else
|
||||
struct AspellConfig *config;
|
||||
AspellDictInfoList *list;
|
||||
AspellDictInfoEnumeration *elements;
|
||||
const AspellDictInfo *dict;
|
||||
int rc;
|
||||
|
||||
rc = 0;
|
||||
|
||||
config = new_aspell_config ();
|
||||
list = get_aspell_dict_info_list (config);
|
||||
elements = aspell_dict_info_list_elements (list);
|
||||
|
||||
while ((dict = aspell_dict_info_enumeration_next (elements)) != NULL)
|
||||
{
|
||||
if (strcmp (dict->name, lang) == 0)
|
||||
{
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete_aspell_dict_info_enumeration (elements);
|
||||
delete_aspell_config (config);
|
||||
|
||||
return rc;
|
||||
#endif /* USE_ENCHANT */
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if dictionaries are valid (called when user creates/changes
|
||||
* dictionaries for a buffer).
|
||||
*
|
||||
* An error is displayed for each invalid dictionary found.
|
||||
*/
|
||||
|
||||
void
|
||||
spell_speller_check_dictionaries (const char *dict_list)
|
||||
{
|
||||
char **argv;
|
||||
int argc, i;
|
||||
|
||||
if (dict_list)
|
||||
{
|
||||
argv = weechat_string_split (dict_list, ",", 0, 0, &argc);
|
||||
if (argv)
|
||||
{
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
if (!spell_speller_dict_supported (argv[i]))
|
||||
{
|
||||
weechat_printf (NULL,
|
||||
_("%s: warning: dictionary \"%s\" is not "
|
||||
"available on your system"),
|
||||
SPELL_PLUGIN_NAME, argv[i]);
|
||||
}
|
||||
}
|
||||
weechat_string_free_split (argv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates and adds a new speller instance in the hashtable.
|
||||
*
|
||||
* Returns pointer to new speller, NULL if error.
|
||||
*/
|
||||
|
||||
#ifdef USE_ENCHANT
|
||||
EnchantDict *
|
||||
#else
|
||||
AspellSpeller *
|
||||
#endif /* USE_ENCHANT */
|
||||
spell_speller_new (const char *lang)
|
||||
{
|
||||
#ifdef USE_ENCHANT
|
||||
EnchantDict *new_speller;
|
||||
#else
|
||||
AspellConfig *config;
|
||||
AspellCanHaveError *ret;
|
||||
AspellSpeller *new_speller;
|
||||
#endif /* USE_ENCHANT */
|
||||
struct t_infolist *infolist;
|
||||
|
||||
if (!lang)
|
||||
return NULL;
|
||||
|
||||
if (weechat_spell_plugin->debug)
|
||||
{
|
||||
weechat_printf (NULL,
|
||||
"%s: creating new speller for lang \"%s\"",
|
||||
SPELL_PLUGIN_NAME, lang);
|
||||
}
|
||||
|
||||
#ifdef USE_ENCHANT
|
||||
new_speller = enchant_broker_request_dict (broker, lang);
|
||||
if (!new_speller)
|
||||
{
|
||||
weechat_printf (NULL,
|
||||
_("%s%s: error: unable to create speller for lang \"%s\""),
|
||||
weechat_prefix ("error"), SPELL_PLUGIN_NAME,
|
||||
lang);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
/* create a speller instance for the newly created cell */
|
||||
config = new_aspell_config ();
|
||||
aspell_config_replace (config, "lang", lang);
|
||||
#endif /* USE_ENCHANT */
|
||||
|
||||
/* apply all options */
|
||||
infolist = weechat_infolist_get ("option", NULL, "spell.option.*");
|
||||
if (infolist)
|
||||
{
|
||||
while (weechat_infolist_next (infolist))
|
||||
{
|
||||
#ifdef USE_ENCHANT
|
||||
/* TODO: set option with enchant */
|
||||
#else
|
||||
aspell_config_replace (config,
|
||||
weechat_infolist_string (infolist, "option_name"),
|
||||
weechat_infolist_string (infolist, "value"));
|
||||
#endif /* USE_ENCHANT */
|
||||
}
|
||||
weechat_infolist_free (infolist);
|
||||
}
|
||||
|
||||
#ifndef USE_ENCHANT
|
||||
ret = new_aspell_speller (config);
|
||||
|
||||
if (aspell_error (ret) != 0)
|
||||
{
|
||||
weechat_printf (NULL,
|
||||
"%s%s: error: %s",
|
||||
weechat_prefix ("error"), SPELL_PLUGIN_NAME,
|
||||
aspell_error_message (ret));
|
||||
delete_aspell_config (config);
|
||||
delete_aspell_can_have_error (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_speller = to_aspell_speller (ret);
|
||||
#endif /* USE_ENCHANT */
|
||||
|
||||
weechat_hashtable_set (spell_spellers, lang, new_speller);
|
||||
|
||||
#ifndef USE_ENCHANT
|
||||
/* free configuration */
|
||||
delete_aspell_config (config);
|
||||
#endif /* USE_ENCHANT */
|
||||
|
||||
return new_speller;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates hashtable entries with a string containing a list of dicts.
|
||||
*/
|
||||
|
||||
void
|
||||
spell_speller_add_dicts_to_hash (struct t_hashtable *hashtable,
|
||||
const char *dict)
|
||||
{
|
||||
char **dicts;
|
||||
int num_dicts, i;
|
||||
|
||||
if (!dict || !dict[0])
|
||||
return;
|
||||
|
||||
dicts = weechat_string_split (dict, ",", 0, 0, &num_dicts);
|
||||
if (dicts)
|
||||
{
|
||||
for (i = 0; i < num_dicts; i++)
|
||||
{
|
||||
weechat_hashtable_set (hashtable, dicts[i], NULL);
|
||||
}
|
||||
weechat_string_free_split (dicts);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes a speller if it is NOT in hashtable "used_spellers".
|
||||
*/
|
||||
|
||||
void
|
||||
spell_speller_remove_unused_cb (void *data,
|
||||
struct t_hashtable *hashtable,
|
||||
const void *key, const void *value)
|
||||
{
|
||||
struct t_hashtable *used_spellers;
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) value;
|
||||
|
||||
used_spellers = (struct t_hashtable *)data;
|
||||
|
||||
/* if speller is not in "used_spellers", remove it (not used any more) */
|
||||
if (!weechat_hashtable_has_key (used_spellers, key))
|
||||
weechat_hashtable_remove (hashtable, key);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes unused spellers from hashtable "spell_spellers".
|
||||
*/
|
||||
|
||||
void
|
||||
spell_speller_remove_unused ()
|
||||
{
|
||||
struct t_hashtable *used_spellers;
|
||||
struct t_infolist *infolist;
|
||||
|
||||
if (weechat_spell_plugin->debug)
|
||||
{
|
||||
weechat_printf (NULL,
|
||||
"%s: removing unused spellers",
|
||||
SPELL_PLUGIN_NAME);
|
||||
}
|
||||
|
||||
/* create a hashtable that will contain all used spellers */
|
||||
used_spellers = weechat_hashtable_new (32,
|
||||
WEECHAT_HASHTABLE_STRING,
|
||||
WEECHAT_HASHTABLE_STRING,
|
||||
NULL, NULL);
|
||||
if (!used_spellers)
|
||||
return;
|
||||
|
||||
/* collect used spellers and store them in hashtable "used_spellers" */
|
||||
spell_speller_add_dicts_to_hash (used_spellers,
|
||||
weechat_config_string (spell_config_check_default_dict));
|
||||
infolist = weechat_infolist_get ("option", NULL, "spell.dict.*");
|
||||
if (infolist)
|
||||
{
|
||||
while (weechat_infolist_next (infolist))
|
||||
{
|
||||
spell_speller_add_dicts_to_hash (used_spellers,
|
||||
weechat_infolist_string (infolist, "value"));
|
||||
}
|
||||
weechat_infolist_free (infolist);
|
||||
}
|
||||
|
||||
/*
|
||||
* look at current spellers, and remove spellers that are not in hashtable
|
||||
* "used_spellers"
|
||||
*/
|
||||
weechat_hashtable_map (spell_spellers,
|
||||
&spell_speller_remove_unused_cb,
|
||||
used_spellers);
|
||||
|
||||
weechat_hashtable_free (used_spellers);
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback called when a key is removed in hashtable "spell_spellers".
|
||||
*/
|
||||
|
||||
void
|
||||
spell_speller_free_value_cb (struct t_hashtable *hashtable,
|
||||
const void *key, void *value)
|
||||
{
|
||||
#ifdef USE_ENCHANT
|
||||
EnchantDict *ptr_speller;
|
||||
#else
|
||||
AspellSpeller *ptr_speller;
|
||||
#endif /* USE_ENCHANT */
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) hashtable;
|
||||
|
||||
if (weechat_spell_plugin->debug)
|
||||
{
|
||||
weechat_printf (NULL,
|
||||
"%s: removing speller for lang \"%s\"",
|
||||
SPELL_PLUGIN_NAME, (const char *)key);
|
||||
}
|
||||
|
||||
/* free speller */
|
||||
#ifdef USE_ENCHANT
|
||||
ptr_speller = (EnchantDict *)value;
|
||||
enchant_broker_free_dict (broker, ptr_speller);
|
||||
#else
|
||||
ptr_speller = (AspellSpeller *)value;
|
||||
aspell_speller_save_all_word_lists (ptr_speller);
|
||||
delete_aspell_speller (ptr_speller);
|
||||
#endif /* USE_ENCHANT */
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a structure for buffer speller info in hashtable
|
||||
* "spell_buffer_spellers".
|
||||
*/
|
||||
|
||||
struct t_spell_speller_buffer *
|
||||
spell_speller_buffer_new (struct t_gui_buffer *buffer)
|
||||
{
|
||||
const char *buffer_dicts;
|
||||
char **dicts;
|
||||
int num_dicts, i;
|
||||
struct t_spell_speller_buffer *new_speller_buffer;
|
||||
#ifdef USE_ENCHANT
|
||||
EnchantDict *ptr_speller;
|
||||
#else
|
||||
AspellSpeller *ptr_speller;
|
||||
#endif /* USE_ENCHANT */
|
||||
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
weechat_hashtable_remove (spell_speller_buffer, buffer);
|
||||
|
||||
new_speller_buffer = malloc (sizeof (*new_speller_buffer));
|
||||
if (!new_speller_buffer)
|
||||
return NULL;
|
||||
|
||||
new_speller_buffer->spellers = NULL;
|
||||
new_speller_buffer->modifier_string = NULL;
|
||||
new_speller_buffer->input_pos = -1;
|
||||
new_speller_buffer->modifier_result = NULL;
|
||||
|
||||
buffer_dicts = spell_get_dict (buffer);
|
||||
if (buffer_dicts)
|
||||
{
|
||||
dicts = weechat_string_split (buffer_dicts, ",", 0, 0, &num_dicts);
|
||||
if (dicts && (num_dicts > 0))
|
||||
{
|
||||
new_speller_buffer->spellers =
|
||||
#ifdef USE_ENCHANT
|
||||
malloc ((num_dicts + 1) * sizeof (EnchantDict *));
|
||||
#else
|
||||
malloc ((num_dicts + 1) * sizeof (AspellSpeller *));
|
||||
#endif /* USE_ENCHANT */
|
||||
if (new_speller_buffer->spellers)
|
||||
{
|
||||
for (i = 0; i < num_dicts; i++)
|
||||
{
|
||||
ptr_speller = weechat_hashtable_get (spell_spellers,
|
||||
dicts[i]);
|
||||
if (!ptr_speller)
|
||||
ptr_speller = spell_speller_new (dicts[i]);
|
||||
new_speller_buffer->spellers[i] = ptr_speller;
|
||||
}
|
||||
new_speller_buffer->spellers[num_dicts] = NULL;
|
||||
}
|
||||
}
|
||||
if (dicts)
|
||||
weechat_string_free_split (dicts);
|
||||
}
|
||||
|
||||
weechat_hashtable_set (spell_speller_buffer,
|
||||
buffer,
|
||||
new_speller_buffer);
|
||||
|
||||
weechat_bar_item_update ("spell_dict");
|
||||
|
||||
return new_speller_buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback called when a key is removed in hashtable
|
||||
* "spell_speller_buffer".
|
||||
*/
|
||||
|
||||
void
|
||||
spell_speller_buffer_free_value_cb (struct t_hashtable *hashtable,
|
||||
const void *key, void *value)
|
||||
{
|
||||
struct t_spell_speller_buffer *ptr_speller_buffer;
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) hashtable;
|
||||
(void) key;
|
||||
|
||||
ptr_speller_buffer = (struct t_spell_speller_buffer *)value;
|
||||
|
||||
if (ptr_speller_buffer->spellers)
|
||||
free (ptr_speller_buffer->spellers);
|
||||
if (ptr_speller_buffer->modifier_string)
|
||||
free (ptr_speller_buffer->modifier_string);
|
||||
if (ptr_speller_buffer->modifier_result)
|
||||
free (ptr_speller_buffer->modifier_result);
|
||||
|
||||
free (ptr_speller_buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes spellers (creates hashtables).
|
||||
*
|
||||
* Returns:
|
||||
* 1: OK (hashtables created)
|
||||
* 0: error (not enough memory)
|
||||
*/
|
||||
|
||||
int
|
||||
spell_speller_init ()
|
||||
{
|
||||
spell_spellers = weechat_hashtable_new (32,
|
||||
WEECHAT_HASHTABLE_STRING,
|
||||
WEECHAT_HASHTABLE_POINTER,
|
||||
NULL, NULL);
|
||||
if (!spell_spellers)
|
||||
return 0;
|
||||
weechat_hashtable_set_pointer (spell_spellers,
|
||||
"callback_free_value",
|
||||
&spell_speller_free_value_cb);
|
||||
|
||||
spell_speller_buffer = weechat_hashtable_new (32,
|
||||
WEECHAT_HASHTABLE_POINTER,
|
||||
WEECHAT_HASHTABLE_POINTER,
|
||||
NULL, NULL);
|
||||
if (!spell_speller_buffer)
|
||||
{
|
||||
weechat_hashtable_free (spell_spellers);
|
||||
return 0;
|
||||
}
|
||||
weechat_hashtable_set_pointer (spell_speller_buffer,
|
||||
"callback_free_value",
|
||||
&spell_speller_buffer_free_value_cb);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ends spellers (removes hashtables).
|
||||
*/
|
||||
|
||||
void
|
||||
spell_speller_end ()
|
||||
{
|
||||
weechat_hashtable_free (spell_spellers);
|
||||
weechat_hashtable_free (spell_speller_buffer);
|
||||
}
|
||||
Reference in New Issue
Block a user