Aspell: execute the command in pipe mode instead of loading the dll for getting suggestions: simpler and no crashes of the whole UI in case of problem

This commit is contained in:
Jean-Francois Dockes 2021-04-23 10:50:22 +02:00
parent 9abaf84be6
commit 7310709e08
10 changed files with 141 additions and 1076 deletions

View File

@ -58,7 +58,6 @@ librcldir = $(libdir)/recoll
librcl_LTLIBRARIES = librecoll.la
librecoll_la_SOURCES = \
aspell/aspell-local.h \
aspell/rclaspell.cpp \
aspell/rclaspell.h \
bincimapmime/convert.cc \

View File

@ -1,729 +0,0 @@
/* Automatically generated file. Do not edit directly. */
/* This file is part of The New Aspell
* Copyright (C) 2001-2002 by Kevin Atkinson under the GNU LGPL
* license version 2.0 or 2.1. You should have received a copy of the
* LGPL license along with this library if you did not you can find it
* at http://www.gnu.org/. */
#ifndef ASPELL_ASPELL__H
#define ASPELL_ASPELL__H
#ifdef __cplusplus
extern "C" {
#endif
/******************************* type id *******************************/
union AspellTypeId {
unsigned int num;
char str[4];
};
typedef union AspellTypeId AspellTypeId;
/************************** mutable container **************************/
typedef struct AspellMutableContainer AspellMutableContainer;
int aspell_mutable_container_add(struct AspellMutableContainer * ths, const char * to_add);
int aspell_mutable_container_remove(struct AspellMutableContainer * ths, const char * to_rem);
void aspell_mutable_container_clear(struct AspellMutableContainer * ths);
struct AspellMutableContainer * aspell_mutable_container_to_mutable_container(struct AspellMutableContainer * ths);
/******************************* key info *******************************/
enum AspellKeyInfoType {AspellKeyInfoString, AspellKeyInfoInt, AspellKeyInfoBool, AspellKeyInfoList};
typedef enum AspellKeyInfoType AspellKeyInfoType;
struct AspellKeyInfo {
/* The name of the key. */
const char * name;
/* The key type. */
enum AspellKeyInfoType type;
/* The default value of the key. */
const char * def;
/* A brief description of the key or NULL if internal value. */
const char * desc;
int flags;
int other_data;
};
typedef struct AspellKeyInfo AspellKeyInfo;
/******************************** config ********************************/
typedef struct AspellKeyInfoEnumeration AspellKeyInfoEnumeration;
int aspell_key_info_enumeration_at_end(const struct AspellKeyInfoEnumeration * ths);
const struct AspellKeyInfo * aspell_key_info_enumeration_next(struct AspellKeyInfoEnumeration * ths);
void delete_aspell_key_info_enumeration(struct AspellKeyInfoEnumeration * ths);
struct AspellKeyInfoEnumeration * aspell_key_info_enumeration_clone(const struct AspellKeyInfoEnumeration * ths);
void aspell_key_info_enumeration_assign(struct AspellKeyInfoEnumeration * ths, const struct AspellKeyInfoEnumeration * other);
typedef struct AspellConfig AspellConfig;
struct AspellConfig * new_aspell_config();
void delete_aspell_config(struct AspellConfig * ths);
struct AspellConfig * aspell_config_clone(const struct AspellConfig * ths);
void aspell_config_assign(struct AspellConfig * ths, const struct AspellConfig * other);
unsigned int aspell_config_error_number(const struct AspellConfig * ths);
const char * aspell_config_error_message(const struct AspellConfig * ths);
const struct AspellError * aspell_config_error(const struct AspellConfig * ths);
/* Sets extra keys which this config class should
* accept. begin and end are expected to point to
* the beginning and ending of an array of Aspell
* Key Info. */
void aspell_config_set_extra(struct AspellConfig * ths, const struct AspellKeyInfo * begin, const struct AspellKeyInfo * end);
/* Returns the KeyInfo object for the
* corresponding key or returns NULL and sets
* error_num to PERROR_UNKNOWN_KEY if the key is
* not valid. The pointer returned is valid for
* the lifetime of the object. */
const struct AspellKeyInfo * aspell_config_keyinfo(struct AspellConfig * ths, const char * key);
/* Returns a newly allocated enumeration of all
* the possible objects this config class uses. */
struct AspellKeyInfoEnumeration * aspell_config_possible_elements(struct AspellConfig * ths, int include_extra);
/* Returns the default value for given key which
* may involve substituting variables, thus it is
* not the same as keyinfo(key)->def returns NULL
* and sets error_num to PERROR_UNKNOWN_KEY if
* the key is not valid. Uses the temporary
* string. */
const char * aspell_config_get_default(struct AspellConfig * ths, const char * key);
/* Returns a newly allocated enumeration of all
* the key/value pairs. This DOES not include ones
* which are set to their default values. */
struct AspellStringPairEnumeration * aspell_config_elements(struct AspellConfig * ths);
/* Inserts an item, if the item already exists it
* will be replaced. Returns TRUE if it succeeded
* or FALSE on error. If the key in not valid it
* sets error_num to PERROR_UNKNOWN_KEY, if the
* value is not valid it will set error_num to
* PERROR_BAD_VALUE, if the value can not be
* changed it sets error_num to
* PERROR_CANT_CHANGE_VALUE, and if the value is
* a list and you are trying to set its directory,
* it sets error_num to PERROR_LIST_SET */
int aspell_config_replace(struct AspellConfig * ths, const char * key, const char * value);
/* Remove a key and returns TRUE if it exists
* otherwise return FALSE. This effectively sets
* the key to its default value. Calling replace
* with a value of "<default>" will also call
* remove. If the key does not exist then it sets
* error_num to 0 or PERROR_NOT, if the key is
* not valid then it sets error_num to
* PERROR_UNKNOWN_KEY, if the value can not be
* changed then it sets error_num to
* PERROR_CANT_CHANGE_VALUE */
int aspell_config_remove(struct AspellConfig * ths, const char * key);
int aspell_config_have(const struct AspellConfig * ths, const char * key);
/* Returns NULL on error. */
const char * aspell_config_retrieve(struct AspellConfig * ths, const char * key);
int aspell_config_retrieve_list(struct AspellConfig * ths, const char * key, struct AspellMutableContainer * lst);
/* Return -1 on error, 0 if false, 1 if true. */
int aspell_config_retrieve_bool(struct AspellConfig * ths, const char * key);
/* Return -1 on error. */
int aspell_config_retrieve_int(struct AspellConfig * ths, const char * key);
/******************************** error ********************************/
struct AspellError {
const char * mesg;
const struct AspellErrorInfo * err;
};
typedef struct AspellError AspellError;
int aspell_error_is_a(const struct AspellError * ths, const struct AspellErrorInfo * e);
struct AspellErrorInfo {
const struct AspellErrorInfo * isa;
const char * mesg;
unsigned int num_parms;
const char * parms[3];
};
typedef struct AspellErrorInfo AspellErrorInfo;
/**************************** can have error ****************************/
typedef struct AspellCanHaveError AspellCanHaveError;
unsigned int aspell_error_number(const struct AspellCanHaveError * ths);
const char * aspell_error_message(const struct AspellCanHaveError * ths);
const struct AspellError * aspell_error(const struct AspellCanHaveError * ths);
void delete_aspell_can_have_error(struct AspellCanHaveError * ths);
/******************************** errors ********************************/
extern const struct AspellErrorInfo * const aerror_other;
extern const struct AspellErrorInfo * const aerror_operation_not_supported;
extern const struct AspellErrorInfo * const aerror_cant_copy;
extern const struct AspellErrorInfo * const aerror_unimplemented_method;
extern const struct AspellErrorInfo * const aerror_file;
extern const struct AspellErrorInfo * const aerror_cant_open_file;
extern const struct AspellErrorInfo * const aerror_cant_read_file;
extern const struct AspellErrorInfo * const aerror_cant_write_file;
extern const struct AspellErrorInfo * const aerror_invalid_name;
extern const struct AspellErrorInfo * const aerror_bad_file_format;
extern const struct AspellErrorInfo * const aerror_dir;
extern const struct AspellErrorInfo * const aerror_cant_read_dir;
extern const struct AspellErrorInfo * const aerror_config;
extern const struct AspellErrorInfo * const aerror_unknown_key;
extern const struct AspellErrorInfo * const aerror_cant_change_value;
extern const struct AspellErrorInfo * const aerror_bad_key;
extern const struct AspellErrorInfo * const aerror_bad_value;
extern const struct AspellErrorInfo * const aerror_duplicate;
extern const struct AspellErrorInfo * const aerror_key_not_string;
extern const struct AspellErrorInfo * const aerror_key_not_int;
extern const struct AspellErrorInfo * const aerror_key_not_bool;
extern const struct AspellErrorInfo * const aerror_key_not_list;
extern const struct AspellErrorInfo * const aerror_no_value_reset;
extern const struct AspellErrorInfo * const aerror_no_value_enable;
extern const struct AspellErrorInfo * const aerror_no_value_disable;
extern const struct AspellErrorInfo * const aerror_no_value_clear;
extern const struct AspellErrorInfo * const aerror_language_related;
extern const struct AspellErrorInfo * const aerror_unknown_language;
extern const struct AspellErrorInfo * const aerror_unknown_soundslike;
extern const struct AspellErrorInfo * const aerror_language_not_supported;
extern const struct AspellErrorInfo * const aerror_no_wordlist_for_lang;
extern const struct AspellErrorInfo * const aerror_mismatched_language;
extern const struct AspellErrorInfo * const aerror_affix;
extern const struct AspellErrorInfo * const aerror_corrupt_affix;
extern const struct AspellErrorInfo * const aerror_invalid_cond;
extern const struct AspellErrorInfo * const aerror_invalid_cond_strip;
extern const struct AspellErrorInfo * const aerror_incorrect_encoding;
extern const struct AspellErrorInfo * const aerror_encoding;
extern const struct AspellErrorInfo * const aerror_unknown_encoding;
extern const struct AspellErrorInfo * const aerror_encoding_not_supported;
extern const struct AspellErrorInfo * const aerror_conversion_not_supported;
extern const struct AspellErrorInfo * const aerror_pipe;
extern const struct AspellErrorInfo * const aerror_cant_create_pipe;
extern const struct AspellErrorInfo * const aerror_process_died;
extern const struct AspellErrorInfo * const aerror_bad_input;
extern const struct AspellErrorInfo * const aerror_invalid_string;
extern const struct AspellErrorInfo * const aerror_invalid_word;
extern const struct AspellErrorInfo * const aerror_invalid_affix;
extern const struct AspellErrorInfo * const aerror_inapplicable_affix;
extern const struct AspellErrorInfo * const aerror_unknown_unichar;
extern const struct AspellErrorInfo * const aerror_word_list_flags;
extern const struct AspellErrorInfo * const aerror_invalid_flag;
extern const struct AspellErrorInfo * const aerror_conflicting_flags;
extern const struct AspellErrorInfo * const aerror_version_control;
extern const struct AspellErrorInfo * const aerror_bad_version_string;
extern const struct AspellErrorInfo * const aerror_filter;
extern const struct AspellErrorInfo * const aerror_cant_dlopen_file;
extern const struct AspellErrorInfo * const aerror_empty_filter;
extern const struct AspellErrorInfo * const aerror_no_such_filter;
extern const struct AspellErrorInfo * const aerror_confusing_version;
extern const struct AspellErrorInfo * const aerror_bad_version;
extern const struct AspellErrorInfo * const aerror_identical_option;
extern const struct AspellErrorInfo * const aerror_options_only;
extern const struct AspellErrorInfo * const aerror_invalid_option_modifier;
extern const struct AspellErrorInfo * const aerror_cant_describe_filter;
extern const struct AspellErrorInfo * const aerror_filter_mode_file;
extern const struct AspellErrorInfo * const aerror_mode_option_name;
extern const struct AspellErrorInfo * const aerror_no_filter_to_option;
extern const struct AspellErrorInfo * const aerror_bad_mode_key;
extern const struct AspellErrorInfo * const aerror_expect_mode_key;
extern const struct AspellErrorInfo * const aerror_mode_version_requirement;
extern const struct AspellErrorInfo * const aerror_confusing_mode_version;
extern const struct AspellErrorInfo * const aerror_bad_mode_version;
extern const struct AspellErrorInfo * const aerror_missing_magic_expression;
extern const struct AspellErrorInfo * const aerror_empty_file_ext;
extern const struct AspellErrorInfo * const aerror_filter_mode_expand;
extern const struct AspellErrorInfo * const aerror_unknown_mode;
extern const struct AspellErrorInfo * const aerror_mode_extend_expand;
extern const struct AspellErrorInfo * const aerror_filter_mode_magic;
extern const struct AspellErrorInfo * const aerror_file_magic_pos;
extern const struct AspellErrorInfo * const aerror_file_magic_range;
extern const struct AspellErrorInfo * const aerror_missing_magic;
extern const struct AspellErrorInfo * const aerror_bad_magic;
extern const struct AspellErrorInfo * const aerror_expression;
extern const struct AspellErrorInfo * const aerror_invalid_expression;
/******************************* speller *******************************/
typedef struct AspellSpeller AspellSpeller;
struct AspellCanHaveError * new_aspell_speller(struct AspellConfig * config);
struct AspellSpeller * to_aspell_speller(struct AspellCanHaveError * obj);
void delete_aspell_speller(struct AspellSpeller * ths);
unsigned int aspell_speller_error_number(const struct AspellSpeller * ths);
const char * aspell_speller_error_message(const struct AspellSpeller * ths);
const struct AspellError * aspell_speller_error(const struct AspellSpeller * ths);
struct AspellConfig * aspell_speller_config(struct AspellSpeller * ths);
/* Returns 0 if it is not in the dictionary,
* 1 if it is, or -1 on error. */
int aspell_speller_check(struct AspellSpeller * ths, const char * word, int word_size);
/* Add this word to your own personal word list. */
int aspell_speller_add_to_personal(struct AspellSpeller * ths, const char * word, int word_size);
/* Add this word to the current spelling session. */
int aspell_speller_add_to_session(struct AspellSpeller * ths, const char * word, int word_size);
/* This is your own personal word list file plus
* any extra words added during this session to
* your own personal word list. */
const struct AspellWordList * aspell_speller_personal_word_list(struct AspellSpeller * ths);
/* This is a list of words added to this session
* that are not in the main word list or in your
* own personal list but are considered valid for
* this spelling session. */
const struct AspellWordList * aspell_speller_session_word_list(struct AspellSpeller * ths);
/* This is the main list of words used during this
* spelling session. */
const struct AspellWordList * aspell_speller_main_word_list(struct AspellSpeller * ths);
int aspell_speller_save_all_word_lists(struct AspellSpeller * ths);
int aspell_speller_clear_session(struct AspellSpeller * ths);
/* Return NULL on error.
* The word list returned by suggest is only
* valid until the next call to suggest. */
const struct AspellWordList * aspell_speller_suggest(struct AspellSpeller * ths, const char * word, int word_size);
int aspell_speller_store_replacement(struct AspellSpeller * ths, const char * mis, int mis_size, const char * cor, int cor_size);
/******************************** filter ********************************/
typedef struct AspellFilter AspellFilter;
void delete_aspell_filter(struct AspellFilter * ths);
unsigned int aspell_filter_error_number(const struct AspellFilter * ths);
const char * aspell_filter_error_message(const struct AspellFilter * ths);
const struct AspellError * aspell_filter_error(const struct AspellFilter * ths);
struct AspellFilter * to_aspell_filter(struct AspellCanHaveError * obj);
/*************************** document checker ***************************/
struct AspellToken {
unsigned int offset;
unsigned int len;
};
typedef struct AspellToken AspellToken;
typedef struct AspellDocumentChecker AspellDocumentChecker;
void delete_aspell_document_checker(struct AspellDocumentChecker * ths);
unsigned int aspell_document_checker_error_number(const struct AspellDocumentChecker * ths);
const char * aspell_document_checker_error_message(const struct AspellDocumentChecker * ths);
const struct AspellError * aspell_document_checker_error(const struct AspellDocumentChecker * ths);
/* Creates a new document checker.
* The speller class is expected to last until
* this class is destroyed.
* If config is given it will be used to override
* any relevent options set by this speller class.
* The config class is not once this function is done.
* If filter is given then it will take ownership of
* the filter class and use it to do the filtering.
* You are expected to free the checker when done. */
struct AspellCanHaveError * new_aspell_document_checker(struct AspellSpeller * speller);
struct AspellDocumentChecker * to_aspell_document_checker(struct AspellCanHaveError * obj);
/* Reset the internal state of the filter.
* Should be called whenever a new document is
* being filtered. */
void aspell_document_checker_reset(struct AspellDocumentChecker * ths);
/* Process a string.
* The string passed in should only be split on
* white space characters. Furthermore, between
* calls to reset, each string should be passed
* in exactly once and in the order they appeared
* in the document. Passing in strings out of
* order, skipping strings or passing them in
* more than once may lead to undefined results. */
void aspell_document_checker_process(struct AspellDocumentChecker * ths, const char * str, int size);
/* Returns the next misspelled word in the
* processed string. If there are no more
* misspelled words, then token.word will be
* NULL and token.size will be 0 */
struct AspellToken aspell_document_checker_next_misspelling(struct AspellDocumentChecker * ths);
/* Returns the underlying filter class. */
struct AspellFilter * aspell_document_checker_filter(struct AspellDocumentChecker * ths);
/****************************** word list ******************************/
typedef struct AspellWordList AspellWordList;
int aspell_word_list_empty(const struct AspellWordList * ths);
unsigned int aspell_word_list_size(const struct AspellWordList * ths);
struct AspellStringEnumeration * aspell_word_list_elements(const struct AspellWordList * ths);
/************************** string enumeration **************************/
typedef struct AspellStringEnumeration AspellStringEnumeration;
void delete_aspell_string_enumeration(struct AspellStringEnumeration * ths);
struct AspellStringEnumeration * aspell_string_enumeration_clone(const struct AspellStringEnumeration * ths);
void aspell_string_enumeration_assign(struct AspellStringEnumeration * ths, const struct AspellStringEnumeration * other);
int aspell_string_enumeration_at_end(const struct AspellStringEnumeration * ths);
const char * aspell_string_enumeration_next(struct AspellStringEnumeration * ths);
/********************************* info *********************************/
struct AspellModuleInfo {
const char * name;
double order_num;
const char * lib_dir;
struct AspellStringList * dict_dirs;
struct AspellStringList * dict_exts;
};
typedef struct AspellModuleInfo AspellModuleInfo;
struct AspellDictInfo {
/* The Name to identify this dictionary by. */
const char * name;
/* The language code to identify this dictionary.
* A two letter UPPER-CASE ISO 639 language code
* and an optional two letter ISO 3166 country
* code after a dash or underscore. */
const char * code;
/* Any extra information to distinguish this
* variety of dictionary from other dictionaries
* which may have the same language and size. */
const char * jargon;
int size;
/* A two char digit code describing the size of
* the dictionary: 10=tiny, 20=really small,
* 30=small, 40=med-small, 50=med, 60=med-large,
* 70=large, 80=huge, 90=insane. Please check
* the README in aspell-lang-200?????.tar.bz2 or
* see SCOWL (http://wordlist.sourceforge.net)
* for an example of how these sizes are used. */
const char * size_str;
struct AspellModuleInfo * module;
};
typedef struct AspellDictInfo AspellDictInfo;
typedef struct AspellModuleInfoList AspellModuleInfoList;
struct AspellModuleInfoList * get_aspell_module_info_list(struct AspellConfig * config);
int aspell_module_info_list_empty(const struct AspellModuleInfoList * ths);
unsigned int aspell_module_info_list_size(const struct AspellModuleInfoList * ths);
struct AspellModuleInfoEnumeration * aspell_module_info_list_elements(const struct AspellModuleInfoList * ths);
typedef struct AspellDictInfoList AspellDictInfoList;
struct AspellDictInfoList * get_aspell_dict_info_list(struct AspellConfig * config);
int aspell_dict_info_list_empty(const struct AspellDictInfoList * ths);
unsigned int aspell_dict_info_list_size(const struct AspellDictInfoList * ths);
struct AspellDictInfoEnumeration * aspell_dict_info_list_elements(const struct AspellDictInfoList * ths);
typedef struct AspellModuleInfoEnumeration AspellModuleInfoEnumeration;
int aspell_module_info_enumeration_at_end(const struct AspellModuleInfoEnumeration * ths);
const struct AspellModuleInfo * aspell_module_info_enumeration_next(struct AspellModuleInfoEnumeration * ths);
void delete_aspell_module_info_enumeration(struct AspellModuleInfoEnumeration * ths);
struct AspellModuleInfoEnumeration * aspell_module_info_enumeration_clone(const struct AspellModuleInfoEnumeration * ths);
void aspell_module_info_enumeration_assign(struct AspellModuleInfoEnumeration * ths, const struct AspellModuleInfoEnumeration * other);
typedef struct AspellDictInfoEnumeration AspellDictInfoEnumeration;
int aspell_dict_info_enumeration_at_end(const struct AspellDictInfoEnumeration * ths);
const struct AspellDictInfo * aspell_dict_info_enumeration_next(struct AspellDictInfoEnumeration * ths);
void delete_aspell_dict_info_enumeration(struct AspellDictInfoEnumeration * ths);
struct AspellDictInfoEnumeration * aspell_dict_info_enumeration_clone(const struct AspellDictInfoEnumeration * ths);
void aspell_dict_info_enumeration_assign(struct AspellDictInfoEnumeration * ths, const struct AspellDictInfoEnumeration * other);
/***************************** string list *****************************/
typedef struct AspellStringList AspellStringList;
struct AspellStringList * new_aspell_string_list();
int aspell_string_list_empty(const struct AspellStringList * ths);
unsigned int aspell_string_list_size(const struct AspellStringList * ths);
struct AspellStringEnumeration * aspell_string_list_elements(const struct AspellStringList * ths);
int aspell_string_list_add(struct AspellStringList * ths, const char * to_add);
int aspell_string_list_remove(struct AspellStringList * ths, const char * to_rem);
void aspell_string_list_clear(struct AspellStringList * ths);
struct AspellMutableContainer * aspell_string_list_to_mutable_container(struct AspellStringList * ths);
void delete_aspell_string_list(struct AspellStringList * ths);
struct AspellStringList * aspell_string_list_clone(const struct AspellStringList * ths);
void aspell_string_list_assign(struct AspellStringList * ths, const struct AspellStringList * other);
/****************************** string map ******************************/
typedef struct AspellStringMap AspellStringMap;
struct AspellStringMap * new_aspell_string_map();
int aspell_string_map_add(struct AspellStringMap * ths, const char * to_add);
int aspell_string_map_remove(struct AspellStringMap * ths, const char * to_rem);
void aspell_string_map_clear(struct AspellStringMap * ths);
struct AspellMutableContainer * aspell_string_map_to_mutable_container(struct AspellStringMap * ths);
void delete_aspell_string_map(struct AspellStringMap * ths);
struct AspellStringMap * aspell_string_map_clone(const struct AspellStringMap * ths);
void aspell_string_map_assign(struct AspellStringMap * ths, const struct AspellStringMap * other);
int aspell_string_map_empty(const struct AspellStringMap * ths);
unsigned int aspell_string_map_size(const struct AspellStringMap * ths);
struct AspellStringPairEnumeration * aspell_string_map_elements(const struct AspellStringMap * ths);
/* Insert a new element.
* Will NOT overwrite an existing entry.
* Returns FALSE if the element already exists. */
int aspell_string_map_insert(struct AspellStringMap * ths, const char * key, const char * value);
/* Insert a new element.
* Will overwrite an existing entry.
* Always returns TRUE. */
int aspell_string_map_replace(struct AspellStringMap * ths, const char * key, const char * value);
/* Looks up an element and returns the value.
* Returns NULL if the element does not exist.
* Returns an empty string if the element exists
* but has a NULL value. */
const char * aspell_string_map_lookup(const struct AspellStringMap * ths, const char * key);
/***************************** string pair *****************************/
struct AspellStringPair {
const char * first;
const char * second;
};
typedef struct AspellStringPair AspellStringPair;
/*********************** string pair enumeration ***********************/
typedef struct AspellStringPairEnumeration AspellStringPairEnumeration;
int aspell_string_pair_enumeration_at_end(const struct AspellStringPairEnumeration * ths);
struct AspellStringPair aspell_string_pair_enumeration_next(struct AspellStringPairEnumeration * ths);
void delete_aspell_string_pair_enumeration(struct AspellStringPairEnumeration * ths);
struct AspellStringPairEnumeration * aspell_string_pair_enumeration_clone(const struct AspellStringPairEnumeration * ths);
void aspell_string_pair_enumeration_assign(struct AspellStringPairEnumeration * ths, const struct AspellStringPairEnumeration * other);
/******************************** cache ********************************/
/* Reset the global cache(s) so that cache queries will
* create a new object. If existing objects are still in
* use they are not deleted. If which is NULL then all
* caches will be reset. Current caches are "encode",
* "decode", "dictionary", "language", and "keyboard". */
int aspell_reset_cache(const char * which);
#ifdef __cplusplus
}
#endif
#endif /* ASPELL_ASPELL__H */

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2006-2019 J.F.Dockes
/* Copyright (C) 2006-2021 J.F.Dockes
* 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
@ -18,8 +18,6 @@
#ifdef RCL_USE_ASPELL
#include ASPELL_INCLUDE
#include <mutex>
#include <stdlib.h>
@ -34,72 +32,11 @@
using namespace std;
// Aspell library entry points
class AspellApi {
public:
struct AspellConfig *(*new_aspell_config)();
int (*aspell_config_replace)(struct AspellConfig *, const char * key,
const char * value);
struct AspellCanHaveError *(*new_aspell_speller)(struct AspellConfig *);
void (*delete_aspell_config)(struct AspellConfig *);
void (*delete_aspell_can_have_error)(struct AspellCanHaveError *);
struct AspellSpeller * (*to_aspell_speller)(struct AspellCanHaveError *);
struct AspellConfig * (*aspell_speller_config)(struct AspellSpeller *);
const struct AspellWordList * (*aspell_speller_suggest)
(struct AspellSpeller *, const char *, int);
int (*aspell_speller_check)(struct AspellSpeller *, const char *, int);
struct AspellStringEnumeration * (*aspell_word_list_elements)
(const struct AspellWordList * ths);
const char * (*aspell_string_enumeration_next)
(struct AspellStringEnumeration * ths);
void (*delete_aspell_string_enumeration)(struct AspellStringEnumeration *);
const struct AspellError *(*aspell_error)
(const struct AspellCanHaveError *);
const char *(*aspell_error_message)(const struct AspellCanHaveError *);
const char *(*aspell_speller_error_message)(const struct AspellSpeller *);
void (*delete_aspell_speller)(struct AspellSpeller *);
};
static AspellApi aapi;
static std::mutex o_aapi_mutex;
#define NMTOPTR(NM, TP) \
if ((aapi.NM = TP dlib_sym(m_data->m_handle, #NM)) == 0) { \
badnames += #NM + string(" "); \
}
static const vector<string> aspell_lib_suffixes {
#if defined(__APPLE__)
".15.dylib",
".dylib",
#elif defined(_WIN32)
"-15.dll",
#else
".so",
".so.15",
#endif
};
// Private rclaspell data
class AspellData {
public:
~AspellData() {
LOGDEB2("~AspellData\n" );
if (m_handle) {
dlib_close(m_handle);
m_handle = nullptr;
}
if (m_speller) {
// Dumps core if I do this??
//aapi.delete_aspell_speller(m_speller);
m_speller = nullptr;
LOGDEB2("~AspellData: speller done\n" );
}
}
void *m_handle{nullptr};
string m_exec;
AspellSpeller *m_speller{nullptr};
ExecCmd m_speller;
#ifdef _WIN32
string m_datadir;
#endif
@ -118,7 +55,6 @@ Aspell::~Aspell()
bool Aspell::init(string &reason)
{
std::unique_lock<std::mutex> locker(o_aapi_mutex);
deleteZ(m_data);
// Language: we get this from the configuration, else from the NLS
@ -149,11 +85,10 @@ bool Aspell::init(string &reason)
m_config->getConfParam("aspellAddCreateParam", m_data->m_addCreateParam);
#ifdef _WIN32
m_data->m_datadir = path_cat(
path_pkgdatadir(),
"filters/aspell-installed/mingw32/lib/aspell-0.60");
path_pkgdatadir(), "filters/aspell-installed/mingw32/lib/aspell-0.60");
if (m_data->m_addCreateParam.empty()) {
m_data->m_addCreateParam = string("--local-data-dir=") +
path_cat(m_config->getConfDir(), "aspell");
m_data->m_addCreateParam =
string("--local-data-dir=") + path_cat(m_config->getConfDir(), "aspell");
}
#endif // WIN32
@ -179,110 +114,16 @@ bool Aspell::init(string &reason)
return false;
}
// Don't know what with Apple and (DY)LD_LIBRARY_PATH. Does not work
// So we look in all ../lib in the PATH...
#if defined(__APPLE__)
vector<string> path;
const char *pp = getenv("PATH");
if (pp) {
stringToTokens(pp, path, ":");
}
#endif
reason = "Could not open shared library ";
string libbase("libaspell");
string lib;
for (const auto& suff : aspell_lib_suffixes) {
lib = libbase + suff;
reason += string("[") + lib + "] ";
if ((m_data->m_handle = dlib_open(lib)) != 0) {
reason.erase();
goto found;
}
// Above was the normal lookup: let dlopen search the directories.
// Also look in other places for Apple and Windows.
#if defined(__APPLE__)
for (const auto& dir : path) {
string lib1 = path_canon(dir + "/../lib/" + lib);
if ((m_data->m_handle = dlib_open(lib1)) != 0) {
reason.erase();
lib=lib1;
goto found;
}
}
#endif
#if defined(_WIN32) && !defined(_MSC_VER)
// Look in the directory of the aspell binary. When building
// with msvc, the aspell .exe is still the mingw one, but we
// copy the msvc dll in the recoll top directory, so no need
// to look in the aspell one.
{
string bindir = path_getfather(m_data->m_exec);
string lib1 = path_cat(bindir, lib);
if ((m_data->m_handle = dlib_open(lib1)) != 0) {
reason.erase();
lib=lib1;
goto found;
}
}
#endif
}
found:
if (m_data->m_handle == 0) {
reason += string(" : ") + dlib_error();
deleteZ(m_data);
return false;
}
string badnames;
NMTOPTR(new_aspell_config, (struct AspellConfig *(*)()));
NMTOPTR(aspell_config_replace, (int (*)(struct AspellConfig *,
const char *, const char *)));
NMTOPTR(new_aspell_speller,
(struct AspellCanHaveError *(*)(struct AspellConfig *)));
NMTOPTR(delete_aspell_config,
(void (*)(struct AspellConfig *)));
NMTOPTR(delete_aspell_can_have_error,
(void (*)(struct AspellCanHaveError *)));
NMTOPTR(to_aspell_speller,
(struct AspellSpeller *(*)(struct AspellCanHaveError *)));
NMTOPTR(aspell_speller_config,
(struct AspellConfig *(*)(struct AspellSpeller *)));
NMTOPTR(aspell_speller_suggest,
(const struct AspellWordList *(*)(struct AspellSpeller *,
const char *, int)));
NMTOPTR(aspell_speller_check,
(int (*)(struct AspellSpeller *, const char *, int)));
NMTOPTR(aspell_word_list_elements,
(struct AspellStringEnumeration *(*)
(const struct AspellWordList *)));
NMTOPTR(aspell_string_enumeration_next,
(const char * (*)(struct AspellStringEnumeration *)));
NMTOPTR(delete_aspell_string_enumeration,
(void (*)(struct AspellStringEnumeration *)));
NMTOPTR(aspell_error,
(const struct AspellError*(*)(const struct AspellCanHaveError *)));
NMTOPTR(aspell_error_message,
(const char *(*)(const struct AspellCanHaveError *)));
NMTOPTR(aspell_speller_error_message,
(const char *(*)(const struct AspellSpeller *)));
NMTOPTR(delete_aspell_speller, (void (*)(struct AspellSpeller *)));
if (!badnames.empty()) {
reason = string("Aspell::init: symbols not found:") + badnames;
deleteZ(m_data);
return false;
}
return true;
}
bool Aspell::ok() const
{
return m_data != 0 && m_data->m_handle != 0;
return nullptr != m_data;
}
string Aspell::dicPath()
{
string ccdir = m_config->getAspellcacheDir();
@ -409,84 +250,76 @@ bool Aspell::buildDict(Rcl::Db &db, string &reason)
return true;
}
static const unsigned int ldatadiroptsz =
string("--local-data-dir=").size();
static const unsigned int ldatadiroptsz = strlen("--local-data-dir=");
bool Aspell::make_speller(string& reason)
{
if (!ok())
return false;
if (m_data->m_speller != 0)
if (m_data->m_speller.getChildPid() > 0)
return true;
AspellCanHaveError *ret;
// aspell --lang=[lang] --encoding=utf-8 --master=[dicPath()] --sug-mode=fast pipe
string cmdstring(m_data->m_exec);
ExecCmd aspell;
vector<string> args;
args.push_back(string("--lang=")+ m_lang);
cmdstring += string(" ") + args.back();
args.push_back("--encoding=utf-8");
cmdstring += string(" ") + args.back();
AspellConfig *config = aapi.new_aspell_config();
aapi.aspell_config_replace(config, "lang", m_lang.c_str());
aapi.aspell_config_replace(config, "encoding", "utf-8");
aapi.aspell_config_replace(config, "master", dicPath().c_str());
aapi.aspell_config_replace(config, "sug-mode", "fast");
#ifdef _WIN32
aapi.aspell_config_replace(config, "data-dir", m_data->m_datadir.c_str());
args.push_back(string("--data-dir=") + m_data->m_datadir);
cmdstring += string(" ") + args.back();
#endif
if (m_data->m_addCreateParam.size() > ldatadiroptsz) {
aapi.aspell_config_replace(
config, "local-data-dir",
m_data->m_addCreateParam.substr(ldatadiroptsz).c_str());
args.push_back(
string("--local-data-dir=") + m_data->m_addCreateParam.substr(ldatadiroptsz));
cmdstring += string(" ") + args.back();
}
// aapi.aspell_config_replace(config, "sug-edit-dist", "2");
ret = aapi.new_aspell_speller(config);
aapi.delete_aspell_config(config);
if (aapi.aspell_error(ret) != 0) {
reason = aapi.aspell_error_message(ret);
aapi.delete_aspell_can_have_error(ret);
if (!m_data->m_addCreateParam.empty()) {
args.push_back(m_data->m_addCreateParam);
cmdstring += string(" ") + args.back();
}
args.push_back(string("--master=") + dicPath());
cmdstring += string(" ") + args.back();
args.push_back(string("--sug-mode=fast"));
cmdstring += string(" ") + args.back();
args.push_back("pipe");
cmdstring += string(" ") + args.back();
// Keep stderr by default when querying?
bool keepStderr = true;
m_config->getConfParam("aspellKeepStderr", &keepStderr);
if (!keepStderr)
m_data->m_speller.setStderr("/dev/null");
LOGDEB("Starting aspell command [" << cmdstring << "]\n");
if (m_data->m_speller.startExec(m_data->m_exec, args, true, true) != 0) {
LOGERR("Can't start aspell\n");
return false;
}
m_data->m_speller = aapi.to_aspell_speller(ret);
// Read initial line from aspell: version etc.
string line;
if (m_data->m_speller.getline(line, 2) <= 0) {
LOGERR("rclaspell: failed reading initial aspell line. Command was " << cmdstring << "\n");
m_data->m_speller.zapChild();
return false;
}
LOGDEB("rclaspell: aspell initial answer: [" << line << "]\n");
return true;
}
bool Aspell::check(const string &iterm, string& reason)
{
LOGDEB("Aspell::check [" << iterm << "]\n");
string mterm(iterm);
if (!Rcl::Db::isSpellingCandidate(mterm)) {
LOGDEB0("Aspell::check: [" << mterm <<
" not spelling candidate, return true\n");
return true;
}
if (!ok() || !make_speller(reason))
return false;
if (iterm.empty())
return true; //??
if (!o_index_stripchars) {
string lower;
if (!unacmaybefold(mterm, lower, "UTF-8", UNACOP_FOLD)) {
LOGERR("Aspell::check: cant lowercase input\n");
return false;
}
mterm.swap(lower);
}
int ret = aapi.aspell_speller_check(m_data->m_speller,
mterm.c_str(), mterm.length());
reason.clear();
switch (ret) {
case 0: return false;
case 1: return true;
default:
case -1:
reason.append("Aspell error: ");
reason.append(aapi.aspell_speller_error_message(m_data->m_speller));
return false;
}
}
bool Aspell::suggest(Rcl::Db &db, const string &_term,
list<string>& suggestions, string& reason)
bool Aspell::suggest(
Rcl::Db &db, const string &_term, vector<string>& suggestions, string& reason)
{
LOGDEB("Aspell::suggest: term [" << _term << "]\n");
if (!ok() || !make_speller(reason))
@ -496,8 +329,7 @@ bool Aspell::suggest(Rcl::Db &db, const string &_term,
return true; //??
if (!Rcl::Db::isSpellingCandidate(mterm)) {
LOGDEB0("Aspell::suggest: [" << mterm <<
" not spelling candidate, return empty/true\n");
LOGDEB0("Aspell::suggest: [" << mterm << " not spelling candidate, return empty/true\n");
return true;
}
@ -510,27 +342,37 @@ bool Aspell::suggest(Rcl::Db &db, const string &_term,
mterm.swap(lower);
}
const AspellWordList *wl =
aapi.aspell_speller_suggest(m_data->m_speller,
mterm.c_str(), mterm.length());
if (wl == 0) {
reason = aapi.aspell_speller_error_message(m_data->m_speller);
m_data->m_speller.send(mterm + "\n");
std::string line;
if (m_data->m_speller.getline(line, 3) <= 0) {
reason.append("Aspell error: ");
return false;
}
AspellStringEnumeration *els = aapi.aspell_word_list_elements(wl);
const char *word;
while ((word = aapi.aspell_string_enumeration_next(els)) != 0) {
LOGDEB0("Aspell::suggest: got [" << word << "]\n");
// Check that the word exists in the index (we don't want
// aspell computed stuff, only exact terms from the
// dictionary). We used to also check that it stems
// differently from the base word but this is complicated
// (stemming on/off + language), so we now leave this to the
// caller.
LOGDEB1("ASPELL: got answer: " << line << "\n");
string empty;
if (m_data->m_speller.getline(empty, 1) <= 0) {
reason.append("Aspell: failed reading final empty line\n");
return false;
}
if (line[0] == '*' || line[0] == '#') {
// Word is in dictionary, or there are no suggestions
return true;
}
string::size_type colon;
// Aspell suggestions line: & original count offset: miss, miss, …
if (line[0] != '&' || (colon = line.find(':')) == string::npos || colon == line.size()-1) {
// ??
reason.append("Aspell: bad answer line: ");
reason.append(line);
return false;
}
std::vector<std::string> words;
stringSplitString(line.substr(colon + 2), words, ", ");
for (const auto& word : words) {
if (db.termExists(word))
suggestions.push_back(word);
}
aapi.delete_aspell_string_enumeration(els);
return true;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2006 J.F.Dockes
/* Copyright (C) 2006-2021 J.F.Dockes
* 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
@ -27,12 +27,10 @@
* exist in the document set for a given word.
* A specific aspell dictionary is created out of all the terms in the
* xapian index, and we then use it to expand a term to spelling neighbours.
* We use the aspell C api for term expansion, but have
* to execute the program to create dictionaries.
*/
#include <string>
#include <list>
#include <vector>
#include "rclconfig.h"
#include "rcldb.h"
@ -40,7 +38,7 @@
class AspellData;
class Aspell {
public:
public:
Aspell(const RclConfig *cnf);
~Aspell();
@ -54,19 +52,11 @@ class Aspell {
* of an indexing pass. */
bool buildDict(Rcl::Db &db, std::string &reason);
/** Check that word is in dictionary. Note that this would mean
* that the EXACT word is: aspell just does a lookup, no
* grammatical, case or diacritics magic of any kind
*
* @return true if word in dic, false if not. reason.size() -> error
*/
bool check(const std::string& term, std::string& reason);
/** Return a list of possible expansions for a given word */
bool suggest(Rcl::Db &db, const std::string& term,
std::list<std::string> &suggestions, std::string &reason);
private:
std::vector<std::string> &suggestions, std::string &reason);
private:
std::string dicPath();
const RclConfig *m_config;
std::string m_lang;

View File

@ -10,9 +10,6 @@
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Path to the aspell api include file */
#define ASPELL_INCLUDE "../aspell/aspell-local.h"
/* Path to the aspell program */
#define ASPELL_PROG "/opt/local/bin/aspell"

View File

@ -4,9 +4,6 @@
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Path to the aspell api include file */
#define ASPELL_INCLUDE "aspell-local.h"
/* Aspell program parameter to findFilter(). */
#define ASPELL_PROG "aspell-installed/mingw32/bin/aspell"

View File

@ -3,9 +3,6 @@
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Path to the aspell api include file */
#undef ASPELL_INCLUDE
/* Path to the aspell program */
#undef ASPELL_PROG

View File

@ -114,20 +114,8 @@ if test X$withAspell != Xno ; then
if test X$aspellProg != X ; then
aspellBase=`dirname $aspellProg`
aspellBase=`dirname $aspellBase`
AC_DEFINE_UNQUOTED(ASPELL_PROG, "$aspellProg",
[Path to the aspell program])
if test -f $aspellBase/include/aspell.h ; then
AC_DEFINE_UNQUOTED(ASPELL_INCLUDE, "$aspellBase/include/aspell.h",
[Path to the aspell api include file])
else
AC_MSG_NOTICE([aspell support enabled but aspell package not found. Compiling with internal aspell interface file])
AC_DEFINE(ASPELL_INCLUDE, ["aspell-local.h"])
fi
else
# aspell support enabled but no aspell install yet
AC_MSG_NOTICE([aspell support enabled but aspell package not found. Compiling with internal aspell interface file])
AC_DEFINE(ASPELL_INCLUDE, ["aspell-local.h"])
fi
AC_DEFINE_UNQUOTED(ASPELL_PROG, "$aspellProg", [Path to the aspell program])
fi
fi
if test -f /usr/include/sys/inotify.h -o -f /usr/include/linux/inotify.h; then

View File

@ -1453,14 +1453,11 @@ bool Db::getSpellingSuggestions(const string& word, vector<string>& suggs)
return false;
}
list<string> asuggs;
string reason;
if (!m_aspell->suggest(*this, term, asuggs, reason)) {
LOGERR("Db::getSpellingSuggestions: aspell failed: " << reason <<
"\n");
if (!m_aspell->suggest(*this, term, suggs, reason)) {
LOGERR("Db::getSpellingSuggestions: aspell failed: " << reason << "\n");
return false;
}
suggs = vector<string>(asuggs.begin(), asuggs.end());
#endif
} else {
#ifdef TESTING_XAPIAN_SPELL

View File

@ -37,11 +37,10 @@ static char *thisprog;
RclConfig *rclconfig;
static char usage [] =
" -b : build dictionary\n"
" -s <term>: suggestions for term\n"
" -c <term>: check term\n"
"\n"
;
" -b : build dictionary\n"
" -s <term>: suggestions for term\n"
"\n"
;
static void
Usage(void)
{
@ -63,83 +62,71 @@ int main(int argc, char **argv)
argc--; argv++;
while (argc > 0 && **argv == '-') {
(*argv)++;
if (!(**argv))
/* Cas du "adb - core" */
Usage();
while (**argv)
switch (*(*argv)++) {
case 'b': op_flags |= OPT_b; break;
case 'c': op_flags |= OPT_c; if (argc < 2) Usage();
word = *(++argv);
argc--;
goto b1;
case 's': op_flags |= OPT_s; if (argc < 2) Usage();
word = *(++argv);
argc--;
goto b1;
default: Usage(); break;
}
(*argv)++;
if (!(**argv))
/* Cas du "adb - core" */
Usage();
while (**argv)
switch (*(*argv)++) {
case 'b': op_flags |= OPT_b; break;
case 'c': op_flags |= OPT_c; if (argc < 2) Usage();
word = *(++argv);
argc--;
goto b1;
case 's': op_flags |= OPT_s; if (argc < 2) Usage();
word = *(++argv);
argc--;
goto b1;
default: Usage(); break;
}
b1: argc--; argv++;
}
if (argc != 0 || op_flags == 0)
Usage();
Usage();
string reason;
rclconfig = recollinit(0, 0, 0, reason);
if (!rclconfig || !rclconfig->ok()) {
fprintf(stderr, "Configuration problem: %s\n", reason.c_str());
exit(1);
fprintf(stderr, "Configuration problem: %s\n", reason.c_str());
exit(1);
}
string dbdir = rclconfig->getDbDir();
if (dbdir.empty()) {
fprintf(stderr, "No db directory in configuration");
exit(1);
fprintf(stderr, "No db directory in configuration");
exit(1);
}
Rcl::Db rcldb(rclconfig);
if (!rcldb.open(Rcl::Db::DbRO, 0)) {
fprintf(stderr, "Could not open database in %s\n", dbdir.c_str());
exit(1);
fprintf(stderr, "Could not open database in %s\n", dbdir.c_str());
exit(1);
}
Aspell aspell(rclconfig);
if (!aspell.init(reason)) {
cerr << "Init failed: " << reason << endl;
exit(1);
cerr << "Init failed: " << reason << endl;
exit(1);
}
if (op_flags & OPT_b) {
if (!aspell.buildDict(rcldb, reason)) {
cerr << "buildDict failed: " << reason << endl;
exit(1);
}
} else if (op_flags & OPT_c) {
bool ret = aspell.check(word, reason);
if (!ret && reason.size()) {
cerr << "Aspell error: " << reason << endl;
return 1;
}
cout << word;
if (ret) {
cout << " is in dictionary" << endl;
if (!aspell.buildDict(rcldb, reason)) {
cerr << "buildDict failed: " << reason << endl;
exit(1);
}
} else {
cout << " not in dictionary" << endl;
}
} else {
list<string> suggs;
if (!aspell.suggest(rcldb, word, suggs, reason)) {
cerr << "suggest failed: " << reason << endl;
exit(1);
}
cout << "Suggestions for " << word << ":" << endl;
for (list<string>::iterator it = suggs.begin();
it != suggs.end(); it++) {
cout << *it << endl;
}
list<string> suggs;
if (!aspell.suggest(rcldb, word, suggs, reason)) {
cerr << "suggest failed: " << reason << endl;
exit(1);
}
cout << "Suggestions for " << word << ":" << endl;
for (list<string>::iterator it = suggs.begin();
it != suggs.end(); it++) {
cout << *it << endl;
}
}
exit(0);
}