--- mozilla/extensions/spellcheck/myspell/src/mozMySpell.cpp.myspell 2006-01-12 11:57:36.000000000 +0200 +++ mozilla/extensions/spellcheck/myspell/src/mozMySpell.cpp 2006-01-12 11:57:37.000000000 +0200 @@ -68,6 +68,7 @@ #include "nsUnicharUtilCIID.h" #include "nsUnicharUtils.h" #include "nsCRT.h" +#include "prio.h" #include const PRInt32 kFirstDirSize=8; @@ -108,7 +109,7 @@ if (*aDictionary && !mDictionary.Equals(aDictionary)) { mDictionary = aDictionary; - nsAutoString affFileName, dictFileName; + nsAutoString affFileName, dictFileName, pluginFileName; // XXX This isn't really good. nsIFile->Path isn't xp save etc. // see nsIFile.idl @@ -122,26 +123,62 @@ return NS_ERROR_FAILURE; rv = file->Append(NS_LITERAL_STRING("myspell")); NS_ENSURE_SUCCESS(rv, rv); - rv = file->Append(mDictionary + NS_LITERAL_STRING(".aff")); + rv = file->Append(mDictionary + NS_LITERAL_STRING(".plugin")); NS_ENSURE_SUCCESS(rv, rv); - file->GetPath(affFileName); - - rv = NS_GetSpecialDirectory(NS_XPCOM_COMPONENT_DIR, getter_AddRefs(file)); - NS_ENSURE_SUCCESS(rv, rv); - if (!file) - return NS_ERROR_FAILURE; - rv = file->Append(NS_LITERAL_STRING("myspell")); - NS_ENSURE_SUCCESS(rv, rv); - rv = file->Append(mDictionary + NS_LITERAL_STRING(".dic")); - NS_ENSURE_SUCCESS(rv, rv); - file->GetPath(dictFileName); + file->GetPath(pluginFileName); + + if (PR_Access(NS_ConvertUTF16toUTF8(pluginFileName).get(), PR_ACCESS_READ_OK)!=PR_SUCCESS) { + nsresult rv = NS_GetSpecialDirectory(NS_XPCOM_COMPONENT_DIR, getter_AddRefs(file)); + NS_ENSURE_SUCCESS(rv, rv); + if (!file) + return NS_ERROR_FAILURE; + rv = file->Append(NS_LITERAL_STRING("myspell")); + NS_ENSURE_SUCCESS(rv, rv); + rv = file->Append(mDictionary + NS_LITERAL_STRING(".aff")); + NS_ENSURE_SUCCESS(rv, rv); + file->GetPath(affFileName); - // SetDictionary can be called multiple times, so we might have a valid mMySpell instance - // which needs cleaned up. - if (mMySpell) - delete mMySpell; + rv = NS_GetSpecialDirectory(NS_XPCOM_COMPONENT_DIR, getter_AddRefs(file)); + NS_ENSURE_SUCCESS(rv, rv); + if (!file) + return NS_ERROR_FAILURE; + rv = file->Append(NS_LITERAL_STRING("myspell")); + NS_ENSURE_SUCCESS(rv, rv); + rv = file->Append(mDictionary + NS_LITERAL_STRING(".dic")); + NS_ENSURE_SUCCESS(rv, rv); + file->GetPath(dictFileName); - mMySpell = new MySpell(NS_ConvertUTF16toUTF8(affFileName).get(), NS_ConvertUTF16toUTF8(dictFileName).get()); + // SetDictionary can be called multiple times, so we might have a valid mMySpell instance + // which needs cleaned up. + if (mMySpell) + delete mMySpell; + + mMySpell = new MySpell(NS_ConvertUTF16toUTF8(affFileName).get(), NS_ConvertUTF16toUTF8(dictFileName).get()); + } else { + // TODO: implement reading plugin description + rv = NS_GetSpecialDirectory(NS_XPCOM_COMPONENT_DIR, getter_AddRefs(file)); + NS_ENSURE_SUCCESS(rv, rv); + if (!file) + return NS_ERROR_FAILURE; + rv = file->Append(NS_LITERAL_STRING("myspell")); + NS_ENSURE_SUCCESS(rv, rv); + rv = file->Append(mDictionary + NS_LITERAL_STRING(".plugin")); + NS_ENSURE_SUCCESS(rv, rv); + file->GetPath(dictFileName); + + // SetDictionary can be called multiple times, so we might have a valid mMySpell instance + // which needs cleaned up. + if (mMySpell) + delete mMySpell; + mMySpell = 0; + + MySpellPlugin * tmp = new MySpellPlugin (NS_ConvertUTF16toUTF8(pluginFileName).get()); + if (tmp && *tmp) { + mMySpell = tmp; + } else { + delete tmp; + } + } if (!mMySpell) return NS_ERROR_FAILURE; @@ -261,22 +298,39 @@ nsAutoString fileName; theFile->GetLeafName(fileName); PRInt32 dotLocation = fileName.FindChar('.'); - if ((dotLocation != -1) && - Substring(fileName,dotLocation,4).EqualsLiteral(".dic")) { - if (tempCount >= arraySize) { - arraySize = 2 * tempCount; - newPtr = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * arraySize); - if (!newPtr){ - NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(tempCount, tmpPtr); - return NS_ERROR_OUT_OF_MEMORY; + if (dotLocation != -1) { + if (Substring(fileName,dotLocation,4).EqualsLiteral(".dic")) { + if (tempCount >= arraySize) { + arraySize = 2 * tempCount; + newPtr = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * arraySize); + if (!newPtr){ + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(tempCount, tmpPtr); + return NS_ERROR_OUT_OF_MEMORY; + } + for (PRInt32 i = 0; i < tempCount; ++i){ + newPtr[i] = tmpPtr[i]; + } + nsMemory::Free(tmpPtr); + tmpPtr=newPtr; } - for (PRInt32 i = 0; i < tempCount; ++i){ - newPtr[i] = tmpPtr[i]; + tmpPtr[tempCount++] = ToNewUnicode(Substring(fileName,0,dotLocation)); + } + else if (Substring(fileName,dotLocation,7).EqualsLiteral(".plugin")) { + if (tempCount >= arraySize) { + arraySize = 2 * tempCount; + newPtr = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * arraySize); + if (!newPtr){ + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(tempCount, tmpPtr); + return NS_ERROR_OUT_OF_MEMORY; + } + for (PRInt32 i = 0; i < tempCount; ++i){ + newPtr[i] = tmpPtr[i]; + } + nsMemory::Free(tmpPtr); + tmpPtr=newPtr; } - nsMemory::Free(tmpPtr); - tmpPtr=newPtr; - } - tmpPtr[tempCount++] = ToNewUnicode(Substring(fileName,0,dotLocation)); + tmpPtr[tempCount++] = ToNewUnicode(Substring(fileName,0,dotLocation)); + } } } } --- mozilla/extensions/spellcheck/myspell/src/tm_openoffice.hxx.myspell 2006-01-12 11:57:36.000000000 +0200 +++ mozilla/extensions/spellcheck/myspell/src/tm_openoffice.hxx 2006-01-12 11:57:36.000000000 +0200 @@ -0,0 +1,40 @@ +/* + * TM API definitions for OpenOffice + */ + +#define TM_IGNORE_CAPS (1<<1) +#define TM_IGNORE_DIGITS (1<<2) + +struct tm_in_s { + const unsigned char *buf; + int buf_len; +}; +typedef struct tm_in_s tm_in_t; + +struct tm_out_s { + int status; + int err_start; + int err_len; + unsigned char *change; +}; +typedef struct tm_out_s tm_out_t; + +typedef int (version_func_type)(void); +typedef int (init_func_type)(void **speller_handle_ptr); +typedef int (terminate_func_type)(void *speller_handle); +typedef int (open_func_type)(void *speller_handle, + const char *dict_path); +typedef int (encoding_func_type)(void *speller_handle, + const char *encoding_name); +typedef int (option_func_type)(void *speller_handle, + const char *option_type, + const char *option_str); +typedef int (check_func_type)(void *speller_handle, + const tm_in_t *input, + tm_out_t *output); +typedef int (suggest_func_type) (void *speller_handle, + const char *word, + int word_length, + char *buffer, + int buffer_length, + int *returned_word_count); --- mozilla/extensions/spellcheck/myspell/src/myspellplugin.cpp.myspell 2006-01-12 11:57:36.000000000 +0200 +++ mozilla/extensions/spellcheck/myspell/src/myspellplugin.cpp 2006-01-13 21:08:00.000000000 +0200 @@ -0,0 +1,346 @@ +#include "license.readme" +#include "myspell.hxx" +#include "tm_openoffice.hxx" + +#include "nsReadableUtils.h" +#include "nsXPIDLString.h" +#include "nsISimpleEnumerator.h" +#include "nsDirectoryService.h" +#include "nsDirectoryServiceDefs.h" +#include "mozISpellI18NManager.h" +#include "nsICharsetConverterManager.h" +#include "nsUnicharUtilCIID.h" +#include "nsUnicharUtils.h" +#include "nsCRT.h" + +#include +#include +#include +#include + + +#define __DEBUG_MYSPELLPLUGIN__ + + +#ifdef __DEBUG_MYSPELLPLUGIN__ + +#include + +int debug_open_tried = 0; +FILE * debug = 0; + +inline void debugf (const char * fmt, ...) +{ + if (!debug && !debug_open_tried) + { + debug = fopen ("myspellplugin.debug", "wt"); + debug_open_tried = 1; + } + + if (debug) + { + va_list args; + va_start (args, fmt); + vfprintf (debug, fmt, args); + va_end (args); + fflush (debug); + } + else abort(); +} + + + +#else + +inline void debugf (const char * fmt, ...) +{ + (void) fmt; +} + +#endif + + + + +/* Version check */ +#define IS_VERSION_ACCEPTABLE(ver) ((ver) < 0x00020000) + + + +struct MySpellPlugin::spellcheck_funct +{ + /** The initialization function of the loaded library */ + version_func_type * version_func_; + + init_func_type * init_func_; + + /// The termination function of the loaded library + terminate_func_type* terminate_func_; + + /// The dictionary open function of the loaded library + open_func_type* open_func_; + + /// The spell checking function of the loaded library + check_func_type* check_func_; + + /// The suggestion generation function of the loaded library + suggest_func_type* suggest_func_; + + /// The encoding specification function of the loaded library + encoding_func_type* encoding_func_; + + /// The option setting function of the loaded library + option_func_type* option_func_; +}; + + +static int is_absolute_path (const char * src) +{ + return src[0]=='/' +#ifdef __WIN32__ + || src[0]=='\\' + || (isalpha(src[0]) && src[1]==':' && + (src[2]=='/' || src[2]=='\\')) +#endif + ; +} + + +static char * path_resolve (const char * src) +{ + debugf ("path_resolve('%s')\n", src); + + if (is_absolute_path(src)) + { + debugf ("path is absolute: returning unchanged\n"); + return strdup(src); + } + + const char * dname = "myspell"; + nsAutoString resolved_path; + nsAutoString a_src = NS_ConvertUTF8toUTF16(src); + nsCOMPtr file; + nsresult rv; + + rv = NS_GetSpecialDirectory(NS_XPCOM_COMPONENT_DIR, + getter_AddRefs(file)); + NS_ENSURE_SUCCESS(rv, NS_OK); + if (!file) return strdup(src); + + rv = file->Append(NS_LITERAL_STRING("myspell")); + NS_ENSURE_SUCCESS(rv, NS_OK); + + file->GetPath (resolved_path); + + resolved_path += NS_LITERAL_STRING("/"); + resolved_path += a_src; + + char * result = strdup (NS_ConvertUTF16toUTF8(resolved_path).get()); + debugf ("resolved path = '%s'\n", result); + + return result; +} + + + +MySpellPlugin::MySpellPlugin (const char * plugin_path_) + : is_ok (false) + , dl_handle (0) + , funct (0) + , speller_handle (0) + , plugin_path (0) + , library (0) + , dictionary (0) + , encoding (0) +{ + plugin_path = strdup (plugin_path_); + + char line [512]; + FILE * input = fopen (plugin_path, "r"); + if (!input) return; + while ( fgets (line, 512, input ) != 0 ) + { + char *key, *val, *tmp; + val = strchr(line, ':'); + if (!val) continue; + *val++ = 0; + key = line; + while (*key && isspace(*key)) key++; + tmp = key + strlen(key) - 1; + while (tmp>=key && isspace(*tmp)) *tmp--=0; + while (*val && isspace(*val)) val++; + tmp = val + strlen(val) - 1; + while (tmp>=key && isspace(*tmp)) *tmp--=0; + if (strcmp(key,"library")==0) library=path_resolve(val); + else if (strcmp(key,"dictionary")==0) dictionary=path_resolve(val); + else if (strcmp(key,"encoding")==0) encoding=strdup(val); + } + fclose (input); + if (!library || !dictionary || !encoding) return; + + dl_handle = PR_LoadLibrary (library); + if (dl_handle == 0) { + debugf ("Unable to open library %s\n", library); + return; + } + + funct = new struct spellcheck_funct; + + funct->version_func_ = (version_func_type*) PR_FindSymbol ( + dl_handle, "Tm_version"); + if (funct->version_func_ == 0) { + debugf ("Unable to locate symbol Tm_version in library\n"); + return; + } + + // Check the version + int version = (*funct->version_func_)(); + if (!IS_VERSION_ACCEPTABLE(version)) { + debugf ("Library version %d not supported", version); + return; + } + + funct->init_func_ = (init_func_type*)PR_FindSymbol( + dl_handle, "Tm_init"); + funct->terminate_func_ = (terminate_func_type*)PR_FindSymbol( + dl_handle, "Tm_terminate"); + funct->open_func_ = (open_func_type*)PR_FindSymbol( + dl_handle, "Tm_open"); + funct->check_func_ = (check_func_type*)PR_FindSymbol( + dl_handle, "Tm_check_buffer"); + funct->suggest_func_ = (suggest_func_type*)PR_FindSymbol( + dl_handle, "Tm_suggest"); + funct->encoding_func_ = (encoding_func_type*)PR_FindSymbol( + dl_handle, "Tm_set_encoding"); + funct->option_func_ = (option_func_type*)PR_FindSymbol( + dl_handle, "Tm_set_option"); + + if ( !funct->init_func_ || !funct->terminate_func_ || + !funct->open_func_ || !funct->check_func_ || + !funct->suggest_func_ || !funct->encoding_func_ || + !funct->option_func_ ) + { + debugf ("One or more symbols not found in library\n"); + return; + } + + int status = (*funct->init_func_)(&speller_handle); + if (status != 0) { + debugf ("Initializing spell checker failed"); + return; + } + + status = (*funct->open_func_) (speller_handle, dictionary); + if (status != 0) { + debugf ("Unable to open dictionary file %s\n", dictionary); + return; + } + + status = (*funct->encoding_func_) (speller_handle, encoding); + if (status != 0) { + debugf ("Unable to set encoding to %s\n", encoding); + return; + } + + is_ok = true; + + debugf ("MySpellPlugin succeeded\n"); +} + + + + +MySpellPlugin::~MySpellPlugin () +{ + is_ok = false; + + if (funct) + { + if (funct->terminate_func_ && speller_handle) + (*funct->terminate_func_)(speller_handle); + delete funct; + } + + if (dl_handle) + { + PR_UnloadLibrary (dl_handle); + } + + free (library); + free (dictionary); + free (encoding); +} + + + +int MySpellPlugin::suggest (char *** slst, const char * word) +{ + const int maxSug = 25; + const int sugBufferSize = 2048; + int ns = 0, status; + char ** wlst = (char **) calloc(maxSug, sizeof(char *)); + char * p; + char buf [sugBufferSize]; + + *slst = 0; + if (!wlst) return 0; + + status = (*funct->suggest_func_) (speller_handle, + word, + strlen(word), + buf, + sugBufferSize, + &ns); + + debugf ("Returned from suggest_func: status=%d ns=%d\n", status, ns); + + if (status==0) { + int i; + p = buf; + if (ns>maxSug) ns=maxSug; + for (i=0; icheck_func_)(speller_handle, &in, &out); + if (status != 0) return 0; + + return 1; +} + + +char * MySpellPlugin::get_dic_encoding() +{ + return encoding; +} + --- mozilla/extensions/spellcheck/myspell/src/Makefile.in.myspell 2006-01-12 11:57:36.000000000 +0200 +++ mozilla/extensions/spellcheck/myspell/src/Makefile.in 2006-01-12 11:57:36.000000000 +0200 @@ -65,6 +65,7 @@ suggestmgr.cpp \ csutil.cpp \ myspell.cpp \ + myspellplugin.cpp \ mozMySpell.cpp \ mozMySpellFactory.cpp \ $(NULL) --- mozilla/extensions/spellcheck/myspell/src/myspell.hxx.myspell 2006-01-12 11:57:36.000000000 +0200 +++ mozilla/extensions/spellcheck/myspell/src/myspell.hxx 2006-01-13 21:06:25.000000000 +0200 @@ -5,13 +5,27 @@ #include "affixmgr.hxx" #include "suggestmgr.hxx" #include "csutil.hxx" +#include "nspr.h" #define NOCAP 0 #define INITCAP 1 #define ALLCAP 2 #define HUHCAP 3 -class MySpell + +class MySpellBase +{ +public: + MySpellBase (void) {} + virtual ~MySpellBase () {}; + + virtual int suggest (char ***slst, const char * word) = 0; + virtual int spell (const char *) = 0; + virtual char * get_dic_encoding() = 0; +}; + + +class MySpell : public MySpellBase { AffixMgr* pAMgr; HashMgr* pHMgr; @@ -22,15 +36,54 @@ public: MySpell(const char * affpath, const char * dpath); - ~MySpell(); + virtual ~MySpell(); - int suggest(char*** slst, const char * word); - int spell(const char *); - char * get_dic_encoding(); + virtual int suggest(char*** slst, const char * word); + virtual int spell(const char *); + virtual char * get_dic_encoding(); private: int cleanword(char *, const char *, int *, int *); char * check(const char *); }; + + + + +class MySpellPlugin : public MySpellBase +{ + /** I am hiding implementation from user here */ + struct spellcheck_funct; + + bool is_ok; + + /** The dynamically loadable library handle */ + PRLibrary * dl_handle; + + struct spellcheck_funct * funct; + + /** Spell checker handle */ + void * speller_handle; + + char * plugin_path; + + char * library; + char * dictionary; + char * encoding; + +public: + MySpellPlugin (const char * pluginPath); + + virtual ~MySpellPlugin (); + + virtual int suggest (char *** slst, const char * word); + + virtual int spell (const char *); + + virtual char * get_dic_encoding(); + + operator bool () const { return is_ok; } +}; + #endif --- mozilla/extensions/spellcheck/myspell/src/mozMySpell.h.myspell 2006-01-12 11:57:36.000000000 +0200 +++ mozilla/extensions/spellcheck/myspell/src/mozMySpell.h 2006-01-12 11:57:37.000000000 +0200 @@ -86,7 +86,7 @@ nsCOMPtr mDecoder; nsString mDictionary; nsString mLanguage; - MySpell *mMySpell; + MySpellBase *mMySpell; }; #endif