#include "stdafx.h" #include "common.h" #include "sabbu.h" #ifdef HAVE_ASPELL #ifndef _WINDOWS #include #endif #endif //#include "aspell.h" #ifdef _WINDOWS struct AspellDictInfo { /* name to identify the dictionary by */ const char * name; const char * code; const char * jargon; int size; const char * size_str; struct AspellModuleInfo * module; }; struct AspellConfig * (*new_aspell_config)() = NULL; struct AspellDictInfoList * (*get_aspell_dict_info_list)(struct AspellConfig * config); unsigned int (*aspell_dict_info_list_size)(const struct AspellDictInfoList * ths); struct AspellDictInfoEnumeration * (*aspell_dict_info_list_elements)(const struct AspellDictInfoList * ths); const struct AspellDictInfo * (*aspell_dict_info_enumeration_next)(struct AspellDictInfoEnumeration * ths); struct AspellCanHaveError * (*new_aspell_speller)(struct AspellConfig * config); unsigned int (*aspell_error_number)(const struct AspellCanHaveError * ths); struct AspellSpeller * (*to_aspell_speller)(struct AspellCanHaveError * obj); int (*aspell_speller_check)(struct AspellSpeller * ths, const char * word, int word_size); const struct AspellWordList * (*aspell_speller_suggest)(struct AspellSpeller * ths, const char * word, int word_size); 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 * ths); int (*aspell_config_replace)(struct AspellConfig *ths, const char * key, const char * value); void (*delete_aspell_speller)(struct AspellSpeller *ths); int (*aspell_speller_add_to_session)(struct AspellSpeller * ths, const char * word, int word_size); int (*aspell_speller_add_to_personal)(struct AspellSpeller * ths, const char * word, int word_size); int (*aspell_speller_save_all_word_lists)(struct AspellSpeller * ths); const char *(*aspell_config_retrieve)(struct AspellConfig * ths, const char * key); struct AspellConfig *(*aspell_speller_config)(struct AspellSpeller * ths); #endif enum spell_status_enum { ASPELL_NOT_INITIALIZED, ASPELL_NOT_INSTALLED, ASPELL_NOT_COMPILED, ASPELL_LOAD_ERROR, ASPELL_AVAILABLE } spell_status = ASPELL_NOT_INITIALIZED; struct AspellConfig *aspell_config = NULL; gboolean spell_load_symbol(GModule *module, char *symbol, void **dest) { if(!g_module_symbol(module, symbol, dest)) { spell_status = ASPELL_LOAD_ERROR; return FALSE; } return TRUE; } #ifdef _WINDOWS void spell_init() { HKEY hkey; int rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Aspell", 0, KEY_QUERY_VALUE, &hkey); if(rv != ERROR_SUCCESS) { spell_status = ASPELL_NOT_INSTALLED; return; } WCHAR value[255]; DWORD len = 255; rv = RegQueryValueExW(hkey, L"Path", 0, 0, (LPBYTE) value, &len); if(rv != ERROR_SUCCESS) { spell_status = ASPELL_NOT_INSTALLED; return; } char *path = g_utf16_to_utf8(value, -1, NULL, NULL, NULL); char *dll = kry_strdup_printf(KRY_LOC "%s\\aspell-15.dll", path); kry_free(path); GModule *module = g_module_open(dll, G_MODULE_BIND_LAZY); if(!module) { spell_status = ASPELL_LOAD_ERROR; return; } if(!spell_load_symbol(module, "new_aspell_config", (void **) &new_aspell_config)) return; if(!spell_load_symbol(module, "get_aspell_dict_info_list", (void **) &get_aspell_dict_info_list)) return; if(!spell_load_symbol(module, "aspell_dict_info_list_elements", (void **) &aspell_dict_info_list_elements)) return; if(!spell_load_symbol(module, "aspell_dict_info_enumeration_next", (void **) &aspell_dict_info_enumeration_next)) return; if(!spell_load_symbol(module, "new_aspell_speller", (void **) &new_aspell_speller)) return; if(!spell_load_symbol(module, "aspell_error_number", (void **) &aspell_error_number)) return; if(!spell_load_symbol(module, "to_aspell_speller", (void **) &to_aspell_speller)) return; if(!spell_load_symbol(module, "aspell_speller_check", (void **) &aspell_speller_check)) return; if(!spell_load_symbol(module, "aspell_speller_suggest", (void **) &aspell_speller_suggest)) return; if(!spell_load_symbol(module, "aspell_word_list_elements", (void **) &aspell_word_list_elements)) return; if(!spell_load_symbol(module, "aspell_string_enumeration_next", (void **) &aspell_string_enumeration_next)) return; if(!spell_load_symbol(module, "delete_aspell_string_enumeration", (void **) &delete_aspell_string_enumeration)) return; if(!spell_load_symbol(module, "aspell_config_replace", (void **) &aspell_config_replace)) return; if(!spell_load_symbol(module, "delete_aspell_speller", (void **) &delete_aspell_speller)) return; if(!spell_load_symbol(module, "aspell_speller_add_to_session", (void **) &aspell_speller_add_to_session)) return; if(!spell_load_symbol(module, "aspell_speller_add_to_personal", (void **) &aspell_speller_add_to_personal)) return; if(!spell_load_symbol(module, "aspell_speller_save_all_word_lists", (void **) &aspell_speller_save_all_word_lists)) return; if(!spell_load_symbol(module, "aspell_config_retrieve", (void **) &aspell_config_retrieve)) return; aspell_config = new_aspell_config(); aspell_config_replace(aspell_config, "encoding", "utf-8"); spell_status = ASPELL_AVAILABLE; } #else void spell_init() { #ifdef HAVE_ASPELL aspell_config = new_aspell_config(); aspell_config_replace(aspell_config, "encoding", "utf-8"); spell_status = ASPELL_AVAILABLE; #else spell_status = ASPELL_NOT_COMPILED; #endif } #endif #ifdef HAVE_ASPELL struct AspellSpeller *spell_create(char *lang) { if(lang) aspell_config_replace(aspell_config, "lang", lang); AspellCanHaveError * possible_err = new_aspell_speller(aspell_config); if(aspell_error_number(possible_err) != 0) return NULL; struct AspellSpeller *speller = to_aspell_speller(possible_err); return speller; } void spell_destroy(struct AspellSpeller *speller) { aspell_speller_save_all_word_lists(speller); delete_aspell_speller(speller); } GList *spell_get_dict_list() { GList *dicts = NULL; struct AspellDictInfoList *list = get_aspell_dict_info_list(aspell_config); struct AspellDictInfoEnumeration *enumr = aspell_dict_info_list_elements(list); char *last_code = NULL; while(const struct AspellDictInfo *info = aspell_dict_info_enumeration_next(enumr)) { if(last_code && !strcmp(info->code, last_code)) continue; dicts = g_list_append(dicts, (gpointer) info->name); last_code = (char *) info->code; } return dicts; } struct dict_code_to_name_entry { char *code; char *name; }; struct dict_code_to_name_entry dict_code_to_name_map[] = { {"br", "Breton"}, {"cs", "Czech"}, {"cy", "Welsh"}, {"da", "Danish"}, {"de", "German"}, {"el", "Greek"}, {"en", "English"}, {"en_GB", "British English"}, {"en_CA", "Canadian English"}, {"en_US", "American English"}, {"eo", "Esperanto"}, {"es", "Spanish"}, {"fo", "Faroese"}, {"fr", "French"}, {"it", "Italian"}, {"nl", "Dutch"}, {"no", "Norwegian"}, {"pl", "Polish"}, {"pt", "Portuguese"}, {"ro", "Romanian"}, {"ru", "Russian"}, {"sk", "Slovak"}, {"sv", "Swedish"}, {"uk", "Ukrainian"}, }; char *spell_get_dict_name_from_code(char *code) { for(unsigned int i = 0; i < sizeof(dict_code_to_name_map) / sizeof(dict_code_to_name_entry); i++) { if(!strcmp(dict_code_to_name_map[i].code, code)) return dict_code_to_name_map[i].name; } return code; } char *spell_get_current_dict_name(struct AspellSpeller *speller) { return ""; /*struct AspellConfig *config = aspell_speller_config(speller); return spell_get_dict_name_from_code((char *) aspell_config_retrieve(config, "lang"));*/ } gboolean spell_check_word(struct AspellSpeller *speller, char *word) { return aspell_speller_check(speller, word, -1); } GList *spell_get_suggestions(struct AspellSpeller *speller, char *word) { GList *list = NULL; const AspellWordList *suggestions = aspell_speller_suggest(speller, word, -1); AspellStringEnumeration * elements = aspell_word_list_elements(suggestions); while (const char *suggest = aspell_string_enumeration_next(elements)) { list = g_list_append(list, kry_strdup(suggest)); } delete_aspell_string_enumeration(elements); return list; } void spell_add_to_session(struct AspellSpeller *speller, char *word) { aspell_speller_add_to_session(speller, word, strlen(word)); } void spell_add_to_personal(struct AspellSpeller *speller, char *word) { aspell_speller_add_to_personal(speller, word, strlen(word)); } gboolean spell_is_available() { return spell_status == ASPELL_AVAILABLE; } char *spell_get_error() { switch(spell_status) { case ASPELL_AVAILABLE: return "No Error"; case ASPELL_NOT_INSTALLED: return "You must have aspell installed in order to use this feature.\n\n" "Aspell is available from http://www.aspell.net/win32\n\n" "Install Aspell and restart Sabbu to use this feature."; case ASPELL_LOAD_ERROR: return "There was an error loading the Aspell library."; default: return "Unknown Error"; }; } #endif gboolean spell_is_boundary(gunichar c) { return (g_unichar_isspace(c) || g_unichar_ispunct(c) || g_unichar_isdigit(c)); } char *spell_find_word_start(char *text, int *offset, gboolean search_backward) { gboolean search_forward = !search_backward; if(search_backward) { gboolean first_char = TRUE; do { gunichar c = g_utf8_get_char(text); if(first_char && spell_is_boundary(c)) { search_forward = TRUE; break; } first_char = FALSE; if(*offset == 0) break; if(spell_is_boundary(c)) { text = g_utf8_next_char(text); (*offset)++; break; } (*offset)--; } while((text = g_utf8_prev_char(text))); } if(search_forward) { do { gunichar c = g_utf8_get_char(text); if(c == 0 || !spell_is_boundary(c)) break; (*offset)++; } while((text = g_utf8_next_char(text))); } return text; } char *spell_get_word(char **text, int *offset, int *offset_end, int *prefer_end_bound, gboolean start_backward) { if(prefer_end_bound && *offset_end >= *prefer_end_bound) return NULL; *offset = *offset_end; *text = spell_find_word_start(*text, offset, start_backward); *offset_end = *offset; if(!*text || *text[0] == 0) return NULL; char *text_orig = *text; char *text_next; do { gunichar c = g_utf8_get_char(*text); if(c == 0) { if(text_orig == *text) return NULL; else break; } text_next = g_utf8_next_char(*text); gunichar nc = g_utf8_get_char(text_next); if(g_unichar_isspace(c) || (g_unichar_ispunct(c) && (c != '\'' || nc == 's')) || g_unichar_isdigit(c)) break; (*offset_end)++; } while((*text = text_next)); int len = *text - text_orig; char *str = (char *) kry_malloc(len + 1); memcpy(str, text_orig, len); str[len] = 0; return str; }