diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/affentry.cpp spellcheck/hunspell/hunspell/affentry.cpp
--- spellcheck.old/hunspell/hunspell/affentry.cpp	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/affentry.cpp	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,924 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef MOZILLA_CLIENT
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+#include <cstdio>
+#else
+#include <stdlib.h> 
+#include <string.h>
+#include <stdio.h> 
+#include <ctype.h>
+#endif
+
+#include "affentry.hxx"
+#include "csutil.hxx"
+
+#ifndef MOZILLA_CLIENT
+#ifndef W32
+using namespace std;
+#endif
+#endif
+
+
+PfxEntry::PfxEntry(AffixMgr* pmgr, affentry* dp)
+{
+  // register affix manager
+  pmyMgr = pmgr;
+
+  // set up its intial values
+ 
+  aflag = dp->aflag;         // flag 
+  strip = dp->strip;         // string to strip
+  appnd = dp->appnd;         // string to append
+  stripl = dp->stripl;       // length of strip string
+  appndl = dp->appndl;       // length of append string
+  numconds = dp->numconds;   // number of conditions to match
+  opts = dp->opts;         // cross product flag
+  // then copy over all of the conditions
+  memcpy(&conds.base[0],&dp->conds.base[0],SETSIZE*sizeof(conds.base[0]));
+  next = NULL;
+  nextne = NULL;
+  nexteq = NULL;
+#ifdef HUNSPELL_EXPERIMENTAL
+  morphcode = dp->morphcode;
+#endif
+  contclass = dp->contclass;
+  contclasslen = dp->contclasslen;
+}
+
+
+PfxEntry::~PfxEntry()
+{
+    aflag = 0;
+    if (appnd) free(appnd);
+    if (strip) free(strip);
+    pmyMgr = NULL;
+    appnd = NULL;
+    strip = NULL;
+    if (opts & aeUTF8) {
+        for (int i = 0; i < numconds; i++) {
+            if (conds.utf8.wchars[i]) free(conds.utf8.wchars[i]);
+        }
+    }
+#ifdef HUNSPELL_EXPERIMENTAL
+    if (morphcode && !(opts & aeALIASM)) free(morphcode);
+#endif
+    if (contclass && !(opts & aeALIASF)) free(contclass);
+}
+
+// add prefix to this word assuming conditions hold
+char * PfxEntry::add(const char * word, int len)
+{
+    char tword[MAXWORDUTF8LEN + 4];
+
+    if ((len > stripl) && (len >= numconds) && test_condition(word) &&
+       (!stripl || (strncmp(word, strip, stripl) == 0)) && 
+       ((MAXWORDUTF8LEN + 4) > (len + appndl - stripl))) {
+    /* we have a match so add prefix */
+              char * pp = tword;
+              if (appndl) {
+                  strcpy(tword,appnd);
+                  pp += appndl;
+               }
+               strcpy(pp, (word + stripl));
+               return mystrdup(tword);
+     }
+     return NULL;    
+}
+
+
+inline int PfxEntry::test_condition(const char * st)
+{
+    int cond;
+    unsigned char * cp = (unsigned char *)st;
+    if (!(opts & aeUTF8)) { // 256-character codepage
+        for (cond = 0;  cond < numconds;  cond++) {
+            if ((conds.base[*cp++] & (1 << cond)) == 0) return 0;
+        }
+    } else { // UTF-8 encoding
+      unsigned short wc;
+      for (cond = 0;  cond < numconds;  cond++) {
+        // a simple 7-bit ASCII character in UTF-8
+        if ((*cp >> 7) == 0) {
+            // also check limit (end of word)
+            if ((!*cp) || ((conds.utf8.ascii[*cp++] & (1 << cond)) == 0)) return 0;
+        // UTF-8 multibyte character
+        } else {
+            // not dot wildcard in rule
+            if (!conds.utf8.all[cond]) {
+                if (conds.utf8.neg[cond]) {
+                    u8_u16((w_char *) &wc, 1, (char *) cp);
+                    if (conds.utf8.wchars[cond] && 
+                        flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
+                            wc, (short) conds.utf8.wlen[cond])) return 0;
+                } else {
+                    if (!conds.utf8.wchars[cond]) return 0;
+                    u8_u16((w_char *) &wc, 1, (char *) cp);
+                    if (!flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
+                         wc, (short)conds.utf8.wlen[cond])) return 0;
+                }
+            }
+            // jump to next UTF-8 character
+            for(cp++; (*cp & 0xc0) == 0x80; cp++);
+        }
+      }
+    }
+    return 1;
+}
+
+
+// check if this prefix entry matches 
+struct hentry * PfxEntry::checkword(const char * word, int len, char in_compound, const FLAG needflag)
+{
+    int                 tmpl;   // length of tmpword
+    struct hentry *     he;     // hash entry of root word or NULL
+    char                tmpword[MAXWORDUTF8LEN + 4];
+
+    // on entry prefix is 0 length or already matches the beginning of the word.
+    // So if the remaining root word has positive length
+    // and if there are enough chars in root word and added back strip chars
+    // to meet the number of characters conditions, then test it
+
+     tmpl = len - appndl;
+
+     if ((tmpl > 0) &&  (tmpl + stripl >= numconds)) {
+
+            // generate new root word by removing prefix and adding
+            // back any characters that would have been stripped
+
+            if (stripl) strcpy (tmpword, strip);
+            strcpy ((tmpword + stripl), (word + appndl));
+
+            // now make sure all of the conditions on characters
+            // are met.  Please see the appendix at the end of
+            // this file for more info on exactly what is being
+            // tested
+
+            // if all conditions are met then check if resulting
+            // root word in the dictionary
+
+            if (test_condition(tmpword)) {
+                tmpl += stripl;
+                if ((he = pmyMgr->lookup(tmpword)) != NULL) {
+                   do {
+                      if (TESTAFF(he->astr, aflag, he->alen) &&
+                        // forbid single prefixes with pseudoroot flag
+                        ! TESTAFF(contclass, pmyMgr->get_pseudoroot(), contclasslen) &&
+                        // needflag
+                        ((!needflag) || TESTAFF(he->astr, needflag, he->alen) ||
+                         (contclass && TESTAFF(contclass, needflag, contclasslen))))
+                            return he;
+                      he = he->next_homonym; // check homonyms
+                   } while (he);
+                }
+                
+                // prefix matched but no root word was found 
+                // if aeXPRODUCT is allowed, try again but now 
+                // ross checked combined with a suffix
+
+                //if ((opts & aeXPRODUCT) && in_compound) {
+                if ((opts & aeXPRODUCT)) {
+                   he = pmyMgr->suffix_check(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, NULL, 
+                        0, NULL, FLAG_NULL, needflag, in_compound);
+                   if (he) return he;
+                }
+            }
+     }
+    return NULL;
+}
+
+// check if this prefix entry matches 
+struct hentry * PfxEntry::check_twosfx(const char * word, int len,
+    char in_compound, const FLAG needflag)
+{
+    int                 tmpl;   // length of tmpword
+    struct hentry *     he;     // hash entry of root word or NULL
+    char                tmpword[MAXWORDUTF8LEN + 4];
+
+    // on entry prefix is 0 length or already matches the beginning of the word.
+    // So if the remaining root word has positive length
+    // and if there are enough chars in root word and added back strip chars
+    // to meet the number of characters conditions, then test it
+
+     tmpl = len - appndl;
+
+     if ((tmpl > 0) &&  (tmpl + stripl >= numconds)) {
+
+            // generate new root word by removing prefix and adding
+            // back any characters that would have been stripped
+
+            if (stripl) strcpy (tmpword, strip);
+            strcpy ((tmpword + stripl), (word + appndl));
+
+            // now make sure all of the conditions on characters
+            // are met.  Please see the appendix at the end of
+            // this file for more info on exactly what is being
+            // tested
+
+            // if all conditions are met then check if resulting
+            // root word in the dictionary
+
+            if (test_condition(tmpword)) {
+                tmpl += stripl;
+
+                // prefix matched but no root word was found 
+                // if aeXPRODUCT is allowed, try again but now 
+                // cross checked combined with a suffix
+
+                if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
+                   he = pmyMgr->suffix_check_twosfx(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, needflag);
+                   if (he) return he;
+                }
+            }
+     }
+    return NULL;
+}
+
+#ifdef HUNSPELL_EXPERIMENTAL
+// check if this prefix entry matches 
+char * PfxEntry::check_twosfx_morph(const char * word, int len,
+         char in_compound, const FLAG needflag)
+{
+    int                 tmpl;   // length of tmpword
+    char                tmpword[MAXWORDUTF8LEN + 4];
+
+    // on entry prefix is 0 length or already matches the beginning of the word.
+    // So if the remaining root word has positive length
+    // and if there are enough chars in root word and added back strip chars
+    // to meet the number of characters conditions, then test it
+
+     tmpl = len - appndl;
+
+     if ((tmpl > 0) &&  (tmpl + stripl >= numconds)) {
+
+            // generate new root word by removing prefix and adding
+            // back any characters that would have been stripped
+
+            if (stripl) strcpy (tmpword, strip);
+            strcpy ((tmpword + stripl), (word + appndl));
+
+            // now make sure all of the conditions on characters
+            // are met.  Please see the appendix at the end of
+            // this file for more info on exactly what is being
+            // tested
+
+            // if all conditions are met then check if resulting
+            // root word in the dictionary
+
+            if (test_condition(tmpword)) {
+                tmpl += stripl;
+
+                // prefix matched but no root word was found 
+                // if aeXPRODUCT is allowed, try again but now 
+                // ross checked combined with a suffix
+
+                if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
+                    return pmyMgr->suffix_check_twosfx_morph(tmpword, tmpl,
+                             aeXPRODUCT, (AffEntry *)this, needflag);
+                }
+            }
+     }
+    return NULL;
+}
+
+// check if this prefix entry matches 
+char * PfxEntry::check_morph(const char * word, int len, char in_compound, const FLAG needflag)
+{
+    int                 tmpl;   // length of tmpword
+    struct hentry *     he;     // hash entry of root word or NULL
+    char                tmpword[MAXWORDUTF8LEN + 4];
+    char                result[MAXLNLEN];
+    char * st;
+    
+    *result = '\0';
+
+    // on entry prefix is 0 length or already matches the beginning of the word.
+    // So if the remaining root word has positive length
+    // and if there are enough chars in root word and added back strip chars
+    // to meet the number of characters conditions, then test it
+
+     tmpl = len - appndl;
+
+     if ((tmpl > 0) &&  (tmpl + stripl >= numconds)) {
+
+            // generate new root word by removing prefix and adding
+            // back any characters that would have been stripped
+
+            if (stripl) strcpy (tmpword, strip);
+            strcpy ((tmpword + stripl), (word + appndl));
+
+            // now make sure all of the conditions on characters
+            // are met.  Please see the appendix at the end of
+            // this file for more info on exactly what is being
+            // tested
+
+            // if all conditions are met then check if resulting
+            // root word in the dictionary
+
+            if (test_condition(tmpword)) {
+                tmpl += stripl;
+                if ((he = pmyMgr->lookup(tmpword)) != NULL) {
+                    do {
+                      if (TESTAFF(he->astr, aflag, he->alen) &&
+                        // forbid single prefixes with pseudoroot flag
+                        ! TESTAFF(contclass, pmyMgr->get_pseudoroot(), contclasslen) &&
+                        // needflag
+                        ((!needflag) || TESTAFF(he->astr, needflag, he->alen) ||
+                         (contclass && TESTAFF(contclass, needflag, contclasslen)))) {
+                            if (morphcode) strcat(result, morphcode); else strcat(result,getKey());
+                            if (he->description) {
+                                if ((*(he->description)=='[')||(*(he->description)=='<')) strcat(result,he->word);
+                                strcat(result,he->description);
+                            }
+                            strcat(result, "\n");
+                      }
+                      he = he->next_homonym;
+                    } while (he);
+                }
+
+                // prefix matched but no root word was found 
+                // if aeXPRODUCT is allowed, try again but now 
+                // ross checked combined with a suffix
+
+                if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
+                   st = pmyMgr->suffix_check_morph(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, 
+                     FLAG_NULL, needflag);
+                   if (st) {
+                        strcat(result, st);
+                        free(st);
+                   }
+                }
+            }
+     }
+     
+    if (*result) return mystrdup(result);
+    return NULL;
+}
+#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+
+SfxEntry::SfxEntry(AffixMgr * pmgr, affentry* dp)
+{
+  // register affix manager
+  pmyMgr = pmgr;
+
+  // set up its intial values
+  aflag = dp->aflag;         // char flag 
+  strip = dp->strip;         // string to strip
+  appnd = dp->appnd;         // string to append
+  stripl = dp->stripl;       // length of strip string
+  appndl = dp->appndl;       // length of append string
+  numconds = dp->numconds;   // number of conditions to match
+  opts = dp->opts;         // cross product flag
+
+  // then copy over all of the conditions
+  memcpy(&conds.base[0],&dp->conds.base[0],SETSIZE*sizeof(conds.base[0]));
+
+  rappnd = myrevstrdup(appnd);
+
+#ifdef HUNSPELL_EXPERIMENTAL
+  morphcode = dp->morphcode;
+#endif
+  contclass = dp->contclass;
+  contclasslen = dp->contclasslen;
+}
+
+
+SfxEntry::~SfxEntry()
+{
+    aflag = 0;
+    if (appnd) free(appnd);
+    if (rappnd) free(rappnd);
+    if (strip) free(strip);
+    pmyMgr = NULL;
+    appnd = NULL;
+    strip = NULL;    
+    if (opts & aeUTF8) {
+        for (int i = 0; i < numconds; i++) {
+            if (conds.utf8.wchars[i]) free(conds.utf8.wchars[i]);  
+        }
+    }
+#ifdef HUNSPELL_EXPERIMENTAL
+    if (morphcode && !(opts & aeALIASM)) free(morphcode);
+#endif
+    if (contclass && !(opts & aeALIASF)) free(contclass);
+}
+
+// add suffix to this word assuming conditions hold
+char * SfxEntry::add(const char * word, int len)
+{
+    char                tword[MAXWORDUTF8LEN + 4];
+
+     /* make sure all conditions match */
+     if ((len > stripl) && (len >= numconds) && test_condition(word + len, word) &&
+        (!stripl || (strcmp(word + len - stripl, strip) == 0)) &&
+        ((MAXWORDUTF8LEN + 4) > (len + appndl - stripl))) {
+              /* we have a match so add suffix */
+              strcpy(tword,word);
+              if (appndl) {
+                  strcpy(tword + len - stripl, appnd);
+              } else {
+                  *(tword + len - stripl) = '\0';
+              }
+              return mystrdup(tword);
+     }
+     return NULL;
+}
+
+
+inline int SfxEntry::test_condition(const char * st, const char * beg)
+{
+    int cond;
+    unsigned char * cp = (unsigned char *) st;
+    if (!(opts & aeUTF8)) { // 256-character codepage
+        // Domolki affix algorithm
+        for (cond = numconds;  --cond >= 0; ) {
+            if ((conds.base[*--cp] & (1 << cond)) == 0) return 0;
+        }
+    } else { // UTF-8 encoding
+      unsigned short wc;
+      for (cond = numconds;  --cond >= 0; ) {
+        // go to next character position and check limit
+        if ((char *) --cp < beg) return 0;
+        // a simple 7-bit ASCII character in UTF-8
+        if ((*cp >> 7) == 0) {
+            if ((conds.utf8.ascii[*cp] & (1 << cond)) == 0) return 0;
+        // UTF-8 multibyte character
+        } else {
+            // go to first character of UTF-8 multibyte character
+            for (; (*cp & 0xc0) == 0x80; cp--);
+            // not dot wildcard in rule
+            if (!conds.utf8.all[cond]) {
+                if (conds.utf8.neg[cond]) {
+                    u8_u16((w_char *) &wc, 1, (char *) cp);
+                    if (conds.utf8.wchars[cond] && 
+                        flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
+                            wc, (short) conds.utf8.wlen[cond])) return 0;
+                } else {
+                    if (!conds.utf8.wchars[cond]) return 0;
+                    u8_u16((w_char *) &wc, 1, (char *) cp);
+                    if (!flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
+                         wc, (short)conds.utf8.wlen[cond])) return 0;
+                }
+            }
+        }
+      }
+    }
+    return 1;
+}
+
+
+
+// see if this suffix is present in the word 
+struct hentry * SfxEntry::checkword(const char * word, int len, int optflags,
+    AffEntry* ppfx, char ** wlst, int maxSug, int * ns, const FLAG cclass, const FLAG needflag,
+    const FLAG badflag)
+{
+    int                 tmpl;            // length of tmpword 
+    struct hentry *     he;              // hash entry pointer
+    unsigned char *     cp;
+    char                tmpword[MAXWORDUTF8LEN + 4];
+    PfxEntry* ep = (PfxEntry *) ppfx;
+
+    // if this suffix is being cross checked with a prefix
+    // but it does not support cross products skip it
+
+    if (((optflags & aeXPRODUCT) != 0) && ((opts & aeXPRODUCT) == 0))
+        return NULL;
+
+    // upon entry suffix is 0 length or already matches the end of the word.
+    // So if the remaining root word has positive length
+    // and if there are enough chars in root word and added back strip chars
+    // to meet the number of characters conditions, then test it
+
+    tmpl = len - appndl;
+    // the second condition is not enough for UTF-8 strings
+    // it checked in test_condition()
+    
+    if ((tmpl > 0)  &&  (tmpl + stripl >= numconds)) {
+
+            // generate new root word by removing suffix and adding
+            // back any characters that would have been stripped or
+            // or null terminating the shorter string
+
+            strcpy (tmpword, word);
+            cp = (unsigned char *)(tmpword + tmpl);
+            if (stripl) {
+                strcpy ((char *)cp, strip);
+                tmpl += stripl;
+                cp = (unsigned char *)(tmpword + tmpl);
+            } else *cp = '\0';
+
+            // now make sure all of the conditions on characters
+            // are met.  Please see the appendix at the end of
+            // this file for more info on exactly what is being            // tested
+
+            // if all conditions are met then check if resulting
+            // root word in the dictionary
+
+            if (test_condition((char *) cp, (char *) tmpword)) {
+
+#ifdef SZOSZABLYA_POSSIBLE_ROOTS
+                fprintf(stdout,"%s %s %c\n", word, tmpword, aflag);
+#endif
+                if ((he = pmyMgr->lookup(tmpword)) != NULL) {
+                    do {
+                        // check conditional suffix (enabled by prefix)
+                        if ((TESTAFF(he->astr, aflag, he->alen) || (ep && ep->getCont() &&
+                                    TESTAFF(ep->getCont(), aflag, ep->getContLen()))) && 
+                            (((optflags & aeXPRODUCT) == 0) || 
+                            TESTAFF(he->astr, ep->getFlag(), he->alen) ||
+                             // enabled by prefix
+                            ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen))
+                            ) &&
+                            // handle cont. class
+                            ((!cclass) || 
+                                ((contclass) && TESTAFF(contclass, cclass, contclasslen))
+                            ) &&
+                            // check only in compound homonyms (bad flags)
+                            (!badflag || !TESTAFF(he->astr, badflag, he->alen)
+                            ) &&                            
+                            // handle required flag
+                            ((!needflag) || 
+                              (TESTAFF(he->astr, needflag, he->alen) ||
+                              ((contclass) && TESTAFF(contclass, needflag, contclasslen)))
+                            )
+                        ) return he;
+                        he = he->next_homonym; // check homonyms
+                    } while (he);
+
+                // obsolote stemming code (used only by the 
+                // experimental SuffixMgr:suggest_pos_stems)
+                // store resulting root in wlst
+                } else if (wlst && (*ns < maxSug)) {
+                    int cwrd = 1;
+                    for (int k=0; k < *ns; k++) 
+                        if (strcmp(tmpword, wlst[k]) == 0) cwrd = 0;
+                    if (cwrd) {
+                        wlst[*ns] = mystrdup(tmpword);
+                        if (wlst[*ns] == NULL) {
+                            for (int j=0; j<*ns; j++) free(wlst[j]);
+                            *ns = -1;
+                            return NULL;
+                        }
+                        (*ns)++;
+                    }
+                }
+            }
+    }
+    return NULL;
+}
+
+// see if two-level suffix is present in the word 
+struct hentry * SfxEntry::check_twosfx(const char * word, int len, int optflags,
+    AffEntry* ppfx, const FLAG needflag)
+{
+    int                 tmpl;            // length of tmpword 
+    struct hentry *     he;              // hash entry pointer
+    unsigned char *     cp;
+    char                tmpword[MAXWORDUTF8LEN + 4];
+    PfxEntry* ep = (PfxEntry *) ppfx;
+
+
+    // if this suffix is being cross checked with a prefix
+    // but it does not support cross products skip it
+
+    if ((optflags & aeXPRODUCT) != 0 &&  (opts & aeXPRODUCT) == 0)
+        return NULL;
+
+    // upon entry suffix is 0 length or already matches the end of the word.
+    // So if the remaining root word has positive length
+    // and if there are enough chars in root word and added back strip chars
+    // to meet the number of characters conditions, then test it
+
+    tmpl = len - appndl;
+
+    if ((tmpl > 0)  &&  (tmpl + stripl >= numconds)) {
+
+            // generate new root word by removing suffix and adding
+            // back any characters that would have been stripped or
+            // or null terminating the shorter string
+
+            strcpy (tmpword, word);
+            cp = (unsigned char *)(tmpword + tmpl);
+            if (stripl) {
+                strcpy ((char *)cp, strip);
+                tmpl += stripl;
+                cp = (unsigned char *)(tmpword + tmpl);
+            } else *cp = '\0';
+
+            // now make sure all of the conditions on characters
+            // are met.  Please see the appendix at the end of
+            // this file for more info on exactly what is being
+            // tested
+
+            // if all conditions are met then recall suffix_check
+
+            if (test_condition((char *) cp, (char *) tmpword)) {
+                if (ppfx) {
+                    // handle conditional suffix
+                    if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) 
+                        he = pmyMgr->suffix_check(tmpword, tmpl, 0, NULL, NULL, 0, NULL, (FLAG) aflag, needflag);
+                    else
+                        he = pmyMgr->suffix_check(tmpword, tmpl, optflags, ppfx, NULL, 0, NULL, (FLAG) aflag, needflag);
+                } else {
+                    he = pmyMgr->suffix_check(tmpword, tmpl, 0, NULL, NULL, 0, NULL, (FLAG) aflag, needflag);
+                }
+                if (he) return he;
+            }
+    }
+    return NULL;
+}
+
+#ifdef HUNSPELL_EXPERIMENTAL
+// see if two-level suffix is present in the word 
+char * SfxEntry::check_twosfx_morph(const char * word, int len, int optflags,
+    AffEntry* ppfx, const FLAG needflag)
+{
+    int                 tmpl;            // length of tmpword 
+    unsigned char *     cp;
+    char                tmpword[MAXWORDUTF8LEN + 4];
+    PfxEntry* ep = (PfxEntry *) ppfx;
+    char * st;
+
+    char result[MAXLNLEN];
+    
+    *result = '\0';
+
+    // if this suffix is being cross checked with a prefix
+    // but it does not support cross products skip it
+
+    if ((optflags & aeXPRODUCT) != 0 &&  (opts & aeXPRODUCT) == 0)
+        return NULL;
+
+    // upon entry suffix is 0 length or already matches the end of the word.
+    // So if the remaining root word has positive length
+    // and if there are enough chars in root word and added back strip chars
+    // to meet the number of characters conditions, then test it
+
+    tmpl = len - appndl;
+
+    if ((tmpl > 0)  &&  (tmpl + stripl >= numconds)) {
+
+            // generate new root word by removing suffix and adding
+            // back any characters that would have been stripped or
+            // or null terminating the shorter string
+
+            strcpy (tmpword, word);
+            cp = (unsigned char *)(tmpword + tmpl);
+            if (stripl) {
+                strcpy ((char *)cp, strip);
+                tmpl += stripl;
+                cp = (unsigned char *)(tmpword + tmpl);
+            } else *cp = '\0';
+
+            // now make sure all of the conditions on characters
+            // are met.  Please see the appendix at the end of
+            // this file for more info on exactly what is being
+            // tested
+
+            // if all conditions are met then recall suffix_check
+
+            if (test_condition((char *) cp, (char *) tmpword)) {
+                if (ppfx) {
+                    // handle conditional suffix
+                    if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) {
+                        st = pmyMgr->suffix_check_morph(tmpword, tmpl, 0, NULL, aflag, needflag);
+                        if (st) {
+                            if (((PfxEntry *) ppfx)->getMorph()) {
+                                strcat(result, ((PfxEntry *) ppfx)->getMorph());
+                            }
+                            strcat(result,st);
+                            free(st);
+                            mychomp(result);
+                        }
+                    } else {
+                        st = pmyMgr->suffix_check_morph(tmpword, tmpl, optflags, ppfx, aflag, needflag);
+                        if (st) {
+                            strcat(result, st);
+                            free(st);
+                            mychomp(result);
+                        }
+                    }
+                } else {
+                        st = pmyMgr->suffix_check_morph(tmpword, tmpl, 0, NULL, aflag, needflag);
+                        if (st) {
+                            strcat(result, st);
+                            free(st);
+                            mychomp(result);
+                        }
+                }
+                if (*result) return mystrdup(result);
+            }
+    }
+    return NULL;
+}
+#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+
+// get next homonym with same affix
+struct hentry * SfxEntry::get_next_homonym(struct hentry * he, int optflags, AffEntry* ppfx, 
+    const FLAG cclass, const FLAG needflag)
+{
+    PfxEntry* ep = (PfxEntry *) ppfx;
+    FLAG eFlag = ep ? ep->getFlag() : FLAG_NULL;
+
+    while (he->next_homonym) {
+        he = he->next_homonym;
+        if ((TESTAFF(he->astr, aflag, he->alen) || (ep && ep->getCont() && TESTAFF(ep->getCont(), aflag, ep->getContLen()))) && 
+                            ((optflags & aeXPRODUCT) == 0 || 
+                            TESTAFF(he->astr, eFlag, he->alen) ||
+                             // handle conditional suffix
+                            ((contclass) && TESTAFF(contclass, eFlag, contclasslen))
+                            ) &&
+                            // handle cont. class
+                            ((!cclass) || 
+                                ((contclass) && TESTAFF(contclass, cclass, contclasslen))
+                            ) &&
+                            // handle required flag
+                            ((!needflag) || 
+                              (TESTAFF(he->astr, needflag, he->alen) ||
+                              ((contclass) && TESTAFF(contclass, needflag, contclasslen)))
+                            )
+                        ) return he;
+    }
+    return NULL;
+}
+
+
+#if 0
+
+Appendix:  Understanding Affix Code
+
+
+An affix is either a  prefix or a suffix attached to root words to make 
+other words.
+
+Basically a Prefix or a Suffix is set of AffEntry objects
+which store information about the prefix or suffix along 
+with supporting routines to check if a word has a particular 
+prefix or suffix or a combination.
+
+The structure affentry is defined as follows:
+
+struct affentry
+{
+   unsigned short aflag;    // ID used to represent the affix
+   char * strip;            // string to strip before adding affix
+   char * appnd;            // the affix string to add
+   unsigned char stripl;    // length of the strip string
+   unsigned char appndl;    // length of the affix string
+   char numconds;           // the number of conditions that must be met
+   char opts;               // flag: aeXPRODUCT- combine both prefix and suffix 
+   char   conds[SETSIZE];   // array which encodes the conditions to be met
+};
+
+
+Here is a suffix borrowed from the en_US.aff file.  This file 
+is whitespace delimited.
+
+SFX D Y 4 
+SFX D   0     e          d
+SFX D   y     ied        [^aeiou]y
+SFX D   0     ed         [^ey]
+SFX D   0     ed         [aeiou]y
+
+This information can be interpreted as follows:
+
+In the first line has 4 fields
+
+Field
+-----
+1     SFX - indicates this is a suffix
+2     D   - is the name of the character flag which represents this suffix
+3     Y   - indicates it can be combined with prefixes (cross product)
+4     4   - indicates that sequence of 4 affentry structures are needed to
+               properly store the affix information
+
+The remaining lines describe the unique information for the 4 SfxEntry 
+objects that make up this affix.  Each line can be interpreted
+as follows: (note fields 1 and 2 are as a check against line 1 info)
+
+Field
+-----
+1     SFX         - indicates this is a suffix
+2     D           - is the name of the character flag for this affix
+3     y           - the string of chars to strip off before adding affix
+                         (a 0 here indicates the NULL string)
+4     ied         - the string of affix characters to add
+5     [^aeiou]y   - the conditions which must be met before the affix
+                    can be applied
+
+Field 5 is interesting.  Since this is a suffix, field 5 tells us that
+there are 2 conditions that must be met.  The first condition is that 
+the next to the last character in the word must *NOT* be any of the 
+following "a", "e", "i", "o" or "u".  The second condition is that
+the last character of the word must end in "y".
+
+So how can we encode this information concisely and be able to 
+test for both conditions in a fast manner?  The answer is found
+but studying the wonderful ispell code of Geoff Kuenning, et.al. 
+(now available under a normal BSD license).
+
+If we set up a conds array of 256 bytes indexed (0 to 255) and access it
+using a character (cast to an unsigned char) of a string, we have 8 bits
+of information we can store about that character.  Specifically we
+could use each bit to say if that character is allowed in any of the 
+last (or first for prefixes) 8 characters of the word.
+
+Basically, each character at one end of the word (up to the number 
+of conditions) is used to index into the conds array and the resulting 
+value found there says whether the that character is valid for a 
+specific character position in the word.  
+
+For prefixes, it does this by setting bit 0 if that char is valid 
+in the first position, bit 1 if valid in the second position, and so on. 
+
+If a bit is not set, then that char is not valid for that postion in the
+word.
+
+If working with suffixes bit 0 is used for the character closest 
+to the front, bit 1 for the next character towards the end, ..., 
+with bit numconds-1 representing the last char at the end of the string. 
+
+Note: since entries in the conds[] are 8 bits, only 8 conditions 
+(read that only 8 character positions) can be examined at one
+end of a word (the beginning for prefixes and the end for suffixes.
+
+So to make this clearer, lets encode the conds array values for the 
+first two affentries for the suffix D described earlier.
+
+
+  For the first affentry:    
+     numconds = 1             (only examine the last character)
+
+     conds['e'] =  (1 << 0)   (the word must end in an E)
+     all others are all 0
+
+  For the second affentry:
+     numconds = 2             (only examine the last two characters)     
+
+     conds[X] = conds[X] | (1 << 0)     (aeiou are not allowed)
+         where X is all characters *but* a, e, i, o, or u
+         
+
+     conds['y'] = (1 << 1)     (the last char must be a y)
+     all other bits for all other entries in the conds array are zero
+
+
+#endif
+
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/affentry.hxx spellcheck/hunspell/hunspell/affentry.hxx
--- spellcheck.old/hunspell/hunspell/affentry.hxx	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/affentry.hxx	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,187 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef _AFFIX_HXX_
+#define _AFFIX_HXX_
+
+#include "atypes.hxx"
+#include "baseaffix.hxx"
+#include "affixmgr.hxx"
+
+/* A Prefix Entry  */
+
+class PfxEntry : public AffEntry
+{
+       AffixMgr*    pmyMgr;
+
+       PfxEntry * next;
+       PfxEntry * nexteq;
+       PfxEntry * nextne;
+       PfxEntry * flgnxt;
+
+public:
+
+  PfxEntry(AffixMgr* pmgr, affentry* dp );
+  ~PfxEntry();
+
+  inline bool          allowCross() { return ((opts & aeXPRODUCT) != 0); }
+  struct hentry *      checkword(const char * word, int len, char in_compound, 
+                            const FLAG needflag = FLAG_NULL);
+
+  struct hentry *      check_twosfx(const char * word, int len, char in_compound, const FLAG needflag = NULL);
+
+  char *      check_morph(const char * word, int len, char in_compound,
+                            const FLAG needflag = FLAG_NULL);
+
+  char *      check_twosfx_morph(const char * word, int len,
+                  char in_compound, const FLAG needflag = FLAG_NULL);
+
+  inline FLAG getFlag()   { return aflag;   }
+  inline const char *  getKey()    { return appnd;  } 
+  char *               add(const char * word, int len);
+
+  inline short getKeyLen() { return appndl; } 
+
+  inline const char *  getMorph()    { return morphcode;  } 
+
+  inline const unsigned short * getCont()    { return contclass;  } 
+  inline short           getContLen()    { return contclasslen;  } 
+
+  inline PfxEntry *    getNext()   { return next;   }
+  inline PfxEntry *    getNextNE() { return nextne; }
+  inline PfxEntry *    getNextEQ() { return nexteq; }
+  inline PfxEntry *    getFlgNxt() { return flgnxt; }
+
+  inline void   setNext(PfxEntry * ptr)   { next = ptr;   }
+  inline void   setNextNE(PfxEntry * ptr) { nextne = ptr; }
+  inline void   setNextEQ(PfxEntry * ptr) { nexteq = ptr; }
+  inline void   setFlgNxt(PfxEntry * ptr) { flgnxt = ptr; }
+  
+  inline int    test_condition(const char * st);
+};
+
+
+
+
+/* A Suffix Entry */
+
+class SfxEntry : public AffEntry
+{
+       AffixMgr*    pmyMgr;
+       char *       rappnd;
+
+       SfxEntry *   next;
+       SfxEntry *   nexteq;
+       SfxEntry *   nextne;
+       SfxEntry *   flgnxt;
+           
+       SfxEntry *   l_morph;
+       SfxEntry *   r_morph;
+       SfxEntry *   eq_morph;
+
+public:
+
+  SfxEntry(AffixMgr* pmgr, affentry* dp );
+  ~SfxEntry();
+
+  inline bool          allowCross() { return ((opts & aeXPRODUCT) != 0); }
+  struct hentry *   checkword(const char * word, int len, int optflags, 
+                    AffEntry* ppfx, char ** wlst, int maxSug, int * ns,
+//                    const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, char in_compound=IN_CPD_NOT);
+                    const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, const FLAG badflag = 0);
+
+  struct hentry *   check_twosfx(const char * word, int len, int optflags, AffEntry* ppfx, const FLAG needflag = NULL);
+
+  char *      check_twosfx_morph(const char * word, int len, int optflags,
+                 AffEntry* ppfx, const FLAG needflag = FLAG_NULL);
+  struct hentry * get_next_homonym(struct hentry * he);
+  struct hentry * get_next_homonym(struct hentry * word, int optflags, AffEntry* ppfx, 
+    const FLAG cclass, const FLAG needflag);
+
+
+  inline FLAG getFlag()   { return aflag;   }
+  inline const char *  getKey()    { return rappnd; } 
+  char *               add(const char * word, int len);
+
+
+  inline const char *  getMorph()    { return morphcode;  } 
+
+  inline const unsigned short * getCont()    { return contclass;  } 
+  inline short           getContLen()    { return contclasslen;  } 
+  inline const char *  getAffix()    { return appnd; } 
+
+  inline short getKeyLen() { return appndl; } 
+
+  inline SfxEntry *    getNext()   { return next;   }
+  inline SfxEntry *    getNextNE() { return nextne; }
+  inline SfxEntry *    getNextEQ() { return nexteq; }
+
+  inline SfxEntry *    getLM() { return l_morph; }
+  inline SfxEntry *    getRM() { return r_morph; }
+  inline SfxEntry *    getEQM() { return eq_morph; }
+  inline SfxEntry *    getFlgNxt() { return flgnxt; }
+
+  inline void   setNext(SfxEntry * ptr)   { next = ptr;   }
+  inline void   setNextNE(SfxEntry * ptr) { nextne = ptr; }
+  inline void   setNextEQ(SfxEntry * ptr) { nexteq = ptr; }
+  inline void   setFlgNxt(SfxEntry * ptr) { flgnxt = ptr; }
+
+  inline int    test_condition(const char * st, const char * begin);
+};
+
+#endif
+
+
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/affixmgr.cpp spellcheck/hunspell/hunspell/affixmgr.cpp
--- spellcheck.old/hunspell/hunspell/affixmgr.cpp	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/affixmgr.cpp	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,4155 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef MOZILLA_CLIENT
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+#include <cstdio>
+#else
+#include <stdlib.h> 
+#include <string.h>
+#include <stdio.h> 
+#include <ctype.h>
+#endif
+
+#include "affixmgr.hxx"
+#include "affentry.hxx"
+#include "langnum.hxx"
+
+#include "csutil.hxx"
+
+#ifndef MOZILLA_CLIENT
+#ifndef W32
+using namespace std;
+#endif
+#endif
+
+AffixMgr::AffixMgr(const char * affpath, HashMgr* ptr) 
+{
+  // register hash manager and load affix data from aff file
+  pHMgr = ptr;
+  keystring = NULL;
+  trystring = NULL;
+  encoding=NULL;
+  utf8 = 0;
+  complexprefixes = 0;
+  maptable = NULL;
+  nummap = 0;
+  breaktable = NULL;
+  numbreak = 0;
+  reptable = NULL;
+  numrep = 0;
+  checkcpdtable = NULL;
+  numcheckcpd = 0;
+  defcpdtable = NULL;
+  numdefcpd = 0;
+  phone = NULL;
+  compoundflag = FLAG_NULL; // permits word in compound forms
+  compoundbegin = FLAG_NULL; // may be first word in compound forms
+  compoundmiddle = FLAG_NULL; // may be middle word in compound forms
+  compoundend = FLAG_NULL; // may be last word in compound forms
+  compoundroot = FLAG_NULL; // compound word signing flag
+  compoundpermitflag = FLAG_NULL; // compound permitting flag for suffixed word
+  compoundforbidflag = FLAG_NULL; // compound fordidden flag for suffixed word
+  checkcompounddup = 0; // forbid double words in compounds
+  checkcompoundrep = 0; // forbid bad compounds (may be non compound word with a REP substitution)
+  checkcompoundcase = 0; // forbid upper and lowercase combinations at word bounds
+  checkcompoundtriple = 0; // forbid compounds with triple letters
+  forbiddenword = FLAG_NULL; // forbidden word signing flag
+  nosuggest = FLAG_NULL; // don't suggest words signed with NOSUGGEST flag
+  lang = NULL; // language
+  langnum = 0; // language code (see http://l10n.openoffice.org/languages.html)
+  pseudoroot = FLAG_NULL; // forbidden root, allowed only with suffixes
+  cpdwordmax = -1; // default: unlimited wordcount in compound words
+  cpdmin = -1;  // undefined
+  cpdmaxsyllable = 0; // default: unlimited syllablecount in compound words
+  cpdvowels=NULL; // vowels (for calculating of Hungarian compounding limit, O(n) search! XXX)
+  cpdvowels_utf16=NULL; // vowels for UTF-8 encoding (bsearch instead of O(n) search)
+  cpdvowels_utf16_len=0; // vowels
+  pfxappnd=NULL; // previous prefix for counting the syllables of prefix BUG
+  sfxappnd=NULL; // previous suffix for counting a special syllables BUG
+  cpdsyllablenum=NULL; // syllable count incrementing flag
+  checknum=0; // checking numbers, and word with numbers
+  wordchars=NULL; // letters + spec. word characters
+  wordchars_utf16=NULL; // letters + spec. word characters
+  wordchars_utf16_len=0; // letters + spec. word characters
+  ignorechars=NULL; // letters + spec. word characters
+  ignorechars_utf16=NULL; // letters + spec. word characters
+  ignorechars_utf16_len=0; // letters + spec. word characters
+  version=NULL; // affix and dictionary file version string
+  havecontclass=0; // flags of possible continuing classes (double affix)
+  // LEMMA_PRESENT: not put root into the morphological output. Lemma presents
+  // in morhological description in dictionary file. It's often combined with PSEUDOROOT.
+  lemma_present = FLAG_NULL; 
+  circumfix = FLAG_NULL; 
+  onlyincompound = FLAG_NULL; 
+  flag_mode = FLAG_CHAR; // default one-character flags in affix and dic file
+  maxngramsugs = -1; // undefined
+  nosplitsugs = 0;
+  sugswithdots = 0;
+  keepcase = 0;
+  checksharps = 0;
+
+  derived = NULL; // XXX not threadsafe variable for experimental stemming
+  sfx = NULL;
+  pfx = NULL;
+
+  for (int i=0; i < SETSIZE; i++) {
+     pStart[i] = NULL;
+     sStart[i] = NULL;
+     pFlag[i] = NULL;
+     sFlag[i] = NULL;
+  }
+
+  for (int j=0; j < CONTSIZE; j++) {
+    contclasses[j] = 0;
+  }
+
+  if (parse_file(affpath)) {
+     HUNSPELL_WARNING(stderr, "Failure loading aff file %s\n",affpath);
+  }
+  
+  if (cpdmin == -1) cpdmin = MINCPDLEN;
+
+}
+
+
+AffixMgr::~AffixMgr() 
+{
+ 
+  // pass through linked prefix entries and clean up
+  for (int i=0; i < SETSIZE ;i++) {
+       pFlag[i] = NULL;
+       PfxEntry * ptr = (PfxEntry *)pStart[i];
+       PfxEntry * nptr = NULL;
+       while (ptr) {
+            nptr = ptr->getNext();
+            delete(ptr);
+            ptr = nptr;
+            nptr = NULL;
+       }  
+  }
+
+  // pass through linked suffix entries and clean up
+  for (int j=0; j < SETSIZE ; j++) {
+       sFlag[j] = NULL;
+       SfxEntry * ptr = (SfxEntry *)sStart[j];
+       SfxEntry * nptr = NULL;
+       while (ptr) {
+            nptr = ptr->getNext();
+            delete(ptr);
+            ptr = nptr;
+            nptr = NULL;
+       }
+       sStart[j] = NULL;
+  }
+
+  if (keystring) free(keystring);
+  keystring=NULL;
+  if (trystring) free(trystring);
+  trystring=NULL;
+  if (encoding) free(encoding);
+  encoding=NULL;
+  if (maptable) {  
+     for (int j=0; j < nummap; j++) {
+        if (maptable[j].set) free(maptable[j].set);
+        if (maptable[j].set_utf16) free(maptable[j].set_utf16);
+        maptable[j].set = NULL;
+        maptable[j].len = 0;
+     }
+     free(maptable);  
+     maptable = NULL;
+  }
+  nummap = 0;
+  if (breaktable) {
+     for (int j=0; j < numbreak; j++) {
+        if (breaktable[j]) free(breaktable[j]);
+        breaktable[j] = NULL;
+     }
+     free(breaktable);  
+     breaktable = NULL;
+  }
+  numbreak = 0;
+  if (reptable) {
+     for (int j=0; j < numrep; j++) {
+        free(reptable[j].pattern);
+        free(reptable[j].pattern2);
+     }
+     free(reptable);  
+     reptable = NULL;
+  }
+  if (phone && phone->rules) {
+     for (int j=0; j < phone->num + 1; j++) {
+        free(phone->rules[j * 2]);
+        free(phone->rules[j * 2 + 1]);
+     }
+     free(phone->rules);
+     free(phone);  
+     phone = NULL;
+  }
+
+  if (defcpdtable) {  
+     for (int j=0; j < numdefcpd; j++) {
+        free(defcpdtable[j].def);
+        defcpdtable[j].def = NULL;
+     }
+     free(defcpdtable);  
+     defcpdtable = NULL;
+  }
+  numrep = 0;
+  if (checkcpdtable) {  
+     for (int j=0; j < numcheckcpd; j++) {
+        free(checkcpdtable[j].pattern);
+        free(checkcpdtable[j].pattern2);
+        checkcpdtable[j].pattern = NULL;
+        checkcpdtable[j].pattern2 = NULL;
+     }
+     free(checkcpdtable);  
+     checkcpdtable = NULL;
+  }
+  numcheckcpd = 0;
+  FREE_FLAG(compoundflag);
+  FREE_FLAG(compoundbegin);
+  FREE_FLAG(compoundmiddle);
+  FREE_FLAG(compoundend);
+  FREE_FLAG(compoundpermitflag);
+  FREE_FLAG(compoundforbidflag);
+  FREE_FLAG(compoundroot);
+  FREE_FLAG(forbiddenword);
+  FREE_FLAG(nosuggest);
+  FREE_FLAG(pseudoroot);
+  FREE_FLAG(lemma_present);
+  FREE_FLAG(circumfix);
+  FREE_FLAG(onlyincompound);
+  
+  cpdwordmax = 0;
+  pHMgr = NULL;
+  cpdmin = 0;
+  cpdmaxsyllable = 0;
+  if (cpdvowels) free(cpdvowels);
+  if (cpdvowels_utf16) free(cpdvowels_utf16);
+  if (cpdsyllablenum) free(cpdsyllablenum);
+  free_utf_tbl();
+  if (lang) free(lang);
+  if (wordchars) free(wordchars);
+  if (wordchars_utf16) free(wordchars_utf16);
+  if (ignorechars) free(ignorechars);
+  if (ignorechars_utf16) free(ignorechars_utf16);
+  if (version) free(version);
+  if (derived) free(derived);
+  checknum=0;
+}
+
+
+// read in aff file and build up prefix and suffix entry objects 
+int  AffixMgr::parse_file(const char * affpath)
+{
+
+  // io buffers
+  char line[MAXLNLEN+1];
+ 
+  // affix type
+  char ft;
+  
+  // checking flag duplication
+  char dupflags[CONTSIZE];
+  char dupflags_ini = 1;
+
+  // first line indicator for removing byte order mark
+  int firstline = 1;
+  
+  // open the affix file
+  FILE * afflst;
+  afflst = fopen(affpath,"r");
+  if (!afflst) {
+    HUNSPELL_WARNING(stderr, "error: could not open affix description file %s\n",affpath);
+    return 1;
+  }
+
+  // step one is to parse the affix file building up the internal
+  // affix data structures
+
+
+    // read in each line ignoring any that do not
+    // start with a known line type indicator
+    while (fgets(line,MAXLNLEN,afflst)) {
+       mychomp(line);
+
+       /* remove byte order mark */
+       if (firstline) {
+         firstline = 0;
+         if (strncmp(line,"\xEF\xBB\xBF",3) == 0) {
+            memmove(line, line+3, strlen(line+3)+1);
+            HUNSPELL_WARNING(stderr, "warning: affix file begins with byte order mark: possible incompatibility with old Hunspell versions\n");
+         }
+       }
+
+       /* parse in the keyboard string */
+       if (strncmp(line,"KEY",3) == 0) {
+          if (parse_string(line, &keystring, "KEY")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the try string */
+       if (strncmp(line,"TRY",3) == 0) {
+          if (parse_string(line, &trystring, "TRY")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the name of the character set used by the .dict and .aff */
+       if (strncmp(line,"SET",3) == 0) {
+          if (parse_string(line, &encoding, "SET")) {
+             fclose(afflst);
+             return 1;
+          }
+          if (strcmp(encoding, "UTF-8") == 0) {
+             utf8 = 1;
+#ifndef OPENOFFICEORG
+#ifndef MOZILLA_CLIENT
+             if (initialize_utf_tbl()) return 1;
+#endif
+#endif
+          }
+       }
+
+       /* parse COMPLEXPREFIXES for agglutinative languages with right-to-left writing system */
+       if (strncmp(line,"COMPLEXPREFIXES",15) == 0)
+                   complexprefixes = 1;
+
+       /* parse in the flag used by the controlled compound words */
+       if (strncmp(line,"COMPOUNDFLAG",12) == 0) {
+          if (parse_flag(line, &compoundflag, "COMPOUNDFLAG")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag used by compound words */
+       if (strncmp(line,"COMPOUNDBEGIN",13) == 0) {
+          if (complexprefixes) {
+            if (parse_flag(line, &compoundend, "COMPOUNDBEGIN")) {
+              fclose(afflst);
+              return 1;
+            }
+          } else {
+            if (parse_flag(line, &compoundbegin, "COMPOUNDBEGIN")) {
+              fclose(afflst);
+              return 1;
+            }
+          }
+       }
+
+       /* parse in the flag used by compound words */
+       if (strncmp(line,"COMPOUNDMIDDLE",14) == 0) {
+          if (parse_flag(line, &compoundmiddle, "COMPOUNDMIDDLE")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+       /* parse in the flag used by compound words */
+       if (strncmp(line,"COMPOUNDEND",11) == 0) {
+          if (complexprefixes) {
+            if (parse_flag(line, &compoundbegin, "COMPOUNDEND")) {
+              fclose(afflst);
+              return 1;
+            }
+          } else {
+            if (parse_flag(line, &compoundend, "COMPOUNDEND")) {
+              fclose(afflst);
+              return 1;
+            }
+          }
+       }
+
+       /* parse in the data used by compound_check() method */
+       if (strncmp(line,"COMPOUNDWORDMAX",15) == 0) {
+          if (parse_num(line, &cpdwordmax, "COMPOUNDWORDMAX")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag sign compounds in dictionary */
+       if (strncmp(line,"COMPOUNDROOT",12) == 0) {
+          if (parse_flag(line, &compoundroot, "COMPOUNDROOT")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag used by compound_check() method */
+       if (strncmp(line,"COMPOUNDPERMITFLAG",18) == 0) {
+          if (parse_flag(line, &compoundpermitflag, "COMPOUNDPERMITFLAG")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag used by compound_check() method */
+       if (strncmp(line,"COMPOUNDFORBIDFLAG",18) == 0) {
+          if (parse_flag(line, &compoundforbidflag, "COMPOUNDFORBIDFLAG")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       if (strncmp(line,"CHECKCOMPOUNDDUP",16) == 0) {
+                   checkcompounddup = 1;
+       }
+
+       if (strncmp(line,"CHECKCOMPOUNDREP",16) == 0) {
+                   checkcompoundrep = 1;
+       }
+
+       if (strncmp(line,"CHECKCOMPOUNDTRIPLE",19) == 0) {
+                   checkcompoundtriple = 1;
+       }
+
+       if (strncmp(line,"CHECKCOMPOUNDCASE",17) == 0) {
+                   checkcompoundcase = 1;
+       }
+
+       if (strncmp(line,"NOSUGGEST",9) == 0) {
+          if (parse_flag(line, &nosuggest, "NOSUGGEST")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag used by forbidden words */
+       if (strncmp(line,"FORBIDDENWORD",13) == 0) {
+          if (parse_flag(line, &forbiddenword, "FORBIDDENWORD")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag used by forbidden words */
+       if (strncmp(line,"LEMMA_PRESENT",13) == 0) {
+          if (parse_flag(line, &lemma_present, "LEMMA_PRESENT")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag used by circumfixes */
+       if (strncmp(line,"CIRCUMFIX",9) == 0) {
+          if (parse_flag(line, &circumfix, "CIRCUMFIX")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag used by fogemorphemes */
+       if (strncmp(line,"ONLYINCOMPOUND",14) == 0) {
+          if (parse_flag(line, &onlyincompound, "ONLYINCOMPOUND")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag used by `pseudoroots' */
+       if (strncmp(line,"PSEUDOROOT",10) == 0) {
+          if (parse_flag(line, &pseudoroot, "PSEUDOROOT")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag used by `pseudoroots' */
+       if (strncmp(line,"NEEDAFFIX",9) == 0) {
+          if (parse_flag(line, &pseudoroot, "NEEDAFFIX")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the minimal length for words in compounds */
+       if (strncmp(line,"COMPOUNDMIN",11) == 0) {
+          if (parse_num(line, &cpdmin, "COMPOUNDMIN")) {
+             fclose(afflst);
+             return 1;
+          }
+          if (cpdmin < 1) cpdmin = 1;
+       }
+
+       /* parse in the max. words and syllables in compounds */
+       if (strncmp(line,"COMPOUNDSYLLABLE",16) == 0) {
+          if (parse_cpdsyllable(line)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag used by compound_check() method */
+       if (strncmp(line,"SYLLABLENUM",11) == 0) {
+          if (parse_string(line, &cpdsyllablenum, "SYLLABLENUM")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the flag used by the controlled compound words */
+       if (strncmp(line,"CHECKNUM",8) == 0) {
+           checknum=1;
+       }
+
+       /* parse in the extra word characters */
+       if (strncmp(line,"WORDCHARS",9) == 0) {
+          if (parse_array(line, &wordchars, &wordchars_utf16, &wordchars_utf16_len, "WORDCHARS", utf8)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the ignored characters (for example, Arabic optional diacretics charachters */
+       if (strncmp(line,"IGNORE",6) == 0) {
+          if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, "IGNORE", utf8)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the typical fault correcting table */
+       if (strncmp(line,"REP",3) == 0) {
+          if (parse_reptable(line, afflst)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the phonetic translation table */
+       if (strncmp(line,"PHONE",5) == 0) {
+          if (parse_phonetable(line, afflst)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the checkcompoundpattern table */
+       if (strncmp(line,"CHECKCOMPOUNDPATTERN",20) == 0) {
+          if (parse_checkcpdtable(line, afflst)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the defcompound table */
+       if (strncmp(line,"COMPOUNDRULE",12) == 0) {
+          if (parse_defcpdtable(line, afflst)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the related character map table */
+       if (strncmp(line,"MAP",3) == 0) {
+          if (parse_maptable(line, afflst)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the word breakpoints table */
+       if (strncmp(line,"BREAK",5) == 0) {
+          if (parse_breaktable(line, afflst)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       /* parse in the language for language specific codes */
+       if (strncmp(line,"LANG",4) == 0) {
+          if (parse_string(line, &lang, "LANG")) {
+             fclose(afflst);
+             return 1;
+          }
+          langnum = get_lang_num(lang);
+       }
+
+       if (strncmp(line,"VERSION",7) == 0) {
+          if (parse_string(line, &version, "VERSION")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       if (strncmp(line,"MAXNGRAMSUGS",12) == 0) {
+          if (parse_num(line, &maxngramsugs, "MAXNGRAMSUGS")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       if (strncmp(line,"NOSPLITSUGS",11) == 0) {
+                   nosplitsugs=1;
+       }
+
+       if (strncmp(line,"SUGSWITHDOTS",12) == 0) {
+                   sugswithdots=1;
+       }
+
+       /* parse in the flag used by forbidden words */
+       if (strncmp(line,"KEEPCASE",8) == 0) {
+          if (parse_flag(line, &keepcase, "KEEPCASE")) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       if (strncmp(line,"CHECKSHARPS",11) == 0) {
+                   checksharps=1;
+       }
+
+       /* parse this affix: P - prefix, S - suffix */
+       ft = ' ';
+       if (strncmp(line,"PFX",3) == 0) ft = complexprefixes ? 'S' : 'P';
+       if (strncmp(line,"SFX",3) == 0) ft = complexprefixes ? 'P' : 'S';
+       if (ft != ' ') {
+          if (dupflags_ini) {
+            for (int i = 0; i < CONTSIZE; i++) dupflags[i] = 0;
+            dupflags_ini = 0;
+          }
+          if (parse_affix(line, ft, afflst, dupflags)) {
+             fclose(afflst);
+             process_pfx_tree_to_list();
+             process_sfx_tree_to_list();
+             return 1;
+          }
+       }
+
+    }
+    fclose(afflst);
+
+    // convert affix trees to sorted list
+    process_pfx_tree_to_list();
+    process_sfx_tree_to_list();
+
+    // now we can speed up performance greatly taking advantage of the 
+    // relationship between the affixes and the idea of "subsets".
+
+    // View each prefix as a potential leading subset of another and view
+    // each suffix (reversed) as a potential trailing subset of another.
+
+    // To illustrate this relationship if we know the prefix "ab" is found in the
+    // word to examine, only prefixes that "ab" is a leading subset of need be examined.
+    // Furthermore is "ab" is not present then none of the prefixes that "ab" is
+    // is a subset need be examined.
+    // The same argument goes for suffix string that are reversed.
+
+    // Then to top this off why not examine the first char of the word to quickly
+    // limit the set of prefixes to examine (i.e. the prefixes to examine must 
+    // be leading supersets of the first character of the word (if they exist)
+ 
+    // To take advantage of this "subset" relationship, we need to add two links
+    // from entry.  One to take next if the current prefix is found (call it nexteq)
+    // and one to take next if the current prefix is not found (call it nextne).
+
+    // Since we have built ordered lists, all that remains is to properly intialize 
+    // the nextne and nexteq pointers that relate them
+
+    process_pfx_order();
+    process_sfx_order();
+
+    /* get encoding for CHECKCOMPOUNDCASE */
+    char * enc = get_encoding();
+    csconv = get_current_cs(enc);
+    free(enc);
+    enc = NULL;
+
+    // temporary BREAK definition for German dash handling (OOo issue 64400)
+    if ((langnum == LANG_de) && (!breaktable)) {
+        breaktable = (char **) malloc(sizeof(char *));
+        if (!breaktable) return 1;
+        breaktable[0] = mystrdup("-");
+        numbreak = 1;
+    }
+    return 0;
+}
+
+
+// we want to be able to quickly access prefix information
+// both by prefix flag, and sorted by prefix string itself 
+// so we need to set up two indexes
+
+int AffixMgr::build_pfxtree(AffEntry* pfxptr)
+{
+  PfxEntry * ptr;
+  PfxEntry * pptr;
+  PfxEntry * ep = (PfxEntry*) pfxptr;
+
+  // get the right starting points
+  const char * key = ep->getKey();
+  const unsigned char flg = (unsigned char) (ep->getFlag() & 0x00FF);
+
+  // first index by flag which must exist
+  ptr = (PfxEntry*)pFlag[flg];
+  ep->setFlgNxt(ptr);
+  pFlag[flg] = (AffEntry *) ep;
+
+
+  // handle the special case of null affix string
+  if (strlen(key) == 0) {
+    // always inset them at head of list at element 0
+     ptr = (PfxEntry*)pStart[0];
+     ep->setNext(ptr);
+     pStart[0] = (AffEntry*)ep;
+     return 0;
+  }
+
+  // now handle the normal case
+  ep->setNextEQ(NULL);
+  ep->setNextNE(NULL);
+
+  unsigned char sp = *((const unsigned char *)key);
+  ptr = (PfxEntry*)pStart[sp];
+  
+  // handle the first insert 
+  if (!ptr) {
+     pStart[sp] = (AffEntry*)ep;
+     return 0;
+  }
+
+
+  // otherwise use binary tree insertion so that a sorted
+  // list can easily be generated later
+  pptr = NULL;
+  for (;;) {
+    pptr = ptr;
+    if (strcmp(ep->getKey(), ptr->getKey() ) <= 0) {
+       ptr = ptr->getNextEQ();
+       if (!ptr) {
+          pptr->setNextEQ(ep);
+          break;
+       }
+    } else {
+       ptr = ptr->getNextNE();
+       if (!ptr) {
+          pptr->setNextNE(ep);
+          break;
+       }
+    }
+  }
+  return 0;
+}
+
+// we want to be able to quickly access suffix information
+// both by suffix flag, and sorted by the reverse of the
+// suffix string itself; so we need to set up two indexes
+int AffixMgr::build_sfxtree(AffEntry* sfxptr)
+{
+  SfxEntry * ptr;
+  SfxEntry * pptr;
+  SfxEntry * ep = (SfxEntry *) sfxptr;
+
+  /* get the right starting point */
+  const char * key = ep->getKey();
+  const unsigned char flg = (unsigned char) (ep->getFlag() & 0x00FF);
+
+  // first index by flag which must exist
+  ptr = (SfxEntry*)sFlag[flg];
+  ep->setFlgNxt(ptr);
+  sFlag[flg] = (AffEntry *) ep;
+
+  // next index by affix string
+
+  // handle the special case of null affix string
+  if (strlen(key) == 0) {
+    // always inset them at head of list at element 0
+     ptr = (SfxEntry*)sStart[0];
+     ep->setNext(ptr);
+     sStart[0] = (AffEntry*)ep;
+     return 0;
+  }
+
+  // now handle the normal case
+  ep->setNextEQ(NULL);
+  ep->setNextNE(NULL);
+
+  unsigned char sp = *((const unsigned char *)key);
+  ptr = (SfxEntry*)sStart[sp];
+  
+  // handle the first insert 
+  if (!ptr) {
+     sStart[sp] = (AffEntry*)ep;
+     return 0;
+  }
+
+  // otherwise use binary tree insertion so that a sorted
+  // list can easily be generated later
+  pptr = NULL;
+  for (;;) {
+    pptr = ptr;
+    if (strcmp(ep->getKey(), ptr->getKey() ) <= 0) {
+       ptr = ptr->getNextEQ();
+       if (!ptr) {
+          pptr->setNextEQ(ep);
+          break;
+       }
+    } else {
+       ptr = ptr->getNextNE();
+       if (!ptr) {
+          pptr->setNextNE(ep);
+          break;
+       }
+    }
+  }
+  return 0;
+}
+
+// convert from binary tree to sorted list
+int AffixMgr::process_pfx_tree_to_list()
+{
+  for (int i=1; i< SETSIZE; i++) {
+    pStart[i] = process_pfx_in_order(pStart[i],NULL);
+  }
+  return 0;
+}
+
+
+AffEntry* AffixMgr::process_pfx_in_order(AffEntry* ptr, AffEntry* nptr)
+{
+  if (ptr) {
+    nptr = process_pfx_in_order(((PfxEntry*) ptr)->getNextNE(), nptr);
+    ((PfxEntry*) ptr)->setNext((PfxEntry*) nptr);
+    nptr = process_pfx_in_order(((PfxEntry*) ptr)->getNextEQ(), ptr);
+  }
+  return nptr;
+}
+
+
+// convert from binary tree to sorted list
+int AffixMgr:: process_sfx_tree_to_list()
+{
+  for (int i=1; i< SETSIZE; i++) {
+    sStart[i] = process_sfx_in_order(sStart[i],NULL);
+  }
+  return 0;
+}
+
+AffEntry* AffixMgr::process_sfx_in_order(AffEntry* ptr, AffEntry* nptr)
+{
+  if (ptr) {
+    nptr = process_sfx_in_order(((SfxEntry*) ptr)->getNextNE(), nptr);
+    ((SfxEntry*) ptr)->setNext((SfxEntry*) nptr);
+    nptr = process_sfx_in_order(((SfxEntry*) ptr)->getNextEQ(), ptr);
+  }
+  return nptr;
+}
+
+
+// reinitialize the PfxEntry links NextEQ and NextNE to speed searching
+// using the idea of leading subsets this time
+int AffixMgr::process_pfx_order()
+{
+    PfxEntry* ptr;
+
+    // loop through each prefix list starting point
+    for (int i=1; i < SETSIZE; i++) {
+
+         ptr = (PfxEntry*)pStart[i];
+
+         // look through the remainder of the list
+         //  and find next entry with affix that 
+         // the current one is not a subset of
+         // mark that as destination for NextNE
+         // use next in list that you are a subset
+         // of as NextEQ
+
+         for (; ptr != NULL; ptr = ptr->getNext()) {
+
+             PfxEntry * nptr = ptr->getNext();
+             for (; nptr != NULL; nptr = nptr->getNext()) {
+                 if (! isSubset( ptr->getKey() , nptr->getKey() )) break;
+             }
+             ptr->setNextNE(nptr);
+             ptr->setNextEQ(NULL);
+             if ((ptr->getNext()) && isSubset(ptr->getKey() , (ptr->getNext())->getKey())) 
+                 ptr->setNextEQ(ptr->getNext());
+         }
+
+         // now clean up by adding smart search termination strings:
+         // if you are already a superset of the previous prefix
+         // but not a subset of the next, search can end here
+         // so set NextNE properly
+
+         ptr = (PfxEntry *) pStart[i];
+         for (; ptr != NULL; ptr = ptr->getNext()) {
+             PfxEntry * nptr = ptr->getNext();
+             PfxEntry * mptr = NULL;
+             for (; nptr != NULL; nptr = nptr->getNext()) {
+                 if (! isSubset(ptr->getKey(),nptr->getKey())) break;
+                 mptr = nptr;
+             }
+             if (mptr) mptr->setNextNE(NULL);
+         }
+    }
+    return 0;
+}
+
+// initialize the SfxEntry links NextEQ and NextNE to speed searching
+// using the idea of leading subsets this time
+int AffixMgr::process_sfx_order()
+{
+    SfxEntry* ptr;
+
+    // loop through each prefix list starting point
+    for (int i=1; i < SETSIZE; i++) {
+
+         ptr = (SfxEntry *) sStart[i];
+
+         // look through the remainder of the list
+         //  and find next entry with affix that 
+         // the current one is not a subset of
+         // mark that as destination for NextNE
+         // use next in list that you are a subset
+         // of as NextEQ
+
+         for (; ptr != NULL; ptr = ptr->getNext()) {
+             SfxEntry * nptr = ptr->getNext();
+             for (; nptr != NULL; nptr = nptr->getNext()) {
+                 if (! isSubset(ptr->getKey(),nptr->getKey())) break;
+             }
+             ptr->setNextNE(nptr);
+             ptr->setNextEQ(NULL);
+             if ((ptr->getNext()) && isSubset(ptr->getKey(),(ptr->getNext())->getKey())) 
+                 ptr->setNextEQ(ptr->getNext());
+         }
+
+
+         // now clean up by adding smart search termination strings:
+         // if you are already a superset of the previous suffix
+         // but not a subset of the next, search can end here
+         // so set NextNE properly
+
+         ptr = (SfxEntry *) sStart[i];
+         for (; ptr != NULL; ptr = ptr->getNext()) {
+             SfxEntry * nptr = ptr->getNext();
+             SfxEntry * mptr = NULL;
+             for (; nptr != NULL; nptr = nptr->getNext()) {
+                 if (! isSubset(ptr->getKey(),nptr->getKey())) break;
+                 mptr = nptr;
+             }
+             if (mptr) mptr->setNextNE(NULL);
+         }
+    }
+    return 0;
+}
+
+
+
+// takes aff file condition string and creates the
+// conds array - please see the appendix at the end of the
+// file affentry.cpp which describes what is going on here
+// in much more detail
+
+int AffixMgr::encodeit(struct affentry * ptr, char * cs)
+{
+  unsigned char c;
+  int i, j, k;
+  unsigned char mbr[MAXLNLEN];
+  w_char wmbr[MAXLNLEN];
+  w_char * wpos = wmbr;
+
+  // now clear the conditions array */
+  for (i=0;i<SETSIZE;i++) ptr->conds.base[i] = (unsigned char) 0;
+
+  // now parse the string to create the conds array */
+  int nc = strlen(cs);
+  unsigned char neg = 0;   // complement indicator
+  int grp = 0;   // group indicator
+  unsigned char n = 0;     // number of conditions
+  int ec = 0;    // end condition indicator
+  int nm = 0;    // number of member in group
+
+  // if no condition just return
+  if (strcmp(cs,".")==0) {
+    ptr->numconds = 0;
+    return 0;
+  }
+
+  i = 0;
+  while (i < nc) {
+    c = *((unsigned char *)(cs + i));
+
+    // start group indicator
+    if (c == '[') {
+       grp = 1;
+       c = 0;
+    }
+
+    // complement flag
+    if ((grp == 1) && (c == '^')) {
+       neg = 1;
+       c = 0;
+    }
+
+    // end goup indicator
+    if (c == ']') {
+       ec = 1;
+       c = 0;
+    }
+
+    // add character of group to list
+    if ((grp == 1) && (c != 0)) {
+      *(mbr + nm) = c;
+      nm++;
+      c = 0;
+    }
+
+    // end of condition 
+    if (c != 0) {
+       ec = 1;
+    }
+
+  if (ec) {    
+    if (!utf8) {
+      if (grp == 1) {
+        if (neg == 0) {
+          // set the proper bits in the condition array vals for those chars
+          for (j=0;j<nm;j++) {
+             k = (unsigned int) mbr[j];
+             ptr->conds.base[k] = ptr->conds.base[k] | ((unsigned char)1 << n);
+          }
+        } else {
+          // complement so set all of them and then unset indicated ones
+           for (j=0;j<SETSIZE;j++) ptr->conds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n);
+           for (j=0;j<nm;j++) {
+             k = (unsigned int) mbr[j];
+             ptr->conds.base[k] = ptr->conds.base[k] & ~((unsigned char)1 << n);
+           }
+        }
+        neg = 0;
+        grp = 0;   
+        nm = 0;
+      } else {
+         // not a group so just set the proper bit for this char
+         // but first handle special case of . inside condition
+         if (c == '.') {
+            // wild card character so set them all
+            for (j=0;j<SETSIZE;j++) ptr->conds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n);
+         } else {  
+            ptr->conds.base[(unsigned int) c] = ptr->conds.base[(unsigned int)c] | ((unsigned char)1 << n);
+         }
+      }
+      n++;
+      ec = 0;
+    } else { // UTF-8 character set
+      if (grp == 1) {
+        ptr->conds.utf8.neg[n] = neg;
+        if (neg == 0) {
+          // set the proper bits in the condition array vals for those chars
+          for (j=0;j<nm;j++) {
+             k = (unsigned int) mbr[j];
+             if (k >> 7) {
+                u8_u16(wpos, 1, (char *) mbr + j);
+                wpos++;
+                if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character
+             } else {
+                ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] | ((unsigned char)1 << n);
+             }
+          }
+        } else { // neg == 1
+          // complement so set all of them and then unset indicated ones
+           for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n);
+           for (j=0;j<nm;j++) {
+             k = (unsigned int) mbr[j];
+             if (k >> 7) {
+                u8_u16(wpos, 1, (char *) mbr + j);
+                wpos++;
+                if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character
+             } else {
+                ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] & ~((unsigned char)1 << n);
+             }
+           }
+        }
+        neg = 0;
+        grp = 0;   
+        nm = 0;
+        ptr->conds.utf8.wlen[n] = wpos - wmbr;
+        if ((wpos - wmbr) != 0) {
+            ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char) * (wpos - wmbr));
+            if (!ptr->conds.utf8.wchars[n]) return 1;
+            memcpy(ptr->conds.utf8.wchars[n], wmbr, sizeof(w_char) * (wpos - wmbr));
+            flag_qsort((unsigned short *) ptr->conds.utf8.wchars[n], 0, ptr->conds.utf8.wlen[n]);
+            wpos = wmbr;
+        }
+      } else { // grp == 0
+         // is UTF-8 character?
+         if (c >> 7) {
+            ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char));
+            if (!ptr->conds.utf8.wchars[n]) return 1;
+            ptr->conds.utf8.wlen[n] = 1;
+            u8_u16(ptr->conds.utf8.wchars[n], 1, cs + i);
+            if ((c & 0xe0) == 0xe0) i+=2; else i++; // 3-byte UFT-8 character
+         } else {
+            ptr->conds.utf8.wchars[n] = NULL;
+            // not a group so just set the proper bit for this char
+            // but first handle special case of . inside condition
+            if (c == '.') {
+                ptr->conds.utf8.all[n] = 1;
+                // wild card character so set them all
+                for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n);
+            } else {
+                ptr->conds.utf8.all[n] = 0;
+                ptr->conds.utf8.ascii[(unsigned int) c] = ptr->conds.utf8.ascii[(unsigned int)c] | ((unsigned char)1 << n);
+            }
+         }
+         neg = 0;
+      }
+      n++;
+      ec = 0;
+      neg = 0;
+    }  
+  }
+
+    i++;
+  }
+  ptr->numconds = n;
+  return 0;
+}
+
+ // return 1 if s1 is a leading subset of s2
+/* inline int AffixMgr::isSubset(const char * s1, const char * s2)
+ {
+    while ((*s1 == *s2) && *s1) {
+        s1++;
+        s2++;
+    }
+    return (*s1 == '\0');
+ }
+*/
+
+ // return 1 if s1 is a leading subset of s2 (dots are for infixes)
+inline int AffixMgr::isSubset(const char * s1, const char * s2)
+ {
+    while (((*s1 == *s2) || (*s1 == '.')) && (*s1 != '\0')) {
+        s1++;
+        s2++;
+    }
+    return (*s1 == '\0');
+ }
+
+
+// check word for prefixes
+struct hentry * AffixMgr::prefix_check(const char * word, int len, char in_compound,
+    const FLAG needflag)
+{
+    struct hentry * rv= NULL;
+
+    pfx = NULL;
+    pfxappnd = NULL;
+    sfxappnd = NULL;
+    
+    // first handle the special case of 0 length prefixes
+    PfxEntry * pe = (PfxEntry *) pStart[0];
+    while (pe) {
+        if (
+            // fogemorpheme
+              ((in_compound != IN_CPD_NOT) || !(pe->getCont() &&
+                  (TESTAFF(pe->getCont(), onlyincompound, pe->getContLen())))) &&
+            // permit prefixes in compounds
+              ((in_compound != IN_CPD_END) || (pe->getCont() &&
+                  (TESTAFF(pe->getCont(), compoundpermitflag, pe->getContLen()))))
+              ) {
+                    // check prefix
+                    rv = pe->checkword(word, len, in_compound, needflag);
+                    if (rv) {
+                        pfx=(AffEntry *)pe; // BUG: pfx not stateless
+                        return rv;
+                    }
+             }
+       pe = pe->getNext();
+    }
+  
+    // now handle the general case
+    unsigned char sp = *((const unsigned char *)word);
+    PfxEntry * pptr = (PfxEntry *)pStart[sp];
+
+    while (pptr) {
+        if (isSubset(pptr->getKey(),word)) {
+             if (
+            // fogemorpheme
+              ((in_compound != IN_CPD_NOT) || !(pptr->getCont() &&
+                  (TESTAFF(pptr->getCont(), onlyincompound, pptr->getContLen())))) &&
+            // permit prefixes in compounds
+              ((in_compound != IN_CPD_END) || (pptr->getCont() &&
+                  (TESTAFF(pptr->getCont(), compoundpermitflag, pptr->getContLen()))))
+              ) {
+            // check prefix
+                  rv = pptr->checkword(word, len, in_compound, needflag);
+                  if (rv) {
+                    pfx=(AffEntry *)pptr; // BUG: pfx not stateless
+                    return rv;
+                  }
+             }
+             pptr = pptr->getNextEQ();
+        } else {
+             pptr = pptr->getNextNE();
+        }
+    }
+    
+    return NULL;
+}
+
+// check word for prefixes
+struct hentry * AffixMgr::prefix_check_twosfx(const char * word, int len,
+    char in_compound, const FLAG needflag)
+{
+    struct hentry * rv= NULL;
+
+    pfx = NULL;
+    sfxappnd = NULL;
+    
+    // first handle the special case of 0 length prefixes
+    PfxEntry * pe = (PfxEntry *) pStart[0];
+    
+    while (pe) {
+        rv = pe->check_twosfx(word, len, in_compound, needflag);
+        if (rv) return rv;
+        pe = pe->getNext();
+    }
+  
+    // now handle the general case
+    unsigned char sp = *((const unsigned char *)word);
+    PfxEntry * pptr = (PfxEntry *)pStart[sp];
+
+    while (pptr) {
+        if (isSubset(pptr->getKey(),word)) {
+            rv = pptr->check_twosfx(word, len, in_compound, needflag);
+            if (rv) {
+                pfx = (AffEntry *)pptr;
+                return rv;
+            }
+            pptr = pptr->getNextEQ();
+        } else {
+             pptr = pptr->getNextNE();
+        }
+    }
+    
+    return NULL;
+}
+
+#ifdef HUNSPELL_EXPERIMENTAL
+// check word for prefixes
+char * AffixMgr::prefix_check_morph(const char * word, int len, char in_compound,
+    const FLAG needflag)
+{
+    char * st;
+
+    char result[MAXLNLEN];
+    result[0] = '\0';
+
+    pfx = NULL;
+    sfxappnd = NULL;
+    
+    // first handle the special case of 0 length prefixes
+    PfxEntry * pe = (PfxEntry *) pStart[0];
+    while (pe) {
+       st = pe->check_morph(word,len,in_compound, needflag);
+       if (st) {
+            strcat(result, st);
+            free(st);
+       }
+       // if (rv) return rv;
+       pe = pe->getNext();
+    }
+  
+    // now handle the general case
+    unsigned char sp = *((const unsigned char *)word);
+    PfxEntry * pptr = (PfxEntry *)pStart[sp];
+
+    while (pptr) {
+        if (isSubset(pptr->getKey(),word)) {
+            st = pptr->check_morph(word,len,in_compound, needflag);
+            if (st) {
+              // fogemorpheme
+              if ((in_compound != IN_CPD_NOT) || !((pptr->getCont() && 
+                        (TESTAFF(pptr->getCont(), onlyincompound, pptr->getContLen()))))) {
+                    strcat(result, st);
+                    pfx = (AffEntry *)pptr;
+                }
+                free(st);
+            }
+            pptr = pptr->getNextEQ();
+        } else {
+            pptr = pptr->getNextNE();
+        }
+    }
+    
+    if (*result) return mystrdup(result);
+    return NULL;
+}
+
+
+// check word for prefixes
+char * AffixMgr::prefix_check_twosfx_morph(const char * word, int len,
+    char in_compound, const FLAG needflag)
+{
+    char * st;
+
+    char result[MAXLNLEN];
+    result[0] = '\0';
+
+    pfx = NULL;
+    sfxappnd = NULL;
+    
+    // first handle the special case of 0 length prefixes
+    PfxEntry * pe = (PfxEntry *) pStart[0];
+    while (pe) {
+        st = pe->check_twosfx_morph(word,len,in_compound, needflag);
+        if (st) {
+            strcat(result, st);
+            free(st);
+        }
+        pe = pe->getNext();
+    }
+  
+    // now handle the general case
+    unsigned char sp = *((const unsigned char *)word);
+    PfxEntry * pptr = (PfxEntry *)pStart[sp];
+
+    while (pptr) {
+        if (isSubset(pptr->getKey(),word)) {
+            st = pptr->check_twosfx_morph(word, len, in_compound, needflag);
+            if (st) {
+                strcat(result, st);
+                free(st);
+                pfx = (AffEntry *)pptr;
+            }
+            pptr = pptr->getNextEQ();
+        } else {
+            pptr = pptr->getNextNE();
+        }
+    }
+    
+    if (*result) return mystrdup(result);
+    return NULL;
+}
+#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+
+
+// Is word a non compound with a REP substitution (see checkcompoundrep)?
+int AffixMgr::cpdrep_check(const char * word, int wl)
+{
+  char candidate[MAXLNLEN];
+  const char * r;
+  int lenr, lenp;
+
+  if ((wl < 2) || !numrep) return 0;
+
+  for (int i=0; i < numrep; i++ ) {
+      r = word;
+      lenr = strlen(reptable[i].pattern2);
+      lenp = strlen(reptable[i].pattern);
+      // search every occurence of the pattern in the word
+      while ((r=strstr(r, reptable[i].pattern)) != NULL) {
+          strcpy(candidate, word);
+          if (r-word + lenr + strlen(r+lenp) >= MAXLNLEN) break;
+          strcpy(candidate+(r-word),reptable[i].pattern2);
+          strcpy(candidate+(r-word)+lenr, r+lenp);
+          if (candidate_check(candidate,strlen(candidate))) return 1;
+          r++; // search for the next letter
+      }
+   }
+   return 0;
+}
+
+// forbid compoundings when there are special patterns at word bound
+int AffixMgr::cpdpat_check(const char * word, int pos)
+{
+  int len;
+  for (int i = 0; i < numcheckcpd; i++) {
+      if (isSubset(checkcpdtable[i].pattern2, word + pos) &&
+        (len = strlen(checkcpdtable[i].pattern)) && (pos > len) &&
+        (strncmp(word + pos - len, checkcpdtable[i].pattern, len) == 0)) return 1;
+  }
+  return 0;
+}
+
+// forbid compounding with neighbouring upper and lower case characters at word bounds
+int AffixMgr::cpdcase_check(const char * word, int pos)
+{
+  if (utf8) {
+      w_char u, w;
+      const char * p;
+      u8_u16(&u, 1, word + pos);
+      for (p = word + pos - 1; (*p & 0xc0) == 0x80; p--);
+      u8_u16(&w, 1, p);
+      unsigned short a = (u.h << 8) + u.l;
+      unsigned short b = (w.h << 8) + w.l;
+      if (((unicodetoupper(a, langnum) == a) || (unicodetoupper(b, langnum) == b))) return 1;
+  } else {
+      unsigned char a = *(word + pos - 1);
+      unsigned char b = *(word + pos);
+      if ((csconv[a].ccase || csconv[b].ccase) && (a != '-') && (b != '-')) return 1;
+  }
+  return 0;
+}
+
+// check compound patterns
+int AffixMgr::defcpd_check(hentry *** words, short wnum, hentry * rv, hentry ** def, char all)
+{
+  signed short btpp[MAXWORDLEN]; // metacharacter (*, ?) positions for backtracking
+  signed short btwp[MAXWORDLEN]; // word positions for metacharacters
+  int btnum[MAXWORDLEN]; // number of matched characters in metacharacter positions
+  short bt = 0;  
+  int i;
+  int ok;
+  int w = 0;
+  if (!*words) {
+    w = 1;
+    *words = def;
+  }
+  (*words)[wnum] = rv;
+
+  for (i = 0; i < numdefcpd; i++) {
+    signed short pp = 0; // pattern position
+    signed short wp = 0; // "words" position
+    int ok2;
+    ok = 1;
+    ok2 = 1;
+    do {
+      while ((pp < defcpdtable[i].len) && (wp <= wnum)) {
+        if (((pp+1) < defcpdtable[i].len) &&
+          ((defcpdtable[i].def[pp+1] == '*') || (defcpdtable[i].def[pp+1] == '?'))) {
+            int wend = (defcpdtable[i].def[pp+1] == '?') ? wp : wnum;
+            ok2 = 1;
+            pp+=2;
+            btpp[bt] = pp;
+            btwp[bt] = wp;
+            while (wp <= wend) {
+                if (!(*words)[wp]->alen || 
+                  !TESTAFF((*words)[wp]->astr, defcpdtable[i].def[pp-2], (*words)[wp]->alen)) {
+                    ok2 = 0;
+                    break;
+                }
+                wp++;
+            }
+            if (wp <= wnum) ok2 = 0;
+            btnum[bt] = wp - btwp[bt];
+            if (btnum[bt] > 0) bt++;
+            if (ok2) break;
+        } else {
+            ok2 = 1;
+            if (!(*words)[wp] || !(*words)[wp]->alen || 
+              !TESTAFF((*words)[wp]->astr, defcpdtable[i].def[pp], (*words)[wp]->alen)) {
+                ok = 0;
+                break;
+            }
+            pp++;
+            wp++;
+            if ((defcpdtable[i].len == pp) && !(wp > wnum)) ok = 0;
+        }
+      }
+    if (ok && ok2) { 
+        int r = pp;
+        while ((defcpdtable[i].len > r) && ((r+1) < defcpdtable[i].len) &&
+            ((defcpdtable[i].def[r+1] == '*') || (defcpdtable[i].def[r+1] == '?'))) r+=2;
+        if (defcpdtable[i].len <= r) return 1;
+    }    
+    // backtrack
+    if (bt) do {
+        ok = 1;
+        btnum[bt - 1]--;
+        pp = btpp[bt - 1];
+        wp = btwp[bt - 1] + btnum[bt - 1];
+    } while ((btnum[bt - 1] < 0) && --bt);
+  } while (bt);
+
+  if (ok && ok2 && (!all || (defcpdtable[i].len <= pp))) return 1; 
+  // check zero ending
+  while (ok && ok2 && (defcpdtable[i].len > pp) && ((pp+1) < defcpdtable[i].len) &&
+    ((defcpdtable[i].def[pp+1] == '*') || (defcpdtable[i].def[pp+1] == '?'))) pp+=2;
+  if (ok && ok2 && (defcpdtable[i].len <= pp)) return 1;
+  }
+  (*words)[wnum] = NULL;
+  if (w) *words = NULL;
+  return 0;
+}
+
+inline int AffixMgr::candidate_check(const char * word, int len)
+{
+  struct hentry * rv=NULL;
+  
+  rv = lookup(word);
+  if (rv) return 1;
+
+//  rv = prefix_check(word,len,1);
+//  if (rv) return 1;
+  
+  rv = affix_check(word,len);
+  if (rv) return 1;
+  return 0;
+}
+
+// calculate number of syllable for compound-checking
+short AffixMgr::get_syllable(const char * word, int wlen)
+{
+    if (cpdmaxsyllable==0) return 0;
+    
+    short num=0;
+
+    if (!utf8) {
+        for (int i=0; i<wlen; i++) {
+            if (strchr(cpdvowels, word[i])) num++;
+        }
+    } else if (cpdvowels_utf16) {
+        w_char w[MAXWORDUTF8LEN];
+        int i = u8_u16(w, MAXWORDUTF8LEN, word);
+        for (; i > 0; i--) {
+            if (flag_bsearch((unsigned short *) cpdvowels_utf16,
+                ((unsigned short *) w)[i - 1], cpdvowels_utf16_len)) num++;
+        }
+    }
+    return num;
+}
+
+// check if compound word is correctly spelled
+// hu_mov_rule = spec. Hungarian rule (XXX)
+struct hentry * AffixMgr::compound_check(const char * word, int len, 
+    short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words = NULL,
+    char hu_mov_rule = 0, int * cmpdstemnum = NULL, int * cmpdstem = NULL, char is_sug = 0)
+{
+    int i; 
+    short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
+    int oldcmpdstemnum = 0;
+    struct hentry * rv = NULL;
+    struct hentry * rv_first;
+    struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking
+    char st [MAXWORDUTF8LEN + 4];
+    char ch;
+    int cmin;
+    int cmax;
+    
+    int checked_prefix;
+
+#ifdef HUNSTEM
+    if (cmpdstemnum) {
+        if (wordnum == 0) {
+            *cmpdstemnum = 1;
+        } else {
+            (*cmpdstemnum)++;
+        }
+    }
+#endif
+    if (utf8) {
+        for (cmin = 0, i = 0; (i < cpdmin) && word[cmin]; i++) {
+          cmin++;
+          for (; (word[cmin] & 0xc0) == 0x80; cmin++);
+        }
+        for (cmax = len, i = 0; (i < (cpdmin - 1)) && cmax; i++) {
+          cmax--;
+          for (; (word[cmax] & 0xc0) == 0x80; cmax--);
+        }
+    } else {
+        cmin = cpdmin;
+        cmax = len - cpdmin + 1;
+    }
+
+    strcpy(st, word);
+
+    for (i = cmin; i < cmax; i++) {
+
+        oldnumsyllable = numsyllable;
+        oldwordnum = wordnum;
+        checked_prefix = 0;
+
+        // go to end of the UTF-8 character
+        if (utf8) {
+            for (; (st[i] & 0xc0) == 0x80; i++);
+            if (i >= cmax) return NULL;
+        }
+
+        
+        ch = st[i];
+        st[i] = '\0';
+
+        sfx = NULL;
+        pfx = NULL;
+        
+        // FIRST WORD
+        
+        rv = lookup(st); // perhaps without prefix
+
+        // search homonym with compound flag
+        while ((rv) && !hu_mov_rule &&
+            ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
+                !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
+                  (compoundbegin && !wordnum &&
+                        TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
+                  (compoundmiddle && wordnum && !words &&
+                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
+                  (numdefcpd &&
+                    ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) ||
+                    (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))))
+                  ))) {
+            rv = rv->next_homonym;
+        }
+
+        if (!rv) {
+            if (compoundflag && 
+             !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) {
+                if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL,
+                        FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule &&
+                    ((SfxEntry*)sfx)->getCont() &&
+                        ((compoundforbidflag && TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
+                            ((SfxEntry*)sfx)->getContLen())) || (compoundend &&
+                        TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, 
+                            ((SfxEntry*)sfx)->getContLen())))) {
+                        rv = NULL;
+                }
+            }
+            if (rv ||
+              (((wordnum == 0) && compoundbegin &&
+                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
+                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundbegin)))) ||
+              ((wordnum > 0) && compoundmiddle &&
+                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
+                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle)))))
+              ) checked_prefix = 1;
+        // else check forbiddenwords and pseudoroot
+        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
+            TESTAFF(rv->astr, pseudoroot, rv->alen) || 
+            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen))
+             )) {
+                st[i] = ch;
+                continue;
+        }
+
+            // check non_compound flag in suffix and prefix
+            if ((rv) && !hu_mov_rule &&
+                ((pfx && ((PfxEntry*)pfx)->getCont() &&
+                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, 
+                        ((PfxEntry*)pfx)->getContLen())) ||
+                (sfx && ((SfxEntry*)sfx)->getCont() &&
+                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
+                        ((SfxEntry*)sfx)->getContLen())))) {
+                    rv = NULL;
+            }
+
+            // check compoundend flag in suffix and prefix
+            if ((rv) && !checked_prefix && compoundend && !hu_mov_rule &&
+                ((pfx && ((PfxEntry*)pfx)->getCont() &&
+                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundend, 
+                        ((PfxEntry*)pfx)->getContLen())) ||
+                (sfx && ((SfxEntry*)sfx)->getCont() &&
+                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, 
+                        ((SfxEntry*)sfx)->getContLen())))) {
+                    rv = NULL;
+            }
+            
+            // check compoundmiddle flag in suffix and prefix
+            if ((rv) && !checked_prefix && (wordnum==0) && compoundmiddle && !hu_mov_rule &&
+                ((pfx && ((PfxEntry*)pfx)->getCont() &&
+                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundmiddle, 
+                        ((PfxEntry*)pfx)->getContLen())) ||
+                (sfx && ((SfxEntry*)sfx)->getCont() &&
+                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundmiddle, 
+                        ((SfxEntry*)sfx)->getContLen())))) {
+                    rv = NULL;
+            }       
+
+        // check forbiddenwords
+        if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
+            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) {
+                return NULL;
+            }
+
+        // increment word number, if the second root has a compoundroot flag
+        if ((rv) && compoundroot && 
+            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
+                wordnum++;
+        }
+
+        // first word is acceptable in compound words?
+        if (((rv) && 
+          ( checked_prefix || (words && words[wnum]) ||
+            (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
+            ((oldwordnum == 0) && compoundbegin && TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
+            ((oldwordnum > 0) && compoundmiddle && TESTAFF(rv->astr, compoundmiddle, rv->alen))// ||
+//            (numdefcpd && )
+
+// LANG_hu section: spec. Hungarian rule
+            || ((langnum == LANG_hu) && hu_mov_rule && (
+                    TESTAFF(rv->astr, 'F', rv->alen) || // XXX hardwired Hungarian dictionary codes
+                    TESTAFF(rv->astr, 'G', rv->alen) ||
+                    TESTAFF(rv->astr, 'H', rv->alen)
+                )
+              )
+// END of LANG_hu section
+          )
+          && ! (( checkcompoundtriple && // test triple letters
+                   (word[i-1]==word[i]) && (
+                      ((i>1) && (word[i-1]==word[i-2])) || 
+                      ((word[i-1]==word[i+1])) // may be word[i+1] == '\0'
+                   )
+               ) ||
+               ( 
+                 // test CHECKCOMPOUNDPATTERN
+                 numcheckcpd && cpdpat_check(word, i)
+               ) ||
+               ( 
+                 checkcompoundcase && cpdcase_check(word, i)
+               ))
+         )
+// LANG_hu section: spec. Hungarian rule
+         || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) &&
+              (sfx && ((SfxEntry*)sfx)->getCont() && ( // XXX hardwired Hungarian dic. codes
+                        TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) 'x', ((SfxEntry*)sfx)->getContLen()) ||
+                        TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) '%', ((SfxEntry*)sfx)->getContLen())
+                    )                
+               )
+             )
+// END of LANG_hu section
+         ) {
+
+// LANG_hu section: spec. Hungarian rule
+            if (langnum == LANG_hu) {
+                // calculate syllable number of the word            
+                numsyllable += get_syllable(st, i);
+
+                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
+                if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++;
+            }
+// END of LANG_hu section
+
+#ifdef HUNSTEM
+            if (cmpdstem) cmpdstem[*cmpdstemnum - 1] = i;
+#endif
+
+            // NEXT WORD(S)
+            rv_first = rv;
+            rv = lookup((word+i)); // perhaps without prefix
+
+        // search homonym with compound flag
+        while ((rv) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
+                        !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
+                          (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) ||
+                           (numdefcpd && words && defcpd_check(&words, wnum + 1, rv, NULL,1))))) {
+            rv = rv->next_homonym;
+        }
+
+            if (rv && words && words[wnum + 1]) return rv;
+
+            oldnumsyllable2 = numsyllable;
+            oldwordnum2 = wordnum;
+
+// LANG_hu section: spec. Hungarian rule, XXX hardwired dictionary code
+            if ((rv) && (langnum == LANG_hu) && (TESTAFF(rv->astr, 'I', rv->alen)) && !(TESTAFF(rv->astr, 'J', rv->alen))) {
+                numsyllable--;
+            }
+// END of LANG_hu section
+
+            // increment word number, if the second root has a compoundroot flag
+            if ((rv) && (compoundroot) && 
+                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
+                    wordnum++;
+            }
+
+            // check forbiddenwords
+            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
+               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
+
+            // second word is acceptable, as a root?
+            // hungarian conventions: compounding is acceptable,
+            // when compound forms consist of 2 words, or if more,
+            // then the syllable number of root words must be 6, or lesser.
+
+            if ((rv) && (
+                      (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
+                      (compoundend && TESTAFF(rv->astr, compoundend, rv->alen))
+                    )
+                && (
+                      ((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || 
+                      ((cpdmaxsyllable==0) || 
+                          (numsyllable + get_syllable(&(rv->word), rv->clen)<=cpdmaxsyllable))
+                    )
+                && (
+                     (!checkcompounddup || (rv != rv_first))
+                   )
+                )
+                 {
+                      // forbid compound word, if it is a non compound word with typical fault
+                      if (checkcompoundrep && cpdrep_check(word,len)) return NULL;
+                      return rv;
+            }
+
+            numsyllable = oldnumsyllable2 ;
+            wordnum = oldwordnum2;
+
+            // perhaps second word has prefix or/and suffix
+            sfx = NULL;
+            sfxflag = FLAG_NULL;
+            rv = (compoundflag) ? affix_check((word+i),strlen(word+i), compoundflag, IN_CPD_END) : NULL;
+            if (!rv && compoundend) {
+                sfx = NULL;
+                pfx = NULL;
+                rv = affix_check((word+i),strlen(word+i), compoundend, IN_CPD_END);
+            }
+            
+            if (!rv && numdefcpd && words) {
+                rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END);
+                if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1)) return rv;
+                rv = NULL;
+            }
+
+            // check non_compound flag in suffix and prefix
+            if ((rv) && 
+                ((pfx && ((PfxEntry*)pfx)->getCont() &&
+                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, 
+                        ((PfxEntry*)pfx)->getContLen())) ||
+                (sfx && ((SfxEntry*)sfx)->getCont() &&
+                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
+                        ((SfxEntry*)sfx)->getContLen())))) {
+                    rv = NULL;
+            }
+
+            // check forbiddenwords
+            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
+               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
+
+            // pfxappnd = prefix of word+i, or NULL
+            // calculate syllable number of prefix.
+            // hungarian convention: when syllable number of prefix is more,
+            // than 1, the prefix+word counts as two words.
+
+            if (langnum == LANG_hu) {
+                // calculate syllable number of the word
+                numsyllable += get_syllable(word + i, strlen(word + i));
+                
+                // - affix syllable num.
+                // XXX only second suffix (inflections, not derivations)
+                if (sfxappnd) {
+                    char * tmp = myrevstrdup(sfxappnd);
+                    numsyllable -= get_syllable(tmp, strlen(tmp));
+                    free(tmp);
+                }
+                
+                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
+                if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++;
+
+                // increment syllable num, if last word has a SYLLABLENUM flag
+                // and the suffix is beginning `s'
+            
+                if (cpdsyllablenum) {
+                    switch (sfxflag) {
+                        case 'c': { numsyllable+=2; break; }
+                        case 'J': { numsyllable += 1; break; }
+                        case 'I': { if (TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; }
+                    }
+                }
+            }
+            
+            // increment word number, if the second word has a compoundroot flag
+            if ((rv) && (compoundroot) && 
+                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
+                    wordnum++;
+            }
+
+            // second word is acceptable, as a word with prefix or/and suffix?
+            // hungarian conventions: compounding is acceptable,
+            // when compound forms consist 2 word, otherwise
+            // the syllable number of root words is 6, or lesser.
+            if ((rv) && 
+                    (
+                      ((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) || 
+                      ((cpdmaxsyllable == 0) || 
+                          (numsyllable <= cpdmaxsyllable))
+                    )
+                && (
+                   (!checkcompounddup || (rv != rv_first))
+                   )) {
+                    // forbid compound word, if it is a non compound word with typical fault
+                    if (checkcompoundrep && cpdrep_check(word, len)) return NULL;
+                    return rv;
+            }
+
+            numsyllable = oldnumsyllable2;
+            wordnum = oldwordnum2;
+#ifdef HUNSTEM
+            if (cmpdstemnum) oldcmpdstemnum = *cmpdstemnum;
+#endif
+            // perhaps second word is a compound word (recursive call)
+            if (wordnum < maxwordnum) {
+                rv = compound_check((word+i),strlen(word+i), wordnum+1,
+                     numsyllable, maxwordnum, wnum + 1, words,
+                     0, cmpdstemnum, cmpdstem, is_sug);
+            } else {
+                rv=NULL;
+            }
+            if (rv) {
+                // forbid compound word, if it is a non compound word with typical fault
+                if (checkcompoundrep && cpdrep_check(word, len)) return NULL;
+                return rv;
+            } else {
+#ifdef HUNSTEM
+            if (cmpdstemnum) *cmpdstemnum = oldcmpdstemnum;
+#endif
+            }
+        }
+        st[i] = ch;
+        wordnum = oldwordnum;
+        numsyllable = oldnumsyllable;
+    }
+    
+    return NULL;
+}    
+
+#ifdef HUNSPELL_EXPERIMENTAL
+// check if compound word is correctly spelled
+// hu_mov_rule = spec. Hungarian rule (XXX)
+int AffixMgr::compound_check_morph(const char * word, int len, 
+    short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words,
+    char hu_mov_rule = 0, char ** result = NULL, char * partresult = NULL)
+{
+    int i;
+    short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
+    int ok = 0;
+
+    struct hentry * rv = NULL;
+    struct hentry * rv_first;
+    struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking
+    char st [MAXWORDUTF8LEN + 4];
+    char ch;
+    
+    int checked_prefix;
+    char presult[MAXLNLEN];
+
+    int cmin;
+    int cmax;
+    
+    if (utf8) {
+        for (cmin = 0, i = 0; (i < cpdmin) && word[cmin]; i++) {
+          cmin++;
+          for (; (word[cmin] & 0xc0) == 0x80; cmin++);
+        }
+        for (cmax = len, i = 0; (i < (cpdmin - 1)) && cmax; i++) {
+          cmax--;
+          for (; (word[cmax] & 0xc0) == 0x80; cmax--);
+        }
+    } else {
+        cmin = cpdmin;
+        cmax = len - cpdmin + 1;
+    }
+
+    strcpy(st, word);
+
+    for (i = cmin; i < cmax; i++) {
+        oldnumsyllable = numsyllable;
+        oldwordnum = wordnum;
+        checked_prefix = 0;
+
+        // go to end of the UTF-8 character
+        if (utf8) {
+            for (; (st[i] & 0xc0) == 0x80; i++);
+            if (i >= cmax) return 0;
+        }
+        
+        ch = st[i];
+        st[i] = '\0';
+        sfx = NULL;
+
+        // FIRST WORD
+        *presult = '\0';
+        if (partresult) strcat(presult, partresult);
+        
+        rv = lookup(st); // perhaps without prefix
+
+        // search homonym with compound flag
+        while ((rv) && !hu_mov_rule && 
+            ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
+                !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
+                (compoundbegin && !wordnum &&
+                        TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
+                (compoundmiddle && wordnum && !words &&
+                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
+                  (numdefcpd &&
+                    ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) ||
+                    (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))))
+                  ))) {
+            rv = rv->next_homonym;
+        }
+
+        if (rv)  {
+            if (rv->description) {
+                if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen))
+                                        strcat(presult, st);
+                strcat(presult, rv->description);
+            }
+        }
+        
+        if (!rv) {
+            if (compoundflag && 
+             !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) {
+                if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL,
+                        FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule &&
+                    ((SfxEntry*)sfx)->getCont() &&
+                        ((compoundforbidflag && TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
+                            ((SfxEntry*)sfx)->getContLen())) || (compoundend &&
+                        TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, 
+                            ((SfxEntry*)sfx)->getContLen())))) {
+                        rv = NULL;
+                }
+            }
+            
+            if (rv ||
+              (((wordnum == 0) && compoundbegin &&
+                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
+                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundbegin)))) ||
+              ((wordnum > 0) && compoundmiddle &&
+                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
+                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle)))))
+              ) {
+                //char * p = prefix_check_morph(st, i, 0, compound);
+                char * p = NULL;
+                if (compoundflag) p = affix_check_morph(st, i, compoundflag);
+                if (!p || (*p == '\0')) {
+                   if ((wordnum == 0) && compoundbegin) {
+                     p = affix_check_morph(st, i, compoundbegin);
+                   } else if ((wordnum > 0) && compoundmiddle) {
+                     p = affix_check_morph(st, i, compoundmiddle);                   
+                   }
+                }
+                if (*p != '\0') {
+                    line_uniq(p);
+                    if (strchr(p, '\n')) {
+                        strcat(presult, "(");
+                        strcat(presult, line_join(p, '|'));
+                        strcat(presult, ")");
+                      } else {
+                        strcat(presult, p);
+                      }
+                }
+                if (presult[strlen(presult) - 1] == '\n') {
+                    presult[strlen(presult) - 1] = '\0';
+                }
+                checked_prefix = 1;
+                //strcat(presult, "+");
+            }
+        // else check forbiddenwords
+        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
+            TESTAFF(rv->astr, pseudoroot, rv->alen))) {
+                st[i] = ch;
+                continue;
+        }
+
+            // check non_compound flag in suffix and prefix
+            if ((rv) && !hu_mov_rule &&
+                ((pfx && ((PfxEntry*)pfx)->getCont() &&
+                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, 
+                        ((PfxEntry*)pfx)->getContLen())) ||
+                (sfx && ((SfxEntry*)sfx)->getCont() &&
+                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
+                        ((SfxEntry*)sfx)->getContLen())))) {
+                    continue;
+            }
+
+            // check compoundend flag in suffix and prefix
+            if ((rv) && !checked_prefix && compoundend && !hu_mov_rule &&
+                ((pfx && ((PfxEntry*)pfx)->getCont() &&
+                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundend, 
+                        ((PfxEntry*)pfx)->getContLen())) ||
+                (sfx && ((SfxEntry*)sfx)->getCont() &&
+                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, 
+                        ((SfxEntry*)sfx)->getContLen())))) {
+                    continue;
+            }
+
+            // check compoundmiddle flag in suffix and prefix
+            if ((rv) && !checked_prefix && (wordnum==0) && compoundmiddle && !hu_mov_rule &&
+                ((pfx && ((PfxEntry*)pfx)->getCont() &&
+                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundmiddle, 
+                        ((PfxEntry*)pfx)->getContLen())) ||
+                (sfx && ((SfxEntry*)sfx)->getCont() &&
+                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundmiddle, 
+                        ((SfxEntry*)sfx)->getContLen())))) {
+                    rv = NULL;
+            }       
+
+        // check forbiddenwords
+        if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) continue;
+
+        // increment word number, if the second root has a compoundroot flag
+        if ((rv) && (compoundroot) && 
+            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
+                wordnum++;
+        }
+
+        // first word is acceptable in compound words?
+        if (((rv) && 
+          ( checked_prefix || (words && words[wnum]) ||
+            (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
+            ((oldwordnum == 0) && compoundbegin && TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
+            ((oldwordnum > 0) && compoundmiddle && TESTAFF(rv->astr, compoundmiddle, rv->alen)) 
+// LANG_hu section: spec. Hungarian rule
+            || ((langnum == LANG_hu) && // hu_mov_rule
+                hu_mov_rule && (
+                    TESTAFF(rv->astr, 'F', rv->alen) ||
+                    TESTAFF(rv->astr, 'G', rv->alen) ||
+                    TESTAFF(rv->astr, 'H', rv->alen)
+                )
+              )
+// END of LANG_hu section
+          )
+          && ! (( checkcompoundtriple && // test triple letters
+                   (word[i-1]==word[i]) && (
+                      ((i>1) && (word[i-1]==word[i-2])) || 
+                      ((word[i-1]==word[i+1])) // may be word[i+1] == '\0'
+                   )
+               ) ||
+               (
+                   // test CHECKCOMPOUNDPATTERN
+                   numcheckcpd && cpdpat_check(word, i)
+               ) ||
+               ( 
+                 checkcompoundcase && cpdcase_check(word, i)
+               ))
+         )
+// LANG_hu section: spec. Hungarian rule
+         || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) &&
+              (sfx && ((SfxEntry*)sfx)->getCont() && (
+                        TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) 'x', ((SfxEntry*)sfx)->getContLen()) ||
+                        TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) '%', ((SfxEntry*)sfx)->getContLen())
+                    )                
+               )
+             )
+// END of LANG_hu section
+         ) {
+
+// LANG_hu section: spec. Hungarian rule
+            if (langnum == LANG_hu) {
+                // calculate syllable number of the word
+                numsyllable += get_syllable(st, i);
+
+                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
+                if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++;
+            }
+// END of LANG_hu section
+
+            // NEXT WORD(S)
+            rv_first = rv;
+            rv = lookup((word+i)); // perhaps without prefix
+
+        // search homonym with compound flag
+        while ((rv) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
+                        !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
+                          (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) ||
+                           (numdefcpd && defcpd_check(&words, wnum + 1, rv, NULL,1))))) {
+            rv = rv->next_homonym;
+        }
+
+            if (rv && words && words[wnum + 1]) {
+                  strcat(*result, presult);
+                  if (complexprefixes && rv->description) strcat(*result, rv->description);
+                  if (rv->description && ((!rv->astr) || 
+                     !TESTAFF(rv->astr, lemma_present, rv->alen)))
+                        strcat(*result, &(rv->word));
+                  if (!complexprefixes && rv->description) strcat(*result, rv->description);
+                  strcat(*result, "\n");
+                  ok = 1;
+                  return 0;
+            }
+
+            oldnumsyllable2 = numsyllable;
+            oldwordnum2 = wordnum;
+
+// LANG_hu section: spec. Hungarian rule
+            if ((rv) && (langnum == LANG_hu) && (TESTAFF(rv->astr, 'I', rv->alen)) && !(TESTAFF(rv->astr, 'J', rv->alen))) {
+                numsyllable--;
+            }
+// END of LANG_hu section
+            // increment word number, if the second root has a compoundroot flag
+            if ((rv) && (compoundroot) && 
+                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
+                    wordnum++;
+            }
+
+            // check forbiddenwords
+            if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) {
+                st[i] = ch;
+                continue;
+            }
+                    
+            // second word is acceptable, as a root?
+            // hungarian conventions: compounding is acceptable,
+            // when compound forms consist of 2 words, or if more,
+            // then the syllable number of root words must be 6, or lesser.
+            if ((rv) && (
+                      (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
+                      (compoundend && TESTAFF(rv->astr, compoundend, rv->alen))
+                    )
+                && (
+                      ((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || 
+                      ((cpdmaxsyllable==0) || 
+                          (numsyllable+get_syllable(&(rv->word),rv->wlen)<=cpdmaxsyllable))
+                    )
+                && (
+                     (!checkcompounddup || (rv != rv_first))
+                   )
+                )
+                 {
+                      // bad compound word
+                      strcat(*result, presult);
+                                          
+                      if (rv->description) {
+                        if (complexprefixes) strcat(*result, rv->description);
+                        if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen))
+                                               strcat(*result, &(rv->word));
+                        if (!complexprefixes) strcat(*result, rv->description);
+                      }
+                      strcat(*result, "\n");
+                              ok = 1;
+            }
+
+            numsyllable = oldnumsyllable2 ;
+            wordnum = oldwordnum2;
+
+            // perhaps second word has prefix or/and suffix
+            sfx = NULL;
+            sfxflag = FLAG_NULL;
+
+            if (compoundflag) rv = affix_check((word+i),strlen(word+i), compoundflag); else rv = NULL;
+
+            if (!rv && compoundend) {
+                sfx = NULL;
+                pfx = NULL;
+                rv = affix_check((word+i),strlen(word+i), compoundend);
+            }
+
+            if (!rv && numdefcpd && words) {
+                rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END);
+                if (rv && words && defcpd_check(&words, wnum + 1, rv, NULL, 1)) {
+                      char * m = NULL;
+                      if (compoundflag) m = affix_check_morph((word+i),strlen(word+i), compoundflag);
+                      if ((!m || *m == '\0') && compoundend)
+                            m = affix_check_morph((word+i),strlen(word+i), compoundend);
+                      strcat(*result, presult);
+                      if (m) {
+                        line_uniq(m);
+                        if (strchr(m, '\n')) {
+                            strcat(*result, "(");
+                            strcat(*result, line_join(m, '|'));
+                            strcat(*result, ")");
+                        } else {
+                            strcat(*result, m);
+                        }
+                        free(m);
+                      }
+                      strcat(*result, "\n");
+                      ok = 1;
+                }
+            }
+
+            // check non_compound flag in suffix and prefix
+            if ((rv) && 
+                ((pfx && ((PfxEntry*)pfx)->getCont() &&
+                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, 
+                        ((PfxEntry*)pfx)->getContLen())) ||
+                (sfx && ((SfxEntry*)sfx)->getCont() &&
+                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
+                        ((SfxEntry*)sfx)->getContLen())))) {
+                    rv = NULL;
+            }
+
+            // check forbiddenwords
+            if ((rv) && (rv->astr) && (TESTAFF(rv->astr,forbiddenword,rv->alen))
+                    && (! TESTAFF(rv->astr, pseudoroot, rv->alen))) {
+                        st[i] = ch;
+                        continue;
+                    }
+
+            if (langnum == LANG_hu) {
+                // calculate syllable number of the word
+                numsyllable += get_syllable(word + i, strlen(word + i));
+
+                // - affix syllable num.
+                // XXX only second suffix (inflections, not derivations)
+                if (sfxappnd) {
+                    char * tmp = myrevstrdup(sfxappnd);
+                    numsyllable -= get_syllable(tmp, strlen(tmp));
+                    free(tmp);
+                }
+
+                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
+                if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++;
+
+                // increment syllable num, if last word has a SYLLABLENUM flag
+                // and the suffix is beginning `s'
+
+                if (cpdsyllablenum) {
+                    switch (sfxflag) {
+                        case 'c': { numsyllable+=2; break; }
+                        case 'J': { numsyllable += 1; break; }
+                        case 'I': { if (rv && TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; }
+                    }
+                }
+            }
+
+            // increment word number, if the second word has a compoundroot flag
+            if ((rv) && (compoundroot) && 
+                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
+                    wordnum++;
+            }
+            // second word is acceptable, as a word with prefix or/and suffix?
+            // hungarian conventions: compounding is acceptable,
+            // when compound forms consist 2 word, otherwise
+            // the syllable number of root words is 6, or lesser.
+            if ((rv) && 
+                    (
+                      ((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || 
+                      ((cpdmaxsyllable==0) || 
+                          (numsyllable <= cpdmaxsyllable))
+                    )
+                && (
+                   (!checkcompounddup || (rv != rv_first))
+                   )) {
+                      char * m = NULL;
+                      if (compoundflag) m = affix_check_morph((word+i),strlen(word+i), compoundflag);
+                      if ((!m || *m == '\0') && compoundend)
+                            m = affix_check_morph((word+i),strlen(word+i), compoundend);
+                      strcat(*result, presult);
+                      if (m) {
+                        line_uniq(m);
+                        if (strchr(m, '\n')) {
+                            strcat(*result, "(");
+                            strcat(*result, line_join(m, '|'));
+                            strcat(*result, ")");
+                        } else {
+                            strcat(*result, m);
+                        }
+                        free(m);
+                      }
+                      strcat(*result, "\n");
+                      ok = 1;
+            }
+
+            numsyllable = oldnumsyllable2;
+            wordnum = oldwordnum2;
+
+            // perhaps second word is a compound word (recursive call)
+            if ((wordnum < maxwordnum) && (ok == 0)) {
+                        compound_check_morph((word+i),strlen(word+i), wordnum+1, 
+                             numsyllable, maxwordnum, wnum + 1, words, 0, result, presult);
+            } else {
+                rv=NULL;
+            }
+        }
+        st[i] = ch;
+        wordnum = oldwordnum;
+        numsyllable = oldnumsyllable;
+    }
+    return 0;
+}    
+#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+
+ // return 1 if s1 (reversed) is a leading subset of end of s2
+/* inline int AffixMgr::isRevSubset(const char * s1, const char * end_of_s2, int len)
+ {
+    while ((len > 0) && *s1 && (*s1 == *end_of_s2)) {
+        s1++;
+        end_of_s2--;
+        len--;
+    }
+    return (*s1 == '\0');
+ }
+ */
+
+inline int AffixMgr::isRevSubset(const char * s1, const char * end_of_s2, int len)
+ {
+    while ((len > 0) && (*s1 != '\0') && ((*s1 == *end_of_s2) || (*s1 == '.'))) {
+        s1++;
+        end_of_s2--;
+        len--;
+    }
+    return (*s1 == '\0');
+ }
+
+// check word for suffixes
+
+struct hentry * AffixMgr::suffix_check (const char * word, int len, 
+       int sfxopts, AffEntry * ppfx, char ** wlst, int maxSug, int * ns, 
+       const FLAG cclass, const FLAG needflag, char in_compound)
+{
+    struct hentry * rv = NULL;
+    char result[MAXLNLEN];
+
+    PfxEntry* ep = (PfxEntry *) ppfx;
+
+    // first handle the special case of 0 length suffixes
+    SfxEntry * se = (SfxEntry *) sStart[0];
+
+    while (se) {
+        if (!cclass || se->getCont()) {
+            // suffixes are not allowed in beginning of compounds
+            if ((((in_compound != IN_CPD_BEGIN)) || // && !cclass
+             // except when signed with compoundpermitflag flag
+             (se->getCont() && compoundpermitflag &&
+                TESTAFF(se->getCont(),compoundpermitflag,se->getContLen()))) && (!circumfix ||
+              // no circumfix flag in prefix and suffix
+              ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(),
+                   circumfix, ep->getContLen())) &&
+               (!se->getCont() || !(TESTAFF(se->getCont(),circumfix,se->getContLen())))) ||
+              // circumfix flag in prefix AND suffix
+              ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(),
+                   circumfix, ep->getContLen())) &&
+               (se->getCont() && (TESTAFF(se->getCont(),circumfix,se->getContLen())))))  &&
+            // fogemorpheme
+              (in_compound || 
+                 !((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) &&
+            // pseudoroot on prefix or first suffix
+              (cclass || 
+                   !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) ||
+                   (ppfx && !((ep->getCont()) &&
+                     TESTAFF(ep->getCont(), pseudoroot,
+                       ep->getContLen())))
+              )
+            ) {
+                rv = se->checkword(word,len, sfxopts, ppfx, wlst, maxSug, ns, (FLAG) cclass, 
+                    needflag, (in_compound ? 0 : onlyincompound));
+                if (rv) {
+                    sfx=(AffEntry *)se; // BUG: sfx not stateless
+                    return rv;
+                }
+            }
+        }
+       se = se->getNext();
+    }
+  
+    // now handle the general case
+    unsigned char sp = *((const unsigned char *)(word + len - 1));
+    SfxEntry * sptr = (SfxEntry *) sStart[sp];
+
+    while (sptr) {
+        if (isRevSubset(sptr->getKey(), word + len - 1, len)
+        ) {
+            // suffixes are not allowed in beginning of compounds
+            if ((((in_compound != IN_CPD_BEGIN)) || // && !cclass
+             // except when signed with compoundpermitflag flag
+             (sptr->getCont() && compoundpermitflag &&
+                TESTAFF(sptr->getCont(),compoundpermitflag,sptr->getContLen()))) && (!circumfix ||
+              // no circumfix flag in prefix and suffix
+              ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(),
+                   circumfix, ep->getContLen())) &&
+               (!sptr->getCont() || !(TESTAFF(sptr->getCont(),circumfix,sptr->getContLen())))) ||
+              // circumfix flag in prefix AND suffix
+              ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(),
+                   circumfix, ep->getContLen())) &&
+               (sptr->getCont() && (TESTAFF(sptr->getCont(),circumfix,sptr->getContLen())))))  &&
+            // fogemorpheme
+              (in_compound || 
+                 !((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) &&
+            // pseudoroot on prefix or first suffix
+              (cclass || 
+                  !(sptr->getCont() && TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())) ||
+                  (ppfx && !((ep->getCont()) &&
+                     TESTAFF(ep->getCont(), pseudoroot,
+                       ep->getContLen())))
+              )
+            ) {
+                rv = sptr->checkword(word,len, sfxopts, ppfx, wlst,
+                    maxSug, ns, cclass, needflag, (in_compound ? 0 : onlyincompound));
+                if (rv) {
+                    sfx=(AffEntry *)sptr; // BUG: sfx not stateless
+                    sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless
+                    if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless
+                    if (cclass || sptr->getCont()) {
+                                if (!derived) {
+                                        derived = mystrdup(word);
+                                } else {
+                                        strcpy(result, derived); // XXX check size
+                                        strcat(result, "\n");
+                                        strcat(result, word);
+                                        free(derived);
+                                        derived = mystrdup(result);
+                                }
+                    }
+                    return rv;
+                }
+             }
+             sptr = sptr->getNextEQ();
+        } else {
+             sptr = sptr->getNextNE();
+        }
+    }
+
+    return NULL;
+}
+
+// check word for two-level suffixes
+
+struct hentry * AffixMgr::suffix_check_twosfx(const char * word, int len, 
+       int sfxopts, AffEntry * ppfx, const FLAG needflag)
+{
+    struct hentry * rv = NULL;
+
+    // first handle the special case of 0 length suffixes
+    SfxEntry * se = (SfxEntry *) sStart[0];
+    while (se) {
+        if (contclasses[se->getFlag()])
+        {
+            rv = se->check_twosfx(word,len, sfxopts, ppfx, needflag);
+            if (rv) return rv;
+        }
+        se = se->getNext();
+    }
+  
+    // now handle the general case
+    unsigned char sp = *((const unsigned char *)(word + len - 1));
+    SfxEntry * sptr = (SfxEntry *) sStart[sp];
+
+    while (sptr) {
+        if (isRevSubset(sptr->getKey(), word + len - 1, len)) {
+            if (contclasses[sptr->getFlag()])
+            {
+                rv = sptr->check_twosfx(word,len, sfxopts, ppfx, needflag);
+                if (rv) {
+                    sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless
+                    if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless
+                    return rv;
+                }
+            }
+            sptr = sptr->getNextEQ();
+        } else {
+             sptr = sptr->getNextNE();
+        }
+    }
+
+    return NULL;
+}
+
+#ifdef HUNSPELL_EXPERIMENTAL
+char * AffixMgr::suffix_check_twosfx_morph(const char * word, int len, 
+       int sfxopts, AffEntry * ppfx, const FLAG needflag)
+{
+    char result[MAXLNLEN];
+    char result2[MAXLNLEN];
+    char result3[MAXLNLEN];
+    
+    char * st;
+
+    result[0] = '\0';
+    result2[0] = '\0';
+    result3[0] = '\0';
+
+    // first handle the special case of 0 length suffixes
+    SfxEntry * se = (SfxEntry *) sStart[0];
+    while (se) {
+        if (contclasses[se->getFlag()])
+        {
+            st = se->check_twosfx_morph(word,len, sfxopts, ppfx, needflag);
+            if (st) {
+                if (ppfx) {
+                    if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph());
+                }
+                strcat(result, st);
+                free(st);
+                if (se->getMorph()) strcat(result, se->getMorph());
+                strcat(result, "\n");
+            }
+        }
+        se = se->getNext();
+    }
+  
+    // now handle the general case
+    unsigned char sp = *((const unsigned char *)(word + len - 1));
+    SfxEntry * sptr = (SfxEntry *) sStart[sp];
+
+    while (sptr) {
+        if (isRevSubset(sptr->getKey(), word + len - 1, len)) {
+            if (contclasses[sptr->getFlag()]) 
+            {
+                st = sptr->check_twosfx_morph(word,len, sfxopts, ppfx, needflag);
+                if (st) {
+                    sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless
+                    if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless
+                    strcpy(result2, st);
+                    free(st);
+
+                result3[0] = '\0';
+#ifdef DEBUG
+                unsigned short flag = sptr->getFlag();
+                if (flag_mode == FLAG_NUM) {
+                    sprintf(result3, "<%d>", sptr->getKey());
+                } else if (flag_mode == FLAG_LONG) {
+                    sprintf(result3, "<%c%c>", flag >> 8, (flag << 8) >>8);
+                } else sprintf(result3, "<%c>", flag);
+                strcat(result3, ":");
+#endif
+                if (sptr->getMorph()) strcat(result3, sptr->getMorph());
+                strlinecat(result2, result3);
+                strcat(result2, "\n");
+                strcat(result,  result2);
+                }
+            }
+            sptr = sptr->getNextEQ();
+        } else {
+             sptr = sptr->getNextNE();
+        }
+    }
+    if (result) return mystrdup(result);
+    return NULL;
+}
+
+char * AffixMgr::suffix_check_morph(const char * word, int len, 
+       int sfxopts, AffEntry * ppfx, const FLAG cclass, const FLAG needflag, char in_compound)
+{
+    char result[MAXLNLEN];
+    
+    struct hentry * rv = NULL;
+
+    result[0] = '\0';
+
+    PfxEntry* ep = (PfxEntry *) ppfx;
+
+    // first handle the special case of 0 length suffixes
+    SfxEntry * se = (SfxEntry *) sStart[0];
+    while (se) {
+        if (!cclass || se->getCont()) {
+            // suffixes are not allowed in beginning of compounds
+            if (((((in_compound != IN_CPD_BEGIN)) || // && !cclass
+             // except when signed with compoundpermitflag flag
+             (se->getCont() && compoundpermitflag &&
+                TESTAFF(se->getCont(),compoundpermitflag,se->getContLen()))) && (!circumfix ||
+              // no circumfix flag in prefix and suffix
+              ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(),
+                   circumfix, ep->getContLen())) &&
+               (!se->getCont() || !(TESTAFF(se->getCont(),circumfix,se->getContLen())))) ||
+              // circumfix flag in prefix AND suffix
+              ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(),
+                   circumfix, ep->getContLen())) &&
+               (se->getCont() && (TESTAFF(se->getCont(),circumfix,se->getContLen())))))  &&
+            // fogemorpheme
+              (in_compound || 
+                 !((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) &&
+            // pseudoroot on prefix or first suffix
+              (cclass || 
+                   !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) ||
+                   (ppfx && !((ep->getCont()) &&
+                     TESTAFF(ep->getCont(), pseudoroot,
+                       ep->getContLen())))
+              )
+            ))
+            rv = se->checkword(word,len, sfxopts, ppfx, NULL, 0, 0, cclass, needflag);
+         while (rv) {
+           if (ppfx) {
+                if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph());
+            }
+            if (complexprefixes && rv->description) strcat(result, rv->description);
+            if (rv->description && ((!rv->astr) || 
+                                        !TESTAFF(rv->astr, lemma_present, rv->alen)))
+                                               strcat(result, &(rv->word));
+            if (!complexprefixes && rv->description) strcat(result, rv->description);
+            if (se->getMorph()) strcat(result, se->getMorph());
+            strcat(result, "\n");
+            rv = se->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag);
+         }
+       }
+       se = se->getNext();
+    }
+  
+    // now handle the general case
+    unsigned char sp = *((const unsigned char *)(word + len - 1));
+    SfxEntry * sptr = (SfxEntry *) sStart[sp];
+
+    while (sptr) {
+        if (isRevSubset(sptr->getKey(), word + len - 1, len)
+        ) {
+            // suffixes are not allowed in beginning of compounds
+            if (((((in_compound != IN_CPD_BEGIN)) || // && !cclass
+             // except when signed with compoundpermitflag flag
+             (sptr->getCont() && compoundpermitflag &&
+                TESTAFF(sptr->getCont(),compoundpermitflag,sptr->getContLen()))) && (!circumfix ||
+              // no circumfix flag in prefix and suffix
+              ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(),
+                   circumfix, ep->getContLen())) &&
+               (!sptr->getCont() || !(TESTAFF(sptr->getCont(),circumfix,sptr->getContLen())))) ||
+              // circumfix flag in prefix AND suffix
+              ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(),
+                   circumfix, ep->getContLen())) &&
+               (sptr->getCont() && (TESTAFF(sptr->getCont(),circumfix,sptr->getContLen())))))  &&
+            // fogemorpheme
+              (in_compound || 
+                 !((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) &&
+            // pseudoroot on first suffix
+              (cclass || !(sptr->getCont() && 
+                   TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())))
+            )) rv = sptr->checkword(word,len, sfxopts, ppfx, NULL, 0, 0, cclass, needflag);
+            while (rv) {
+                    if (ppfx) {
+                        if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph());
+                    }    
+                    if (complexprefixes && rv->description) strcat(result, rv->description);
+                    if (rv->description && ((!rv->astr) || 
+                        !TESTAFF(rv->astr, lemma_present, rv->alen))) strcat(result, &(rv->word));
+                    if (!complexprefixes && rv->description) strcat(result, rv->description);
+#ifdef DEBUG
+                unsigned short flag = sptr->getFlag();
+                if (flag_mode == FLAG_NUM) {
+                    sprintf(result, "<%d>", sptr->getKey());
+                } else if (flag_mode == FLAG_LONG) {
+                    sprintf(result, "<%c%c>", flag >> 8, (flag << 8) >>8);
+                } else sprintf(result, "<%c>", flag);
+                strcat(result, ":");
+#endif
+
+                if (sptr->getMorph()) strcat(result, sptr->getMorph());
+                strcat(result, "\n");
+                rv = sptr->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag);
+            }
+             sptr = sptr->getNextEQ();
+        } else {
+             sptr = sptr->getNextNE();
+        }
+    }
+
+    if (*result) return mystrdup(result);
+    return NULL;
+}
+#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+
+
+// check if word with affixes is correctly spelled
+struct hentry * AffixMgr::affix_check (const char * word, int len, const FLAG needflag, char in_compound)
+{
+    struct hentry * rv= NULL;
+    if (derived) free(derived);
+    derived =  NULL;
+
+    // check all prefixes (also crossed with suffixes if allowed) 
+    rv = prefix_check(word, len, in_compound, needflag);
+    if (rv) return rv;
+
+    // if still not found check all suffixes
+    rv = suffix_check(word, len, 0, NULL, NULL, 0, NULL, FLAG_NULL, needflag, in_compound);
+
+    if (havecontclass) {
+        sfx = NULL;
+        pfx = NULL;
+        if (rv) return rv;
+        // if still not found check all two-level suffixes
+        rv = suffix_check_twosfx(word, len, 0, NULL, needflag);
+        if (rv) return rv;
+        // if still not found check all two-level suffixes
+        rv = prefix_check_twosfx(word, len, IN_CPD_NOT, needflag);
+    }
+    return rv;
+}
+
+#ifdef HUNSPELL_EXPERIMENTAL
+// check if word with affixes is correctly spelled
+char * AffixMgr::affix_check_morph(const char * word, int len, const FLAG needflag, char in_compound)
+{
+    char result[MAXLNLEN];
+    char * st = NULL;
+
+    *result = '\0';
+    
+    // check all prefixes (also crossed with suffixes if allowed) 
+    st = prefix_check_morph(word, len, in_compound);
+    if (st) {
+        strcat(result, st);
+        free(st);
+    }
+
+    // if still not found check all suffixes    
+    st = suffix_check_morph(word, len, 0, NULL, '\0', needflag, in_compound);
+    if (st) {
+        strcat(result, st);
+        free(st);
+    }
+
+    if (havecontclass) {
+        sfx = NULL;
+        pfx = NULL;
+        // if still not found check all two-level suffixes
+        st = suffix_check_twosfx_morph(word, len, 0, NULL, needflag);
+        if (st) {
+            strcat(result, st);
+            free(st);
+        }
+
+        // if still not found check all two-level suffixes
+        st = prefix_check_twosfx_morph(word, len, IN_CPD_NOT, needflag);
+        if (st) {
+            strcat(result, st);
+            free(st);
+        }
+    }
+    
+    return mystrdup(result);
+}
+#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+
+
+int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts,
+    int wl, const unsigned short * ap, unsigned short al, char * bad, int badl,
+    char * phone)
+{
+
+    int nh=0;
+    // first add root word to list
+    if ((nh < maxn) && !(al && ((pseudoroot && TESTAFF(ap, pseudoroot, al)) ||
+         (onlyincompound && TESTAFF(ap, onlyincompound, al))))) {
+       wlst[nh].word = mystrdup(ts);
+       wlst[nh].allow = (1 == 0);
+       wlst[nh].orig = NULL;
+       nh++;
+       // add special phonetic version
+       if (phone && (nh < maxn)) {
+    	    wlst[nh].word = mystrdup(phone);
+    	    wlst[nh].allow = (1 == 0);
+    	    wlst[nh].orig = mystrdup(ts);
+    	    nh++;
+       }
+    }
+
+    // handle suffixes
+    for (int i = 0; i < al; i++) {
+       const unsigned char c = (unsigned char) (ap[i] & 0x00FF);
+       SfxEntry * sptr = (SfxEntry *)sFlag[c];
+       while (sptr) {
+         if ((sptr->getFlag() == ap[i]) && (!sptr->getKeyLen() || ((badl > sptr->getKeyLen()) &&
+                (strcmp(sptr->getAffix(), bad + badl - sptr->getKeyLen()) == 0))) &&
+                // check pseudoroot flag
+                !(sptr->getCont() && ((pseudoroot && 
+                      TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())) ||
+                  (circumfix && 
+                      TESTAFF(sptr->getCont(), circumfix, sptr->getContLen())) ||
+                  (onlyincompound && 
+                      TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))
+                ) {
+            char * newword = sptr->add(ts, wl);
+            if (newword) {
+                if (nh < maxn) {
+                    wlst[nh].word = newword;
+                    wlst[nh].allow = sptr->allowCross();
+                    wlst[nh].orig = NULL;
+                    nh++;
+                    // add special phonetic version
+    		    if (phone && (nh < maxn)) {
+    			char st[MAXWORDUTF8LEN];
+    			strcpy(st, phone);
+    			strcat(st, sptr->getKey());
+    			reverseword(st + strlen(phone));
+    			wlst[nh].word = mystrdup(st);
+    			wlst[nh].allow = (1 == 0);
+    			wlst[nh].orig = mystrdup(newword);
+    			nh++;
+    		    }
+                } else {
+                    free(newword);
+                }
+            }
+         }
+         sptr = (SfxEntry *)sptr ->getFlgNxt();
+       }
+    }
+
+    int n = nh;
+
+    // handle cross products of prefixes and suffixes
+    for (int j=1;j<n ;j++)
+       if (wlst[j].allow) {
+          for (int k = 0; k < al; k++) {
+    	     const unsigned char c = (unsigned char) (ap[k] & 0x00FF);
+             PfxEntry * cptr = (PfxEntry *) pFlag[c];
+             while (cptr) {
+                if ((cptr->getFlag() == ap[k]) && cptr->allowCross() && (!cptr->getKeyLen() || ((badl > cptr->getKeyLen()) &&
+                        (strncmp(cptr->getKey(), bad, cptr->getKeyLen()) == 0)))) {
+                    int l1 = strlen(wlst[j].word);
+                    char * newword = cptr->add(wlst[j].word, l1);
+                    if (newword) {
+                       if (nh < maxn) {
+                          wlst[nh].word = newword;
+                          wlst[nh].allow = cptr->allowCross();
+                	  wlst[nh].orig = NULL;
+                          nh++;
+                       } else {
+                          free(newword);
+                       }
+                    }
+                }
+                cptr = (PfxEntry *)cptr ->getFlgNxt();
+             }
+          }
+       }
+
+
+    // now handle pure prefixes
+    for (int m = 0; m < al; m ++) {
+       const unsigned char c = (unsigned char) (ap[m] & 0x00FF);
+       PfxEntry * ptr = (PfxEntry *) pFlag[c];
+       while (ptr) {
+         if ((ptr->getFlag() == ap[m]) && (!ptr->getKeyLen() || ((badl > ptr->getKeyLen()) &&
+                (strncmp(ptr->getKey(), bad, ptr->getKeyLen()) == 0))) &&
+                // check pseudoroot flag
+                !(ptr->getCont() && ((pseudoroot && 
+                      TESTAFF(ptr->getCont(), pseudoroot, ptr->getContLen())) ||
+                     (circumfix && 
+                      TESTAFF(ptr->getCont(), circumfix, ptr->getContLen())) ||                      
+                  (onlyincompound && 
+                      TESTAFF(ptr->getCont(), onlyincompound, ptr->getContLen()))))
+                ) {
+            char * newword = ptr->add(ts, wl);
+            if (newword) {
+                if (nh < maxn) {
+                    wlst[nh].word = newword;
+                    wlst[nh].allow = ptr->allowCross();
+                    wlst[nh].orig = NULL;
+                    nh++;
+                } else {
+                    free(newword);
+                } 
+            }
+         }
+         ptr = (PfxEntry *)ptr ->getFlgNxt();
+       }
+    }
+
+    return nh;
+}
+
+
+
+// return length of replacing table
+int AffixMgr::get_numrep()
+{
+  return numrep;
+}
+
+// return replacing table
+struct replentry * AffixMgr::get_reptable()
+{
+  if (! reptable ) return NULL;
+  return reptable;
+}
+
+// return replacing table
+struct phonetable * AffixMgr::get_phonetable()
+{
+  if (! phone ) return NULL;
+  return phone;
+}
+
+// return length of character map table
+int AffixMgr::get_nummap()
+{
+  return nummap;
+}
+
+// return character map table
+struct mapentry * AffixMgr::get_maptable()
+{
+  if (! maptable ) return NULL;
+  return maptable;
+}
+
+// return length of word break table
+int AffixMgr::get_numbreak()
+{
+  return numbreak;
+}
+
+// return character map table
+char ** AffixMgr::get_breaktable()
+{
+  if (! breaktable ) return NULL;
+  return breaktable;
+}
+
+// return text encoding of dictionary
+char * AffixMgr::get_encoding()
+{
+  if (! encoding ) {
+      encoding = mystrdup("ISO8859-1");
+  }
+  return mystrdup(encoding);
+}
+
+// return text encoding of dictionary
+int AffixMgr::get_langnum()
+{
+  return langnum;
+}
+
+// return double prefix option
+int AffixMgr::get_complexprefixes()
+{
+  return complexprefixes;
+}
+
+FLAG AffixMgr::get_keepcase()
+{
+  return keepcase;
+}
+
+int AffixMgr::get_checksharps()
+{
+  return checksharps;
+}
+
+// return the preferred ignore string for suggestions
+char * AffixMgr::get_ignore()
+{
+  if (!ignorechars) return NULL;
+  return ignorechars;
+}
+
+// return the preferred ignore string for suggestions
+unsigned short * AffixMgr::get_ignore_utf16(int * len)
+{
+  *len = ignorechars_utf16_len;
+  return ignorechars_utf16;
+}
+
+// return the keyboard string for suggestions
+char * AffixMgr::get_key_string()
+{
+  if (! keystring ) return NULL;
+  return mystrdup(keystring);
+}
+
+// return the preferred try string for suggestions
+char * AffixMgr::get_try_string()
+{
+  if (! trystring ) return NULL;
+  return mystrdup(trystring);
+}
+
+// return the preferred try string for suggestions
+const char * AffixMgr::get_wordchars()
+{
+  return wordchars;
+}
+
+unsigned short * AffixMgr::get_wordchars_utf16(int * len)
+{
+  *len = wordchars_utf16_len;
+  return wordchars_utf16;
+}
+
+// is there compounding?
+int AffixMgr::get_compound()
+{
+  return compoundflag || compoundbegin || numdefcpd;
+}
+
+// return the compound words control flag
+FLAG AffixMgr::get_compoundflag()
+{
+  return compoundflag;
+}
+
+// return the forbidden words control flag
+FLAG AffixMgr::get_forbiddenword()
+{
+  return forbiddenword;
+}
+
+// return the forbidden words control flag
+FLAG AffixMgr::get_nosuggest()
+{
+  return nosuggest;
+}
+
+// return the forbidden words flag modify flag
+FLAG AffixMgr::get_pseudoroot()
+{
+  return pseudoroot;
+}
+
+// return the onlyincompound flag
+FLAG AffixMgr::get_onlyincompound()
+{
+  return onlyincompound;
+}
+
+// return the compound word signal flag
+FLAG AffixMgr::get_compoundroot()
+{
+  return compoundroot;
+}
+
+// return the compound begin signal flag
+FLAG AffixMgr::get_compoundbegin()
+{
+  return compoundbegin;
+}
+
+// return the value of checknum
+int AffixMgr::get_checknum()
+{
+  return checknum;
+}
+
+// return the value of prefix
+const char * AffixMgr::get_prefix()
+{
+  if (pfx) return ((PfxEntry *)pfx)->getKey();
+  return NULL;
+}
+
+// return the value of suffix
+const char * AffixMgr::get_suffix()
+{
+  return sfxappnd;
+}
+
+// return the value of derived form (base word with first suffix).
+const char * AffixMgr::get_derived()
+{
+  return derived;
+}
+
+// return the value of suffix
+const char * AffixMgr::get_version()
+{
+  return version;
+}
+
+// return lemma_present flag
+FLAG AffixMgr::get_lemma_present()
+{
+  return lemma_present;
+}
+
+// utility method to look up root words in hash table
+struct hentry * AffixMgr::lookup(const char * word)
+{
+  if (! pHMgr) return NULL;
+  return pHMgr->lookup(word);
+}
+
+// return the value of suffix
+const int AffixMgr::have_contclass()
+{
+  return havecontclass;
+}
+
+// return utf8
+int AffixMgr::get_utf8()
+{
+  return utf8;
+}
+
+// return nosplitsugs
+int AffixMgr::get_maxngramsugs(void)
+{
+  return maxngramsugs;
+}
+
+// return nosplitsugs
+int AffixMgr::get_nosplitsugs(void)
+{
+  return nosplitsugs;
+}
+
+// return sugswithdots
+int AffixMgr::get_sugswithdots(void)
+{
+  return sugswithdots;
+}
+
+/* parse flag */
+int AffixMgr::parse_flag(char * line, unsigned short * out, const char * name) {
+   char * s = NULL;
+   if (*out != FLAG_NULL) {
+      HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", name);
+      return 1;
+   }
+   if (parse_string(line, &s, name)) return 1;
+   *out = pHMgr->decode_flag(s);
+   free(s);
+   return 0;
+}
+
+/* parse num */
+int AffixMgr::parse_num(char * line, int * out, const char * name) {
+   char * s = NULL;
+   if (*out != -1) {
+      HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", name);
+      return 1;
+   }
+   if (parse_string(line, &s, name)) return 1;
+   *out = atoi(s);
+   free(s);
+   return 0;
+}
+
+/* parse in the max syllablecount of compound words and  */
+int  AffixMgr::parse_cpdsyllable(char * line)
+{
+   char * tp = line;
+   char * piece;
+   int i = 0;
+   int np = 0;
+   w_char w[MAXWORDLEN];
+   piece = mystrsep(&tp, 0);
+   while (piece) {
+      if (*piece != '\0') {
+          switch(i) {
+             case 0: { np++; break; }
+             case 1: { cpdmaxsyllable = atoi(piece); np++; break; }
+             case 2: {
+                if (!utf8) {
+                    cpdvowels = mystrdup(piece);
+                } else {
+                    int n = u8_u16(w, MAXWORDLEN, piece);
+                    if (n > 0) {
+                        flag_qsort((unsigned short *) w, 0, n);
+                        cpdvowels_utf16 = (w_char *) malloc(n * sizeof(w_char));
+                        if (!cpdvowels_utf16) return 1;
+                        memcpy(cpdvowels_utf16, w, n * sizeof(w_char));
+                    }
+                    cpdvowels_utf16_len = n;
+                }
+                np++;
+                break;
+             }
+             default: break;
+          }
+          i++;
+      }
+      free(piece);
+      piece = mystrsep(&tp, 0);
+   }
+   if (np < 2) {
+      HUNSPELL_WARNING(stderr, "error: missing compoundsyllable information\n");
+      return 1;
+   }
+   if (np == 2) cpdvowels = mystrdup("aeiouAEIOU");
+   return 0;
+}
+
+/* parse in the typical fault correcting table */
+int  AffixMgr::parse_reptable(char * line, FILE * af)
+{
+   if (numrep != 0) {
+      HUNSPELL_WARNING(stderr, "error: duplicate REP tables used\n");
+      return 1;
+   }
+   char * tp = line;
+   char * piece;
+   int i = 0;
+   int np = 0;
+   piece = mystrsep(&tp, 0);
+   while (piece) {
+       if (*piece != '\0') {
+          switch(i) {
+             case 0: { np++; break; }
+             case 1: { 
+                       numrep = atoi(piece);
+                       if (numrep < 1) {
+                          HUNSPELL_WARNING(stderr, "incorrect number of entries in replacement table\n");
+                          free(piece);
+                          return 1;
+                       }
+                       reptable = (replentry *) malloc(numrep * sizeof(struct replentry));
+                       if (!reptable) return 1;
+                       np++;
+                       break;
+                     }
+             default: break;
+          }
+          i++;
+       }
+       free(piece);
+       piece = mystrsep(&tp, 0);
+   }
+   if (np != 2) {
+      HUNSPELL_WARNING(stderr, "error: missing replacement table information\n");
+      return 1;
+   } 
+ 
+   /* now parse the numrep lines to read in the remainder of the table */
+   char * nl = line;
+   for (int j=0; j < numrep; j++) {
+        if (!fgets(nl,MAXLNLEN,af)) return 1;
+        mychomp(nl);
+        tp = nl;
+        i = 0;
+        reptable[j].pattern = NULL;
+        reptable[j].pattern2 = NULL;
+        piece = mystrsep(&tp, 0);
+        while (piece) {
+           if (*piece != '\0') {
+               switch(i) {
+                  case 0: {
+                             if (strncmp(piece,"REP",3) != 0) {
+                                 HUNSPELL_WARNING(stderr, "error: replacement table is corrupt\n");
+                                 numrep = 0;
+                                 free(piece);
+                                 return 1;
+                             }
+                             break;
+                          }
+                  case 1: { reptable[j].pattern = mystrrep(mystrdup(piece),"_"," "); break; }
+                  case 2: { reptable[j].pattern2 = mystrrep(mystrdup(piece),"_"," "); break; }
+                  default: break;
+               }
+               i++;
+           }
+           free(piece);
+           piece = mystrsep(&tp, 0);
+        }
+        if ((!(reptable[j].pattern)) || (!(reptable[j].pattern2))) {
+             HUNSPELL_WARNING(stderr, "error: replacement table is corrupt\n");
+             numrep = 0;
+             return 1;
+        }
+   }
+   return 0;
+}
+
+/* parse in the typical fault correcting table */
+int  AffixMgr::parse_phonetable(char * line, FILE * af)
+{
+   if (phone) {
+      HUNSPELL_WARNING(stderr, "error: duplicate PHONE tables used\n");
+      return 1;
+   }
+   char * tp = line;
+   char * piece;
+   int i = 0;
+   int np = 0;
+   piece = mystrsep(&tp, 0);
+   while (piece) {
+       if (*piece != '\0') {
+          switch(i) {
+             case 0: { np++; break; }
+             case 1: { 
+            	       phone = (phonetable *) malloc(sizeof(struct phonetable));
+            	       phone->num = atoi(piece);
+            	       phone->rules = NULL;
+            	       phone->utf8 = utf8;
+                       if (!phone) return 1;
+                       if (phone->num < 1) {
+                          HUNSPELL_WARNING(stderr, "incorrect number of entries in phonelacement table\n");
+                          free(piece);
+                          return 1;
+                       }
+                       phone->rules = (char * *) malloc(2 * (phone->num + 1) * sizeof(char *));
+                       if (!phone->rules) return 1;
+                       np++;
+                       break;
+                     }
+             default: break;
+          }
+          i++;
+       }
+       free(piece);
+       piece = mystrsep(&tp, 0);
+   }
+   if (np != 2) {
+      HUNSPELL_WARNING(stderr, "error: missing PHONE table information\n");
+      return 1;
+   } 
+ 
+   /* now parse the phone->num lines to read in the remainder of the table */
+   char * nl = line;
+   for (int j=0; j < phone->num; j++) {
+        if (!fgets(nl,MAXLNLEN,af)) return 1;
+        mychomp(nl);
+        tp = nl;
+        i = 0;
+        phone->rules[j * 2] = NULL;
+        phone->rules[j * 2 + 1] = NULL;
+        piece = mystrsep(&tp, 0);
+        while (piece) {
+           if (*piece != '\0') {
+               switch(i) {
+                  case 0: {
+                             if (strncmp(piece,"PHONE",5) != 0) {
+                                 HUNSPELL_WARNING(stderr, "error: PHONE table is corrupt\n");
+                                 phone->num = 0;
+                                 free(piece);
+                                 return 1;
+                             }
+                             break;
+                          }
+                  case 1: { phone->rules[j * 2] = mystrrep(mystrdup(piece),"_",""); break; }
+                  case 2: { phone->rules[j * 2 + 1] = mystrrep(mystrdup(piece),"_",""); break; }
+                  default: break;
+               }
+               i++;
+           }
+           free(piece);
+           piece = mystrsep(&tp, 0);
+        }
+        if ((!(phone->rules[j * 2])) || (!(phone->rules[j * 2 + 1]))) {
+             HUNSPELL_WARNING(stderr, "error: PHONE table is corrupt\n");
+             phone->num = 0;
+             return 1;
+        }
+   }
+   phone->rules[phone->num * 2] = mystrdup("");
+   phone->rules[phone->num * 2 + 1] = mystrdup("");
+   init_phonet_hash(*phone);
+   return 0;
+}
+
+/* parse in the checkcompoundpattern table */
+int  AffixMgr::parse_checkcpdtable(char * line, FILE * af)
+{
+   if (numcheckcpd != 0) {
+      HUNSPELL_WARNING(stderr, "error: duplicate compound pattern tables used\n");
+      return 1;
+   }
+   char * tp = line;
+   char * piece;
+   int i = 0;
+   int np = 0;
+   piece = mystrsep(&tp, 0);
+   while (piece) {
+       if (*piece != '\0') {
+          switch(i) {
+             case 0: { np++; break; }
+             case 1: { 
+                       numcheckcpd = atoi(piece);
+                       if (numcheckcpd < 1) {
+                          HUNSPELL_WARNING(stderr, "incorrect number of entries in compound pattern table\n");
+                          free(piece);
+                          return 1;
+                       }
+                       checkcpdtable = (replentry *) malloc(numcheckcpd * sizeof(struct replentry));
+                       if (!checkcpdtable) return 1;
+                       np++;
+                       break;
+                     }
+             default: break;
+          }
+          i++;
+       }
+       free(piece);
+       piece = mystrsep(&tp, 0);
+   }
+   if (np != 2) {
+      HUNSPELL_WARNING(stderr, "error: missing compound pattern table information\n");
+      return 1;
+   } 
+ 
+   /* now parse the numcheckcpd lines to read in the remainder of the table */
+   char * nl = line;
+   for (int j=0; j < numcheckcpd; j++) {
+        if (!fgets(nl,MAXLNLEN,af)) return 1;
+        mychomp(nl);
+        tp = nl;
+        i = 0;
+        checkcpdtable[j].pattern = NULL;
+        checkcpdtable[j].pattern2 = NULL;
+        piece = mystrsep(&tp, 0);
+        while (piece) {
+           if (*piece != '\0') {
+               switch(i) {
+                  case 0: {
+                             if (strncmp(piece,"CHECKCOMPOUNDPATTERN",20) != 0) {
+                                 HUNSPELL_WARNING(stderr, "error: compound pattern table is corrupt\n");
+                                 numcheckcpd = 0;
+                                 free(piece);
+                                 return 1;
+                             }
+                             break;
+                          }
+                  case 1: { checkcpdtable[j].pattern = mystrdup(piece); break; }
+                  case 2: { checkcpdtable[j].pattern2 = mystrdup(piece); break; }
+                  default: break;
+               }
+               i++;
+           }
+           free(piece);
+           piece = mystrsep(&tp, 0);
+        }
+        if ((!(checkcpdtable[j].pattern)) || (!(checkcpdtable[j].pattern2))) {
+             HUNSPELL_WARNING(stderr, "error: compound pattern table is corrupt\n");
+	     numcheckcpd = 0;
+	     return 1;
+        }
+   }
+   return 0;
+}
+
+/* parse in the compound rule table */
+int  AffixMgr::parse_defcpdtable(char * line, FILE * af)
+{
+   if (numdefcpd != 0) {
+      HUNSPELL_WARNING(stderr, "error: duplicate compound rule tables used\n");
+      return 1;
+   }
+   char * tp = line;
+   char * piece;
+   int i = 0;
+   int np = 0;
+   piece = mystrsep(&tp, 0);
+   while (piece) {
+       if (*piece != '\0') {
+          switch(i) {
+             case 0: { np++; break; }
+             case 1: { 
+                       numdefcpd = atoi(piece);
+                       if (numdefcpd < 1) {
+                          HUNSPELL_WARNING(stderr, "incorrect number of entries in compound rule table\n");
+                          free(piece);
+                          return 1;
+                       }
+                       defcpdtable = (flagentry *) malloc(numdefcpd * sizeof(flagentry));
+                       if (!defcpdtable) return 1;
+                       np++;
+                       break;
+                     }
+             default: break;
+          }
+          i++;
+       }
+       free(piece);
+       piece = mystrsep(&tp, 0);
+   }
+   if (np != 2) {
+      HUNSPELL_WARNING(stderr, "error: missing compound rule table information\n");
+      return 1;
+   } 
+ 
+   /* now parse the numdefcpd lines to read in the remainder of the table */
+   char * nl = line;
+   for (int j=0; j < numdefcpd; j++) {
+        if (!fgets(nl,MAXLNLEN,af)) return 1;
+        mychomp(nl);
+        tp = nl;
+        i = 0;
+        defcpdtable[j].def = NULL;
+        piece = mystrsep(&tp, 0);
+        while (piece) {
+           if (*piece != '\0') {
+               switch(i) {
+                  case 0: {
+                             if (strncmp(piece, "COMPOUNDRULE", 12) != 0) {
+                                 HUNSPELL_WARNING(stderr, "error: compound rule table is corrupt\n");
+                                 free(piece);
+                                 numdefcpd = 0;
+                                 return 1;
+                             }
+                             break;
+                          }
+                  case 1: { 
+                            defcpdtable[j].len = 
+                                pHMgr->decode_flags(&(defcpdtable[j].def), piece);
+                            break; 
+                           }
+                  default: break;
+               }
+               i++;
+           }
+           free(piece);
+           piece = mystrsep(&tp, 0);
+        }
+        if (!defcpdtable[j].len) {
+             HUNSPELL_WARNING(stderr, "error: compound rule table is corrupt\n");
+             numdefcpd = 0;
+             return 1;
+        }
+   }
+   return 0;
+}
+
+
+/* parse in the character map table */
+int  AffixMgr::parse_maptable(char * line, FILE * af)
+{
+   if (nummap != 0) {
+      HUNSPELL_WARNING(stderr, "error: duplicate MAP tables used\n");
+      return 1;
+   }
+   char * tp = line;
+   char * piece;
+   int i = 0;
+   int np = 0;
+   piece = mystrsep(&tp, 0);
+   while (piece) {
+       if (*piece != '\0') {
+          switch(i) {
+             case 0: { np++; break; }
+             case 1: { 
+                       nummap = atoi(piece);
+                       if (nummap < 1) {
+                          HUNSPELL_WARNING(stderr, "incorrect number of entries in map table\n");
+                          free(piece);
+                          return 1;
+                       }
+                       maptable = (mapentry *) malloc(nummap * sizeof(struct mapentry));
+                       if (!maptable) return 1;
+                       np++;
+                       break;
+                     }
+             default: break;
+          }
+          i++;
+       }
+       free(piece);
+       piece = mystrsep(&tp, 0);
+   }
+   if (np != 2) {
+      HUNSPELL_WARNING(stderr, "error: missing map table information\n");
+      return 1;
+   } 
+ 
+   /* now parse the nummap lines to read in the remainder of the table */
+   char * nl = line;
+   for (int j=0; j < nummap; j++) {
+        if (!fgets(nl,MAXLNLEN,af)) return 1;
+        mychomp(nl);
+        tp = nl;
+        i = 0;
+        maptable[j].set = NULL;
+        maptable[j].len = 0;
+        piece = mystrsep(&tp, 0);
+        while (piece) {
+           if (*piece != '\0') {
+               switch(i) {
+                  case 0: {
+                             if (strncmp(piece,"MAP",3) != 0) {
+                                 HUNSPELL_WARNING(stderr, "error: map table is corrupt\n");
+                                 nummap = 0;
+                                 free(piece);
+                                 return 1;
+                             }
+                             break;
+                          }
+                  case 1: {
+                            maptable[j].len = 0;
+                            maptable[j].set = NULL;
+                            maptable[j].set_utf16 = NULL;
+                            if (!utf8) {
+                                maptable[j].set = mystrdup(piece); 
+                                maptable[j].len = strlen(maptable[j].set);
+                            } else {
+                                w_char w[MAXWORDLEN];
+                                int n = u8_u16(w, MAXWORDLEN, piece);
+                                if (n > 0) {
+                                    flag_qsort((unsigned short *) w, 0, n);
+                                    maptable[j].set_utf16 = (w_char *) malloc(n * sizeof(w_char));
+                                    if (!maptable[j].set_utf16) return 1;
+                                    memcpy(maptable[j].set_utf16, w, n * sizeof(w_char));
+                                }
+                                maptable[j].len = n;
+                            }
+                            break; }
+                  default: break;
+               }
+               i++;
+           }
+           free(piece);
+           piece = mystrsep(&tp, 0);
+        }
+        if ((!(maptable[j].set || maptable[j].set_utf16)) || (!(maptable[j].len))) {
+             HUNSPELL_WARNING(stderr, "error: map table is corrupt\n");
+             nummap = 0;
+             return 1;
+        }
+   }
+   return 0;
+}
+
+/* parse in the word breakpoint table */
+int  AffixMgr::parse_breaktable(char * line, FILE * af)
+{
+   if (numbreak != 0) {
+      HUNSPELL_WARNING(stderr, "error: duplicate word breakpoint tables used\n");
+      return 1;
+   }
+   char * tp = line;
+   char * piece;
+   int i = 0;
+   int np = 0;
+   piece = mystrsep(&tp, 0);
+   while (piece) {
+       if (*piece != '\0') {
+          switch(i) {
+             case 0: { np++; break; }
+             case 1: { 
+                       numbreak = atoi(piece);
+                       if (numbreak < 1) {
+                          HUNSPELL_WARNING(stderr, "incorrect number of entries in BREAK table\n");
+                          free(piece);
+                          return 1;
+                       }
+                       breaktable = (char **) malloc(numbreak * sizeof(char *));
+                       if (!breaktable) return 1;
+                       np++;
+                       break;
+                     }
+             default: break;
+          }
+          i++;
+       }
+       free(piece);
+       piece = mystrsep(&tp, 0);
+   }
+   if (np != 2) {
+      HUNSPELL_WARNING(stderr, "error: missing word breakpoint table information\n");
+      return 1;
+   } 
+ 
+   /* now parse the numbreak lines to read in the remainder of the table */
+   char * nl = line;
+   for (int j=0; j < numbreak; j++) {
+        if (!fgets(nl,MAXLNLEN,af)) return 1;
+        mychomp(nl);
+        tp = nl;
+        i = 0;
+        piece = mystrsep(&tp, 0);
+        while (piece) {
+           if (*piece != '\0') {
+               switch(i) {
+                  case 0: {
+                             if (strncmp(piece,"BREAK",5) != 0) {
+                                 HUNSPELL_WARNING(stderr, "error: BREAK table is corrupt\n");
+                                 free(piece);
+                                 numbreak = 0;
+                                 return 1;
+                             }
+                             break;
+                          }
+                  case 1: {
+                            breaktable[j] = mystrdup(piece);
+                            break;
+                          }
+                  default: break;
+               }
+               i++;
+           }
+           free(piece);
+           piece = mystrsep(&tp, 0);
+        }
+        if (!breaktable) {
+             HUNSPELL_WARNING(stderr, "error: BREAK table is corrupt\n");
+             numbreak = 0;
+             return 1;
+        }
+   }
+   return 0;
+}
+
+int  AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflags)
+{
+   int numents = 0;      // number of affentry structures to parse
+
+   unsigned short aflag = 0;      // affix char identifier
+
+   char ff=0;
+   struct affentry * ptr= NULL;
+   struct affentry * nptr= NULL;
+
+   char * tp = line;
+   char * nl = line;
+   char * piece;
+   int i = 0;
+
+   // checking lines with bad syntax
+#ifdef DEBUG
+   int basefieldnum = 0;
+#endif
+
+   // split affix header line into pieces
+
+   int np = 0;
+   piece = mystrsep(&tp, 0);
+   while (piece) {
+      if (*piece != '\0') {
+          switch(i) {
+             // piece 1 - is type of affix
+             case 0: { np++; break; }
+          
+             // piece 2 - is affix char
+             case 1: { 
+                    np++;
+                    aflag = pHMgr->decode_flag(piece);
+                    if (((at == 'S') && (dupflags[aflag] & dupSFX)) ||
+                        ((at == 'P') && (dupflags[aflag] & dupPFX))) {
+                        HUNSPELL_WARNING(stderr, "error: duplicate affix flag %s in line %s\n", piece, nl);
+                        // return 1; XXX permissive mode for bad dictionaries
+                    }
+                    dupflags[aflag] += ((at == 'S') ? dupSFX : dupPFX);
+                    break; 
+                    }
+             // piece 3 - is cross product indicator 
+             case 2: { np++; if (*piece == 'Y') ff = aeXPRODUCT; break; }
+
+             // piece 4 - is number of affentries
+             case 3: { 
+                       np++;
+                       numents = atoi(piece); 
+                       if (numents == 0) {
+                           char * err = pHMgr->encode_flag(aflag);
+                           HUNSPELL_WARNING(stderr, "error: affix %s header has incorrect entry count in line %s\n",
+                                   err, nl);
+                           free(err);
+                           return 1;
+                       }
+                       ptr = (struct affentry *) malloc(numents * sizeof(struct affentry));
+                       if (!ptr) return 1;
+                       ptr->opts = ff;
+                       if (utf8) ptr->opts += aeUTF8;
+                       if (pHMgr->is_aliasf()) ptr->opts += aeALIASF;
+#ifdef HUNSPELL_EXPERIMENTAL
+                       if (pHMgr->is_aliasm()) ptr->opts += aeALIASM;
+#endif
+                       ptr->aflag = aflag;
+                     }
+
+             default: break;
+          }
+          i++;
+      }
+      free(piece);
+      piece = mystrsep(&tp, 0);
+   }
+   // check to make sure we parsed enough pieces
+   if (np != 4) {
+       char * err = pHMgr->encode_flag(aflag); 
+       HUNSPELL_WARNING(stderr, "error: affix %s header has insufficient data in line %s\n", err, nl);
+       free(err);
+       free(ptr);
+       return 1;
+   }
+ 
+   // store away ptr to first affentry
+   nptr = ptr;
+
+   // now parse numents affentries for this affix
+   for (int j=0; j < numents; j++) {
+      if (!fgets(nl,MAXLNLEN,af)) return 1;
+      mychomp(nl);
+      tp = nl;
+      i = 0;
+      np = 0;
+
+      // split line into pieces
+      piece = mystrsep(&tp, 0);
+      while (piece) {
+         if (*piece != '\0') {
+             switch(i) {
+                // piece 1 - is type
+                case 0: { 
+                          np++;
+                          if (nptr != ptr) nptr->opts = ptr->opts;
+                          break;
+                        }
+
+                // piece 2 - is affix char
+                case 1: { 
+                          np++;
+                          if (pHMgr->decode_flag(piece) != aflag) {
+                              char * err = pHMgr->encode_flag(aflag);
+                              HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl);
+                              HUNSPELL_WARNING(stderr, "error: possible incorrect count\n");
+                              free(err);
+                              free(piece);
+                              return 1;
+                          }
+
+                          if (nptr != ptr) nptr->aflag = ptr->aflag;
+                          break;
+                        }
+
+                // piece 3 - is string to strip or 0 for null 
+                case 2: { 
+                          np++;
+                          if (complexprefixes) {
+                            if (utf8) reverseword_utf(piece); else reverseword(piece);
+                          }
+                          nptr->strip = mystrdup(piece);
+                          nptr->stripl = (unsigned char) strlen(nptr->strip);
+                          if (strcmp(nptr->strip,"0") == 0) {
+                              free(nptr->strip);
+                              nptr->strip=mystrdup("");
+                              nptr->stripl = 0;
+                          }   
+                          break; 
+                        }
+
+                // piece 4 - is affix string or 0 for null
+                case 3: { 
+                          char * dash;  
+#ifdef HUNSPELL_EXPERIMENTAL
+                          nptr->morphcode = NULL;
+#endif
+                          nptr->contclass = NULL;
+                          nptr->contclasslen = 0;
+                          np++;
+                          dash = strchr(piece, '/');
+                          if (dash) {
+                            *dash = '\0';
+
+                            if (ignorechars) {
+                              if (utf8) {
+                                remove_ignored_chars_utf(piece, ignorechars_utf16, ignorechars_utf16_len);
+                              } else {
+                                remove_ignored_chars(piece,ignorechars);
+                              }
+                            }
+                            
+                            if (complexprefixes) {
+                                if (utf8) reverseword_utf(piece); else reverseword(piece);
+                            }
+                            nptr->appnd = mystrdup(piece);
+                            
+                            if (pHMgr->is_aliasf()) {
+                                int index = atoi(dash + 1);
+                                nptr->contclasslen = (unsigned short) pHMgr->get_aliasf(index, &(nptr->contclass));
+                            } else {
+                                nptr->contclasslen = (unsigned short) pHMgr->decode_flags(&(nptr->contclass), dash + 1);
+                                flag_qsort(nptr->contclass, 0, nptr->contclasslen);
+                            }
+                            *dash = '/';
+
+                            havecontclass = 1;
+                            for (unsigned short _i = 0; _i < nptr->contclasslen; _i++) {
+                              contclasses[(nptr->contclass)[_i]] = 1;
+                            }
+                          } else {
+                            if (ignorechars) {
+                              if (utf8) {
+                                remove_ignored_chars_utf(piece, ignorechars_utf16, ignorechars_utf16_len);
+                              } else {
+                                remove_ignored_chars(piece,ignorechars);
+                              }
+                            }
+
+                            if (complexprefixes) {
+                                if (utf8) reverseword_utf(piece); else reverseword(piece);
+                            }
+                            nptr->appnd = mystrdup(piece);       
+                          }
+                          
+                          nptr->appndl = (unsigned char) strlen(nptr->appnd);
+                          if (strcmp(nptr->appnd,"0") == 0) {
+                              free(nptr->appnd);
+                              nptr->appnd=mystrdup("");
+                              nptr->appndl = 0;
+                          }   
+                          break; 
+                        }
+
+                // piece 5 - is the conditions descriptions
+                case 4: { 
+                          np++;
+                          if (complexprefixes) {
+                            int neg = 0;
+                            if (utf8) reverseword_utf(piece); else reverseword(piece);
+                            // reverse condition
+                            for (char * k = piece + strlen(piece) - 1; k >= piece; k--) {
+                                switch(*k) {
+                                  case '[': {
+                                        if (neg) *(k+1) = '['; else *k = ']';
+                                        break;
+                                    }
+                                  case ']': {
+                                        *k = '[';
+                                        if (neg) *(k+1) = '^';
+                                        neg = 0;
+                                        break;
+                                    }
+                                  case '^': {
+                                       if (*(k+1) == ']') neg = 1; else *(k+1) = *k;
+                                       break;
+                                    }
+                                  default: {
+                                    if (neg) *(k+1) = *k;
+                                  }
+                               }
+                            }
+                          }
+                          if (nptr->stripl && (strcmp(piece, ".") != 0) &&
+                            redundant_condition(at, nptr->strip, nptr->stripl, piece, nl))
+                                strcpy(piece, ".");
+                          if (encodeit(nptr,piece)) return 1;
+                         break;
+                }
+                
+#ifdef HUNSPELL_EXPERIMENTAL
+                case 5: {
+                          np++;
+                          if (pHMgr->is_aliasm()) {
+                            int index = atoi(piece);
+                            nptr->morphcode = pHMgr->get_aliasm(index);
+                          } else {
+                            if (complexprefixes) {
+                                if (utf8) reverseword_utf(piece); else reverseword(piece);
+                            }
+                            nptr->morphcode = mystrdup(piece);
+                          }
+                          break; 
+                }
+#endif
+
+                default: break;
+             }
+             i++;
+         }
+         free(piece);
+         piece = mystrsep(&tp, 0);
+      }
+      // check to make sure we parsed enough pieces
+      if (np < 4) {
+          char * err = pHMgr->encode_flag(aflag);
+          HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl);
+          free(err);
+          free(ptr);
+          return 1;
+      }
+
+#ifdef DEBUG
+#ifdef HUNSPELL_EXPERIMENTAL
+      // detect unnecessary fields, excepting comments
+      if (basefieldnum) {
+        int fieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6);
+          if (fieldnum != basefieldnum) 
+            HUNSPELL_WARNING(stderr, "warning: bad field number:\n%s\n", nl);
+      } else {
+        basefieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6);
+      }
+#endif
+#endif
+      nptr++;
+   }
+ 
+   // now create SfxEntry or PfxEntry objects and use links to
+   // build an ordered (sorted by affix string) list
+   nptr = ptr;
+   for (int k = 0; k < numents; k++) {
+      if (at == 'P') {
+          PfxEntry * pfxptr = new PfxEntry(this,nptr);
+          build_pfxtree((AffEntry *)pfxptr);
+      } else {
+          SfxEntry * sfxptr = new SfxEntry(this,nptr);
+          build_sfxtree((AffEntry *)sfxptr); 
+      }
+      nptr++;
+   }      
+   free(ptr);
+   return 0;
+}
+
+int AffixMgr::redundant_condition(char ft, char * strip, int stripl, const char * cond, char * warnvar) {
+  int condl = strlen(cond);
+  int i;
+  int j;
+  int neg;
+  int in;
+  if (ft == 'P') { // prefix
+    if (strncmp(strip, cond, condl) == 0) return 1;
+    if (utf8) {
+    } else {
+      for (i = 0, j = 0; (i < stripl) && (j < condl); i++, j++) {
+        if (cond[j] != '[') {
+          if (cond[j] != strip[i]) {
+            HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar);
+          }
+        } else {
+          neg = (cond[j+1] == '^') ? 1 : 0;
+          in = 0;
+          do {
+            j++;
+            if (strip[i] == cond[j]) in = 1;
+          } while ((j < (condl - 1)) && (cond[j] != ']'));
+          if (j == (condl - 1) && (cond[j] != ']')) {
+            HUNSPELL_WARNING(stderr, "error: missing ] in condition:\n%s\n", warnvar);
+            return 0;
+          }
+          if ((!neg && !in) || (neg && in)) {
+            HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar);
+            return 0;          
+          }
+        }
+      }
+      if (j >= condl) return 1;
+    }
+  } else { // suffix
+    if ((stripl >= condl) && strcmp(strip + stripl - condl, cond) == 0) return 1;
+    if (utf8) {
+    } else {
+      for (i = stripl - 1, j = condl - 1; (i >= 0) && (j >= 0); i--, j--) {
+        if (cond[j] != ']') {
+          if (cond[j] != strip[i]) {
+            HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar);
+          }
+        } else {
+          in = 0;
+          do {
+            j--;
+            if (strip[i] == cond[j]) in = 1;
+          } while ((j > 0) && (cond[j] != '['));
+          if ((j == 0) && (cond[j] != '[')) {
+            HUNSPELL_WARNING(stderr, "error: missing ] in condition:\n%s\n", warnvar);
+            return 0;
+          }
+          neg = (cond[j+1] == '^') ? 1 : 0;
+          if ((!neg && !in) || (neg && in)) {
+            HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar);
+            return 0;          
+          }
+        }
+      }
+      if (j < 0) return 1;
+    }    
+  }
+  return 0;
+}
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/affixmgr.hxx spellcheck/hunspell/hunspell/affixmgr.hxx
--- spellcheck.old/hunspell/hunspell/affixmgr.hxx	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/affixmgr.hxx	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,272 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef _AFFIXMGR_HXX_
+#define _AFFIXMGR_HXX_
+
+#ifdef MOZILLA_CLIENT
+#ifdef __SUNPRO_CC // for SunONE Studio compiler
+using namespace std;
+#endif
+#include <stdio.h>
+#else
+#include <cstdio>
+#endif
+
+#include "atypes.hxx"
+#include "baseaffix.hxx"
+#include "hashmgr.hxx"
+#include "phonet.hxx"
+
+// check flag duplication
+#define dupSFX        (1 << 0)
+#define dupPFX        (1 << 1)
+
+class AffixMgr
+{
+
+  AffEntry *          pStart[SETSIZE];
+  AffEntry *          sStart[SETSIZE];
+  AffEntry *          pFlag[CONTSIZE];
+  AffEntry *          sFlag[CONTSIZE];
+  HashMgr *           pHMgr;
+  char *              keystring;
+  char *              trystring;
+  char *              encoding;
+  struct cs_info *    csconv;
+  int                 utf8;
+  int                 complexprefixes;
+  FLAG                compoundflag;
+  FLAG                compoundbegin;
+  FLAG                compoundmiddle;
+  FLAG                compoundend;
+  FLAG                compoundroot;
+  FLAG                compoundforbidflag;
+  FLAG                compoundpermitflag;
+  int                 checkcompounddup;
+  int                 checkcompoundrep;
+  int                 checkcompoundcase;
+  int                 checkcompoundtriple;
+  FLAG                forbiddenword;
+  FLAG                nosuggest;
+  FLAG                pseudoroot;
+  int                 cpdmin;
+  int                 numrep;
+  replentry *         reptable;
+  int                 nummap;
+  mapentry *          maptable;
+  int                 numbreak;
+  char **             breaktable;
+  int                 numcheckcpd;
+  replentry *         checkcpdtable;
+  int                 numdefcpd;
+  flagentry *         defcpdtable;
+  phonetable *        phone;
+  int                 maxngramsugs;
+  int                 nosplitsugs;
+  int                 sugswithdots;
+  int                 cpdwordmax;
+  int                 cpdmaxsyllable;
+  char *              cpdvowels;
+  w_char *            cpdvowels_utf16;
+  int                 cpdvowels_utf16_len;
+  char *              cpdsyllablenum;
+  const char *        pfxappnd; // BUG: not stateless
+  const char *        sfxappnd; // BUG: not stateless
+  FLAG                sfxflag;  // BUG: not stateless
+  char *              derived;  // BUG: not stateless
+  AffEntry *          sfx;      // BUG: not stateless
+  AffEntry *          pfx;      // BUG: not stateless
+  int                 checknum;
+  char *              wordchars;
+  unsigned short *    wordchars_utf16;
+  int                 wordchars_utf16_len;
+  char *              ignorechars;
+  unsigned short *    ignorechars_utf16;
+  int                 ignorechars_utf16_len;
+  char *              version;
+  char *              lang;
+  int                 langnum;
+  FLAG                lemma_present;
+  FLAG                circumfix;
+  FLAG                onlyincompound;
+  FLAG                keepcase;
+  int                 checksharps;
+
+  int                 havecontclass; // boolean variable
+  char                contclasses[CONTSIZE]; // flags of possible continuing classes (twofold affix)
+  flag                flag_mode;
+  
+public:
+ 
+  AffixMgr(const char * affpath, HashMgr * ptr);
+  ~AffixMgr();
+  struct hentry *     affix_check(const char * word, int len,
+            const unsigned short needflag = (unsigned short) 0, char in_compound = IN_CPD_NOT);
+  struct hentry *     prefix_check(const char * word, int len,
+            char in_compound, const FLAG needflag = FLAG_NULL);
+  inline int isSubset(const char * s1, const char * s2);
+  struct hentry *     prefix_check_twosfx(const char * word, int len,
+            char in_compound, const FLAG needflag = FLAG_NULL);
+  inline int isRevSubset(const char * s1, const char * end_of_s2, int len);
+  struct hentry *     suffix_check(const char * word, int len, int sfxopts, AffEntry* ppfx,
+                        char ** wlst, int maxSug, int * ns, const FLAG cclass = FLAG_NULL,
+                        const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT);
+  struct hentry *     suffix_check_twosfx(const char * word, int len,
+            int sfxopts, AffEntry* ppfx, const FLAG needflag = FLAG_NULL);
+
+  char * affix_check_morph(const char * word, int len,
+                    const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT);
+  char * prefix_check_morph(const char * word, int len,
+                    char in_compound, const FLAG needflag = FLAG_NULL);
+  char * suffix_check_morph (const char * word, int len, int sfxopts, AffEntry * ppfx,
+            const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT);
+
+  char * prefix_check_twosfx_morph(const char * word, int len,
+            char in_compound, const FLAG needflag = FLAG_NULL);
+  char * suffix_check_twosfx_morph(const char * word, int len,
+            int sfxopts, AffEntry * ppfx, const FLAG needflag = FLAG_NULL);
+
+  int                 expand_rootword(struct guessword * wlst, int maxn, const char * ts,
+                        int wl, const unsigned short * ap, unsigned short al, char * bad, int,
+                        char *);
+
+  short               get_syllable (const char * word, int wlen);
+  int                 cpdrep_check(const char * word, int len);
+  int                 cpdpat_check(const char * word, int len);
+  int                 defcpd_check(hentry *** words, short wnum, hentry * rv, hentry ** rwords, char all);
+  int                 cpdcase_check(const char * word, int len);
+  inline int                 candidate_check(const char * word, int len);
+  struct hentry *     compound_check(const char * word, int len,
+                              short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words,
+                              char hu_mov_rule, int * cmpdstemnum, int * cmpdstem, char is_sug);
+
+  int compound_check_morph(const char * word, int len,
+                              short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words,
+                              char hu_mov_rule, char ** result, char * partresult);
+
+  struct hentry *     lookup(const char * word);
+  int                 get_numrep();
+  struct replentry *  get_reptable();
+  struct phonetable * get_phonetable();
+  int                 get_nummap();
+  struct mapentry *   get_maptable();
+  int                 get_numbreak();
+  char **             get_breaktable();
+  char *              get_encoding();
+  int                 get_langnum();
+  char *              get_key_string();
+  char *              get_try_string();
+  const char *        get_wordchars();
+  unsigned short *    get_wordchars_utf16(int * len);
+  char *              get_ignore();
+  unsigned short *    get_ignore_utf16(int * len);
+  int                 get_compound();
+  FLAG                get_compoundflag();
+  FLAG                get_compoundbegin();
+  FLAG                get_forbiddenword();
+  FLAG                get_nosuggest();
+//  FLAG                get_circumfix();
+  FLAG                get_pseudoroot();
+  FLAG                get_onlyincompound();
+  FLAG                get_compoundroot();
+  FLAG                get_lemma_present();
+  int                 get_checknum();
+  char *              get_possible_root();
+  const char *        get_prefix();
+  const char *        get_suffix();
+  const char *        get_derived();
+  const char *        get_version();
+  const int           have_contclass();
+  int                 get_utf8();
+  int                 get_complexprefixes();
+  char *              get_suffixed(char );
+  int                 get_maxngramsugs();
+  int                 get_nosplitsugs();
+  int                 get_sugswithdots(void);
+  FLAG                get_keepcase(void);
+  int                 get_checksharps(void);
+
+private:
+  int  parse_file(const char * affpath);
+//  int  parse_string(char * line, char ** out, const char * name);
+  int  parse_flag(char * line, unsigned short * out, const char * name);
+  int  parse_num(char * line, int * out, const char * name);
+//  int  parse_array(char * line, char ** out, unsigned short ** out_utf16,
+//            int * out_utf16_len, const char * name);
+  int  parse_cpdsyllable(char * line);
+  int  parse_reptable(char * line, FILE * af);
+  int  parse_phonetable(char * line, FILE * af);
+  int  parse_maptable(char * line, FILE * af);
+  int  parse_breaktable(char * line, FILE * af);
+  int  parse_checkcpdtable(char * line, FILE * af);
+  int  parse_defcpdtable(char * line, FILE * af);
+  int  parse_affix(char * line, const char at, FILE * af, char * dupflags);
+
+  int encodeit(struct affentry * ptr, char * cs);
+  int build_pfxtree(AffEntry* pfxptr);
+  int build_sfxtree(AffEntry* sfxptr);
+  int process_pfx_order();
+  int process_sfx_order();
+  AffEntry * process_pfx_in_order(AffEntry * ptr, AffEntry * nptr);
+  AffEntry * process_sfx_in_order(AffEntry * ptr, AffEntry * nptr);
+  int process_pfx_tree_to_list();
+  int process_sfx_tree_to_list();
+  int redundant_condition(char, char * strip, int stripl, const char * cond, char *);
+};
+
+#endif
+
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/atypes.hxx spellcheck/hunspell/hunspell/atypes.hxx
--- spellcheck.old/hunspell/hunspell/atypes.hxx	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/atypes.hxx	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,154 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef _ATYPES_HXX_
+#define _ATYPES_HXX_
+
+#ifndef HUNSPELL_WARNING
+#ifdef HUNSPELL_WARNING_ON
+#define HUNSPELL_WARNING fprintf
+#else
+// empty inline function to switch off warnings (instead of the C99 standard variadic macros)
+static inline void HUNSPELL_WARNING(FILE *, const char *, ...) {}
+#endif
+#endif
+
+// HUNSTEM def.
+#define HUNSTEM
+
+#include "csutil.hxx"
+#include "hashmgr.hxx"
+
+#define SETSIZE         256
+#define CONTSIZE        65536
+#define MAXWORDLEN      100
+#define MAXWORDUTF8LEN  256
+
+// affentry options
+#define aeXPRODUCT      (1 << 0)
+#define aeUTF8          (1 << 1)
+#define aeALIASF        (1 << 2)
+#define aeALIASM        (1 << 3)
+#define aeINFIX         (1 << 4)
+
+// compound options
+#define IN_CPD_NOT   0
+#define IN_CPD_BEGIN 1
+#define IN_CPD_END   2
+#define IN_CPD_OTHER 3
+
+#define MAXLNLEN        8192
+
+#define MINCPDLEN       3
+#define MAXCOMPOUND     10
+
+#define MAXACC          1000
+
+#define FLAG unsigned short
+#define FLAG_NULL 0x00
+#define FREE_FLAG(a) a = 0
+
+#define TESTAFF( a, b , c ) flag_bsearch((unsigned short *) a, (unsigned short) b, c)
+
+struct affentry
+{
+   char * strip;
+   char * appnd;
+   unsigned char stripl;
+   unsigned char appndl;
+   char  numconds;
+   char  opts;
+   unsigned short aflag;
+   union {
+        char   base[SETSIZE];
+        struct {
+                char ascii[SETSIZE/2];
+                char neg[8];
+                char all[8];
+                w_char * wchars[8];
+                int wlen[8];
+        } utf8;
+   } conds;
+#ifdef HUNSPELL_EXPERIMENTAL
+   char *       morphcode;
+#endif
+   unsigned short * contclass;
+   short        contclasslen;
+};
+
+struct mapentry {
+  char * set;
+  w_char * set_utf16;
+  int len;
+};
+
+struct flagentry {
+  FLAG * def;
+  int len;
+};
+
+struct guessword {
+  char * word;
+  bool allow;
+  char * orig;
+};
+
+#endif
+
+
+
+
+
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/baseaffix.hxx spellcheck/hunspell/hunspell/baseaffix.hxx
--- spellcheck.old/hunspell/hunspell/baseaffix.hxx	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/baseaffix.hxx	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,87 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef _BASEAFF_HXX_
+#define _BASEAFF_HXX_
+
+class AffEntry
+{
+public:
+
+protected:
+       char *       appnd;
+       char *       strip;
+       unsigned char  appndl;
+       unsigned char  stripl;
+       char         numconds;
+       char  opts;
+       unsigned short aflag;
+       union {
+         char   base[SETSIZE];
+         struct {
+                char  ascii[SETSIZE/2];
+                char neg[8];
+                char all[8];
+                w_char * wchars[8];
+                int wlen[8];
+         } utf8;
+       } conds;
+       char *       morphcode;
+       unsigned short * contclass;
+       short        contclasslen;
+};
+
+#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/csutil.cpp spellcheck/hunspell/hunspell/csutil.cpp
--- spellcheck.old/hunspell/hunspell/csutil.cpp	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/csutil.cpp	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,5400 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef MOZILLA_CLIENT
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+#include <cctype>
+#else
+#include <stdlib.h> 
+#include <string.h>
+#include <stdio.h> 
+#include <ctype.h>
+#endif
+
+#include "csutil.hxx"
+#include "atypes.hxx"
+#include "langnum.hxx"
+
+#ifdef OPENOFFICEORG
+#  include <unicode/uchar.h>
+#else
+#  ifndef MOZILLA_CLIENT
+#    include "utf_info.cxx"
+#    define UTF_LST_LEN (sizeof(utf_lst) / (sizeof(unicode_info)))
+#  endif
+#endif
+
+#ifdef MOZILLA_CLIENT
+#include "nsCOMPtr.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIUnicodeEncoder.h"
+#include "nsIUnicodeDecoder.h"
+#include "nsICaseConversion.h"
+#include "nsICharsetConverterManager.h"
+#include "nsUnicharUtilCIID.h"
+#include "nsUnicharUtils.h"
+
+static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
+static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
+#endif
+
+#ifdef MOZILLA_CLIENT
+#ifdef __SUNPRO_CC // for SunONE Studio compiler
+using namespace std;
+#endif
+#else
+#ifndef W32
+using namespace std;
+#endif
+#endif
+
+static struct unicode_info2 * utf_tbl = NULL;
+static int utf_tbl_count = 0; // utf_tbl can be used by multiple Hunspell instances
+
+/* only UTF-16 (BMP) implementation */
+char * u16_u8(char * dest, int size, const w_char * src, int srclen) {
+    char * u8 = dest;
+    char * u8_max = u8 + size;
+    const w_char * u2 = src;
+    const w_char * u2_max = src + srclen;
+    while ((u2 < u2_max) && (u8 < u8_max)) {
+        if (u2->h) { // > 0xFF
+            // XXX 4-byte haven't implemented yet.
+            if (u2->h >= 0x08) {   // >= 0x800 (3-byte UTF-8 character)
+                *u8 = 0xe0 + (u2->h >> 4);
+                u8++;
+                if (u8 < u8_max) {
+                    *u8 = 0x80 + ((u2->h & 0xf) << 2) + (u2->l >> 6);
+                    u8++;
+                    if (u8 < u8_max) {
+                        *u8 = 0x80 + (u2->l & 0x3f);
+                        u8++;
+                    }
+                }
+            } else { // < 0x800 (2-byte UTF-8 character)
+                *u8 = 0xc0 + (u2->h << 2) + (u2->l >> 6);
+                u8++;
+                if (u8 < u8_max) {
+                    *u8 = 0x80 + (u2->l & 0x3f);
+                    u8++;
+                }
+            }
+        } else { // <= 0xFF
+            if (u2->l & 0x80) { // >0x80 (2-byte UTF-8 character)
+                *u8 = 0xc0 + (u2->l >> 6);
+                u8++;
+                if (u8 < u8_max) {
+                    *u8 = 0x80 + (u2->l & 0x3f);
+                    u8++;
+                }
+            } else { // < 0x80 (1-byte UTF-8 character)
+                *u8 = u2->l;
+                u8++;
+            }
+        }
+        u2++;
+    }
+    *u8 = '\0';
+    return dest;
+}
+
+
+/* only UTF-16 (BMP) implementation */
+int u8_u16(w_char * dest, int size, const char * src) {
+    const char * u8 = src;
+    w_char * u2 = dest;
+    w_char * u2_max = u2 + size;
+    
+    while ((u2 < u2_max) && *u8) {
+    switch ((*u8) & 0xf0) {
+        case 0x00:
+        case 0x10:
+        case 0x20:
+        case 0x30:
+        case 0x40:
+        case 0x50:
+        case 0x60:
+        case 0x70: {
+            u2->h = 0;
+            u2->l = *u8;
+            break;
+        }
+        case 0x80:
+        case 0x90:
+        case 0xa0:
+        case 0xb0: {
+            HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Unexpected continuation bytes in %d. character position\n%s\n", u8 - src, src);    
+            u2->h = 0xff;
+            u2->l = 0xfd;
+            break;
+        }
+        case 0xc0:
+        case 0xd0: {    // 2-byte UTF-8 codes
+            if ((*(u8+1) & 0xc0) == 0x80) {
+                u2->h = (*u8 & 0x1f) >> 2;
+                u2->l = (*u8 << 6) + (*(u8+1) & 0x3f);
+                u8++;
+            } else {
+                HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %d. character position:\n%s\n", u8 - src, src);
+                u2->h = 0xff;
+                u2->l = 0xfd;
+            }
+            break;
+        }
+        case 0xe0: {    // 3-byte UTF-8 codes
+            if ((*(u8+1) & 0xc0) == 0x80) {
+                u2->h = ((*u8 & 0x0f) << 4) + ((*(u8+1) & 0x3f) >> 2);
+                u8++;
+                if ((*(u8+1) & 0xc0) == 0x80) {
+                    u2->l = (*u8 << 6) + (*(u8+1) & 0x3f);
+                    u8++;
+                } else {
+                    HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %d. character position:\n%s\n", u8 - src, src);
+                    u2->h = 0xff;
+                    u2->l = 0xfd;
+                }
+            } else {
+                HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %d. character position:\n%s\n", u8 - src, src);
+                u2->h = 0xff;
+                u2->l = 0xfd;
+            }
+            break;
+        }
+        case 0xf0: {    // 4 or more byte UTF-8 codes
+            HUNSPELL_WARNING(stderr, "This UTF-8 encoding can't convert to UTF-16:\n%s\n", src);
+            u2->h = 0xff;
+            u2->l = 0xfd;
+            return -1;
+        }
+    }
+    u8++;
+    u2++;
+    }
+    return u2 - dest;
+}
+
+void flag_qsort(unsigned short flags[], int begin, int end) {
+    unsigned short reg;
+    if (end > begin) {
+        unsigned short pivot = flags[begin];
+        int l = begin + 1;
+        int r = end;
+        while(l < r) {
+            if (flags[l] <= pivot) {
+                l++;
+            } else {
+             r--;
+             reg = flags[l];
+             flags[l] = flags[r];
+             flags[r] = reg;
+          }
+       }
+       l--;
+       reg = flags[begin];
+       flags[begin] = flags[l];
+       flags[l] = reg;
+
+       flag_qsort(flags, begin, l);
+       flag_qsort(flags, r, end);
+    }
+ }
+
+int flag_bsearch(unsigned short flags[], unsigned short flag, int length) {
+   int mid;
+   int left = 0;
+   int right = length - 1;
+   while (left <= right) {
+      mid = (left + right) / 2;
+      if (flags[mid] == flag) return 1;
+      if (flag < flags[mid]) right = mid - 1;
+      else left = mid + 1;
+   }
+   return 0;
+}
+
+ // strip strings into token based on single char delimiter
+ // acts like strsep() but only uses a delim char and not
+ // a delim string
+ // default delimiter: white space characters
+ 
+ char * mystrsep(char ** stringp, const char delim)
+ {
+   char * rv = NULL;
+   char * mp = *stringp;
+   int n = strlen(mp);
+   if (n > 0) {
+      char * dp;
+      if (delim) {
+        dp = (char *)memchr(mp,(int)((unsigned char)delim),n);
+      } else {
+        // don't use isspace() here, the string can be in some random charset
+        // that's way different than the locale's
+        for (dp = mp; (*dp && *dp != ' ' && *dp != '\t'); dp++);
+        if (!*dp) dp = NULL;
+      }
+      if (dp) {
+         *stringp = dp+1;
+         int nc = (int)((unsigned long)dp - (unsigned long)mp);
+         rv = (char *) malloc(nc+1);
+	 if (rv) {
+            memcpy(rv,mp,nc);
+            *(rv+nc) = '\0';
+            return rv;
+	 }
+      } else {
+         rv = (char *) malloc(n+1);
+         if (rv) {
+    	    memcpy(rv, mp, n);
+            *(rv+n) = '\0';
+            *stringp = mp + n;
+            return rv;
+         }
+      }
+   }
+   return NULL;
+ }
+
+ 
+ // replaces strdup with ansi version
+ char * mystrdup(const char * s)
+ {
+   char * d = NULL;
+   if (s) {
+      int sl = strlen(s);
+      d = (char *) malloc(((sl+1) * sizeof(char)));
+      if (d) memcpy(d,s,((sl+1)*sizeof(char)));
+   }
+   return d;
+ }
+ 
+ 
+ // remove cross-platform text line end characters
+ void mychomp(char * s)
+ {
+   int k = strlen(s);
+   if ((k > 0) && ((*(s+k-1)=='\r') || (*(s+k-1)=='\n'))) *(s+k-1) = '\0';
+   if ((k > 1) && (*(s+k-2) == '\r')) *(s+k-2) = '\0';
+ }
+ 
+ 
+ //  does an ansi strdup of the reverse of a string
+ char * myrevstrdup(const char * s)
+ {
+     char * d = NULL;
+     if (s) {
+        int sl = strlen(s);
+        d = (char *) malloc((sl+1) * sizeof(char));
+        if (d) {
+          const char * p = s + sl - 1;
+          char * q = d;
+          while (p >= s) *q++ = *p--;
+          *q = '\0';
+        }
+     }
+     return d;
+ }
+
+#ifdef HUNSPELL_EXPERIMENTAL
+ // append s to ends of every lines in text
+ void strlinecat(char * dest, const char * s)
+ {
+    char * dup = mystrdup(dest);
+    char * source = dup;
+    int len = strlen(s);
+    while (*source) {
+        if (*source == '\n') {
+            strncpy(dest, s, len);
+            dest += len;
+        }
+        *dest = *source;
+        source++; dest++;
+    }
+    strcpy(dest, s);
+    free(dup);
+ }
+
+// break text to lines
+// return number of lines
+int line_tok(const char * text, char *** lines) {
+    int linenum = 0;
+    char * dup = mystrdup(text);
+    char * p = strchr(dup, '\n');
+    while (p) {
+        linenum++;
+        *p = '\0';
+        p++;
+        p = strchr(p, '\n');
+    }
+    *lines = (char **) calloc(linenum + 1, sizeof(char *));
+    if (!(*lines)) return -1;
+
+    p = dup; 
+    for (int i = 0; i < linenum + 1; i++) {
+        (*lines)[i] = mystrdup(p);
+        p += strlen(p) + 1;
+    }
+    free(dup);
+    return linenum;
+}
+
+// uniq line in place
+char * line_uniq(char * text) {
+    char ** lines;
+    int linenum = line_tok(text, &lines);
+    int i;
+    strcpy(text, lines[0]);
+    for ( i = 1; i<=linenum; i++ ) {
+        int dup = 0;
+        for (int j = 0; j < i; j++) {
+            if (strcmp(lines[i], lines[j]) == 0) dup = 1;
+        }
+        if (!dup) {
+            if ((i > 1) || (*(lines[0]) != '\0')) strcat(text, "\n");
+            strcat(text, lines[i]);
+        }
+    }
+    for ( i = 0; i<=linenum; i++ ) {
+        if (lines[i]) free(lines[i]);
+    }
+    if (lines) free(lines);
+    return text;
+}
+
+// change \n to char c
+char * line_join(char * text, char c) {
+    char * p;
+    for (p = text; *p; p++) if (*p == '\n') *p = c;
+    return text;
+}
+
+// leave only last {[^}]*} substring for handling zero morphemes
+char * delete_zeros(char * morphout) {
+    char * p = morphout;
+    char * q = p;
+    char * q2 = NULL;
+    int suffix = 0;
+    
+    for (;*p && *(p+1);) {
+        switch (*p) {
+            case '{': 
+                q2 = q;
+                q--;
+                break;
+            case '}':
+                if (q2) {
+                    suffix = 1;
+                    q--;
+                }
+                break; 
+            default:
+                if (suffix) {
+                    q = q2;
+                }
+                suffix = 0;
+                *q = *p;
+        }
+        p++;
+        q++;
+    }
+    *q = '\0';
+    return morphout;
+}
+#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+
+char * mystrrep(char * word, const char * pat, const char * rep) {
+    char * pos = strstr(word, pat);
+    if (pos) {
+        int replen = strlen(rep);
+        int patlen = strlen(pat);
+        if (replen < patlen) {
+            char * end = word + strlen(word);
+            char * next = pos + replen;
+            char * prev = pos + strlen(pat);
+            for (; prev < end; *next = *prev, prev++, next++);
+            *next = '\0';
+        } else if (replen > patlen) {
+            char * end = pos + patlen;
+            char * next = word + strlen(word) + replen - patlen;
+            char * prev = next - replen + patlen;
+            for (; prev >= end; *next = *prev, prev--, next--);
+        }
+        strncpy(pos, rep, replen);
+    }
+    return word;
+}
+
+ // reverse word 
+ int reverseword(char * word) {
+   char r;
+   for (char * dest = word + strlen(word) - 1; word < dest; word++, dest--) {
+     r=*word;
+     *word = *dest;
+     *dest = r;
+   }
+   return 0;
+ }
+
+ // reverse word (error: 1)
+ int reverseword_utf(char * word) {
+   w_char w[MAXWORDLEN];
+   w_char * p;
+   w_char r;
+   int l = u8_u16(w, MAXWORDLEN, word);
+   if (l == -1) return 1;
+   p = w;
+   for (w_char * dest = w + l - 1; p < dest; p++, dest--) {
+     r=*p;
+     *p = *dest;
+     *dest = r;
+   }
+   u16_u8(word, MAXWORDUTF8LEN, w, l);
+   return 0;
+ }
+ 
+ // convert null terminated string to all caps
+ void mkallcap(char * p, const struct cs_info * csconv)
+ {
+   while (*p != '\0') {
+     *p = csconv[((unsigned char) *p)].cupper;
+     p++;
+   }
+ }
+  
+ // convert null terminated string to all little
+ void mkallsmall(char * p, const struct cs_info * csconv)
+ {
+   while (*p != '\0') {
+     *p = csconv[((unsigned char) *p)].clower;
+     p++;
+   }
+ }
+
+void mkallsmall_utf(w_char * u, int nc, int langnum) {
+    for (int i = 0; i < nc; i++) {
+        unsigned short idx = (u[i].h << 8) + u[i].l;
+        if (idx != unicodetolower(idx, langnum)) {
+            u[i].h = (unsigned char) (unicodetolower(idx, langnum) >> 8);
+            u[i].l = (unsigned char) (unicodetolower(idx, langnum) & 0x00FF);
+        }
+    }
+}
+
+void mkallcap_utf(w_char * u, int nc, int langnum) {
+    for (int i = 0; i < nc; i++) {
+        unsigned short idx = (u[i].h << 8) + u[i].l;
+        if (idx != unicodetoupper(idx, langnum)) {
+            u[i].h = (unsigned char) (unicodetoupper(idx, langnum) >> 8);
+            u[i].l = (unsigned char) (unicodetoupper(idx, langnum) & 0x00FF);
+        }
+    }
+}
+ 
+ // convert null terminated string to have intial capital
+ void mkinitcap(char * p, const struct cs_info * csconv)
+ {
+   if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper;
+ }
+
+#ifndef MOZILLA_CLIENT
+ // convert null terminated string to all caps using encoding
+ void enmkallcap(char * d, const char * p, const char * encoding)
+ 
+ {
+   struct cs_info * csconv = get_current_cs(encoding);
+   while (*p != '\0') {
+     *d++ = csconv[((unsigned char) *p)].cupper;
+     p++;
+   }
+   *d = '\0';
+ }
+
+ // convert null terminated string to all little using encoding
+ void enmkallsmall(char * d, const char * p, const char * encoding)
+ {
+   struct cs_info * csconv = get_current_cs(encoding);
+   while (*p != '\0') {
+     *d++ = csconv[((unsigned char) *p)].clower;
+     p++;
+   }
+   *d = '\0';
+ }
+
+ // convert null terminated string to have intial capital using encoding
+ void enmkinitcap(char * d, const char * p, const char * encoding)
+ {
+   struct cs_info * csconv = get_current_cs(encoding);
+   memcpy(d,p,(strlen(p)+1));
+   if (*p != '\0') *d= csconv[((unsigned char)*p)].cupper;
+ }
+
+// these are simple character mappings for the 
+// encodings supported
+// supplying isupper, tolower, and toupper
+
+struct cs_info iso1_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x00, 0xa1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x00, 0xa3, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x00, 0xa5, 0xa5 },
+{ 0x00, 0xa6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa8 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x00, 0xaa, 0xaa },
+{ 0x00, 0xab, 0xab },
+{ 0x00, 0xac, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x00, 0xaf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xb1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x00, 0xb3, 0xb3 },
+{ 0x00, 0xb4, 0xb4 },
+{ 0x00, 0xb5, 0xb5 },
+{ 0x00, 0xb6, 0xb6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xb8 },
+{ 0x00, 0xb9, 0xb9 },
+{ 0x00, 0xba, 0xba },
+{ 0x00, 0xbb, 0xbb },
+{ 0x00, 0xbc, 0xbc },
+{ 0x00, 0xbd, 0xbd },
+{ 0x00, 0xbe, 0xbe },
+{ 0x00, 0xbf, 0xbf },
+{ 0x01, 0xe0, 0xc0 },
+{ 0x01, 0xe1, 0xc1 },
+{ 0x01, 0xe2, 0xc2 },
+{ 0x01, 0xe3, 0xc3 },
+{ 0x01, 0xe4, 0xc4 },
+{ 0x01, 0xe5, 0xc5 },
+{ 0x01, 0xe6, 0xc6 },
+{ 0x01, 0xe7, 0xc7 },
+{ 0x01, 0xe8, 0xc8 },
+{ 0x01, 0xe9, 0xc9 },
+{ 0x01, 0xea, 0xca },
+{ 0x01, 0xeb, 0xcb },
+{ 0x01, 0xec, 0xcc },
+{ 0x01, 0xed, 0xcd },
+{ 0x01, 0xee, 0xce },
+{ 0x01, 0xef, 0xcf },
+{ 0x01, 0xf0, 0xd0 },
+{ 0x01, 0xf1, 0xd1 },
+{ 0x01, 0xf2, 0xd2 },
+{ 0x01, 0xf3, 0xd3 },
+{ 0x01, 0xf4, 0xd4 },
+{ 0x01, 0xf5, 0xd5 },
+{ 0x01, 0xf6, 0xd6 },
+{ 0x00, 0xd7, 0xd7 },
+{ 0x01, 0xf8, 0xd8 },
+{ 0x01, 0xf9, 0xd9 },
+{ 0x01, 0xfa, 0xda },
+{ 0x01, 0xfb, 0xdb },
+{ 0x01, 0xfc, 0xdc },
+{ 0x01, 0xfd, 0xdd },
+{ 0x01, 0xfe, 0xde },
+{ 0x00, 0xdf, 0xdf },
+{ 0x00, 0xe0, 0xc0 },
+{ 0x00, 0xe1, 0xc1 },
+{ 0x00, 0xe2, 0xc2 },
+{ 0x00, 0xe3, 0xc3 },
+{ 0x00, 0xe4, 0xc4 },
+{ 0x00, 0xe5, 0xc5 },
+{ 0x00, 0xe6, 0xc6 },
+{ 0x00, 0xe7, 0xc7 },
+{ 0x00, 0xe8, 0xc8 },
+{ 0x00, 0xe9, 0xc9 },
+{ 0x00, 0xea, 0xca },
+{ 0x00, 0xeb, 0xcb },
+{ 0x00, 0xec, 0xcc },
+{ 0x00, 0xed, 0xcd },
+{ 0x00, 0xee, 0xce },
+{ 0x00, 0xef, 0xcf },
+{ 0x00, 0xf0, 0xd0 },
+{ 0x00, 0xf1, 0xd1 },
+{ 0x00, 0xf2, 0xd2 },
+{ 0x00, 0xf3, 0xd3 },
+{ 0x00, 0xf4, 0xd4 },
+{ 0x00, 0xf5, 0xd5 },
+{ 0x00, 0xf6, 0xd6 },
+{ 0x00, 0xf7, 0xf7 },
+{ 0x00, 0xf8, 0xd8 },
+{ 0x00, 0xf9, 0xd9 },
+{ 0x00, 0xfa, 0xda },
+{ 0x00, 0xfb, 0xdb },
+{ 0x00, 0xfc, 0xdc },
+{ 0x00, 0xfd, 0xdd },
+{ 0x00, 0xfe, 0xde },
+{ 0x00, 0xff, 0xff },
+};
+
+
+struct cs_info iso2_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x01, 0xb1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x01, 0xb3, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x01, 0xb5, 0xa5 },
+{ 0x01, 0xb6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa8 },
+{ 0x01, 0xb9, 0xa9 },
+{ 0x01, 0xba, 0xaa },
+{ 0x01, 0xbb, 0xab },
+{ 0x01, 0xbc, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x01, 0xbe, 0xae },
+{ 0x01, 0xbf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xa1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x00, 0xb3, 0xa3 },
+{ 0x00, 0xb4, 0xb4 },
+{ 0x00, 0xb5, 0xa5 },
+{ 0x00, 0xb6, 0xa6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xb8 },
+{ 0x00, 0xb9, 0xa9 },
+{ 0x00, 0xba, 0xaa },
+{ 0x00, 0xbb, 0xab },
+{ 0x00, 0xbc, 0xac },
+{ 0x00, 0xbd, 0xbd },
+{ 0x00, 0xbe, 0xae },
+{ 0x00, 0xbf, 0xaf },
+{ 0x01, 0xe0, 0xc0 },
+{ 0x01, 0xe1, 0xc1 },
+{ 0x01, 0xe2, 0xc2 },
+{ 0x01, 0xe3, 0xc3 },
+{ 0x01, 0xe4, 0xc4 },
+{ 0x01, 0xe5, 0xc5 },
+{ 0x01, 0xe6, 0xc6 },
+{ 0x01, 0xe7, 0xc7 },
+{ 0x01, 0xe8, 0xc8 },
+{ 0x01, 0xe9, 0xc9 },
+{ 0x01, 0xea, 0xca },
+{ 0x01, 0xeb, 0xcb },
+{ 0x01, 0xec, 0xcc },
+{ 0x01, 0xed, 0xcd },
+{ 0x01, 0xee, 0xce },
+{ 0x01, 0xef, 0xcf },
+{ 0x01, 0xf0, 0xd0 },
+{ 0x01, 0xf1, 0xd1 },
+{ 0x01, 0xf2, 0xd2 },
+{ 0x01, 0xf3, 0xd3 },
+{ 0x01, 0xf4, 0xd4 },
+{ 0x01, 0xf5, 0xd5 },
+{ 0x01, 0xf6, 0xd6 },
+{ 0x00, 0xd7, 0xd7 },
+{ 0x01, 0xf8, 0xd8 },
+{ 0x01, 0xf9, 0xd9 },
+{ 0x01, 0xfa, 0xda },
+{ 0x01, 0xfb, 0xdb },
+{ 0x01, 0xfc, 0xdc },
+{ 0x01, 0xfd, 0xdd },
+{ 0x01, 0xfe, 0xde },
+{ 0x00, 0xdf, 0xdf },
+{ 0x00, 0xe0, 0xc0 },
+{ 0x00, 0xe1, 0xc1 },
+{ 0x00, 0xe2, 0xc2 },
+{ 0x00, 0xe3, 0xc3 },
+{ 0x00, 0xe4, 0xc4 },
+{ 0x00, 0xe5, 0xc5 },
+{ 0x00, 0xe6, 0xc6 },
+{ 0x00, 0xe7, 0xc7 },
+{ 0x00, 0xe8, 0xc8 },
+{ 0x00, 0xe9, 0xc9 },
+{ 0x00, 0xea, 0xca },
+{ 0x00, 0xeb, 0xcb },
+{ 0x00, 0xec, 0xcc },
+{ 0x00, 0xed, 0xcd },
+{ 0x00, 0xee, 0xce },
+{ 0x00, 0xef, 0xcf },
+{ 0x00, 0xf0, 0xd0 },
+{ 0x00, 0xf1, 0xd1 },
+{ 0x00, 0xf2, 0xd2 },
+{ 0x00, 0xf3, 0xd3 },
+{ 0x00, 0xf4, 0xd4 },
+{ 0x00, 0xf5, 0xd5 },
+{ 0x00, 0xf6, 0xd6 },
+{ 0x00, 0xf7, 0xf7 },
+{ 0x00, 0xf8, 0xd8 },
+{ 0x00, 0xf9, 0xd9 },
+{ 0x00, 0xfa, 0xda },
+{ 0x00, 0xfb, 0xdb },
+{ 0x00, 0xfc, 0xdc },
+{ 0x00, 0xfd, 0xdd },
+{ 0x00, 0xfe, 0xde },
+{ 0x00, 0xff, 0xff },
+};
+
+
+struct cs_info iso3_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x01, 0xb1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x00, 0xa3, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x00, 0xa5, 0xa5 },
+{ 0x01, 0xb6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa8 },
+{ 0x01, 0x69, 0xa9 },
+{ 0x01, 0xba, 0xaa },
+{ 0x01, 0xbb, 0xab },
+{ 0x01, 0xbc, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x01, 0xbf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xa1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x00, 0xb3, 0xb3 },
+{ 0x00, 0xb4, 0xb4 },
+{ 0x00, 0xb5, 0xb5 },
+{ 0x00, 0xb6, 0xa6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xb8 },
+{ 0x00, 0xb9, 0x49 },
+{ 0x00, 0xba, 0xaa },
+{ 0x00, 0xbb, 0xab },
+{ 0x00, 0xbc, 0xac },
+{ 0x00, 0xbd, 0xbd },
+{ 0x00, 0xbe, 0xbe },
+{ 0x00, 0xbf, 0xaf },
+{ 0x01, 0xe0, 0xc0 },
+{ 0x01, 0xe1, 0xc1 },
+{ 0x01, 0xe2, 0xc2 },
+{ 0x00, 0xc3, 0xc3 },
+{ 0x01, 0xe4, 0xc4 },
+{ 0x01, 0xe5, 0xc5 },
+{ 0x01, 0xe6, 0xc6 },
+{ 0x01, 0xe7, 0xc7 },
+{ 0x01, 0xe8, 0xc8 },
+{ 0x01, 0xe9, 0xc9 },
+{ 0x01, 0xea, 0xca },
+{ 0x01, 0xeb, 0xcb },
+{ 0x01, 0xec, 0xcc },
+{ 0x01, 0xed, 0xcd },
+{ 0x01, 0xee, 0xce },
+{ 0x01, 0xef, 0xcf },
+{ 0x00, 0xd0, 0xd0 },
+{ 0x01, 0xf1, 0xd1 },
+{ 0x01, 0xf2, 0xd2 },
+{ 0x01, 0xf3, 0xd3 },
+{ 0x01, 0xf4, 0xd4 },
+{ 0x01, 0xf5, 0xd5 },
+{ 0x01, 0xf6, 0xd6 },
+{ 0x00, 0xd7, 0xd7 },
+{ 0x01, 0xf8, 0xd8 },
+{ 0x01, 0xf9, 0xd9 },
+{ 0x01, 0xfa, 0xda },
+{ 0x01, 0xfb, 0xdb },
+{ 0x01, 0xfc, 0xdc },
+{ 0x01, 0xfd, 0xdd },
+{ 0x01, 0xfe, 0xde },
+{ 0x00, 0xdf, 0xdf },
+{ 0x00, 0xe0, 0xc0 },
+{ 0x00, 0xe1, 0xc1 },
+{ 0x00, 0xe2, 0xc2 },
+{ 0x00, 0xe3, 0xe3 },
+{ 0x00, 0xe4, 0xc4 },
+{ 0x00, 0xe5, 0xc5 },
+{ 0x00, 0xe6, 0xc6 },
+{ 0x00, 0xe7, 0xc7 },
+{ 0x00, 0xe8, 0xc8 },
+{ 0x00, 0xe9, 0xc9 },
+{ 0x00, 0xea, 0xca },
+{ 0x00, 0xeb, 0xcb },
+{ 0x00, 0xec, 0xcc },
+{ 0x00, 0xed, 0xcd },
+{ 0x00, 0xee, 0xce },
+{ 0x00, 0xef, 0xcf },
+{ 0x00, 0xf0, 0xf0 },
+{ 0x00, 0xf1, 0xd1 },
+{ 0x00, 0xf2, 0xd2 },
+{ 0x00, 0xf3, 0xd3 },
+{ 0x00, 0xf4, 0xd4 },
+{ 0x00, 0xf5, 0xd5 },
+{ 0x00, 0xf6, 0xd6 },
+{ 0x00, 0xf7, 0xf7 },
+{ 0x00, 0xf8, 0xd8 },
+{ 0x00, 0xf9, 0xd9 },
+{ 0x00, 0xfa, 0xda },
+{ 0x00, 0xfb, 0xdb },
+{ 0x00, 0xfc, 0xdc },
+{ 0x00, 0xfd, 0xdd },
+{ 0x00, 0xfe, 0xde },
+{ 0x00, 0xff, 0xff },
+};
+
+struct cs_info iso4_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x01, 0xb1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x01, 0xb3, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x01, 0xb5, 0xa5 },
+{ 0x01, 0xb6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa8 },
+{ 0x01, 0xb9, 0xa9 },
+{ 0x01, 0xba, 0xaa },
+{ 0x01, 0xbb, 0xab },
+{ 0x01, 0xbc, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x01, 0xbe, 0xae },
+{ 0x00, 0xaf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xa1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x00, 0xb3, 0xa3 },
+{ 0x00, 0xb4, 0xb4 },
+{ 0x00, 0xb5, 0xa5 },
+{ 0x00, 0xb6, 0xa6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xb8 },
+{ 0x00, 0xb9, 0xa9 },
+{ 0x00, 0xba, 0xaa },
+{ 0x00, 0xbb, 0xab },
+{ 0x00, 0xbc, 0xac },
+{ 0x00, 0xbd, 0xbd },
+{ 0x00, 0xbe, 0xae },
+{ 0x00, 0xbf, 0xbf },
+{ 0x01, 0xe0, 0xc0 },
+{ 0x01, 0xe1, 0xc1 },
+{ 0x01, 0xe2, 0xc2 },
+{ 0x01, 0xe3, 0xc3 },
+{ 0x01, 0xe4, 0xc4 },
+{ 0x01, 0xe5, 0xc5 },
+{ 0x01, 0xe6, 0xc6 },
+{ 0x01, 0xe7, 0xc7 },
+{ 0x01, 0xe8, 0xc8 },
+{ 0x01, 0xe9, 0xc9 },
+{ 0x01, 0xea, 0xca },
+{ 0x01, 0xeb, 0xcb },
+{ 0x01, 0xec, 0xcc },
+{ 0x01, 0xed, 0xcd },
+{ 0x01, 0xee, 0xce },
+{ 0x01, 0xef, 0xcf },
+{ 0x01, 0xf0, 0xd0 },
+{ 0x01, 0xf1, 0xd1 },
+{ 0x01, 0xf2, 0xd2 },
+{ 0x01, 0xf3, 0xd3 },
+{ 0x01, 0xf4, 0xd4 },
+{ 0x01, 0xf5, 0xd5 },
+{ 0x01, 0xf6, 0xd6 },
+{ 0x00, 0xd7, 0xd7 },
+{ 0x01, 0xf8, 0xd8 },
+{ 0x01, 0xf9, 0xd9 },
+{ 0x01, 0xfa, 0xda },
+{ 0x01, 0xfb, 0xdb },
+{ 0x01, 0xfc, 0xdc },
+{ 0x01, 0xfd, 0xdd },
+{ 0x01, 0xfe, 0xde },
+{ 0x00, 0xdf, 0xdf },
+{ 0x00, 0xe0, 0xc0 },
+{ 0x00, 0xe1, 0xc1 },
+{ 0x00, 0xe2, 0xc2 },
+{ 0x00, 0xe3, 0xc3 },
+{ 0x00, 0xe4, 0xc4 },
+{ 0x00, 0xe5, 0xc5 },
+{ 0x00, 0xe6, 0xc6 },
+{ 0x00, 0xe7, 0xc7 },
+{ 0x00, 0xe8, 0xc8 },
+{ 0x00, 0xe9, 0xc9 },
+{ 0x00, 0xea, 0xca },
+{ 0x00, 0xeb, 0xcb },
+{ 0x00, 0xec, 0xcc },
+{ 0x00, 0xed, 0xcd },
+{ 0x00, 0xee, 0xce },
+{ 0x00, 0xef, 0xcf },
+{ 0x00, 0xf0, 0xd0 },
+{ 0x00, 0xf1, 0xd1 },
+{ 0x00, 0xf2, 0xd2 },
+{ 0x00, 0xf3, 0xd3 },
+{ 0x00, 0xf4, 0xd4 },
+{ 0x00, 0xf5, 0xd5 },
+{ 0x00, 0xf6, 0xd6 },
+{ 0x00, 0xf7, 0xf7 },
+{ 0x00, 0xf8, 0xd8 },
+{ 0x00, 0xf9, 0xd9 },
+{ 0x00, 0xfa, 0xda },
+{ 0x00, 0xfb, 0xdb },
+{ 0x00, 0xfc, 0xdc },
+{ 0x00, 0xfd, 0xdd },
+{ 0x00, 0xfe, 0xde },
+{ 0x00, 0xff, 0xff },
+};
+
+struct cs_info iso5_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x01, 0xf1, 0xa1 },
+{ 0x01, 0xf2, 0xa2 },
+{ 0x01, 0xf3, 0xa3 },
+{ 0x01, 0xf4, 0xa4 },
+{ 0x01, 0xf5, 0xa5 },
+{ 0x01, 0xf6, 0xa6 },
+{ 0x01, 0xf7, 0xa7 },
+{ 0x01, 0xf8, 0xa8 },
+{ 0x01, 0xf9, 0xa9 },
+{ 0x01, 0xfa, 0xaa },
+{ 0x01, 0xfb, 0xab },
+{ 0x01, 0xfc, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x01, 0xfe, 0xae },
+{ 0x01, 0xff, 0xaf },
+{ 0x01, 0xd0, 0xb0 },
+{ 0x01, 0xd1, 0xb1 },
+{ 0x01, 0xd2, 0xb2 },
+{ 0x01, 0xd3, 0xb3 },
+{ 0x01, 0xd4, 0xb4 },
+{ 0x01, 0xd5, 0xb5 },
+{ 0x01, 0xd6, 0xb6 },
+{ 0x01, 0xd7, 0xb7 },
+{ 0x01, 0xd8, 0xb8 },
+{ 0x01, 0xd9, 0xb9 },
+{ 0x01, 0xda, 0xba },
+{ 0x01, 0xdb, 0xbb },
+{ 0x01, 0xdc, 0xbc },
+{ 0x01, 0xdd, 0xbd },
+{ 0x01, 0xde, 0xbe },
+{ 0x01, 0xdf, 0xbf },
+{ 0x01, 0xe0, 0xc0 },
+{ 0x01, 0xe1, 0xc1 },
+{ 0x01, 0xe2, 0xc2 },
+{ 0x01, 0xe3, 0xc3 },
+{ 0x01, 0xe4, 0xc4 },
+{ 0x01, 0xe5, 0xc5 },
+{ 0x01, 0xe6, 0xc6 },
+{ 0x01, 0xe7, 0xc7 },
+{ 0x01, 0xe8, 0xc8 },
+{ 0x01, 0xe9, 0xc9 },
+{ 0x01, 0xea, 0xca },
+{ 0x01, 0xeb, 0xcb },
+{ 0x01, 0xec, 0xcc },
+{ 0x01, 0xed, 0xcd },
+{ 0x01, 0xee, 0xce },
+{ 0x01, 0xef, 0xcf },
+{ 0x00, 0xd0, 0xb0 },
+{ 0x00, 0xd1, 0xb1 },
+{ 0x00, 0xd2, 0xb2 },
+{ 0x00, 0xd3, 0xb3 },
+{ 0x00, 0xd4, 0xb4 },
+{ 0x00, 0xd5, 0xb5 },
+{ 0x00, 0xd6, 0xb6 },
+{ 0x00, 0xd7, 0xb7 },
+{ 0x00, 0xd8, 0xb8 },
+{ 0x00, 0xd9, 0xb9 },
+{ 0x00, 0xda, 0xba },
+{ 0x00, 0xdb, 0xbb },
+{ 0x00, 0xdc, 0xbc },
+{ 0x00, 0xdd, 0xbd },
+{ 0x00, 0xde, 0xbe },
+{ 0x00, 0xdf, 0xbf },
+{ 0x00, 0xe0, 0xc0 },
+{ 0x00, 0xe1, 0xc1 },
+{ 0x00, 0xe2, 0xc2 },
+{ 0x00, 0xe3, 0xc3 },
+{ 0x00, 0xe4, 0xc4 },
+{ 0x00, 0xe5, 0xc5 },
+{ 0x00, 0xe6, 0xc6 },
+{ 0x00, 0xe7, 0xc7 },
+{ 0x00, 0xe8, 0xc8 },
+{ 0x00, 0xe9, 0xc9 },
+{ 0x00, 0xea, 0xca },
+{ 0x00, 0xeb, 0xcb },
+{ 0x00, 0xec, 0xcc },
+{ 0x00, 0xed, 0xcd },
+{ 0x00, 0xee, 0xce },
+{ 0x00, 0xef, 0xcf },
+{ 0x00, 0xf0, 0xf0 },
+{ 0x00, 0xf1, 0xa1 },
+{ 0x00, 0xf2, 0xa2 },
+{ 0x00, 0xf3, 0xa3 },
+{ 0x00, 0xf4, 0xa4 },
+{ 0x00, 0xf5, 0xa5 },
+{ 0x00, 0xf6, 0xa6 },
+{ 0x00, 0xf7, 0xa7 },
+{ 0x00, 0xf8, 0xa8 },
+{ 0x00, 0xf9, 0xa9 },
+{ 0x00, 0xfa, 0xaa },
+{ 0x00, 0xfb, 0xab },
+{ 0x00, 0xfc, 0xac },
+{ 0x00, 0xfd, 0xfd },
+{ 0x00, 0xfe, 0xae },
+{ 0x00, 0xff, 0xaf },
+};
+
+struct cs_info iso6_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x00, 0xa1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x00, 0xa3, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x00, 0xa5, 0xa5 },
+{ 0x00, 0xa6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa8 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x00, 0xaa, 0xaa },
+{ 0x00, 0xab, 0xab },
+{ 0x00, 0xac, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x00, 0xaf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xb1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x00, 0xb3, 0xb3 },
+{ 0x00, 0xb4, 0xb4 },
+{ 0x00, 0xb5, 0xb5 },
+{ 0x00, 0xb6, 0xb6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xb8 },
+{ 0x00, 0xb9, 0xb9 },
+{ 0x00, 0xba, 0xba },
+{ 0x00, 0xbb, 0xbb },
+{ 0x00, 0xbc, 0xbc },
+{ 0x00, 0xbd, 0xbd },
+{ 0x00, 0xbe, 0xbe },
+{ 0x00, 0xbf, 0xbf },
+{ 0x00, 0xc0, 0xc0 },
+{ 0x00, 0xc1, 0xc1 },
+{ 0x00, 0xc2, 0xc2 },
+{ 0x00, 0xc3, 0xc3 },
+{ 0x00, 0xc4, 0xc4 },
+{ 0x00, 0xc5, 0xc5 },
+{ 0x00, 0xc6, 0xc6 },
+{ 0x00, 0xc7, 0xc7 },
+{ 0x00, 0xc8, 0xc8 },
+{ 0x00, 0xc9, 0xc9 },
+{ 0x00, 0xca, 0xca },
+{ 0x00, 0xcb, 0xcb },
+{ 0x00, 0xcc, 0xcc },
+{ 0x00, 0xcd, 0xcd },
+{ 0x00, 0xce, 0xce },
+{ 0x00, 0xcf, 0xcf },
+{ 0x00, 0xd0, 0xd0 },
+{ 0x00, 0xd1, 0xd1 },
+{ 0x00, 0xd2, 0xd2 },
+{ 0x00, 0xd3, 0xd3 },
+{ 0x00, 0xd4, 0xd4 },
+{ 0x00, 0xd5, 0xd5 },
+{ 0x00, 0xd6, 0xd6 },
+{ 0x00, 0xd7, 0xd7 },
+{ 0x00, 0xd8, 0xd8 },
+{ 0x00, 0xd9, 0xd9 },
+{ 0x00, 0xda, 0xda },
+{ 0x00, 0xdb, 0xdb },
+{ 0x00, 0xdc, 0xdc },
+{ 0x00, 0xdd, 0xdd },
+{ 0x00, 0xde, 0xde },
+{ 0x00, 0xdf, 0xdf },
+{ 0x00, 0xe0, 0xe0 },
+{ 0x00, 0xe1, 0xe1 },
+{ 0x00, 0xe2, 0xe2 },
+{ 0x00, 0xe3, 0xe3 },
+{ 0x00, 0xe4, 0xe4 },
+{ 0x00, 0xe5, 0xe5 },
+{ 0x00, 0xe6, 0xe6 },
+{ 0x00, 0xe7, 0xe7 },
+{ 0x00, 0xe8, 0xe8 },
+{ 0x00, 0xe9, 0xe9 },
+{ 0x00, 0xea, 0xea },
+{ 0x00, 0xeb, 0xeb },
+{ 0x00, 0xec, 0xec },
+{ 0x00, 0xed, 0xed },
+{ 0x00, 0xee, 0xee },
+{ 0x00, 0xef, 0xef },
+{ 0x00, 0xf0, 0xf0 },
+{ 0x00, 0xf1, 0xf1 },
+{ 0x00, 0xf2, 0xf2 },
+{ 0x00, 0xf3, 0xf3 },
+{ 0x00, 0xf4, 0xf4 },
+{ 0x00, 0xf5, 0xf5 },
+{ 0x00, 0xf6, 0xf6 },
+{ 0x00, 0xf7, 0xf7 },
+{ 0x00, 0xf8, 0xf8 },
+{ 0x00, 0xf9, 0xf9 },
+{ 0x00, 0xfa, 0xfa },
+{ 0x00, 0xfb, 0xfb },
+{ 0x00, 0xfc, 0xfc },
+{ 0x00, 0xfd, 0xfd },
+{ 0x00, 0xfe, 0xfe },
+{ 0x00, 0xff, 0xff },
+};
+
+struct cs_info iso7_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x00, 0xa1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x00, 0xa3, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x00, 0xa5, 0xa5 },
+{ 0x00, 0xa6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa8 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x00, 0xaa, 0xaa },
+{ 0x00, 0xab, 0xab },
+{ 0x00, 0xac, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x00, 0xaf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xb1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x00, 0xb3, 0xb3 },
+{ 0x00, 0xb4, 0xb4 },
+{ 0x00, 0xb5, 0xb5 },
+{ 0x01, 0xdc, 0xb6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x01, 0xdd, 0xb8 },
+{ 0x01, 0xde, 0xb9 },
+{ 0x01, 0xdf, 0xba },
+{ 0x00, 0xbb, 0xbb },
+{ 0x01, 0xfc, 0xbc },
+{ 0x00, 0xbd, 0xbd },
+{ 0x01, 0xfd, 0xbe },
+{ 0x01, 0xfe, 0xbf },
+{ 0x00, 0xc0, 0xc0 },
+{ 0x01, 0xe1, 0xc1 },
+{ 0x01, 0xe2, 0xc2 },
+{ 0x01, 0xe3, 0xc3 },
+{ 0x01, 0xe4, 0xc4 },
+{ 0x01, 0xe5, 0xc5 },
+{ 0x01, 0xe6, 0xc6 },
+{ 0x01, 0xe7, 0xc7 },
+{ 0x01, 0xe8, 0xc8 },
+{ 0x01, 0xe9, 0xc9 },
+{ 0x01, 0xea, 0xca },
+{ 0x01, 0xeb, 0xcb },
+{ 0x01, 0xec, 0xcc },
+{ 0x01, 0xed, 0xcd },
+{ 0x01, 0xee, 0xce },
+{ 0x01, 0xef, 0xcf },
+{ 0x01, 0xf0, 0xd0 },
+{ 0x01, 0xf1, 0xd1 },
+{ 0x00, 0xd2, 0xd2 },
+{ 0x01, 0xf3, 0xd3 },
+{ 0x01, 0xf4, 0xd4 },
+{ 0x01, 0xf5, 0xd5 },
+{ 0x01, 0xf6, 0xd6 },
+{ 0x01, 0xf7, 0xd7 },
+{ 0x01, 0xf8, 0xd8 },
+{ 0x01, 0xf9, 0xd9 },
+{ 0x01, 0xfa, 0xda },
+{ 0x01, 0xfb, 0xdb },
+{ 0x00, 0xdc, 0xb6 },
+{ 0x00, 0xdd, 0xb8 },
+{ 0x00, 0xde, 0xb9 },
+{ 0x00, 0xdf, 0xba },
+{ 0x00, 0xe0, 0xe0 },
+{ 0x00, 0xe1, 0xc1 },
+{ 0x00, 0xe2, 0xc2 },
+{ 0x00, 0xe3, 0xc3 },
+{ 0x00, 0xe4, 0xc4 },
+{ 0x00, 0xe5, 0xc5 },
+{ 0x00, 0xe6, 0xc6 },
+{ 0x00, 0xe7, 0xc7 },
+{ 0x00, 0xe8, 0xc8 },
+{ 0x00, 0xe9, 0xc9 },
+{ 0x00, 0xea, 0xca },
+{ 0x00, 0xeb, 0xcb },
+{ 0x00, 0xec, 0xcc },
+{ 0x00, 0xed, 0xcd },
+{ 0x00, 0xee, 0xce },
+{ 0x00, 0xef, 0xcf },
+{ 0x00, 0xf0, 0xd0 },
+{ 0x00, 0xf1, 0xd1 },
+{ 0x00, 0xf2, 0xd3 },
+{ 0x00, 0xf3, 0xd3 },
+{ 0x00, 0xf4, 0xd4 },
+{ 0x00, 0xf5, 0xd5 },
+{ 0x00, 0xf6, 0xd6 },
+{ 0x00, 0xf7, 0xd7 },
+{ 0x00, 0xf8, 0xd8 },
+{ 0x00, 0xf9, 0xd9 },
+{ 0x00, 0xfa, 0xda },
+{ 0x00, 0xfb, 0xdb },
+{ 0x00, 0xfc, 0xbc },
+{ 0x00, 0xfd, 0xbe },
+{ 0x00, 0xfe, 0xbf },
+{ 0x00, 0xff, 0xff },
+};
+
+struct cs_info iso8_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x00, 0xa1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x00, 0xa3, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x00, 0xa5, 0xa5 },
+{ 0x00, 0xa6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa8 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x00, 0xaa, 0xaa },
+{ 0x00, 0xab, 0xab },
+{ 0x00, 0xac, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x00, 0xaf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xb1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x00, 0xb3, 0xb3 },
+{ 0x00, 0xb4, 0xb4 },
+{ 0x00, 0xb5, 0xb5 },
+{ 0x00, 0xb6, 0xb6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xb8 },
+{ 0x00, 0xb9, 0xb9 },
+{ 0x00, 0xba, 0xba },
+{ 0x00, 0xbb, 0xbb },
+{ 0x00, 0xbc, 0xbc },
+{ 0x00, 0xbd, 0xbd },
+{ 0x00, 0xbe, 0xbe },
+{ 0x00, 0xbf, 0xbf },
+{ 0x00, 0xc0, 0xc0 },
+{ 0x00, 0xc1, 0xc1 },
+{ 0x00, 0xc2, 0xc2 },
+{ 0x00, 0xc3, 0xc3 },
+{ 0x00, 0xc4, 0xc4 },
+{ 0x00, 0xc5, 0xc5 },
+{ 0x00, 0xc6, 0xc6 },
+{ 0x00, 0xc7, 0xc7 },
+{ 0x00, 0xc8, 0xc8 },
+{ 0x00, 0xc9, 0xc9 },
+{ 0x00, 0xca, 0xca },
+{ 0x00, 0xcb, 0xcb },
+{ 0x00, 0xcc, 0xcc },
+{ 0x00, 0xcd, 0xcd },
+{ 0x00, 0xce, 0xce },
+{ 0x00, 0xcf, 0xcf },
+{ 0x00, 0xd0, 0xd0 },
+{ 0x00, 0xd1, 0xd1 },
+{ 0x00, 0xd2, 0xd2 },
+{ 0x00, 0xd3, 0xd3 },
+{ 0x00, 0xd4, 0xd4 },
+{ 0x00, 0xd5, 0xd5 },
+{ 0x00, 0xd6, 0xd6 },
+{ 0x00, 0xd7, 0xd7 },
+{ 0x00, 0xd8, 0xd8 },
+{ 0x00, 0xd9, 0xd9 },
+{ 0x00, 0xda, 0xda },
+{ 0x00, 0xdb, 0xdb },
+{ 0x00, 0xdc, 0xdc },
+{ 0x00, 0xdd, 0xdd },
+{ 0x00, 0xde, 0xde },
+{ 0x00, 0xdf, 0xdf },
+{ 0x00, 0xe0, 0xe0 },
+{ 0x00, 0xe1, 0xe1 },
+{ 0x00, 0xe2, 0xe2 },
+{ 0x00, 0xe3, 0xe3 },
+{ 0x00, 0xe4, 0xe4 },
+{ 0x00, 0xe5, 0xe5 },
+{ 0x00, 0xe6, 0xe6 },
+{ 0x00, 0xe7, 0xe7 },
+{ 0x00, 0xe8, 0xe8 },
+{ 0x00, 0xe9, 0xe9 },
+{ 0x00, 0xea, 0xea },
+{ 0x00, 0xeb, 0xeb },
+{ 0x00, 0xec, 0xec },
+{ 0x00, 0xed, 0xed },
+{ 0x00, 0xee, 0xee },
+{ 0x00, 0xef, 0xef },
+{ 0x00, 0xf0, 0xf0 },
+{ 0x00, 0xf1, 0xf1 },
+{ 0x00, 0xf2, 0xf2 },
+{ 0x00, 0xf3, 0xf3 },
+{ 0x00, 0xf4, 0xf4 },
+{ 0x00, 0xf5, 0xf5 },
+{ 0x00, 0xf6, 0xf6 },
+{ 0x00, 0xf7, 0xf7 },
+{ 0x00, 0xf8, 0xf8 },
+{ 0x00, 0xf9, 0xf9 },
+{ 0x00, 0xfa, 0xfa },
+{ 0x00, 0xfb, 0xfb },
+{ 0x00, 0xfc, 0xfc },
+{ 0x00, 0xfd, 0xfd },
+{ 0x00, 0xfe, 0xfe },
+{ 0x00, 0xff, 0xff },
+};
+
+struct cs_info iso9_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0xfd, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0xdd },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x00, 0xa1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x00, 0xa3, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x00, 0xa5, 0xa5 },
+{ 0x00, 0xa6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa8 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x00, 0xaa, 0xaa },
+{ 0x00, 0xab, 0xab },
+{ 0x00, 0xac, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x00, 0xaf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xb1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x00, 0xb3, 0xb3 },
+{ 0x00, 0xb4, 0xb4 },
+{ 0x00, 0xb5, 0xb5 },
+{ 0x00, 0xb6, 0xb6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xb8 },
+{ 0x00, 0xb9, 0xb9 },
+{ 0x00, 0xba, 0xba },
+{ 0x00, 0xbb, 0xbb },
+{ 0x00, 0xbc, 0xbc },
+{ 0x00, 0xbd, 0xbd },
+{ 0x00, 0xbe, 0xbe },
+{ 0x00, 0xbf, 0xbf },
+{ 0x01, 0xe0, 0xc0 },
+{ 0x01, 0xe1, 0xc1 },
+{ 0x01, 0xe2, 0xc2 },
+{ 0x01, 0xe3, 0xc3 },
+{ 0x01, 0xe4, 0xc4 },
+{ 0x01, 0xe5, 0xc5 },
+{ 0x01, 0xe6, 0xc6 },
+{ 0x01, 0xe7, 0xc7 },
+{ 0x01, 0xe8, 0xc8 },
+{ 0x01, 0xe9, 0xc9 },
+{ 0x01, 0xea, 0xca },
+{ 0x01, 0xeb, 0xcb },
+{ 0x01, 0xec, 0xcc },
+{ 0x01, 0xed, 0xcd },
+{ 0x01, 0xee, 0xce },
+{ 0x01, 0xef, 0xcf },
+{ 0x01, 0xf0, 0xd0 },
+{ 0x01, 0xf1, 0xd1 },
+{ 0x01, 0xf2, 0xd2 },
+{ 0x01, 0xf3, 0xd3 },
+{ 0x01, 0xf4, 0xd4 },
+{ 0x01, 0xf5, 0xd5 },
+{ 0x01, 0xf6, 0xd6 },
+{ 0x00, 0xd7, 0xd7 },
+{ 0x01, 0xf8, 0xd8 },
+{ 0x01, 0xf9, 0xd9 },
+{ 0x01, 0xfa, 0xda },
+{ 0x01, 0xfb, 0xdb },
+{ 0x01, 0xfc, 0xdc },
+{ 0x01, 0x69, 0xdd },
+{ 0x01, 0xfe, 0xde },
+{ 0x00, 0xdf, 0xdf },
+{ 0x00, 0xe0, 0xc0 },
+{ 0x00, 0xe1, 0xc1 },
+{ 0x00, 0xe2, 0xc2 },
+{ 0x00, 0xe3, 0xc3 },
+{ 0x00, 0xe4, 0xc4 },
+{ 0x00, 0xe5, 0xc5 },
+{ 0x00, 0xe6, 0xc6 },
+{ 0x00, 0xe7, 0xc7 },
+{ 0x00, 0xe8, 0xc8 },
+{ 0x00, 0xe9, 0xc9 },
+{ 0x00, 0xea, 0xca },
+{ 0x00, 0xeb, 0xcb },
+{ 0x00, 0xec, 0xcc },
+{ 0x00, 0xed, 0xcd },
+{ 0x00, 0xee, 0xce },
+{ 0x00, 0xef, 0xcf },
+{ 0x00, 0xf0, 0xd0 },
+{ 0x00, 0xf1, 0xd1 },
+{ 0x00, 0xf2, 0xd2 },
+{ 0x00, 0xf3, 0xd3 },
+{ 0x00, 0xf4, 0xd4 },
+{ 0x00, 0xf5, 0xd5 },
+{ 0x00, 0xf6, 0xd6 },
+{ 0x00, 0xf7, 0xf7 },
+{ 0x00, 0xf8, 0xd8 },
+{ 0x00, 0xf9, 0xd9 },
+{ 0x00, 0xfa, 0xda },
+{ 0x00, 0xfb, 0xdb },
+{ 0x00, 0xfc, 0xdc },
+{ 0x00, 0xfd, 0x49 },
+{ 0x00, 0xfe, 0xde },
+{ 0x00, 0xff, 0xff },
+};
+
+struct cs_info iso10_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x00, 0xa1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x00, 0xa3, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x00, 0xa5, 0xa5 },
+{ 0x00, 0xa6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa8 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x00, 0xaa, 0xaa },
+{ 0x00, 0xab, 0xab },
+{ 0x00, 0xac, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x00, 0xaf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xb1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x00, 0xb3, 0xb3 },
+{ 0x00, 0xb4, 0xb4 },
+{ 0x00, 0xb5, 0xb5 },
+{ 0x00, 0xb6, 0xb6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xb8 },
+{ 0x00, 0xb9, 0xb9 },
+{ 0x00, 0xba, 0xba },
+{ 0x00, 0xbb, 0xbb },
+{ 0x00, 0xbc, 0xbc },
+{ 0x00, 0xbd, 0xbd },
+{ 0x00, 0xbe, 0xbe },
+{ 0x00, 0xbf, 0xbf },
+{ 0x00, 0xc0, 0xc0 },
+{ 0x00, 0xc1, 0xc1 },
+{ 0x00, 0xc2, 0xc2 },
+{ 0x00, 0xc3, 0xc3 },
+{ 0x00, 0xc4, 0xc4 },
+{ 0x00, 0xc5, 0xc5 },
+{ 0x00, 0xc6, 0xc6 },
+{ 0x00, 0xc7, 0xc7 },
+{ 0x00, 0xc8, 0xc8 },
+{ 0x00, 0xc9, 0xc9 },
+{ 0x00, 0xca, 0xca },
+{ 0x00, 0xcb, 0xcb },
+{ 0x00, 0xcc, 0xcc },
+{ 0x00, 0xcd, 0xcd },
+{ 0x00, 0xce, 0xce },
+{ 0x00, 0xcf, 0xcf },
+{ 0x00, 0xd0, 0xd0 },
+{ 0x00, 0xd1, 0xd1 },
+{ 0x00, 0xd2, 0xd2 },
+{ 0x00, 0xd3, 0xd3 },
+{ 0x00, 0xd4, 0xd4 },
+{ 0x00, 0xd5, 0xd5 },
+{ 0x00, 0xd6, 0xd6 },
+{ 0x00, 0xd7, 0xd7 },
+{ 0x00, 0xd8, 0xd8 },
+{ 0x00, 0xd9, 0xd9 },
+{ 0x00, 0xda, 0xda },
+{ 0x00, 0xdb, 0xdb },
+{ 0x00, 0xdc, 0xdc },
+{ 0x00, 0xdd, 0xdd },
+{ 0x00, 0xde, 0xde },
+{ 0x00, 0xdf, 0xdf },
+{ 0x00, 0xe0, 0xe0 },
+{ 0x00, 0xe1, 0xe1 },
+{ 0x00, 0xe2, 0xe2 },
+{ 0x00, 0xe3, 0xe3 },
+{ 0x00, 0xe4, 0xe4 },
+{ 0x00, 0xe5, 0xe5 },
+{ 0x00, 0xe6, 0xe6 },
+{ 0x00, 0xe7, 0xe7 },
+{ 0x00, 0xe8, 0xe8 },
+{ 0x00, 0xe9, 0xe9 },
+{ 0x00, 0xea, 0xea },
+{ 0x00, 0xeb, 0xeb },
+{ 0x00, 0xec, 0xec },
+{ 0x00, 0xed, 0xed },
+{ 0x00, 0xee, 0xee },
+{ 0x00, 0xef, 0xef },
+{ 0x00, 0xf0, 0xf0 },
+{ 0x00, 0xf1, 0xf1 },
+{ 0x00, 0xf2, 0xf2 },
+{ 0x00, 0xf3, 0xf3 },
+{ 0x00, 0xf4, 0xf4 },
+{ 0x00, 0xf5, 0xf5 },
+{ 0x00, 0xf6, 0xf6 },
+{ 0x00, 0xf7, 0xf7 },
+{ 0x00, 0xf8, 0xf8 },
+{ 0x00, 0xf9, 0xf9 },
+{ 0x00, 0xfa, 0xfa },
+{ 0x00, 0xfb, 0xfb },
+{ 0x00, 0xfc, 0xfc },
+{ 0x00, 0xfd, 0xfd },
+{ 0x00, 0xfe, 0xfe },
+{ 0x00, 0xff, 0xff },
+};
+
+struct cs_info koi8r_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x00, 0xa1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x00, 0xa3, 0xb3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x00, 0xa5, 0xa5 },
+{ 0x00, 0xa6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa8 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x00, 0xaa, 0xaa },
+{ 0x00, 0xab, 0xab },
+{ 0x00, 0xac, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x00, 0xaf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xb1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x01, 0xa3, 0xb3 },
+{ 0x00, 0xb4, 0xb4 },
+{ 0x00, 0xb5, 0xb5 },
+{ 0x00, 0xb6, 0xb6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xb8 },
+{ 0x00, 0xb9, 0xb9 },
+{ 0x00, 0xba, 0xba },
+{ 0x00, 0xbb, 0xbb },
+{ 0x00, 0xbc, 0xbc },
+{ 0x00, 0xbd, 0xbd },
+{ 0x00, 0xbe, 0xbe },
+{ 0x00, 0xbf, 0xbf },
+{ 0x00, 0xc0, 0xe0 },
+{ 0x00, 0xc1, 0xe1 },
+{ 0x00, 0xc2, 0xe2 },
+{ 0x00, 0xc3, 0xe3 },
+{ 0x00, 0xc4, 0xe4 },
+{ 0x00, 0xc5, 0xe5 },
+{ 0x00, 0xc6, 0xe6 },
+{ 0x00, 0xc7, 0xe7 },
+{ 0x00, 0xc8, 0xe8 },
+{ 0x00, 0xc9, 0xe9 },
+{ 0x00, 0xca, 0xea },
+{ 0x00, 0xcb, 0xeb },
+{ 0x00, 0xcc, 0xec },
+{ 0x00, 0xcd, 0xed },
+{ 0x00, 0xce, 0xee },
+{ 0x00, 0xcf, 0xef },
+{ 0x00, 0xd0, 0xf0 },
+{ 0x00, 0xd1, 0xf1 },
+{ 0x00, 0xd2, 0xf2 },
+{ 0x00, 0xd3, 0xf3 },
+{ 0x00, 0xd4, 0xf4 },
+{ 0x00, 0xd5, 0xf5 },
+{ 0x00, 0xd6, 0xf6 },
+{ 0x00, 0xd7, 0xf7 },
+{ 0x00, 0xd8, 0xf8 },
+{ 0x00, 0xd9, 0xf9 },
+{ 0x00, 0xda, 0xfa },
+{ 0x00, 0xdb, 0xfb },
+{ 0x00, 0xdc, 0xfc },
+{ 0x00, 0xdd, 0xfd },
+{ 0x00, 0xde, 0xfe },
+{ 0x00, 0xdf, 0xff },
+{ 0x01, 0xc0, 0xe0 },
+{ 0x01, 0xc1, 0xe1 },
+{ 0x01, 0xc2, 0xe2 },
+{ 0x01, 0xc3, 0xe3 },
+{ 0x01, 0xc4, 0xe4 },
+{ 0x01, 0xc5, 0xe5 },
+{ 0x01, 0xc6, 0xe6 },
+{ 0x01, 0xc7, 0xe7 },
+{ 0x01, 0xc8, 0xe8 },
+{ 0x01, 0xc9, 0xe9 },
+{ 0x01, 0xca, 0xea },
+{ 0x01, 0xcb, 0xeb },
+{ 0x01, 0xcc, 0xec },
+{ 0x01, 0xcd, 0xed },
+{ 0x01, 0xce, 0xee },
+{ 0x01, 0xcf, 0xef },
+{ 0x01, 0xd0, 0xf0 },
+{ 0x01, 0xd1, 0xf1 },
+{ 0x01, 0xd2, 0xf2 },
+{ 0x01, 0xd3, 0xf3 },
+{ 0x01, 0xd4, 0xf4 },
+{ 0x01, 0xd5, 0xf5 },
+{ 0x01, 0xd6, 0xf6 },
+{ 0x01, 0xd7, 0xf7 },
+{ 0x01, 0xd8, 0xf8 },
+{ 0x01, 0xd9, 0xf9 },
+{ 0x01, 0xda, 0xfa },
+{ 0x01, 0xdb, 0xfb },
+{ 0x01, 0xdc, 0xfc },
+{ 0x01, 0xdd, 0xfd },
+{ 0x01, 0xde, 0xfe },
+{ 0x01, 0xdf, 0xff },
+};
+
+struct cs_info koi8u_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x00, 0xa1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x00, 0xa3, 0xb3 },
+{ 0x00, 0xa4, 0xb4 }, /* ie */
+{ 0x00, 0xa5, 0xa5 },
+{ 0x00, 0xa6, 0xb6 }, /* i */
+{ 0x00, 0xa7, 0xb7 }, /* ii */
+{ 0x00, 0xa8, 0xa8 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x00, 0xaa, 0xaa },
+{ 0x00, 0xab, 0xab },
+{ 0x00, 0xac, 0xac },
+{ 0x00, 0xad, 0xbd }, /* g'' */
+{ 0x00, 0xae, 0xae },
+{ 0x00, 0xaf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xb1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x01, 0xa3, 0xb3 },
+{ 0x00, 0xb4, 0xb4 }, /* IE */
+{ 0x00, 0xb5, 0xb5 },
+{ 0x00, 0xb6, 0xb6 }, /* I */
+{ 0x00, 0xb7, 0xb7 }, /* II */
+{ 0x00, 0xb8, 0xb8 },
+{ 0x00, 0xb9, 0xb9 },
+{ 0x00, 0xba, 0xba },
+{ 0x00, 0xbb, 0xbb },
+{ 0x00, 0xbc, 0xbc },
+{ 0x00, 0xbd, 0xbd },
+{ 0x00, 0xbe, 0xbe },
+{ 0x00, 0xbf, 0xbf },
+{ 0x00, 0xc0, 0xe0 },
+{ 0x00, 0xc1, 0xe1 },
+{ 0x00, 0xc2, 0xe2 },
+{ 0x00, 0xc3, 0xe3 },
+{ 0x00, 0xc4, 0xe4 },
+{ 0x00, 0xc5, 0xe5 },
+{ 0x00, 0xc6, 0xe6 },
+{ 0x00, 0xc7, 0xe7 },
+{ 0x00, 0xc8, 0xe8 },
+{ 0x00, 0xc9, 0xe9 },
+{ 0x00, 0xca, 0xea },
+{ 0x00, 0xcb, 0xeb },
+{ 0x00, 0xcc, 0xec },
+{ 0x00, 0xcd, 0xed },
+{ 0x00, 0xce, 0xee },
+{ 0x00, 0xcf, 0xef },
+{ 0x00, 0xd0, 0xf0 },
+{ 0x00, 0xd1, 0xf1 },
+{ 0x00, 0xd2, 0xf2 },
+{ 0x00, 0xd3, 0xf3 },
+{ 0x00, 0xd4, 0xf4 },
+{ 0x00, 0xd5, 0xf5 },
+{ 0x00, 0xd6, 0xf6 },
+{ 0x00, 0xd7, 0xf7 },
+{ 0x00, 0xd8, 0xf8 },
+{ 0x00, 0xd9, 0xf9 },
+{ 0x00, 0xda, 0xfa },
+{ 0x00, 0xdb, 0xfb },
+{ 0x00, 0xdc, 0xfc },
+{ 0x00, 0xdd, 0xfd },
+{ 0x00, 0xde, 0xfe },
+{ 0x00, 0xdf, 0xff },
+{ 0x01, 0xc0, 0xe0 },
+{ 0x01, 0xc1, 0xe1 },
+{ 0x01, 0xc2, 0xe2 },
+{ 0x01, 0xc3, 0xe3 },
+{ 0x01, 0xc4, 0xe4 },
+{ 0x01, 0xc5, 0xe5 },
+{ 0x01, 0xc6, 0xe6 },
+{ 0x01, 0xc7, 0xe7 },
+{ 0x01, 0xc8, 0xe8 },
+{ 0x01, 0xc9, 0xe9 },
+{ 0x01, 0xca, 0xea },
+{ 0x01, 0xcb, 0xeb },
+{ 0x01, 0xcc, 0xec },
+{ 0x01, 0xcd, 0xed },
+{ 0x01, 0xce, 0xee },
+{ 0x01, 0xcf, 0xef },
+{ 0x01, 0xd0, 0xf0 },
+{ 0x01, 0xd1, 0xf1 },
+{ 0x01, 0xd2, 0xf2 },
+{ 0x01, 0xd3, 0xf3 },
+{ 0x01, 0xd4, 0xf4 },
+{ 0x01, 0xd5, 0xf5 },
+{ 0x01, 0xd6, 0xf6 },
+{ 0x01, 0xd7, 0xf7 },
+{ 0x01, 0xd8, 0xf8 },
+{ 0x01, 0xd9, 0xf9 },
+{ 0x01, 0xda, 0xfa },
+{ 0x01, 0xdb, 0xfb },
+{ 0x01, 0xdc, 0xfc },
+{ 0x01, 0xdd, 0xfd },
+{ 0x01, 0xde, 0xfe },
+{ 0x01, 0xdf, 0xff },
+};
+
+struct cs_info cp1251_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x01, 0x90, 0x80 },
+{ 0x01, 0x83, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x81 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x01, 0x9a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x01, 0x9c, 0x8c },
+{ 0x01, 0x9d, 0x8d },
+{ 0x01, 0x9e, 0x8e },
+{ 0x01, 0x9f, 0x8f },
+{ 0x00, 0x90, 0x80 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x8a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x8c },
+{ 0x00, 0x9d, 0x8d },
+{ 0x00, 0x9e, 0x8e },
+{ 0x00, 0x9f, 0x8f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x01, 0xa2, 0xa1 },
+{ 0x00, 0xa2, 0xa1 },
+{ 0x01, 0xbc, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x01, 0xb4, 0xa5 },
+{ 0x00, 0xa6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x01, 0xb8, 0xa8 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x01, 0xba, 0xaa },
+{ 0x00, 0xab, 0xab },
+{ 0x00, 0xac, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x01, 0xbf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xb1 },
+{ 0x01, 0xb3, 0xb2 },
+{ 0x00, 0xb3, 0xb2 },
+{ 0x00, 0xb4, 0xa5 },
+{ 0x00, 0xb5, 0xb5 },
+{ 0x00, 0xb6, 0xb6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xa8 },
+{ 0x00, 0xb9, 0xb9 },
+{ 0x00, 0xba, 0xaa },
+{ 0x00, 0xbb, 0xbb },
+{ 0x00, 0xbc, 0xa3 },
+{ 0x01, 0xbe, 0xbd },
+{ 0x00, 0xbe, 0xbd },
+{ 0x00, 0xbf, 0xaf },
+{ 0x01, 0xe0, 0xc0 },
+{ 0x01, 0xe1, 0xc1 },
+{ 0x01, 0xe2, 0xc2 },
+{ 0x01, 0xe3, 0xc3 },
+{ 0x01, 0xe4, 0xc4 },
+{ 0x01, 0xe5, 0xc5 },
+{ 0x01, 0xe6, 0xc6 },
+{ 0x01, 0xe7, 0xc7 },
+{ 0x01, 0xe8, 0xc8 },
+{ 0x01, 0xe9, 0xc9 },
+{ 0x01, 0xea, 0xca },
+{ 0x01, 0xeb, 0xcb },
+{ 0x01, 0xec, 0xcc },
+{ 0x01, 0xed, 0xcd },
+{ 0x01, 0xee, 0xce },
+{ 0x01, 0xef, 0xcf },
+{ 0x01, 0xf0, 0xd0 },
+{ 0x01, 0xf1, 0xd1 },
+{ 0x01, 0xf2, 0xd2 },
+{ 0x01, 0xf3, 0xd3 },
+{ 0x01, 0xf4, 0xd4 },
+{ 0x01, 0xf5, 0xd5 },
+{ 0x01, 0xf6, 0xd6 },
+{ 0x01, 0xf7, 0xd7 },
+{ 0x01, 0xf8, 0xd8 },
+{ 0x01, 0xf9, 0xd9 },
+{ 0x01, 0xfa, 0xda },
+{ 0x01, 0xfb, 0xdb },
+{ 0x01, 0xfc, 0xdc },
+{ 0x01, 0xfd, 0xdd },
+{ 0x01, 0xfe, 0xde },
+{ 0x01, 0xff, 0xdf },
+{ 0x00, 0xe0, 0xc0 },
+{ 0x00, 0xe1, 0xc1 },
+{ 0x00, 0xe2, 0xc2 },
+{ 0x00, 0xe3, 0xc3 },
+{ 0x00, 0xe4, 0xc4 },
+{ 0x00, 0xe5, 0xc5 },
+{ 0x00, 0xe6, 0xc6 },
+{ 0x00, 0xe7, 0xc7 },
+{ 0x00, 0xe8, 0xc8 },
+{ 0x00, 0xe9, 0xc9 },
+{ 0x00, 0xea, 0xca },
+{ 0x00, 0xeb, 0xcb },
+{ 0x00, 0xec, 0xcc },
+{ 0x00, 0xed, 0xcd },
+{ 0x00, 0xee, 0xce },
+{ 0x00, 0xef, 0xcf },
+{ 0x00, 0xf0, 0xd0 },
+{ 0x00, 0xf1, 0xd1 },
+{ 0x00, 0xf2, 0xd2 },
+{ 0x00, 0xf3, 0xd3 },
+{ 0x00, 0xf4, 0xd4 },
+{ 0x00, 0xf5, 0xd5 },
+{ 0x00, 0xf6, 0xd6 },
+{ 0x00, 0xf7, 0xd7 },
+{ 0x00, 0xf8, 0xd8 },
+{ 0x00, 0xf9, 0xd9 },
+{ 0x00, 0xfa, 0xda },
+{ 0x00, 0xfb, 0xdb },
+{ 0x00, 0xfc, 0xdc },
+{ 0x00, 0xfd, 0xdd },
+{ 0x00, 0xfe, 0xde },
+{ 0x00, 0xff, 0xdf },
+};
+
+struct cs_info iso13_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0A, 0x0A },
+{ 0x00, 0x0B, 0x0B },
+{ 0x00, 0x0C, 0x0C },
+{ 0x00, 0x0D, 0x0D },
+{ 0x00, 0x0E, 0x0E },
+{ 0x00, 0x0F, 0x0F },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1A, 0x1A },
+{ 0x00, 0x1B, 0x1B },
+{ 0x00, 0x1C, 0x1C },
+{ 0x00, 0x1D, 0x1D },
+{ 0x00, 0x1E, 0x1E },
+{ 0x00, 0x1F, 0x1F },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2A, 0x2A },
+{ 0x00, 0x2B, 0x2B },
+{ 0x00, 0x2C, 0x2C },
+{ 0x00, 0x2D, 0x2D },
+{ 0x00, 0x2E, 0x2E },
+{ 0x00, 0x2F, 0x2F },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3A, 0x3A },
+{ 0x00, 0x3B, 0x3B },
+{ 0x00, 0x3C, 0x3C },
+{ 0x00, 0x3D, 0x3D },
+{ 0x00, 0x3E, 0x3E },
+{ 0x00, 0x3F, 0x3F },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6A, 0x4A },
+{ 0x01, 0x6B, 0x4B },
+{ 0x01, 0x6C, 0x4C },
+{ 0x01, 0x6D, 0x4D },
+{ 0x01, 0x6E, 0x4E },
+{ 0x01, 0x6F, 0x4F },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7A, 0x5A },
+{ 0x00, 0x5B, 0x5B },
+{ 0x00, 0x5C, 0x5C },
+{ 0x00, 0x5D, 0x5D },
+{ 0x00, 0x5E, 0x5E },
+{ 0x00, 0x5F, 0x5F },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6A, 0x4A },
+{ 0x00, 0x6B, 0x4B },
+{ 0x00, 0x6C, 0x4C },
+{ 0x00, 0x6D, 0x4D },
+{ 0x00, 0x6E, 0x4E },
+{ 0x00, 0x6F, 0x4F },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7A, 0x5A },
+{ 0x00, 0x7B, 0x7B },
+{ 0x00, 0x7C, 0x7C },
+{ 0x00, 0x7D, 0x7D },
+{ 0x00, 0x7E, 0x7E },
+{ 0x00, 0x7F, 0x7F },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8A, 0x8A },
+{ 0x00, 0x8B, 0x8B },
+{ 0x00, 0x8C, 0x8C },
+{ 0x00, 0x8D, 0x8D },
+{ 0x00, 0x8E, 0x8E },
+{ 0x00, 0x8F, 0x8F },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9A, 0x9A },
+{ 0x00, 0x9B, 0x9B },
+{ 0x00, 0x9C, 0x9C },
+{ 0x00, 0x9D, 0x9D },
+{ 0x00, 0x9E, 0x9E },
+{ 0x00, 0x9F, 0x9F },
+{ 0x00, 0xA0, 0xA0 },
+{ 0x00, 0xA1, 0xA1 },
+{ 0x00, 0xA2, 0xA2 },
+{ 0x00, 0xA3, 0xA3 },
+{ 0x00, 0xA4, 0xA4 },
+{ 0x00, 0xA5, 0xA5 },
+{ 0x00, 0xA6, 0xA6 },
+{ 0x00, 0xA7, 0xA7 },
+{ 0x01, 0xB8, 0xA8 },
+{ 0x00, 0xA9, 0xA9 },
+{ 0x01, 0xBA, 0xAA },
+{ 0x00, 0xAB, 0xAB },
+{ 0x00, 0xAC, 0xAC },
+{ 0x00, 0xAD, 0xAD },
+{ 0x00, 0xAE, 0xAE },
+{ 0x01, 0xBF, 0xAF },
+{ 0x00, 0xB0, 0xB0 },
+{ 0x00, 0xB1, 0xB1 },
+{ 0x00, 0xB2, 0xB2 },
+{ 0x00, 0xB3, 0xB3 },
+{ 0x00, 0xB4, 0xB4 },
+{ 0x00, 0xB5, 0xB5 },
+{ 0x00, 0xB6, 0xB6 },
+{ 0x00, 0xB7, 0xB7 },
+{ 0x00, 0xB8, 0xA8 },
+{ 0x00, 0xB9, 0xB9 },
+{ 0x00, 0xBA, 0xAA },
+{ 0x00, 0xBB, 0xBB },
+{ 0x00, 0xBC, 0xBC },
+{ 0x00, 0xBD, 0xBD },
+{ 0x00, 0xBE, 0xBE },
+{ 0x00, 0xBF, 0xAF },
+{ 0x01, 0xE0, 0xC0 },
+{ 0x01, 0xE1, 0xC1 },
+{ 0x01, 0xE2, 0xC2 },
+{ 0x01, 0xE3, 0xC3 },
+{ 0x01, 0xE4, 0xC4 },
+{ 0x01, 0xE5, 0xC5 },
+{ 0x01, 0xE6, 0xC6 },
+{ 0x01, 0xE7, 0xC7 },
+{ 0x01, 0xE8, 0xC8 },
+{ 0x01, 0xE9, 0xC9 },
+{ 0x01, 0xEA, 0xCA },
+{ 0x01, 0xEB, 0xCB },
+{ 0x01, 0xEC, 0xCC },
+{ 0x01, 0xED, 0xCD },
+{ 0x01, 0xEE, 0xCE },
+{ 0x01, 0xEF, 0xCF },
+{ 0x01, 0xF0, 0xD0 },
+{ 0x01, 0xF1, 0xD1 },
+{ 0x01, 0xF2, 0xD2 },
+{ 0x01, 0xF3, 0xD3 },
+{ 0x01, 0xF4, 0xD4 },
+{ 0x01, 0xF5, 0xD5 },
+{ 0x01, 0xF6, 0xD6 },
+{ 0x00, 0xD7, 0xD7 },
+{ 0x01, 0xF8, 0xD8 },
+{ 0x01, 0xF9, 0xD9 },
+{ 0x01, 0xFA, 0xDA },
+{ 0x01, 0xFB, 0xDB },
+{ 0x01, 0xFC, 0xDC },
+{ 0x01, 0xFD, 0xDD },
+{ 0x01, 0xFE, 0xDE },
+{ 0x00, 0xDF, 0xDF },
+{ 0x00, 0xE0, 0xC0 },
+{ 0x00, 0xE1, 0xC1 },
+{ 0x00, 0xE2, 0xC2 },
+{ 0x00, 0xE3, 0xC3 },
+{ 0x00, 0xE4, 0xC4 },
+{ 0x00, 0xE5, 0xC5 },
+{ 0x00, 0xE6, 0xC6 },
+{ 0x00, 0xE7, 0xC7 },
+{ 0x00, 0xE8, 0xC8 },
+{ 0x00, 0xE9, 0xC9 },
+{ 0x00, 0xEA, 0xCA },
+{ 0x00, 0xEB, 0xCB },
+{ 0x00, 0xEC, 0xCC },
+{ 0x00, 0xED, 0xCD },
+{ 0x00, 0xEE, 0xCE },
+{ 0x00, 0xEF, 0xCF },
+{ 0x00, 0xF0, 0xD0 },
+{ 0x00, 0xF1, 0xD1 },
+{ 0x00, 0xF2, 0xD2 },
+{ 0x00, 0xF3, 0xD3 },
+{ 0x00, 0xF4, 0xD4 },
+{ 0x00, 0xF5, 0xD5 },
+{ 0x00, 0xF6, 0xD6 },
+{ 0x00, 0xF7, 0xF7 },
+{ 0x00, 0xF8, 0xD8 },
+{ 0x00, 0xF9, 0xD9 },
+{ 0x00, 0xFA, 0xDA },
+{ 0x00, 0xFB, 0xDB },
+{ 0x00, 0xFC, 0xDC },
+{ 0x00, 0xFD, 0xDD },
+{ 0x00, 0xFE, 0xDE },
+{ 0x00, 0xFF, 0xFF },
+};
+
+
+struct cs_info iso14_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x01, 0xa2, 0xa1 },
+{ 0x00, 0xa2, 0xa1 },
+{ 0x00, 0xa3, 0xa3 },
+{ 0x01, 0xa5, 0xa4 },
+{ 0x00, 0xa5, 0xa4 },
+{ 0x01, 0xa6, 0xab },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x01, 0xb8, 0xa8 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x01, 0xba, 0xaa },
+{ 0x00, 0xab, 0xa6 },
+{ 0x01, 0xbc, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x01, 0xff, 0xaf },
+{ 0x01, 0xb1, 0xb0 },
+{ 0x00, 0xb1, 0xb0 },
+{ 0x01, 0xb3, 0xb2 },
+{ 0x00, 0xb3, 0xb2 },
+{ 0x01, 0xb5, 0xb4 },
+{ 0x00, 0xb5, 0xb4 },
+{ 0x00, 0xb6, 0xb6 },
+{ 0x01, 0xb9, 0xb7 },
+{ 0x00, 0xb8, 0xa8 },
+{ 0x00, 0xb9, 0xb6 },
+{ 0x00, 0xba, 0xaa },
+{ 0x01, 0xbf, 0xbb },
+{ 0x00, 0xbc, 0xac },
+{ 0x01, 0xbe, 0xbd },
+{ 0x00, 0xbe, 0xbd },
+{ 0x00, 0xbf, 0xbb },
+{ 0x01, 0xe0, 0xc0 },
+{ 0x01, 0xe1, 0xc1 },
+{ 0x01, 0xe2, 0xc2 },
+{ 0x01, 0xe3, 0xc3 },
+{ 0x01, 0xe4, 0xc4 },
+{ 0x01, 0xe5, 0xc5 },
+{ 0x01, 0xe6, 0xc6 },
+{ 0x01, 0xe7, 0xc7 },
+{ 0x01, 0xe8, 0xc8 },
+{ 0x01, 0xe9, 0xc9 },
+{ 0x01, 0xea, 0xca },
+{ 0x01, 0xeb, 0xcb },
+{ 0x01, 0xec, 0xcc },
+{ 0x01, 0xed, 0xcd },
+{ 0x01, 0xee, 0xce },
+{ 0x01, 0xef, 0xcf },
+{ 0x01, 0xf0, 0xd0 },
+{ 0x01, 0xf1, 0xd1 },
+{ 0x01, 0xf2, 0xd2 },
+{ 0x01, 0xf3, 0xd3 },
+{ 0x01, 0xf4, 0xd4 },
+{ 0x01, 0xf5, 0xd5 },
+{ 0x01, 0xf6, 0xd6 },
+{ 0x01, 0xf7, 0xd7 },
+{ 0x01, 0xf8, 0xd8 },
+{ 0x01, 0xf9, 0xd9 },
+{ 0x01, 0xfa, 0xda },
+{ 0x01, 0xfb, 0xdb },
+{ 0x01, 0xfc, 0xdc },
+{ 0x01, 0xfd, 0xdd },
+{ 0x01, 0xfe, 0xde },
+{ 0x00, 0xdf, 0xdf },
+{ 0x00, 0xe0, 0xc0 },
+{ 0x00, 0xe1, 0xc1 },
+{ 0x00, 0xe2, 0xc2 },
+{ 0x00, 0xe3, 0xc3 },
+{ 0x00, 0xe4, 0xc4 },
+{ 0x00, 0xe5, 0xc5 },
+{ 0x00, 0xe6, 0xc6 },
+{ 0x00, 0xe7, 0xc7 },
+{ 0x00, 0xe8, 0xc8 },
+{ 0x00, 0xe9, 0xc9 },
+{ 0x00, 0xea, 0xca },
+{ 0x00, 0xeb, 0xcb },
+{ 0x00, 0xec, 0xcc },
+{ 0x00, 0xed, 0xcd },
+{ 0x00, 0xee, 0xce },
+{ 0x00, 0xef, 0xcf },
+{ 0x00, 0xf0, 0xd0 },
+{ 0x00, 0xf1, 0xd1 },
+{ 0x00, 0xf2, 0xd2 },
+{ 0x00, 0xf3, 0xd3 },
+{ 0x00, 0xf4, 0xd4 },
+{ 0x00, 0xf5, 0xd5 },
+{ 0x00, 0xf6, 0xd6 },
+{ 0x00, 0xf7, 0xd7 },
+{ 0x00, 0xf8, 0xd8 },
+{ 0x00, 0xf9, 0xd9 },
+{ 0x00, 0xfa, 0xda },
+{ 0x00, 0xfb, 0xdb },
+{ 0x00, 0xfc, 0xdc },
+{ 0x00, 0xfd, 0xdd },
+{ 0x00, 0xfe, 0xde },
+{ 0x00, 0xff, 0xff },
+};
+
+struct cs_info iso15_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x00, 0xa1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x00, 0xa3, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x00, 0xa5, 0xa5 },
+{ 0x01, 0xa8, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa6 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x00, 0xaa, 0xaa },
+{ 0x00, 0xab, 0xab },
+{ 0x00, 0xac, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x00, 0xaf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xb1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x00, 0xb3, 0xb3 },
+{ 0x01, 0xb8, 0xb4 },
+{ 0x00, 0xb5, 0xb5 },
+{ 0x00, 0xb6, 0xb6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xb4 },
+{ 0x00, 0xb9, 0xb9 },
+{ 0x00, 0xba, 0xba },
+{ 0x00, 0xbb, 0xbb },
+{ 0x01, 0xbd, 0xbc },
+{ 0x00, 0xbd, 0xbc },
+{ 0x01, 0xff, 0xbe },
+{ 0x00, 0xbf, 0xbf },
+{ 0x01, 0xe0, 0xc0 },
+{ 0x01, 0xe1, 0xc1 },
+{ 0x01, 0xe2, 0xc2 },
+{ 0x01, 0xe3, 0xc3 },
+{ 0x01, 0xe4, 0xc4 },
+{ 0x01, 0xe5, 0xc5 },
+{ 0x01, 0xe6, 0xc6 },
+{ 0x01, 0xe7, 0xc7 },
+{ 0x01, 0xe8, 0xc8 },
+{ 0x01, 0xe9, 0xc9 },
+{ 0x01, 0xea, 0xca },
+{ 0x01, 0xeb, 0xcb },
+{ 0x01, 0xec, 0xcc },
+{ 0x01, 0xed, 0xcd },
+{ 0x01, 0xee, 0xce },
+{ 0x01, 0xef, 0xcf },
+{ 0x01, 0xf0, 0xd0 },
+{ 0x01, 0xf1, 0xd1 },
+{ 0x01, 0xf2, 0xd2 },
+{ 0x01, 0xf3, 0xd3 },
+{ 0x01, 0xf4, 0xd4 },
+{ 0x01, 0xf5, 0xd5 },
+{ 0x01, 0xf6, 0xd6 },
+{ 0x00, 0xd7, 0xd7 },
+{ 0x01, 0xf8, 0xd8 },
+{ 0x01, 0xf9, 0xd9 },
+{ 0x01, 0xfa, 0xda },
+{ 0x01, 0xfb, 0xdb },
+{ 0x01, 0xfc, 0xdc },
+{ 0x01, 0xfd, 0xdd },
+{ 0x01, 0xfe, 0xde },
+{ 0x00, 0xdf, 0xdf },
+{ 0x00, 0xe0, 0xc0 },
+{ 0x00, 0xe1, 0xc1 },
+{ 0x00, 0xe2, 0xc2 },
+{ 0x00, 0xe3, 0xc3 },
+{ 0x00, 0xe4, 0xc4 },
+{ 0x00, 0xe5, 0xc5 },
+{ 0x00, 0xe6, 0xc6 },
+{ 0x00, 0xe7, 0xc7 },
+{ 0x00, 0xe8, 0xc8 },
+{ 0x00, 0xe9, 0xc9 },
+{ 0x00, 0xea, 0xca },
+{ 0x00, 0xeb, 0xcb },
+{ 0x00, 0xec, 0xcc },
+{ 0x00, 0xed, 0xcd },
+{ 0x00, 0xee, 0xce },
+{ 0x00, 0xef, 0xcf },
+{ 0x00, 0xf0, 0xd0 },
+{ 0x00, 0xf1, 0xd1 },
+{ 0x00, 0xf2, 0xd2 },
+{ 0x00, 0xf3, 0xd3 },
+{ 0x00, 0xf4, 0xd4 },
+{ 0x00, 0xf5, 0xd5 },
+{ 0x00, 0xf6, 0xd6 },
+{ 0x00, 0xf7, 0xf7 },
+{ 0x00, 0xf8, 0xd8 },
+{ 0x00, 0xf9, 0xd9 },
+{ 0x00, 0xfa, 0xda },
+{ 0x00, 0xfb, 0xdb },
+{ 0x00, 0xfc, 0xdc },
+{ 0x00, 0xfd, 0xdd },
+{ 0x00, 0xfe, 0xde },
+{ 0x00, 0xff, 0xbe },
+};
+
+struct cs_info iscii_devanagari_tbl[] = {
+{ 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x01 },
+{ 0x00, 0x02, 0x02 },
+{ 0x00, 0x03, 0x03 },
+{ 0x00, 0x04, 0x04 },
+{ 0x00, 0x05, 0x05 },
+{ 0x00, 0x06, 0x06 },
+{ 0x00, 0x07, 0x07 },
+{ 0x00, 0x08, 0x08 },
+{ 0x00, 0x09, 0x09 },
+{ 0x00, 0x0a, 0x0a },
+{ 0x00, 0x0b, 0x0b },
+{ 0x00, 0x0c, 0x0c },
+{ 0x00, 0x0d, 0x0d },
+{ 0x00, 0x0e, 0x0e },
+{ 0x00, 0x0f, 0x0f },
+{ 0x00, 0x10, 0x10 },
+{ 0x00, 0x11, 0x11 },
+{ 0x00, 0x12, 0x12 },
+{ 0x00, 0x13, 0x13 },
+{ 0x00, 0x14, 0x14 },
+{ 0x00, 0x15, 0x15 },
+{ 0x00, 0x16, 0x16 },
+{ 0x00, 0x17, 0x17 },
+{ 0x00, 0x18, 0x18 },
+{ 0x00, 0x19, 0x19 },
+{ 0x00, 0x1a, 0x1a },
+{ 0x00, 0x1b, 0x1b },
+{ 0x00, 0x1c, 0x1c },
+{ 0x00, 0x1d, 0x1d },
+{ 0x00, 0x1e, 0x1e },
+{ 0x00, 0x1f, 0x1f },
+{ 0x00, 0x20, 0x20 },
+{ 0x00, 0x21, 0x21 },
+{ 0x00, 0x22, 0x22 },
+{ 0x00, 0x23, 0x23 },
+{ 0x00, 0x24, 0x24 },
+{ 0x00, 0x25, 0x25 },
+{ 0x00, 0x26, 0x26 },
+{ 0x00, 0x27, 0x27 },
+{ 0x00, 0x28, 0x28 },
+{ 0x00, 0x29, 0x29 },
+{ 0x00, 0x2a, 0x2a },
+{ 0x00, 0x2b, 0x2b },
+{ 0x00, 0x2c, 0x2c },
+{ 0x00, 0x2d, 0x2d },
+{ 0x00, 0x2e, 0x2e },
+{ 0x00, 0x2f, 0x2f },
+{ 0x00, 0x30, 0x30 },
+{ 0x00, 0x31, 0x31 },
+{ 0x00, 0x32, 0x32 },
+{ 0x00, 0x33, 0x33 },
+{ 0x00, 0x34, 0x34 },
+{ 0x00, 0x35, 0x35 },
+{ 0x00, 0x36, 0x36 },
+{ 0x00, 0x37, 0x37 },
+{ 0x00, 0x38, 0x38 },
+{ 0x00, 0x39, 0x39 },
+{ 0x00, 0x3a, 0x3a },
+{ 0x00, 0x3b, 0x3b },
+{ 0x00, 0x3c, 0x3c },
+{ 0x00, 0x3d, 0x3d },
+{ 0x00, 0x3e, 0x3e },
+{ 0x00, 0x3f, 0x3f },
+{ 0x00, 0x40, 0x40 },
+{ 0x01, 0x61, 0x41 },
+{ 0x01, 0x62, 0x42 },
+{ 0x01, 0x63, 0x43 },
+{ 0x01, 0x64, 0x44 },
+{ 0x01, 0x65, 0x45 },
+{ 0x01, 0x66, 0x46 },
+{ 0x01, 0x67, 0x47 },
+{ 0x01, 0x68, 0x48 },
+{ 0x01, 0x69, 0x49 },
+{ 0x01, 0x6a, 0x4a },
+{ 0x01, 0x6b, 0x4b },
+{ 0x01, 0x6c, 0x4c },
+{ 0x01, 0x6d, 0x4d },
+{ 0x01, 0x6e, 0x4e },
+{ 0x01, 0x6f, 0x4f },
+{ 0x01, 0x70, 0x50 },
+{ 0x01, 0x71, 0x51 },
+{ 0x01, 0x72, 0x52 },
+{ 0x01, 0x73, 0x53 },
+{ 0x01, 0x74, 0x54 },
+{ 0x01, 0x75, 0x55 },
+{ 0x01, 0x76, 0x56 },
+{ 0x01, 0x77, 0x57 },
+{ 0x01, 0x78, 0x58 },
+{ 0x01, 0x79, 0x59 },
+{ 0x01, 0x7a, 0x5a },
+{ 0x00, 0x5b, 0x5b },
+{ 0x00, 0x5c, 0x5c },
+{ 0x00, 0x5d, 0x5d },
+{ 0x00, 0x5e, 0x5e },
+{ 0x00, 0x5f, 0x5f },
+{ 0x00, 0x60, 0x60 },
+{ 0x00, 0x61, 0x41 },
+{ 0x00, 0x62, 0x42 },
+{ 0x00, 0x63, 0x43 },
+{ 0x00, 0x64, 0x44 },
+{ 0x00, 0x65, 0x45 },
+{ 0x00, 0x66, 0x46 },
+{ 0x00, 0x67, 0x47 },
+{ 0x00, 0x68, 0x48 },
+{ 0x00, 0x69, 0x49 },
+{ 0x00, 0x6a, 0x4a },
+{ 0x00, 0x6b, 0x4b },
+{ 0x00, 0x6c, 0x4c },
+{ 0x00, 0x6d, 0x4d },
+{ 0x00, 0x6e, 0x4e },
+{ 0x00, 0x6f, 0x4f },
+{ 0x00, 0x70, 0x50 },
+{ 0x00, 0x71, 0x51 },
+{ 0x00, 0x72, 0x52 },
+{ 0x00, 0x73, 0x53 },
+{ 0x00, 0x74, 0x54 },
+{ 0x00, 0x75, 0x55 },
+{ 0x00, 0x76, 0x56 },
+{ 0x00, 0x77, 0x57 },
+{ 0x00, 0x78, 0x58 },
+{ 0x00, 0x79, 0x59 },
+{ 0x00, 0x7a, 0x5a },
+{ 0x00, 0x7b, 0x7b },
+{ 0x00, 0x7c, 0x7c },
+{ 0x00, 0x7d, 0x7d },
+{ 0x00, 0x7e, 0x7e },
+{ 0x00, 0x7f, 0x7f },
+{ 0x00, 0x80, 0x80 },
+{ 0x00, 0x81, 0x81 },
+{ 0x00, 0x82, 0x82 },
+{ 0x00, 0x83, 0x83 },
+{ 0x00, 0x84, 0x84 },
+{ 0x00, 0x85, 0x85 },
+{ 0x00, 0x86, 0x86 },
+{ 0x00, 0x87, 0x87 },
+{ 0x00, 0x88, 0x88 },
+{ 0x00, 0x89, 0x89 },
+{ 0x00, 0x8a, 0x8a },
+{ 0x00, 0x8b, 0x8b },
+{ 0x00, 0x8c, 0x8c },
+{ 0x00, 0x8d, 0x8d },
+{ 0x00, 0x8e, 0x8e },
+{ 0x00, 0x8f, 0x8f },
+{ 0x00, 0x90, 0x90 },
+{ 0x00, 0x91, 0x91 },
+{ 0x00, 0x92, 0x92 },
+{ 0x00, 0x93, 0x93 },
+{ 0x00, 0x94, 0x94 },
+{ 0x00, 0x95, 0x95 },
+{ 0x00, 0x96, 0x96 },
+{ 0x00, 0x97, 0x97 },
+{ 0x00, 0x98, 0x98 },
+{ 0x00, 0x99, 0x99 },
+{ 0x00, 0x9a, 0x9a },
+{ 0x00, 0x9b, 0x9b },
+{ 0x00, 0x9c, 0x9c },
+{ 0x00, 0x9d, 0x9d },
+{ 0x00, 0x9e, 0x9e },
+{ 0x00, 0x9f, 0x9f },
+{ 0x00, 0xa0, 0xa0 },
+{ 0x00, 0xa1, 0xa1 },
+{ 0x00, 0xa2, 0xa2 },
+{ 0x00, 0xa3, 0xa3 },
+{ 0x00, 0xa4, 0xa4 },
+{ 0x00, 0xa5, 0xa5 },
+{ 0x00, 0xa6, 0xa6 },
+{ 0x00, 0xa7, 0xa7 },
+{ 0x00, 0xa8, 0xa8 },
+{ 0x00, 0xa9, 0xa9 },
+{ 0x00, 0xaa, 0xaa },
+{ 0x00, 0xab, 0xab },
+{ 0x00, 0xac, 0xac },
+{ 0x00, 0xad, 0xad },
+{ 0x00, 0xae, 0xae },
+{ 0x00, 0xaf, 0xaf },
+{ 0x00, 0xb0, 0xb0 },
+{ 0x00, 0xb1, 0xb1 },
+{ 0x00, 0xb2, 0xb2 },
+{ 0x00, 0xb3, 0xb3 },
+{ 0x00, 0xb4, 0xb4 },
+{ 0x00, 0xb5, 0xb5 },
+{ 0x00, 0xb6, 0xb6 },
+{ 0x00, 0xb7, 0xb7 },
+{ 0x00, 0xb8, 0xb8 },
+{ 0x00, 0xb9, 0xb9 },
+{ 0x00, 0xba, 0xba },
+{ 0x00, 0xbb, 0xbb },
+{ 0x00, 0xbc, 0xbc },
+{ 0x00, 0xbd, 0xbd },
+{ 0x00, 0xbe, 0xbe },
+{ 0x00, 0xbf, 0xbf },
+{ 0x00, 0xc0, 0xc0 },
+{ 0x00, 0xc1, 0xc1 },
+{ 0x00, 0xc2, 0xc2 },
+{ 0x00, 0xc3, 0xc3 },
+{ 0x00, 0xc4, 0xc4 },
+{ 0x00, 0xc5, 0xc5 },
+{ 0x00, 0xc6, 0xc6 },
+{ 0x00, 0xc7, 0xc7 },
+{ 0x00, 0xc8, 0xc8 },
+{ 0x00, 0xc9, 0xc9 },
+{ 0x00, 0xca, 0xca },
+{ 0x00, 0xcb, 0xcb },
+{ 0x00, 0xcc, 0xcc },
+{ 0x00, 0xcd, 0xcd },
+{ 0x00, 0xce, 0xce },
+{ 0x00, 0xcf, 0xcf },
+{ 0x00, 0xd0, 0xd0 },
+{ 0x00, 0xd1, 0xd1 },
+{ 0x00, 0xd2, 0xd2 },
+{ 0x00, 0xd3, 0xd3 },
+{ 0x00, 0xd4, 0xd4 },
+{ 0x00, 0xd5, 0xd5 },
+{ 0x00, 0xd6, 0xd6 },
+{ 0x00, 0xd7, 0xd7 },
+{ 0x00, 0xd8, 0xd8 },
+{ 0x00, 0xd9, 0xd9 },
+{ 0x00, 0xda, 0xda },
+{ 0x00, 0xdb, 0xdb },
+{ 0x00, 0xdc, 0xdc },
+{ 0x00, 0xdd, 0xdd },
+{ 0x00, 0xde, 0xde },
+{ 0x00, 0xdf, 0xdf },
+{ 0x00, 0xe0, 0xe0 },
+{ 0x00, 0xe1, 0xe1 },
+{ 0x00, 0xe2, 0xe2 },
+{ 0x00, 0xe3, 0xe3 },
+{ 0x00, 0xe4, 0xe4 },
+{ 0x00, 0xe5, 0xe5 },
+{ 0x00, 0xe6, 0xe6 },
+{ 0x00, 0xe7, 0xe7 },
+{ 0x00, 0xe8, 0xe8 },
+{ 0x00, 0xe9, 0xe9 },
+{ 0x00, 0xea, 0xea },
+{ 0x00, 0xeb, 0xeb },
+{ 0x00, 0xec, 0xec },
+{ 0x00, 0xed, 0xed },
+{ 0x00, 0xee, 0xee },
+{ 0x00, 0xef, 0xef },
+{ 0x00, 0xf0, 0xf0 },
+{ 0x00, 0xf1, 0xf1 },
+{ 0x00, 0xf2, 0xf2 },
+{ 0x00, 0xf3, 0xf3 },
+{ 0x00, 0xf4, 0xf4 },
+{ 0x00, 0xf5, 0xf5 },
+{ 0x00, 0xf6, 0xf6 },
+{ 0x00, 0xf7, 0xf7 },
+{ 0x00, 0xf8, 0xf8 },
+{ 0x00, 0xf9, 0xf9 },
+{ 0x00, 0xfa, 0xfa },
+{ 0x00, 0xfb, 0xfb },
+{ 0x00, 0xfc, 0xfc },
+{ 0x00, 0xfd, 0xfd },
+{ 0x00, 0xfe, 0xfe },
+{ 0x00, 0xff, 0xff },
+};
+
+struct enc_entry encds[] = {
+{"ISO8859-1",iso1_tbl},
+{"ISO8859-2",iso2_tbl},
+{"ISO8859-3",iso3_tbl},
+{"ISO8859-4",iso4_tbl},
+{"ISO8859-5",iso5_tbl},
+{"ISO8859-6",iso6_tbl},
+{"ISO8859-7",iso7_tbl},
+{"ISO8859-8",iso8_tbl},
+{"ISO8859-9",iso9_tbl},
+{"ISO8859-10",iso10_tbl},
+{"KOI8-R",koi8r_tbl},
+{"KOI8-U",koi8u_tbl},
+{"microsoft-cp1251",cp1251_tbl},
+{"ISO8859-13", iso13_tbl},
+{"ISO8859-14", iso14_tbl},
+{"ISO8859-15", iso15_tbl},
+{"ISCII-DEVANAGARI", iscii_devanagari_tbl},
+};
+
+struct cs_info * get_current_cs(const char * es) {
+  struct cs_info * ccs = encds[0].cs_table;
+  int n = sizeof(encds) / sizeof(encds[0]);
+  for (int i = 0; i < n; i++) {
+    if (strcmp(es,encds[i].enc_name) == 0) {
+      ccs = encds[i].cs_table;
+    }
+  }
+  return ccs;
+}
+#else
+// XXX This function was rewritten for mozilla. Instead of storing the
+// conversion tables static in this file, create them when needed
+// with help the mozilla backend.
+struct cs_info * get_current_cs(const char * es) {
+  struct cs_info *ccs;
+
+  nsCOMPtr<nsIUnicodeEncoder> encoder; 
+  nsCOMPtr<nsIUnicodeDecoder> decoder; 
+  nsCOMPtr<nsICaseConversion> caseConv;
+
+  nsresult rv;
+  nsCOMPtr<nsICharsetConverterManager> ccm = do_GetService(kCharsetConverterManagerCID, &rv);
+  if (NS_FAILED(rv))
+    return nsnull;
+
+  rv = ccm->GetUnicodeEncoder(es, getter_AddRefs(encoder));
+  if (encoder && NS_SUCCEEDED(rv))
+    encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?');
+  if (NS_FAILED(rv))
+    return nsnull;
+  rv = ccm->GetUnicodeDecoder(es, getter_AddRefs(decoder));
+
+  caseConv = do_GetService(kUnicharUtilCID, &rv);
+  if (NS_FAILED(rv))
+    return nsnull;
+
+  ccs = (struct cs_info *) malloc(256 * sizeof(cs_info));
+
+  PRInt32 charLength = 256;
+  PRInt32 uniLength = 512;
+  char *source = (char *)malloc(charLength * sizeof(char));
+  PRUnichar *uni = (PRUnichar *)malloc(uniLength * sizeof(PRUnichar));
+  char *lower = (char *)malloc(charLength * sizeof(char));
+  char *upper = (char *)malloc(charLength * sizeof(char));
+
+  // Create a long string of all chars.
+  unsigned int i;
+  for (i = 0x00; i <= 0xff ; ++i) {
+    source[i] = i;
+  }
+
+  // Convert this long string to unicode
+  rv = decoder->Convert(source, &charLength, uni, &uniLength);
+
+  // Do case conversion stuff, and convert back.
+  caseConv->ToUpper(uni, uni, uniLength);
+  encoder->Convert(uni, &uniLength, upper, &charLength);
+
+  uniLength = 512;
+  charLength = 256;
+  rv = decoder->Convert(source, &charLength, uni, &uniLength);
+  caseConv->ToLower(uni, uni, uniLength);
+  encoder->Convert(uni, &uniLength, lower, &charLength);
+
+  // Store
+  for (i = 0x00; i <= 0xff ; ++i) {
+    ccs[i].cupper = upper[i];
+    ccs[i].clower = lower[i];
+    
+    if (ccs[i].clower != (unsigned char)i)
+      ccs[i].ccase = true;
+    else
+      ccs[i].ccase = false;
+      
+  }
+
+  free(source);
+  free(uni);
+  free(lower);
+  free(upper);
+
+  return ccs;
+}
+#endif
+
+// primitive isalpha() replacement for tokenization
+char * get_casechars(const char * enc) {
+    struct cs_info * csconv = get_current_cs(enc);
+    char expw[MAXLNLEN];
+    char * p =  expw;
+    for (int i = 0; i <= 255; i++) {
+        if ((csconv[i].cupper != csconv[i].clower)) {
+    	    *p = (char) i;
+    	    p++;
+        }
+    }
+    *p = '\0';
+#ifdef MOZILLA_CLIENT
+    delete csconv;
+#endif
+    return mystrdup(expw);
+}
+
+
+
+struct lang_map lang2enc[] = {
+{"ar", "UTF-8", LANG_ar},
+{"az", "UTF-8", LANG_az},
+{"bg", "microsoft-cp1251", LANG_bg},
+{"ca", "ISO8859-1", LANG_ca},
+{"cs", "ISO8859-2", LANG_cs},
+{"da", "ISO8859-1", LANG_da},
+{"de", "ISO8859-1", LANG_de},
+{"el", "ISO8859-7", LANG_el},
+{"en", "ISO8859-1", LANG_en},
+{"es", "ISO8859-1", LANG_es},
+{"eu", "ISO8859-1", LANG_eu},
+{"gl", "ISO8859-1", LANG_gl},
+{"fr", "ISO8859-15", LANG_fr},
+{"hr", "ISO8859-2", LANG_hr},
+{"hu", "ISO8859-2", LANG_hu},
+{"it", "ISO8859-1", LANG_it},
+{"la", "ISO8859-1", LANG_la},
+{"lv", "ISO8859-13", LANG_lv},
+{"nl", "ISO8859-1", LANG_nl},
+{"pl", "ISO8859-2", LANG_pl},
+{"pt", "ISO8859-1", LANG_pt},
+{"sv", "ISO8859-1", LANG_sv},
+{"tr", "UTF-8", LANG_tr},
+{"ru", "KOI8-R", LANG_ru},
+{"uk", "KOI8-U", LANG_uk}
+};
+
+
+const char * get_default_enc(const char * lang) {
+  int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
+  for (int i = 0; i < n; i++) {
+    if (strcmp(lang,lang2enc[i].lang) == 0) {
+      return lang2enc[i].def_enc;
+    }
+  }
+  return NULL;
+}
+
+int get_lang_num(const char * lang) {
+  int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
+  for (int i = 0; i < n; i++) {
+    if (strncmp(lang,lang2enc[i].lang,2) == 0) {
+      return lang2enc[i].num;
+    }
+  }
+  return LANG_xx;
+}
+
+#ifndef OPENOFFICEORG
+#ifndef MOZILLA_CLIENT
+int initialize_utf_tbl() {
+  utf_tbl_count++;
+  if (utf_tbl) return 0;
+  utf_tbl = (unicode_info2 *) malloc(CONTSIZE * sizeof(unicode_info2));
+  if (utf_tbl) {
+    int j;
+    for (j = 0; j < CONTSIZE; j++) {
+      utf_tbl[j].cletter = 0;
+      utf_tbl[j].clower = (unsigned short) j;
+      utf_tbl[j].cupper = (unsigned short) j;
+    }
+    for (j = 0; j < UTF_LST_LEN; j++) {
+      utf_tbl[utf_lst[j].c].cletter = 1;
+      utf_tbl[utf_lst[j].c].clower = utf_lst[j].clower;
+      utf_tbl[utf_lst[j].c].cupper = utf_lst[j].cupper;
+    }
+  } else return 1;
+  return 0;
+}
+#endif
+#endif
+
+void free_utf_tbl() {
+  if (utf_tbl_count > 0) utf_tbl_count--;
+  if (utf_tbl && (utf_tbl_count == 0)) {
+    free(utf_tbl);
+    utf_tbl = NULL;
+  }
+}
+
+#ifdef MOZILLA_CLIENT
+static nsCOMPtr<nsICaseConversion>& getcaseConv()
+{
+  nsresult rv;
+  static nsCOMPtr<nsICaseConversion> caseConv = do_GetService(kUnicharUtilCID, &rv);
+  return caseConv;
+}
+#endif
+
+unsigned short unicodetoupper(unsigned short c, int langnum)
+{
+  // In Azeri and Turkish, I and i dictinct letters:
+  // There are a dotless lower case i pair of upper `I',
+  // and an upper I with dot pair of lower `i'. 
+  if (c == 0x0069 && ((langnum == LANG_az) || (langnum == LANG_tr)))
+    return 0x0130;
+#ifdef OPENOFFICEORG
+  return u_toupper(c);
+#else
+#ifdef MOZILLA_CLIENT
+  PRUnichar ch2;
+  getcaseConv()->ToUpper((PRUnichar) c, &ch2);
+  return ch2;
+#else
+  return (utf_tbl) ? utf_tbl[c].cupper : c;
+#endif
+#endif
+}
+
+unsigned short unicodetolower(unsigned short c, int langnum)
+{
+  // In Azeri and Turkish, I and i dictinct letters:
+  // There are a dotless lower case i pair of upper `I',
+  // and an upper I with dot pair of lower `i'. 
+  if (c == 0x0049 && ((langnum == LANG_az) || (langnum == LANG_tr)))
+    return 0x0131;
+#ifdef OPENOFFICEORG
+  return u_tolower(c);
+#else
+#ifdef MOZILLA_CLIENT
+  PRUnichar ch2;
+  getcaseConv()->ToLower((PRUnichar) c, &ch2);
+  return ch2;
+#else
+  return (utf_tbl) ? utf_tbl[c].clower : c;
+#endif
+#endif
+}
+
+int unicodeisalpha(unsigned short c)
+{
+#ifdef OPENOFFICEORG
+  return u_isalpha(c);
+#else
+  return (utf_tbl) ? utf_tbl[c].cletter : 0;
+#endif
+}
+
+/* get type of capitalization */
+int get_captype(char * word, int nl, cs_info * csconv) {
+   // now determine the capitalization type of the first nl letters
+   int ncap = 0;
+   int nneutral = 0;
+   int firstcap = 0;
+
+      for (char * q = word; *q != '\0'; q++) {
+         if (csconv[*((unsigned char *)q)].ccase) ncap++;
+         if (csconv[*((unsigned char *)q)].cupper == csconv[*((unsigned char *)q)].clower) nneutral++;
+      }
+      if (ncap) {
+        firstcap = csconv[*((unsigned char *) word)].ccase;
+      }
+
+   // now finally set the captype
+   if (ncap == 0) {
+        return NOCAP;
+   } else if ((ncap == 1) && firstcap) {
+        return INITCAP;
+   } else if ((ncap == nl) || ((ncap + nneutral) == nl)) {
+        return ALLCAP;
+   } else if ((ncap > 1) && firstcap) {
+        return HUHINITCAP;
+   }
+   return HUHCAP;
+}
+
+int get_captype_utf8(w_char * word, int nl, int langnum) {
+   // now determine the capitalization type of the first nl letters
+   int ncap = 0;
+   int nneutral = 0;
+   int firstcap = 0;
+   unsigned short idx;
+   // don't check too long words
+   if (nl >= MAXWORDLEN) return 0;
+   // big Unicode character (non BMP area)
+   if (nl == -1) return NOCAP;
+   for (int i = 0; i < nl; i++) {
+     idx = (word[i].h << 8) + word[i].l;
+     if (idx != unicodetolower(idx, langnum)) ncap++;
+     if (unicodetoupper(idx, langnum) == unicodetolower(idx, langnum)) nneutral++;
+   }
+   if (ncap) {
+      idx = (word[0].h << 8) + word[0].l;
+      firstcap = (idx != unicodetolower(idx, langnum));
+  }
+
+   // now finally set the captype
+   if (ncap == 0) {
+        return NOCAP;
+   } else if ((ncap == 1) && firstcap) {
+        return INITCAP;
+   } else if ((ncap == nl) || ((ncap + nneutral) == nl)) {
+        return ALLCAP;
+   } else if ((ncap > 1) && firstcap) {
+        return HUHINITCAP;
+   }
+   return HUHCAP;
+}
+
+
+// strip all ignored characters in the string
+void remove_ignored_chars_utf(char * word, unsigned short ignored_chars[], int ignored_len)
+{
+   w_char w[MAXWORDLEN];
+   w_char w2[MAXWORDLEN];
+   int i;
+   int j;
+   int len = u8_u16(w, MAXWORDLEN, word);
+   for (i = 0, j = 0; i < len; i++) {
+      if (!flag_bsearch(ignored_chars, ((unsigned short *) w)[i], ignored_len)) {
+         w2[j] = w[i];
+         j++;
+      }
+   }
+   if (j < i) u16_u8(word, MAXWORDUTF8LEN, w2, j);
+}
+
+// strip all ignored characters in the string
+void remove_ignored_chars(char * word, char * ignored_chars)
+{
+   for (char * p = word; *p != '\0'; p++) {
+      if (!strchr(ignored_chars, *p)) {
+        *word = *p;
+        word++;
+      }
+   }
+   *word = '\0';
+}
+
+int parse_string(char * line, char ** out, const char * warnvar)
+{
+   char * tp = line;
+   char * piece;
+   int i = 0;
+   int np = 0;
+   if (*out) {
+      HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", warnvar);
+      return 1;
+   }
+   piece = mystrsep(&tp, 0);
+   while (piece) {
+      if (*piece != '\0') {
+          switch(i) {
+              case 0: { np++; break; }
+              case 1: { 
+                *out = mystrdup(piece);
+                np++;
+                break;
+              }
+              default: break;
+          }
+          i++;
+      }
+      free(piece);
+      piece = mystrsep(&tp, 0);
+   }
+   if (np != 2) {
+      HUNSPELL_WARNING(stderr, "error: missing %s information\n", warnvar);
+      return 1;
+   } 
+   return 0;
+}
+
+int parse_array(char * line, char ** out,
+        unsigned short ** out_utf16, int * out_utf16_len, const char * name, int utf8) {
+   if (parse_string(line, out, name)) return 1;
+   if (utf8) {
+        w_char w[MAXWORDLEN];
+        int n = u8_u16(w, MAXWORDLEN, *out);
+        if (n > 0) {
+            flag_qsort((unsigned short *) w, 0, n);
+            *out_utf16 = (unsigned short *) malloc(n * sizeof(unsigned short));
+            if (!*out_utf16) return 1;
+            memcpy(*out_utf16, w, n * sizeof(unsigned short));
+        }
+        *out_utf16_len = n;
+   }
+   return 0;
+}
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/csutil.hxx spellcheck/hunspell/hunspell/csutil.hxx
--- spellcheck.old/hunspell/hunspell/csutil.hxx	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/csutil.hxx	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,233 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef __CSUTILHXX__
+#define __CSUTILHXX__
+
+// First some base level utility routines
+
+#define NOCAP   0
+#define INITCAP 1
+#define ALLCAP  2
+#define HUHCAP  3
+#define HUHINITCAP  4
+
+#define FIELD_STEM  "st:"
+#define FIELD_POS   "po:"
+#define FIELD_SUFF  "su:"
+#define FIELD_PREF  "pr:"
+#define FIELD_FREQ  "fr:"
+#define FIELD_PHON  "ph:"
+#define FIELD_HYPH  "hy:"
+#define FIELD_COMP  "co:"
+
+// default flags
+#define ONLYUPCASEFLAG 65535
+
+typedef struct {
+    unsigned char l;
+    unsigned char h;
+} w_char;
+
+#define w_char_eq(a,b) (((a).l == (b).l) && ((a).h == (b).h))
+
+// convert UTF-16 characters to UTF-8
+char * u16_u8(char * dest, int size, const w_char * src, int srclen);
+
+// convert UTF-8 characters to UTF-16
+int u8_u16(w_char * dest, int size, const char * src);
+
+// sort 2-byte vector
+void flag_qsort(unsigned short flags[], int begin, int end);
+
+// binary search in 2-byte vector
+int flag_bsearch(unsigned short flags[], unsigned short flag, int right);
+
+// remove end of line char(s)
+void   mychomp(char * s);
+
+// duplicate string
+char * mystrdup(const char * s);
+
+// duplicate reverse of string
+char * myrevstrdup(const char * s);
+
+// parse into tokens with char delimiter
+char * mystrsep(char ** sptr, const char delim);
+// parse into tokens with char delimiter
+char * mystrsep2(char ** sptr, const char delim);
+
+// parse into tokens with char delimiter
+char * mystrrep(char *, const char *, const char *);
+
+// append s to ends of every lines in text
+void strlinecat(char * lines, const char * s);
+
+// tokenize into lines with new line
+   int line_tok(const char * text, char *** lines);
+
+// tokenize into lines with new line and uniq in place
+   char * line_uniq(char * text);
+
+// change \n to c in place
+   char * line_join(char * text, char c);
+
+// leave only last {[^}]*} pattern in string
+   char * delete_zeros(char * morphout);
+
+// reverse word
+   int reverseword(char *);
+
+// reverse word
+   int reverseword_utf(char *);
+
+// character encoding information
+struct cs_info {
+  unsigned char ccase;
+  unsigned char clower;
+  unsigned char cupper;
+};
+
+// two character arrays
+struct replentry {
+  char * pattern;
+  char * pattern2;
+};
+
+// Unicode character encoding information
+struct unicode_info {
+  unsigned short c;
+  unsigned short cupper;
+  unsigned short clower;
+};
+
+struct unicode_info2 {
+  char cletter;
+  unsigned short cupper;
+  unsigned short clower;
+};
+
+int initialize_utf_tbl();
+void free_utf_tbl();
+unsigned short unicodetoupper(unsigned short c, int langnum);
+unsigned short unicodetolower(unsigned short c, int langnum);
+int unicodeisalpha(unsigned short c);
+
+struct enc_entry {
+  const char * enc_name;
+  struct cs_info * cs_table;
+};
+
+// language to encoding default map
+
+struct lang_map {
+  const char * lang;
+  const char * def_enc;
+  int num;
+};
+
+struct cs_info * get_current_cs(const char * es);
+
+const char * get_default_enc(const char * lang);
+
+// get language identifiers of language codes
+int get_lang_num(const char * lang);
+
+// get characters of the given 8bit encoding with lower- and uppercase forms
+char * get_casechars(const char * enc);
+
+// convert null terminated string to all caps using encoding
+void enmkallcap(char * d, const char * p, const char * encoding);
+
+// convert null terminated string to all little using encoding
+void enmkallsmall(char * d, const char * p, const char * encoding);
+
+// convert null terminated string to have intial capital using encoding
+void enmkinitcap(char * d, const char * p, const char * encoding);
+
+// convert null terminated string to all caps
+void mkallcap(char * p, const struct cs_info * csconv);
+
+// convert null terminated string to all little
+void mkallsmall(char * p, const struct cs_info * csconv);
+
+// convert null terminated string to have intial capital
+void mkinitcap(char * p, const struct cs_info * csconv);
+
+// convert first nc characters of UTF-8 string to little
+void mkallsmall_utf(w_char * u, int nc, int langnum);
+
+// convert first nc characters of UTF-8 string to capital
+void mkallcap_utf(w_char * u, int nc, int langnum);
+
+// get type of capitalization
+int get_captype(char * q, int nl, cs_info *);
+
+// get type of capitalization (UTF-8)
+int get_captype_utf8(w_char * q, int nl, int langnum);
+
+// strip all ignored characters in the string
+void remove_ignored_chars_utf(char * word, unsigned short ignored_chars[], int ignored_len);
+
+// strip all ignored characters in the string
+void remove_ignored_chars(char * word, char * ignored_chars);
+
+int parse_string(char * line, char ** out, const char * name);
+
+int parse_array(char * line, char ** out,
+        unsigned short ** out_utf16, int * out_utf16_len, const char * name, int utf8);
+
+#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/hashmgr.cpp spellcheck/hunspell/hunspell/hashmgr.cpp
--- spellcheck.old/hunspell/hunspell/hashmgr.cpp	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/hashmgr.cpp	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,941 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef MOZILLA_CLIENT
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+#include <cctype>
+#else
+#include <stdlib.h> 
+#include <string.h>
+#include <stdio.h> 
+#include <ctype.h>
+#endif
+
+#include "hashmgr.hxx"
+#include "csutil.hxx"
+#include "atypes.hxx"
+
+#ifdef MOZILLA_CLIENT
+#ifdef __SUNPRO_CC // for SunONE Studio compiler
+using namespace std;
+#endif
+#else
+#ifndef W32
+using namespace std;
+#endif
+#endif
+
+// build a hash table from a munched word list
+
+HashMgr::HashMgr(const char * tpath, const char * apath)
+{
+  tablesize = 0;
+  tableptr = NULL;
+  flag_mode = FLAG_CHAR;
+  complexprefixes = 0;
+  utf8 = 0;
+  langnum = 0;
+  lang = NULL;
+  enc = NULL;
+  csconv = 0;
+  ignorechars = NULL;
+  ignorechars_utf16 = NULL;
+  ignorechars_utf16_len = 0;
+  numaliasf = 0;
+  aliasf = NULL;
+  numaliasm = 0;
+  aliasm = NULL;
+  forbiddenword = FLAG_NULL; // forbidden word signing flag
+  load_config(apath);  
+  int ec = load_tables(tpath);
+  if (ec) {
+    /* error condition - what should we do here */
+    HUNSPELL_WARNING(stderr, "Hash Manager Error : %d\n",ec);
+    if (tableptr) {
+      free(tableptr);
+      tableptr = NULL;
+    }
+    tablesize = 0;
+  }
+}
+
+
+HashMgr::~HashMgr()
+{
+  if (tableptr) {
+    // now pass through hash table freeing up everything
+    // go through column by column of the table
+    for (int i=0; i < tablesize; i++) {
+      struct hentry * pt = tableptr[i];
+      struct hentry * nt = NULL;
+/*      if (pt) {
+        if (pt->astr && (!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen))) free(pt->astr);
+#ifdef HUNSPELL_EXPERIMENTAL
+        if (pt->description && !aliasm) free(pt->description);
+#endif
+        pt = pt->next;
+      }
+*/
+      while(pt) {
+        nt = pt->next;
+        if (pt->astr && (!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen))) free(pt->astr);
+#ifdef HUNSPELL_EXPERIMENTAL
+        if (pt->description && !aliasm) free(pt->description);
+#endif
+        free(pt);
+        pt = nt;
+      }
+    }
+    free(tableptr);
+  }
+  tablesize = 0;
+
+  if (aliasf) {
+    for (int j = 0; j < (numaliasf); j++) free(aliasf[j]);
+    free(aliasf);
+    aliasf = NULL;
+    if (aliasflen) {
+      free(aliasflen);
+      aliasflen = NULL;
+    }
+  }
+  if (aliasm) {
+    for (int j = 0; j < (numaliasm); j++) free(aliasm[j]);
+    free(aliasm);
+    aliasm = NULL;
+  }  
+
+#ifndef OPENOFFICEORG
+#ifndef MOZILLA_CLIENT
+  if (utf8) free_utf_tbl();
+#endif
+#endif
+
+  if (enc) free(enc);
+  if (lang) free(lang);
+  
+  if (ignorechars) free(ignorechars);
+  if (ignorechars_utf16) free(ignorechars_utf16);
+}
+
+// lookup a root word in the hashtable
+
+struct hentry * HashMgr::lookup(const char *word) const
+{
+    struct hentry * dp;
+    if (tableptr) {
+       dp = tableptr[hash(word)];
+       if (!dp) return NULL;
+       for (  ;  dp != NULL;  dp = dp->next) {
+          if (strcmp(word,&(dp->word)) == 0) return dp;
+       }
+    }
+    return NULL;
+}
+
+// add a word to the hash table (private)
+int HashMgr::add_word(const char * word, int wbl, int wcl, unsigned short * aff,
+    int al, const char * desc, bool onlyupcase)
+{
+    bool upcasehomonym = false;
+    int descl = (desc) ? strlen(desc) : 0;
+    // variable-length hash record with word and optional fields
+    // instead of mmap implementation temporarily
+    struct hentry* hp = 
+	(struct hentry *) malloc (sizeof(struct hentry) + wbl + descl + 1);
+    if (!hp) return 1;
+    char * hpw = &(hp->word);
+    strcpy(hpw, word);
+    if (desc && strncmp(desc, FIELD_PHON, strlen(FIELD_PHON)) == 0) {
+	strcpy(hpw + wbl + 1, desc + strlen(FIELD_PHON));
+	hp->var = 1;
+    } else {
+	hp->var = 0;
+    }
+    if (ignorechars != NULL) {
+      if (utf8) {
+        remove_ignored_chars_utf(hpw, ignorechars_utf16, ignorechars_utf16_len);
+      } else {
+        remove_ignored_chars(hpw, ignorechars);
+      }
+    }
+    if (complexprefixes) {
+        if (utf8) reverseword_utf(hpw); else reverseword(hpw);
+    }
+
+    int i = hash(hpw);
+
+       hp->blen = (unsigned char) wbl;
+       hp->clen = (unsigned char) wcl;
+       hp->alen = (short) al;
+       hp->astr = aff;
+       hp->next = NULL;      
+       hp->next_homonym = NULL;
+#ifdef HUNSPELL_EXPERIMENTAL       
+       if (aliasm) {
+            hp->description = (desc) ? get_aliasm(atoi(desc)) : mystrdup(desc);
+       } else {
+            hp->description = mystrdup(desc);
+            if (desc && !hp->description)
+            {
+                free(hp->astr);
+                free(hp);
+                return 1;
+            }
+            if (hp->description && complexprefixes) {
+                if (utf8) reverseword_utf(hp->description); else reverseword(hp->description);
+            }
+       }
+#endif
+       
+       struct hentry * dp = tableptr[i];
+       if (!dp) {
+         tableptr[i] = hp;
+         return 0;
+       }
+       while (dp->next != NULL) {
+         if ((!dp->next_homonym) && (strcmp(&(hp->word), &(dp->word)) == 0)) {
+    	    // remove hidden onlyupcase homonym
+            if (!onlyupcase) {
+		if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) {
+		    free(dp->astr);
+		    dp->astr = hp->astr;
+		    dp->alen = hp->alen;
+		    free(hp);
+		    return 0;
+		} else {
+    		    dp->next_homonym = hp;
+    		}
+            } else {
+        	upcasehomonym = true;
+            }
+         }
+         dp=dp->next;
+       }
+       if (strcmp(&(hp->word), &(dp->word)) == 0) {
+    	    // remove hidden onlyupcase homonym
+            if (!onlyupcase) {
+		if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) {
+		    free(dp->astr);
+		    dp->astr = hp->astr;
+		    dp->alen = hp->alen;
+		    free(hp);
+		    return 0;
+		} else {
+    		    dp->next_homonym = hp;
+    		}
+            } else {
+        	upcasehomonym = true;
+            }
+       }
+       if (!upcasehomonym) {
+    	    dp->next = hp;
+       } else {
+    	    // remove hidden onlyupcase homonym
+    	    if (hp->astr) free(hp->astr);
+    	    free(hp);
+       }
+    return 0;
+}     
+
+int HashMgr::add_hidden_capitalized_word(char * word, int wbl, int wcl,
+    unsigned short * flags, int al, char * dp, int captype)
+{
+    // add inner capitalized forms to handle the following allcap forms:
+    // Mixed caps: OpenOffice.org -> OPENOFFICE.ORG
+    // Allcaps with suffixes: CIA's -> CIA'S    
+    if (((captype == HUHCAP) || (captype == HUHINITCAP) ||
+      ((captype == ALLCAP) && (flags != NULL))) &&
+      !((flags != NULL) && TESTAFF(flags, forbiddenword, al))) {
+          unsigned short * flags2 = (unsigned short *) malloc (sizeof(unsigned short) * (al+1));
+	  if (!flags2) return 1;
+          if (al) memcpy(flags2, flags, al * sizeof(unsigned short));
+          flags2[al] = ONLYUPCASEFLAG;
+          if (utf8) {
+              char st[MAXDELEN];
+              w_char w[MAXDELEN];
+              int wlen = u8_u16(w, MAXDELEN, word);
+              mkallsmall_utf(w, wlen, langnum);
+              mkallcap_utf(w, 1, langnum);
+              u16_u8(st, MAXDELEN, w, wlen);
+              return add_word(st,wbl,wcl,flags2,al+1,dp, true);
+           } else {
+               mkallsmall(word, csconv);
+               mkinitcap(word, csconv);
+               return add_word(word,wbl,wcl,flags2,al+1,dp, true);
+           }
+    }
+    return 0;
+}
+
+// detect captype and modify word length for UTF-8 encoding
+int HashMgr::get_clen_and_captype(const char * word, int wbl, int * captype) {
+    int len;
+    if (utf8) {
+      w_char dest_utf[MAXDELEN];
+      len = u8_u16(dest_utf, MAXDELEN, word);
+      *captype = get_captype_utf8(dest_utf, len, langnum);
+    } else {
+      len = wbl;
+      *captype = get_captype((char *) word, len, csconv);
+    }
+    return len;
+}
+
+// add a custom dic. word to the hash table (public)
+int HashMgr::put_word(const char * word, char * aff)
+{
+    unsigned short * flags;
+    int al = 0;
+    if (aff) {
+        al = decode_flags(&flags, aff);
+        flag_qsort(flags, 0, al);
+    } else {
+        flags = NULL;
+    }
+
+    int captype;
+    int wbl = strlen(word);
+    int wcl = get_clen_and_captype(word, wbl, &captype);
+    add_word(word, wbl, wcl, flags, al, NULL, false);
+    return add_hidden_capitalized_word((char *) word, wbl, wcl, flags, al, NULL, captype);
+}
+
+int HashMgr::put_word_pattern(const char * word, const char * pattern)
+{
+    // detect captype and modify word length for UTF-8 encoding
+    struct hentry * dp = lookup(pattern);
+    if (dp && dp->astr) {
+        int captype;
+        int wbl = strlen(word);
+        int wcl = get_clen_and_captype(word, wbl, &captype);
+	if (aliasf) {
+	    add_word(word, wbl, wcl, dp->astr, dp->alen, NULL, false);	
+	} else {
+    	    unsigned short * flags = (unsigned short *) malloc (dp->alen * sizeof(short));
+	    if (flags) {
+		memcpy((void *) flags, (void *) dp->astr, dp->alen * sizeof(short));
+		add_word(word, wbl, wcl, flags, dp->alen, NULL, false);
+	    } else return 1;
+	}
+    	return add_hidden_capitalized_word((char *) word, wbl, wcl, dp->astr, dp->alen, NULL, captype);
+    }
+    return 1;
+}
+
+// walk the hash table entry by entry - null at end
+// initialize: col=-1; hp = NULL; hp = walk_hashtable(&col, hp);
+struct hentry * HashMgr::walk_hashtable(int &col, struct hentry * hp) const
+{  
+  if (hp && hp->next != NULL) return hp->next;
+  for (col++; col < tablesize; col++) {
+    if (tableptr[col]) return tableptr[col];
+  }
+  // null at end and reset to start
+  col = -1;
+  return NULL;
+}
+
+// load a munched word list and build a hash table on the fly
+int HashMgr::load_tables(const char * tpath)
+{
+  int al;
+  char * ap;
+  char * dp;
+  unsigned short * flags;
+
+  // raw dictionary - munched file
+  FILE * rawdict = fopen(tpath, "r");
+  if (rawdict == NULL) return 1;
+
+  // first read the first line of file to get hash table size */
+  char ts[MAXDELEN];
+  if (! fgets(ts, MAXDELEN-1,rawdict)) {
+    HUNSPELL_WARNING(stderr, "error: empty dic file\n");
+    fclose(rawdict);
+    return 2;
+  }
+  mychomp(ts);
+  
+  /* remove byte order mark */
+  if (strncmp(ts,"\xEF\xBB\xBF",3) == 0) {
+    memmove(ts, ts+3, strlen(ts+3)+1);
+    HUNSPELL_WARNING(stderr, "warning: dic file begins with byte order mark: possible incompatibility with old Hunspell versions\n");
+  }
+  
+  if ((*ts < '1') || (*ts > '9')) HUNSPELL_WARNING(stderr, "error - missing word count in dictionary file\n");
+  tablesize = atoi(ts);
+  if (!tablesize) {
+    fclose(rawdict);
+    return 4;
+  }
+  tablesize = tablesize + 5 + USERWORD;
+  if ((tablesize %2) == 0) tablesize++;
+
+  // allocate the hash table
+  tableptr = (struct hentry **) malloc(tablesize * sizeof(struct hentry *));
+  if (! tableptr) {
+    fclose(rawdict);
+    return 3;
+  }
+  for (int i=0; i<tablesize; i++) tableptr[i] = NULL;
+
+  // loop through all words on much list and add to hash
+  // table and create word and affix strings
+
+  while (fgets(ts,MAXDELEN-1,rawdict)) {
+    mychomp(ts);
+    // split each line into word and morphological description
+    dp = strchr(ts,'\t');
+
+    if (dp) {
+      *dp = '\0';
+      dp++;
+    } else {
+      dp = NULL;
+    }
+
+    // split each line into word and affix char strings
+    // "\/" signs slash in words (not affix separator)
+    // "/" at beginning of the line is word character (not affix separator)
+    ap = strchr(ts,'/');
+    while (ap) {
+        if (ap == ts) {
+            ap++;
+            continue;
+        } else if (*(ap - 1) != '\\') break;
+        // replace "\/" with "/"
+        for (char * sp = ap - 1; *sp; *sp = *(sp + 1), sp++);
+        ap = strchr(ap,'/');
+    }
+
+    if (ap) {
+      *ap = '\0';
+      if (aliasf) {
+        int index = atoi(ap + 1);
+        al = get_aliasf(index, &flags);
+        if (!al) {
+            HUNSPELL_WARNING(stderr, "error - bad flag vector alias: %s\n", ts);
+            *ap = '\0';
+        }
+      } else {
+        al = decode_flags(&flags, ap + 1);
+        flag_qsort(flags, 0, al);
+      }
+    } else {
+      al = 0;
+      ap = NULL;
+      flags = NULL;
+    }
+
+    int captype;
+    int wbl = strlen(ts);
+    int wcl = get_clen_and_captype(ts, wbl, &captype);
+    // add the word and its index plus its capitalized form optionally
+    if (add_word(ts,wbl,wcl,flags,al,dp, false) ||
+	add_hidden_capitalized_word(ts, wbl, wcl, flags, al, dp, captype)) {
+	fclose(rawdict);
+	return 5;
+    }
+  }
+
+  fclose(rawdict);
+  return 0;
+}
+
+
+// the hash function is a simple load and rotate
+// algorithm borrowed
+
+int HashMgr::hash(const char * word) const
+{
+    long  hv = 0;
+    for (int i=0; i < 4  &&  *word != 0; i++)
+        hv = (hv << 8) | (*word++);
+    while (*word != 0) {
+      ROTATE(hv,ROTATE_LEN);
+      hv ^= (*word++);
+    }
+    return (unsigned long) hv % tablesize;
+}
+
+int HashMgr::decode_flags(unsigned short ** result, char * flags) {
+    int len;
+    switch (flag_mode) {
+      case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz)
+        len = strlen(flags);
+        if (len%2 == 1) HUNSPELL_WARNING(stderr, "error: length of FLAG_LONG flagvector is odd: %s\n", flags);
+        len /= 2;
+        *result = (unsigned short *) malloc(len * sizeof(short));
+        if (!*result) return -1;
+        for (int i = 0; i < len; i++) {
+            (*result)[i] = (((unsigned short) flags[i * 2]) << 8) + (unsigned short) flags[i * 2 + 1]; 
+        }
+        break;
+      }
+      case FLAG_NUM: { // decimal numbers separated by comma (4521,23,233 -> 4521 23 233)
+        len = 1;
+        char * src = flags; 
+        unsigned short * dest;
+        char * p;
+        for (p = flags; *p; p++) {
+          if (*p == ',') len++;
+        }
+        *result = (unsigned short *) malloc(len * sizeof(short));
+        if (!*result) return -1;
+        dest = *result;
+        for (p = flags; *p; p++) {
+          if (*p == ',') {
+            *dest = (unsigned short) atoi(src);
+            if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
+            src = p + 1;
+            dest++;
+          }
+        }
+        *dest = (unsigned short) atoi(src);
+        if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
+        break;
+      }    
+      case FLAG_UNI: { // UTF-8 characters
+        w_char w[MAXDELEN/2];
+        len = u8_u16(w, MAXDELEN/2, flags);
+        *result = (unsigned short *) malloc(len * sizeof(short));
+        if (!*result) return -1;
+        memcpy(*result, w, len * sizeof(short));
+        break;
+      }
+      default: { // Ispell's one-character flags (erfg -> e r f g)
+        unsigned short * dest;
+        len = strlen(flags);
+        *result = (unsigned short *) malloc(len * sizeof(short));
+        if (!*result) return -1;
+        dest = *result;
+        for (unsigned char * p = (unsigned char *) flags; *p; p++) {
+          *dest = (unsigned short) *p;
+          dest++;
+        }
+      }
+    }      
+    return len;
+}
+
+unsigned short HashMgr::decode_flag(const char * f) {
+    unsigned short s = 0;
+    switch (flag_mode) {
+      case FLAG_LONG:
+        s = ((unsigned short) f[0] << 8) + (unsigned short) f[1];
+        break;
+      case FLAG_NUM:
+        s = (unsigned short) atoi(f);
+        break;
+      case FLAG_UNI:
+        u8_u16((w_char *) &s, 1, f);
+        break;
+      default:
+        s = (unsigned short) *((unsigned char *)f);
+    }
+    if (!s) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
+    return s;
+}
+
+char * HashMgr::encode_flag(unsigned short f) {
+    unsigned char ch[10];
+    if (f==0) return mystrdup("(NULL)");
+    if (flag_mode == FLAG_LONG) {
+        ch[0] = (unsigned char) (f >> 8);
+        ch[1] = (unsigned char) (f - ((f >> 8) << 8));
+        ch[2] = '\0';
+    } else if (flag_mode == FLAG_NUM) {
+        sprintf((char *) ch, "%d", f);
+    } else if (flag_mode == FLAG_UNI) {
+        u16_u8((char *) &ch, 10, (w_char *) &f, 1);
+    } else {
+        ch[0] = (unsigned char) (f);
+        ch[1] = '\0';
+    }
+    return mystrdup((char *) ch);
+}
+
+// read in aff file and set flag mode
+int  HashMgr::load_config(const char * affpath)
+{
+  int firstline = 1;
+  
+  // io buffers
+  char line[MAXDELEN+1];
+ 
+  // open the affix file
+  FILE * afflst;
+  afflst = fopen(affpath,"r");
+  if (!afflst) {
+    HUNSPELL_WARNING(stderr, "Error - could not open affix description file %s\n",affpath);
+    return 1;
+  }
+
+    // read in each line ignoring any that do not
+    // start with a known line type indicator
+
+    while (fgets(line,MAXDELEN,afflst)) {
+        mychomp(line);
+
+       /* remove byte order mark */
+       if (firstline) {
+         firstline = 0;
+         if (strncmp(line,"\xEF\xBB\xBF",3) == 0) memmove(line, line+3, strlen(line+3)+1);
+       }
+
+        /* parse in the try string */
+        if ((strncmp(line,"FLAG",4) == 0) && isspace(line[4])) {
+            if (flag_mode != FLAG_CHAR) {
+                HUNSPELL_WARNING(stderr, "error: duplicate FLAG parameter\n");
+            }
+            if (strstr(line, "long")) flag_mode = FLAG_LONG;
+            if (strstr(line, "num")) flag_mode = FLAG_NUM;
+            if (strstr(line, "UTF-8")) flag_mode = FLAG_UNI;
+            if (flag_mode == FLAG_CHAR) {
+                HUNSPELL_WARNING(stderr, "error: FLAG need `num', `long' or `UTF-8' parameter: %s\n", line);
+            }
+        }
+        if (strncmp(line,"FORBIDDENWORD",13) == 0) {
+          char * st = NULL;
+          if (parse_string(line, &st, "FORBIDDENWORD")) {
+             fclose(afflst);
+             return 1;
+          }
+          forbiddenword = decode_flag(st);
+          free(st);
+        }
+        if (strncmp(line, "SET", 3) == 0) {
+    	  if (parse_string(line, &enc, "SET")) {
+             fclose(afflst);
+             return 1;
+          }    	    
+    	  if (strcmp(enc, "UTF-8") == 0) {
+    	    utf8 = 1;
+#ifndef OPENOFFICEORG
+#ifndef MOZILLA_CLIENT
+    	    initialize_utf_tbl();
+#endif
+#endif
+    	  } else csconv = get_current_cs(enc);
+    	}
+        if (strncmp(line, "LANG", 4) == 0) {    	
+    	  if (parse_string(line, &lang, "LANG")) {
+             fclose(afflst);
+             return 1;
+          }    	    
+    	  langnum = get_lang_num(lang);
+    	}
+
+       /* parse in the ignored characters (for example, Arabic optional diacritics characters */
+       if (strncmp(line,"IGNORE",6) == 0) {
+          if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, "IGNORE", utf8)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+       if ((strncmp(line,"AF",2) == 0) && isspace(line[2])) {
+          if (parse_aliasf(line, afflst)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+
+#ifdef HUNSPELL_EXPERIMENTAL
+       if ((strncmp(line,"AM",2) == 0) && isspace(line[2])) {
+          if (parse_aliasm(line, afflst)) {
+             fclose(afflst);
+             return 1;
+          }
+       }
+#endif
+        if (strncmp(line,"COMPLEXPREFIXES",15) == 0) complexprefixes = 1;
+        if (((strncmp(line,"SFX",3) == 0) || (strncmp(line,"PFX",3) == 0)) && isspace(line[3])) break;
+    }
+    if (csconv == NULL) csconv = get_current_cs("ISO8859-1");
+    fclose(afflst);
+    return 0;
+}
+
+/* parse in the ALIAS table */
+int  HashMgr::parse_aliasf(char * line, FILE * af)
+{
+   if (numaliasf != 0) {
+      HUNSPELL_WARNING(stderr, "error: duplicate AF (alias for flag vector) tables used\n");
+      return 1;
+   }
+   char * tp = line;
+   char * piece;
+   int i = 0;
+   int np = 0;
+   piece = mystrsep(&tp, 0);
+   while (piece) {
+       if (*piece != '\0') {
+          switch(i) {
+             case 0: { np++; break; }
+             case 1: { 
+                       numaliasf = atoi(piece);
+                       if (numaliasf < 1) {
+                          numaliasf = 0;
+                          aliasf = NULL;
+                          aliasflen = NULL;
+                          HUNSPELL_WARNING(stderr, "incorrect number of entries in AF table\n");
+                          free(piece);
+                          return 1;
+                       }
+                       aliasf = (unsigned short **) malloc(numaliasf * sizeof(unsigned short *));
+                       aliasflen = (unsigned short *) malloc(numaliasf * sizeof(short));
+                       if (!aliasf || !aliasflen) {
+                          numaliasf = 0;
+                          if (aliasf) free(aliasf);
+                          if (aliasflen) free(aliasflen);
+                          aliasf = NULL;
+                          aliasflen = NULL;
+                          return 1;
+                       }
+                       np++;
+                       break;
+                     }
+             default: break;
+          }
+          i++;
+       }
+       free(piece);
+       piece = mystrsep(&tp, 0);
+   }
+   if (np != 2) {
+      numaliasf = 0;
+      free(aliasf);
+      free(aliasflen);
+      aliasf = NULL;
+      aliasflen = NULL;
+      HUNSPELL_WARNING(stderr, "error: missing AF table information\n");
+      return 1;
+   } 
+ 
+   /* now parse the numaliasf lines to read in the remainder of the table */
+   char * nl = line;
+   for (int j=0; j < numaliasf; j++) {
+        if (!fgets(nl,MAXDELEN,af)) return 1;
+        mychomp(nl);
+        tp = nl;
+        i = 0;
+        aliasf[j] = NULL;
+        aliasflen[j] = 0;
+        piece = mystrsep(&tp, 0);
+        while (piece) {
+           if (*piece != '\0') {
+               switch(i) {
+                  case 0: {
+                             if (strncmp(piece,"AF",2) != 0) {
+                                 numaliasf = 0;
+                                 free(aliasf);
+                                 free(aliasflen);
+                                 aliasf = NULL;
+                                 aliasflen = NULL;
+                                 HUNSPELL_WARNING(stderr, "error: AF table is corrupt\n");
+                                 free(piece);
+                                 return 1;
+                             }
+                             break;
+                          }
+                  case 1: {
+                            aliasflen[j] = (unsigned short) decode_flags(&(aliasf[j]), piece);
+                            flag_qsort(aliasf[j], 0, aliasflen[j]);
+                            break; 
+                          }
+                  default: break;
+               }
+               i++;
+           }
+           free(piece);
+           piece = mystrsep(&tp, 0);
+        }
+        if (!aliasf[j]) {
+             free(aliasf);
+             free(aliasflen);
+             aliasf = NULL;
+             aliasflen = NULL;
+             numaliasf = 0;
+             HUNSPELL_WARNING(stderr, "error: AF table is corrupt\n");
+             return 1;
+        }
+   }
+   return 0;
+}
+
+int HashMgr::is_aliasf() {
+    return (aliasf != NULL);
+}
+
+int HashMgr::get_aliasf(int index, unsigned short ** fvec) {
+    if ((index > 0) && (index <= numaliasf)) {
+        *fvec = aliasf[index - 1];
+        return aliasflen[index - 1];
+    }
+    HUNSPELL_WARNING(stderr, "error: bad flag alias index: %d\n", index);
+    *fvec = NULL;
+    return 0;
+}
+
+#ifdef HUNSPELL_EXPERIMENTAL
+/* parse morph alias definitions */
+int  HashMgr::parse_aliasm(char * line, FILE * af)
+{
+   if (numaliasm != 0) {
+      HUNSPELL_WARNING(stderr, "error: duplicate AM (aliases for morphological descriptions) tables used\n");
+      return 1;
+   }
+   char * tp = line;
+   char * piece;
+   int i = 0;
+   int np = 0;
+   piece = mystrsep(&tp, 0);
+   while (piece) {
+       if (*piece != '\0') {
+          switch(i) {
+             case 0: { np++; break; }
+             case 1: { 
+                       numaliasm = atoi(piece);
+                       if (numaliasm < 1) {
+                          HUNSPELL_WARNING(stderr, "incorrect number of entries in AM table\n");
+                          free(piece);
+                          return 1;
+                       }
+                       aliasm = (char **) malloc(numaliasm * sizeof(char *));
+                       if (!aliasm) {
+                          numaliasm = 0;
+                          return 1;
+                       }
+                       np++;
+                       break;
+                     }
+             default: break;
+          }
+          i++;
+       }
+       free(piece);
+       piece = mystrsep(&tp, 0);
+   }
+   if (np != 2) {
+      numaliasm = 0;
+      free(aliasm);
+      aliasm = NULL;
+      HUNSPELL_WARNING(stderr, "error: missing AM alias information\n");
+      return 1;
+   } 
+
+   /* now parse the numaliasm lines to read in the remainder of the table */
+   char * nl = line;
+   for (int j=0; j < numaliasm; j++) {
+        if (!fgets(nl,MAXDELEN,af)) return 1;
+        mychomp(nl);
+        tp = nl;
+        i = 0;
+        aliasm[j] = NULL;
+        piece = mystrsep(&tp, 0);
+        while (piece) {
+           if (*piece != '\0') {
+               switch(i) {
+                  case 0: {
+                             if (strncmp(piece,"AM",2) != 0) {
+                                 HUNSPELL_WARNING(stderr, "error: AM table is corrupt\n");
+                                 free(piece);
+                                 numaliasm = 0;
+                                 free(aliasm);
+                                 aliasm = NULL;
+                                 return 1;
+                             }
+                             break;
+                          }
+                  case 1: {
+                            if (complexprefixes) {
+                                if (utf8) reverseword_utf(piece);
+                                    else reverseword(piece);
+                            }
+                            aliasm[j] = mystrdup(piece);
+                            break; }
+                  default: break;
+               }
+               i++;
+           }
+           free(piece);
+           piece = mystrsep(&tp, 0);
+        }
+        if (!aliasm[j]) {
+             numaliasm = 0;
+             free(aliasm);
+             aliasm = NULL;
+             HUNSPELL_WARNING(stderr, "error: map table is corrupt\n");
+             return 1;
+        }
+   }
+   return 0;
+}
+
+int HashMgr::is_aliasm() {
+    return (aliasm != NULL);
+}
+
+char * HashMgr::get_aliasm(int index) {
+    if ((index > 0) && (index <= numaliasm)) return aliasm[index - 1];
+    HUNSPELL_WARNING(stderr, "error: bad morph. alias index: %d\n", index);
+    return NULL;
+}
+#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/hashmgr.hxx spellcheck/hunspell/hunspell/hashmgr.hxx
--- spellcheck.old/hunspell/hunspell/hashmgr.hxx	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/hashmgr.hxx	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,129 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef _HASHMGR_HXX_
+#define _HASHMGR_HXX_
+
+#ifndef MOZILLA_CLIENT
+#include <cstdio>
+#else
+#include <stdio.h>
+#endif
+
+#include "htypes.hxx"
+
+enum flag { FLAG_CHAR, FLAG_LONG, FLAG_NUM, FLAG_UNI };
+
+class HashMgr
+{
+  int             tablesize;
+  struct hentry ** tableptr;
+  int             userword;
+  flag            flag_mode;
+  int             complexprefixes;
+  int             utf8;
+  unsigned short  forbiddenword;
+  int 		  langnum;
+  char *          enc;
+  char *          lang;
+  struct cs_info * csconv;
+  char *          ignorechars;
+  unsigned short * ignorechars_utf16;
+  int             ignorechars_utf16_len;
+  int                 numaliasf; // flag vector `compression' with aliases
+  unsigned short **   aliasf;
+  unsigned short *    aliasflen;
+  int                 numaliasm; // morphological desciption `compression' with aliases
+  char **             aliasm;
+
+
+public:
+  HashMgr(const char * tpath, const char * apath);
+  ~HashMgr();
+
+  struct hentry * lookup(const char *) const;
+  int hash(const char *) const;
+  struct hentry * walk_hashtable(int & col, struct hentry * hp) const;
+
+  int put_word(const char * word, char * ap);
+  int put_word_pattern(const char * word, const char * pattern);
+  int decode_flags(unsigned short ** result, char * flags);
+  unsigned short        decode_flag(const char * flag);
+  char *                encode_flag(unsigned short flag);
+  int is_aliasf();
+  int get_aliasf(int index, unsigned short ** fvec);
+#ifdef HUNSPELL_EXPERIMENTAL
+  int is_aliasm();
+  char * get_aliasm(int index);
+#endif
+
+  
+private:
+  int get_clen_and_captype(const char * word, int wbl, int * captype);
+  int load_tables(const char * tpath);
+  int add_word(const char * word, int wbl, int wcl, unsigned short * ap,
+    int al, const char * desc, bool onlyupcase);
+  int load_config(const char * affpath);
+  int parse_aliasf(char * line, FILE * af);
+  int add_hidden_capitalized_word(char * word, int wbl, int wcl,
+    unsigned short * flags, int al, char * dp, int captype);
+#ifdef HUNSPELL_EXPERIMENTAL
+  int parse_aliasm(char * line, FILE * af);
+#endif
+
+};
+
+#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/htypes.hxx spellcheck/hunspell/hunspell/htypes.hxx
--- spellcheck.old/hunspell/hunspell/htypes.hxx	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/htypes.hxx	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,85 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef _HTYPES_HXX_
+#define _HTYPES_HXX_
+
+#define MAXDELEN    8192
+
+#define ROTATE_LEN   5
+
+#define ROTATE(v,q) \
+   (v) = ((v) << (q)) | (((v) >> (32 - q)) & ((1 << (q))-1));
+
+// approx. number  of user defined words
+#define USERWORD 1000
+
+struct hentry
+{
+  unsigned char blen; // word length in bytes
+  unsigned char clen; // word length in characters (different for UTF-8 enc.)
+  short    alen;      // length of affix flag vector
+  unsigned short * astr;  // affix flag vector
+  struct   hentry * next; // next word with same hash code
+  struct   hentry * next_homonym; // next homonym word (with same hash code)
+#ifdef HUNSPELL_EXPERIMENTAL
+  char *   description; // morphological data (optional)
+#endif
+  char     var;       // variable fields (only for special pronounciation yet)
+  char     word;      // variable-length word (8-bit or UTF-8 encoding)
+};
+
+#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/hunspell.cpp spellcheck/hunspell/hunspell/hunspell.cpp
--- spellcheck.old/hunspell/hunspell/hunspell.cpp	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/hunspell.cpp	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,1807 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef MOZILLA_CLIENT
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+#else
+#include <stdlib.h> 
+#include <string.h>
+#include <stdio.h> 
+#endif
+
+#include "hunspell.hxx"
+#include "hunspell.h"
+
+#ifndef MOZILLA_CLIENT
+#ifndef W32
+using namespace std;
+#endif
+#endif
+
+Hunspell::Hunspell(const char * affpath, const char * dpath)
+{
+    encoding = NULL;
+    csconv = NULL;
+    utf8 = 0;
+    complexprefixes = 0;
+
+    /* first set up the hash manager */
+    pHMgr = new HashMgr(dpath, affpath);
+
+    /* next set up the affix manager */
+    /* it needs access to the hash manager lookup methods */
+    pAMgr = new AffixMgr(affpath,pHMgr);
+
+    /* get the preferred try string and the dictionary */
+    /* encoding from the Affix Manager for that dictionary */
+    char * try_string = pAMgr->get_try_string();
+    encoding = pAMgr->get_encoding();
+    csconv = get_current_cs(encoding);
+    langnum = pAMgr->get_langnum();
+    utf8 = pAMgr->get_utf8();
+    complexprefixes = pAMgr->get_complexprefixes();
+    wordbreak = pAMgr->get_breaktable();
+
+    /* and finally set up the suggestion manager */
+    pSMgr = new SuggestMgr(try_string, MAXSUGGESTION, pAMgr);
+    if (try_string) free(try_string);
+
+}
+
+Hunspell::~Hunspell()
+{
+    if (pSMgr) delete pSMgr;
+    if (pAMgr) delete pAMgr;
+    if (pHMgr) delete pHMgr;
+    pSMgr = NULL;
+    pAMgr = NULL;
+    pHMgr = NULL;
+#ifdef MOZILLA_CLIENT
+    free(csconv);
+#endif
+    csconv= NULL;
+    if (encoding) free(encoding);
+    encoding = NULL;
+}
+
+
+// make a copy of src at destination while removing all leading
+// blanks and removing any trailing periods after recording
+// their presence with the abbreviation flag
+// also since already going through character by character, 
+// set the capitalization type
+// return the length of the "cleaned" (and UTF-8 encoded) word
+
+int Hunspell::cleanword2(char * dest, const char * src, 
+    w_char * dest_utf, int * nc, int * pcaptype, int * pabbrev)
+{ 
+   unsigned char * p = (unsigned char *) dest;
+   const unsigned char * q = (const unsigned char * ) src;
+
+   // first skip over any leading blanks
+   while ((*q != '\0') && (*q == ' ')) q++;
+   
+   // now strip off any trailing periods (recording their presence)
+   *pabbrev = 0;
+   int nl = strlen((const char *)q);
+   while ((nl > 0) && (*(q+nl-1)=='.')) {
+       nl--;
+       (*pabbrev)++;
+   }
+   
+   // if no characters are left it can't be capitalized
+   if (nl <= 0) { 
+       *pcaptype = NOCAP;
+       *p = '\0';
+       return 0;
+   }
+   
+   strncpy(dest, (char *) q, nl);
+   *(dest + nl) = '\0';
+   nl = strlen(dest);
+   if (utf8) {
+      *nc = u8_u16(dest_utf, MAXWORDLEN, dest);
+      // don't check too long words
+      if (*nc >= MAXWORDLEN) return 0;
+      if (*nc == -1) { // big Unicode character (non BMP area)
+         *pcaptype = NOCAP;
+         return nl;
+      }
+     *pcaptype = get_captype_utf8(dest_utf, *nc, langnum);
+   } else {
+     *pcaptype = get_captype(dest, nl, csconv);
+     *nc = nl;
+   }
+   return nl;
+} 
+
+#ifdef HUNSPELL_EXPERIMENTAL
+int Hunspell::cleanword(char * dest, const char * src, 
+    int * pcaptype, int * pabbrev)
+{ 
+   unsigned char * p = (unsigned char *) dest;
+   const unsigned char * q = (const unsigned char * ) src;
+   int firstcap = 0;
+
+   // first skip over any leading blanks
+   while ((*q != '\0') && (*q == ' ')) q++;
+   
+   // now strip off any trailing periods (recording their presence)
+   *pabbrev = 0;
+   int nl = strlen((const char *)q);
+   while ((nl > 0) && (*(q+nl-1)=='.')) {
+       nl--;
+       (*pabbrev)++;
+   }
+   
+   // if no characters are left it can't be capitalized
+   if (nl <= 0) { 
+       *pcaptype = NOCAP;
+       *p = '\0';
+       return 0;
+   }
+
+   // now determine the capitalization type of the first nl letters
+   int ncap = 0;
+   int nneutral = 0;
+   int nc = 0;
+
+   if (!utf8) {
+      while (nl > 0) {
+         nc++;
+         if (csconv[(*q)].ccase) ncap++;
+         if (csconv[(*q)].cupper == csconv[(*q)].clower) nneutral++;
+         *p++ = *q++;
+         nl--;
+      }
+      // remember to terminate the destination string
+      *p = '\0';
+      firstcap = csconv[(unsigned char)(*dest)].ccase;
+   } else {
+      unsigned short idx;
+      w_char t[MAXWORDLEN];
+      nc = u8_u16(t, MAXWORDLEN, src);
+      for (int i = 0; i < nc; i++) {
+         idx = (t[i].h << 8) + t[i].l;
+         unsigned short low = unicodetolower(idx, langnum);
+         if (idx != low) ncap++;
+         if (unicodetoupper(idx, langnum) == low) nneutral++;
+      }
+      u16_u8(dest, MAXWORDUTF8LEN, t, nc);
+      if (ncap) {
+         idx = (t[0].h << 8) + t[0].l;
+         firstcap = (idx != unicodetolower(idx, langnum));
+      }
+   }
+
+   // now finally set the captype
+   if (ncap == 0) {
+        *pcaptype = NOCAP;
+   } else if ((ncap == 1) && firstcap) {
+        *pcaptype = INITCAP;
+   } else if ((ncap == nc) || ((ncap + nneutral) == nc)){
+        *pcaptype = ALLCAP;
+   } else if ((ncap > 1) && firstcap) {
+        *pcaptype = HUHINITCAP;
+   } else {
+        *pcaptype = HUHCAP;
+   }
+   return strlen(dest);
+} 
+#endif       
+
+void Hunspell::mkallcap(char * p)
+{
+  if (utf8) {
+      w_char u[MAXWORDLEN];
+      int nc = u8_u16(u, MAXWORDLEN, p);
+      unsigned short idx;
+      for (int i = 0; i < nc; i++) {
+         idx = (u[i].h << 8) + u[i].l;
+         if (idx != unicodetoupper(idx, langnum)) {
+            u[i].h = (unsigned char) (unicodetoupper(idx, langnum) >> 8);
+            u[i].l = (unsigned char) (unicodetoupper(idx, langnum) & 0x00FF);
+         }
+      }
+      u16_u8(p, MAXWORDUTF8LEN, u, nc);
+  } else {
+    while (*p != '\0') { 
+        *p = csconv[((unsigned char) *p)].cupper;
+        p++;
+    }
+  }
+}
+
+int Hunspell::mkallcap2(char * p, w_char * u, int nc)
+{
+  if (utf8) {
+      unsigned short idx;
+      for (int i = 0; i < nc; i++) {
+         idx = (u[i].h << 8) + u[i].l;
+         unsigned short up = unicodetoupper(idx, langnum);
+         if (idx != up) {
+            u[i].h = (unsigned char) (up >> 8);
+            u[i].l = (unsigned char) (up & 0x00FF);
+         }
+      }
+      u16_u8(p, MAXWORDUTF8LEN, u, nc);
+      return strlen(p);  
+  } else {
+    while (*p != '\0') { 
+        *p = csconv[((unsigned char) *p)].cupper;
+        p++;
+    }
+  }
+  return nc;
+}
+
+
+void Hunspell::mkallsmall(char * p)
+{
+    while (*p != '\0') { 
+        *p = csconv[((unsigned char) *p)].clower;
+        p++;
+    }
+}
+
+int Hunspell::mkallsmall2(char * p, w_char * u, int nc)
+{
+  if (utf8) {
+      unsigned short idx;
+      for (int i = 0; i < nc; i++) {
+         idx = (u[i].h << 8) + u[i].l;
+         unsigned short low = unicodetolower(idx, langnum);
+         if (idx != low) {
+            u[i].h = (unsigned char) (low >> 8);
+            u[i].l = (unsigned char) (low & 0x00FF);
+         }
+      }
+      u16_u8(p, MAXWORDUTF8LEN, u, nc);
+      return strlen(p);
+  } else {
+    while (*p != '\0') { 
+        *p = csconv[((unsigned char) *p)].clower;
+        p++;
+    }
+  }
+  return nc;
+}
+
+// convert UTF-8 sharp S codes to latin 1
+char * Hunspell::sharps_u8_l1(char * dest, char * source) {
+    char * p = dest;
+    *p = *source;
+    for (p++, source++; *(source - 1); p++, source++) {
+        *p = *source;
+        if (*source == '\x9F') *--p = '\xDF';
+    }
+    return dest;
+}
+
+// recursive search for right ss - sharp s permutations
+hentry * Hunspell::spellsharps(char * base, char * pos, int n,
+        int repnum, char * tmp, int * info, char **root) {
+    pos = strstr(pos, "ss");
+    if (pos && (n < MAXSHARPS)) {
+        *pos = '\xC3';
+        *(pos + 1) = '\x9F';
+        hentry * h = spellsharps(base, pos + 2, n + 1, repnum + 1, tmp, info, root);
+        if (h) return h;
+        *pos = 's';
+        *(pos + 1) = 's';
+        h = spellsharps(base, pos + 2, n + 1, repnum, tmp, info, root);
+        if (h) return h;
+    } else if (repnum > 0) {
+        if (utf8) return checkword(base, info, root);
+        return checkword(sharps_u8_l1(tmp, base), info, root);
+    }
+    return NULL;
+}
+
+int Hunspell::is_keepcase(const hentry * rv) {
+    return pAMgr && rv->astr && pAMgr->get_keepcase() &&
+        TESTAFF(rv->astr, pAMgr->get_keepcase(), rv->alen);
+}
+
+/* insert a word to beginning of the suggestion array and return ns */
+int Hunspell::insert_sug(char ***slst, char * word, int ns) {
+    if (ns == MAXSUGGESTION) {
+        ns--;
+        free((*slst)[ns]);
+    }
+    for (int k = ns; k > 0; k--) (*slst)[k] = (*slst)[k - 1];
+    (*slst)[0] = mystrdup(word);
+    return ns + 1;
+}
+
+int Hunspell::spell(const char * word, int * info, char ** root)
+{
+  struct hentry * rv=NULL;
+  // need larger vector. For example, Turkish capital letter I converted a
+  // 2-byte UTF-8 character (dotless i) by mkallsmall.
+  char cw[MAXWORDUTF8LEN];
+  char wspace[MAXWORDUTF8LEN];
+  w_char unicw[MAXWORDLEN];
+  int nc = strlen(word);
+  int wl2 = 0;
+  if (utf8) {
+    if (nc >= MAXWORDUTF8LEN) return 0;
+  } else {
+    if (nc >= MAXWORDLEN) return 0;
+  }
+  int captype = 0;
+  int abbv = 0;
+  int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
+  int info2 = 0;
+  if (wl == 0) return 1;
+  if (root) *root = NULL;
+
+  // allow numbers with dots and commas (but forbid double separators: "..", ",," etc.)
+  enum { NBEGIN, NNUM, NSEP };
+  int nstate = NBEGIN;
+  int i;
+
+  for (i = 0; (i < wl); i++) {
+    if ((cw[i] <= '9') && (cw[i] >= '0')) {
+        nstate = NNUM;
+    } else if ((cw[i] == ',') || (cw[i] == '.') || (cw[i] == '-')) {
+        if ((nstate == NSEP) || (i == 0)) break;
+        nstate = NSEP;
+    } else break;
+  }
+  if ((i == wl) && (nstate == NNUM)) return 1;
+  if (!info) info = &info2; else *info = 0;
+
+  // LANG_hu section: number(s) + (percent or degree) with suffixes
+  if (langnum == LANG_hu) {
+    if ((nstate == NNUM) && ((cw[i] == '%') || ((!utf8 && (cw[i] == '\xB0')) ||
+        (utf8 && (strncmp(cw + i, "\xC2\xB0", 2)==0))))
+               && checkword(cw + i, info, root)) return 1;
+  }
+  // END of LANG_hu section
+
+  switch(captype) {
+     case HUHCAP: 
+     case HUHINITCAP: 
+     case NOCAP: { 
+            rv = checkword(cw, info, root);
+            if ((abbv) && !(rv)) {
+                memcpy(wspace,cw,wl);
+                *(wspace+wl) = '.';
+                *(wspace+wl+1) = '\0';
+                rv = checkword(wspace, info, root);
+            }
+            break;
+         }
+     case ALLCAP: {
+            rv = checkword(cw, info, root);
+            if (rv) break;
+            if (abbv) {
+                memcpy(wspace,cw,wl);
+                *(wspace+wl) = '.';
+                *(wspace+wl+1) = '\0';
+                rv = checkword(wspace, info, root);
+                if (rv) break;
+            }
+            // Spec. prefix handling for Catalan, French, Italian:
+	    // prefixes separated by apostrophe (SANT'ELIA -> Sant'+Elia).
+            if (pAMgr && strchr(cw, '\'')) {
+                wl = mkallsmall2(cw, unicw, nc);
+        	char * apostrophe = strchr(cw, '\'');
+                if (utf8) {
+            	    w_char tmpword[MAXWORDLEN];
+            	    *apostrophe = '\0';
+            	    wl2 = u8_u16(tmpword, MAXWORDLEN, cw);
+            	    *apostrophe = '\'';
+		    if (wl2 < nc) {
+		        mkinitcap2(apostrophe + 1, unicw + wl2 + 1, nc - wl2 - 1);
+			rv = checkword(cw, info, root);
+			if (rv) break;
+		    }
+                } else {
+		    mkinitcap2(apostrophe + 1, unicw, nc);
+		    rv = checkword(cw, info, root);
+		    if (rv) break;
+		}
+		mkinitcap2(cw, unicw, nc);
+		rv = checkword(cw, info, root);
+		if (rv) break;
+            }
+            if (pAMgr && pAMgr->get_checksharps() && strstr(cw, "SS")) {
+                char tmpword[MAXWORDUTF8LEN];
+                wl = mkallsmall2(cw, unicw, nc);
+                memcpy(wspace,cw,(wl+1));
+                rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
+                if (!rv) {
+                    wl2 = mkinitcap2(cw, unicw, nc);
+                    rv = spellsharps(cw, cw, 0, 0, tmpword, info, root);
+                }
+                if ((abbv) && !(rv)) {
+                    *(wspace+wl) = '.';
+                    *(wspace+wl+1) = '\0';
+                    rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
+                    if (!rv) {
+                        memcpy(wspace, cw, wl2);
+                        *(wspace+wl2) = '.';
+                        *(wspace+wl2+1) = '\0';
+                        rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
+                    }
+                }
+                if (rv) break;
+            }
+        }
+     case INITCAP: { 
+             wl = mkallsmall2(cw, unicw, nc);
+             memcpy(wspace,cw,(wl+1));
+             wl2 = mkinitcap2(cw, unicw, nc);
+    	     if (captype == INITCAP) *info += SPELL_INITCAP;
+             rv = checkword(cw, info, root);
+    	     if (captype == INITCAP) *info -= SPELL_INITCAP;
+             // forbid bad capitalization
+             // (for example, ijs -> Ijs instead of IJs in Dutch)
+             // use explicit forms in dic: Ijs/F (F = FORBIDDENWORD flag)
+             if (*info & SPELL_FORBIDDEN) {
+                rv = NULL;
+                break;
+             }             
+             if (rv && is_keepcase(rv) && (captype == ALLCAP)) rv = NULL;
+             if (rv) break;
+
+             rv = checkword(wspace, info, root);
+             if (abbv && !rv) {
+
+                 *(wspace+wl) = '.';
+                 *(wspace+wl+1) = '\0';
+                 rv = checkword(wspace, info, root);
+                 if (!rv) {
+                    memcpy(wspace, cw, wl2);
+                    *(wspace+wl2) = '.';
+                    *(wspace+wl2+1) = '\0';
+    	    	    if (captype == INITCAP) *info += SPELL_INITCAP;
+                    rv = checkword(wspace, info, root);
+    	    	    if (captype == INITCAP) *info -= SPELL_INITCAP;
+                    if (rv && is_keepcase(rv) && (captype == ALLCAP)) rv = NULL;
+                    break;
+                 }
+             }
+             if (rv && is_keepcase(rv) &&
+                ((captype == ALLCAP) ||
+                   // if CHECKSHARPS: KEEPCASE words with \xDF  are allowed
+                   // in INITCAP form, too.
+                   !(pAMgr->get_checksharps() &&
+                      ((utf8 && strstr(wspace, "\xC3\x9F")) ||
+                      (!utf8 && strchr(wspace, '\xDF')))))) rv = NULL;             
+             break;
+           }               
+  }
+  
+  if (rv) return 1;
+
+  // recursive breaking at break points (not good for morphological analysis)
+  if (wordbreak) {
+    char * s;
+    char r;
+    int corr = 0;
+    // German words beginning with "-" are not accepted
+    if (langnum == LANG_de) corr = 1;
+    int numbreak = pAMgr ? pAMgr->get_numbreak() : 0;
+    for (int j = 0; j < numbreak; j++) {
+      s=(char *) strstr(cw + corr, wordbreak[j]);
+      if (s) {
+        r = *s;
+        *s = '\0';
+        // examine 2 sides of the break point
+        if (spell(cw) && spell(s + strlen(wordbreak[j]))) {
+            *s = r;
+            return 1;
+        }
+        *s = r;
+      }
+    }
+  }
+
+  // LANG_hu: compoundings with dashes and n-dashes XXX deprecated!
+  if (langnum == LANG_hu) {
+    int n;
+    // compound word with dash (HU) I18n
+    char * dash;
+    int result = 0;
+    // n-dash
+    dash = (char *) strstr(cw,"\xE2\x80\x93");
+    if (dash && !wordbreak) {
+        *dash = '\0';
+        // examine 2 sides of the dash
+        if (spell(cw) && spell(dash + 3)) {
+            *dash = '\xE2';
+            return 1;
+        }
+        *dash = '\xE2';
+    }
+    dash = (char *) strchr(cw,'-');
+    if (dash) {
+        *dash='\0';      
+        // examine 2 sides of the dash
+        if (dash[1] == '\0') { // base word ending with dash
+            if (spell(cw)) return 1;
+        } else {
+            // first word ending with dash: word-
+            char r2 = *(dash + 1);
+            dash[0]='-';
+            dash[1]='\0';
+            result = spell(cw);
+            dash[1] = r2;
+            dash[0]='\0';
+            if (result && spell(dash+1) && ((strlen(dash+1) > 1) || (dash[1] == 'e') ||
+                ((dash[1] > '0') && (dash[1] < '9')))) return 1;
+        }
+        // affixed number in correct word
+        if (result && (dash > cw) && (((*(dash-1)<='9') && (*(dash-1)>='0')) || (*(dash-1)>='.'))) {
+            *dash='-';
+            n = 1;
+            if (*(dash - n) == '.') n++;
+            // search first not a number character to left from dash
+            while (((dash - n)>=cw) && ((*(dash - n)=='0') || (n < 3)) && (n < 6)) {
+                n++;
+            }
+            if ((dash - n) < cw) n--;
+            // numbers: deprecated
+            for(; n >= 1; n--) {
+                if ((*(dash - n) >= '0') && (*(dash - n) <= '9') &&
+                    checkword(dash - n, info, root)) return 1;
+            }
+        }
+    }
+  }
+  return 0;
+}
+
+struct hentry * Hunspell::checkword(const char * w, int * info, char ** root)
+{
+  struct hentry * he = NULL;
+  int len;
+  char w2[MAXWORDUTF8LEN];
+  const char * word;
+
+  char * ignoredchars = pAMgr->get_ignore();
+  if (ignoredchars != NULL) {
+     strcpy(w2, w);
+     if (utf8) {
+        int ignoredchars_utf16_len;
+        unsigned short * ignoredchars_utf16 = pAMgr->get_ignore_utf16(&ignoredchars_utf16_len);
+        remove_ignored_chars_utf(w2, ignoredchars_utf16, ignoredchars_utf16_len);
+     } else {
+        remove_ignored_chars(w2,ignoredchars);
+     }
+     word = w2;
+  } else word = w;
+
+  // word reversing wrapper for complex prefixes
+  if (complexprefixes) {
+    if (word != w2) {
+      strcpy(w2, word);
+      word = w2;
+    }
+    if (utf8) reverseword_utf(w2); else reverseword(w2);
+  }
+
+  // look word in hash table
+  if (pHMgr) he = pHMgr->lookup(word);
+
+  // check forbidden and onlyincompound words
+  if ((he) && (he->astr) && (pAMgr) && TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
+    if (info) *info += SPELL_FORBIDDEN;
+    // LANG_hu section: set dash information for suggestions
+    if (langnum == LANG_hu) {
+        if (pAMgr->get_compoundflag() &&
+            TESTAFF(he->astr, pAMgr->get_compoundflag(), he->alen)) {
+                if (info) *info += SPELL_COMPOUND;
+        }
+    }
+    return NULL;
+  }
+
+  // he = next not pseudoroot, onlyincompound homonym or onlyupcase word
+  while (he && (he->astr) &&
+    ((pAMgr->get_pseudoroot() && TESTAFF(he->astr, pAMgr->get_pseudoroot(), he->alen)) ||
+       (pAMgr->get_onlyincompound() && TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
+       (info && (*info & SPELL_INITCAP) && TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen))
+    )) he = he->next_homonym;
+
+  // check with affixes
+  if (!he && pAMgr) {
+     // try stripping off affixes */
+     len = strlen(word);
+     he = pAMgr->affix_check(word, len, 0);
+
+     // check compound restriction and onlyupcase
+     if (he && he->astr && (
+        (pAMgr->get_onlyincompound() && 
+    	    TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) || 
+        (info && (*info & SPELL_INITCAP) &&
+    	    TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)))) {
+    	    he = NULL;
+     }
+
+     if (he) {
+        if ((he->astr) && (pAMgr) && TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
+            if (info) *info += SPELL_FORBIDDEN;
+            return NULL;
+        }
+        if (root) {
+            *root = mystrdup(&(he->word));
+            if (complexprefixes) {
+                if (utf8) reverseword_utf(*root); else reverseword(*root);
+            }
+        }
+     // try check compound word
+     } else if (pAMgr->get_compound()) {
+          he = pAMgr->compound_check(word, len, 
+                                  0,0,100,0,NULL,0,NULL,NULL,0);
+          // LANG_hu section: `moving rule' with last dash
+          if ((!he) && (langnum == LANG_hu) && (word[len-1]=='-')) {
+             char * dup = mystrdup(word);
+             dup[len-1] = '\0';
+             he = pAMgr->compound_check(dup, len-1, 
+                                  -5,0,100,0,NULL,1,NULL,NULL,0);
+             free(dup);
+          }
+          // end of LANG speficic region          
+          if (he) {
+                if (root) {
+                    *root = mystrdup(&(he->word));
+                    if (complexprefixes) {
+                        if (utf8) reverseword_utf(*root); else reverseword(*root);
+                    }
+                }
+                if (info) *info += SPELL_COMPOUND;
+          }
+     }
+
+  }
+
+  return he;
+}
+
+int Hunspell::suggest(char*** slst, const char * word)
+{
+  int onlycmpdsug = 0;
+  char cw[MAXWORDUTF8LEN];
+  char wspace[MAXWORDUTF8LEN];
+  if (! pSMgr) return 0;
+  w_char unicw[MAXWORDLEN];
+  int nc = strlen(word);
+  if (utf8) {
+    if (nc >= MAXWORDUTF8LEN) return 0;
+  } else {
+    if (nc >= MAXWORDLEN) return 0;
+  }
+  int captype = 0;
+  int abbv = 0;
+  int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
+  if (wl == 0) return 0;
+  int ns = 0;
+  *slst = NULL;
+  int capwords = 0;
+
+  switch(captype) {
+     case NOCAP:   { 
+                     ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug);
+                     break;
+                   }
+
+     case INITCAP: { 
+                     capwords = 1;
+                     ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug);
+                     if (ns == -1) break;
+                     memcpy(wspace,cw,(wl+1));
+                     mkallsmall2(wspace, unicw, nc);
+                     ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+                     break;
+                   }
+     case HUHINITCAP:
+                    capwords = 1;
+     case HUHCAP: { 
+                     ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug);
+                     if (ns != -1) {
+                        int prevns;
+    		        // something.The -> something. The
+                        char * dot = strchr(cw, '.');
+		        if (dot && (dot > cw)) {
+		            int captype_;
+		            if (utf8) {
+		               w_char w_[MAXWORDLEN];
+			       int wl_ = u8_u16(w_, MAXWORDLEN, dot + 1);
+		               captype_ = get_captype_utf8(w_, wl_, langnum);
+		            } else captype_ = get_captype(dot+1, strlen(dot+1), csconv);
+		    	    if (captype_ == INITCAP) {
+                        	char * st = mystrdup(cw);
+                        	st = (char *) realloc(st, wl + 2);
+				if (st) {
+                        		st[(dot - cw) + 1] = ' ';
+                        		strcpy(st + (dot - cw) + 2, dot + 1);
+                    			ns = insert_sug(slst, st, ns);
+					free(st);
+				}
+		    	    }
+		        }
+                        if (captype == HUHINITCAP) {
+                            // TheOpenOffice.org -> The OpenOffice.org
+                            memcpy(wspace,cw,(wl+1));
+                            mkinitsmall2(wspace, unicw, nc);
+                            ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+                        }
+                        memcpy(wspace,cw,(wl+1));
+                        mkallsmall2(wspace, unicw, nc);
+                        if (spell(wspace)) ns = insert_sug(slst, wspace, ns);
+                        prevns = ns;
+                        ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+                        if (captype == HUHINITCAP) {
+                            mkinitcap2(wspace, unicw, nc);
+                            if (spell(wspace)) ns = insert_sug(slst, wspace, ns);
+                            ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+                        }
+                        // aNew -> "a New" (instead of "a new")
+                        for (int j = prevns; j < ns; j++) {
+                           char * space = strchr((*slst)[j],' ');
+                           if (space) {
+                                int slen = strlen(space + 1);
+                                // different case after space (need capitalisation)
+                                if ((slen < wl) && strcmp(cw + wl - slen, space + 1)) {
+                                    w_char w[MAXWORDLEN];
+                                    int wc = 0;
+                                    char * r = (*slst)[j];
+                                    if (utf8) wc = u8_u16(w, MAXWORDLEN, space + 1);
+                                    mkinitcap2(space + 1, w, wc);
+                                    // set as first suggestion
+                                    for (int k = j; k > 0; k--) (*slst)[k] = (*slst)[k - 1];
+                                    (*slst)[0] = r;
+                                }
+                           }
+                        }
+                     }
+                     break;
+                   }
+
+     case ALLCAP: { 
+                     memcpy(wspace, cw, (wl+1));
+                     mkallsmall2(wspace, unicw, nc);
+                     ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+                     if (ns == -1) break;
+                     if (pAMgr && pAMgr->get_keepcase() && spell(wspace))
+                        ns = insert_sug(slst, wspace, ns);
+                     mkinitcap2(wspace, unicw, nc);
+                     ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
+                     for (int j=0; j < ns; j++) {
+                        mkallcap((*slst)[j]);
+                        if (pAMgr && pAMgr->get_checksharps()) {
+                            char * pos;
+                            if (utf8) {
+                                pos = strstr((*slst)[j], "\xC3\x9F");
+                                while (pos) {
+                                    *pos = 'S';
+                                    *(pos+1) = 'S';
+                                    pos = strstr(pos+2, "\xC3\x9F");
+                                }
+                            } else {
+                                pos = strchr((*slst)[j], '\xDF');
+                                while (pos) {
+                                    (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 2);
+                                    mystrrep((*slst)[j], "\xDF", "SS");
+                                    pos = strchr((*slst)[j], '\xDF');
+                                }
+                            }
+                        }
+                     }
+                     break;
+                   }
+  }
+
+  // LANG_hu section: replace '-' with ' ' in Hungarian
+  if (langnum == LANG_hu) {
+      for (int j=0; j < ns; j++) {
+          char * pos = strchr((*slst)[j],'-');
+          if (pos) {
+              int info;
+              char w[MAXWORDUTF8LEN];
+              *pos = '\0';
+              strcpy(w, (*slst)[j]);
+              strcat(w, pos + 1);
+              spell(w, &info, NULL);
+              if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
+                  *pos = ' ';
+              } else *pos = '-';
+          }
+      }
+  }
+  // END OF LANG_hu section
+  
+  // try ngram approach since found nothing
+  if ((ns == 0 || onlycmpdsug) && pAMgr && (pAMgr->get_maxngramsugs() != 0)) {
+      switch(captype) {
+          case NOCAP: {
+              ns = pSMgr->ngsuggest(*slst, cw, ns, pHMgr);
+              break;
+          }
+          case HUHCAP: {
+              memcpy(wspace,cw,(wl+1));
+              mkallsmall2(wspace, unicw, nc);
+              ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr);
+              break;
+          }
+          case INITCAP: { 
+              capwords = 1;
+              memcpy(wspace,cw,(wl+1));
+              mkallsmall2(wspace, unicw, nc);
+              ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr);
+              break;
+          }
+          case ALLCAP: {
+              memcpy(wspace,cw,(wl+1));
+              mkallsmall2(wspace, unicw, nc);
+	      int oldns = ns;
+              ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr);
+              for (int j = oldns; j < ns; j++) 
+                  mkallcap((*slst)[j]);
+              break;
+         }
+      }
+  }
+
+  // word reversing wrapper for complex prefixes
+  if (complexprefixes) {
+    for (int j = 0; j < ns; j++) {
+      if (utf8) reverseword_utf((*slst)[j]); else reverseword((*slst)[j]);
+    }
+  }
+
+  // capitalize
+  if (capwords) for (int j=0; j < ns; j++) {
+      mkinitcap((*slst)[j]);
+  }
+
+  // expand suggestions with dot(s)
+  if (abbv && pAMgr && pAMgr->get_sugswithdots()) {
+    for (int j = 0; j < ns; j++) {
+      (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 1 + abbv);
+      strcat((*slst)[j], word + strlen(word) - abbv);
+    }
+  }
+
+  // remove bad capitalized and forbidden forms
+  if (pAMgr && (pAMgr->get_keepcase() || pAMgr->get_forbiddenword())) {
+  switch (captype) {
+    case INITCAP:
+    case ALLCAP: {
+      int l = 0;
+      for (int j=0; j < ns; j++) {
+        if (!strchr((*slst)[j],' ') && !spell((*slst)[j])) {
+          char s[MAXSWUTF8L];
+          w_char w[MAXSWL];
+          int len;
+          if (utf8) {
+            len = u8_u16(w, MAXSWL, (*slst)[j]);
+          } else {
+            strcpy(s, (*slst)[j]);
+            len = strlen(s);
+          }
+          mkallsmall2(s, w, len);
+          free((*slst)[j]);          
+          if (spell(s)) {
+            (*slst)[l] = mystrdup(s);
+            l++;
+          } else {
+            mkinitcap2(s, w, len);
+            if (spell(s)) {
+              (*slst)[l] = mystrdup(s);
+              l++;
+            }
+          }
+        } else {
+          (*slst)[l] = (*slst)[j];
+          l++;
+        }    
+      }
+      ns = l;
+    }
+  }
+  }
+
+  // remove duplications
+  int l = 0;
+  for (int j = 0; j < ns; j++) {
+    (*slst)[l] = (*slst)[j];
+    for (int k = 0; k < l; k++) {
+      if (strcmp((*slst)[k], (*slst)[j]) == 0) {
+        free((*slst)[j]);
+        l--;
+      }
+    }
+    l++;
+  }
+  return l;
+}
+
+char * Hunspell::get_dic_encoding()
+{
+  return encoding;
+}
+
+#ifdef HUNSPELL_EXPERIMENTAL
+// XXX need UTF-8 support
+int Hunspell::suggest_auto(char*** slst, const char * word)
+{
+  char cw[MAXWORDUTF8LEN];
+  char wspace[MAXWORDUTF8LEN];
+  if (! pSMgr) return 0;
+  int wl = strlen(word);
+  if (utf8) {
+    if (wl >= MAXWORDUTF8LEN) return 0;
+  } else {
+    if (wl >= MAXWORDLEN) return 0;
+  }
+  int captype = 0;
+  int abbv = 0;
+  wl = cleanword(cw, word, &captype, &abbv);
+  if (wl == 0) return 0;
+  int ns = 0;
+  *slst = NULL; // HU, nsug in pSMgr->suggest
+  
+  switch(captype) {
+     case NOCAP:   { 
+                     ns = pSMgr->suggest_auto(slst, cw, ns);
+                     if (ns>0) break;
+                     break;
+                   }
+
+     case INITCAP: { 
+                     memcpy(wspace,cw,(wl+1));
+                     mkallsmall(wspace);
+                     ns = pSMgr->suggest_auto(slst, wspace, ns);
+                     for (int j=0; j < ns; j++)
+                       mkinitcap((*slst)[j]);
+                     ns = pSMgr->suggest_auto(slst, cw, ns);
+                     break;
+                     
+                   }
+
+     case HUHCAP: { 
+                     ns = pSMgr->suggest_auto(slst, cw, ns);
+                     if (ns == 0) {
+                        memcpy(wspace,cw,(wl+1));
+                        mkallsmall(wspace);
+                        ns = pSMgr->suggest_auto(slst, wspace, ns);
+                     }
+                     break;
+                   }
+
+     case ALLCAP: { 
+                     memcpy(wspace,cw,(wl+1));
+                     mkallsmall(wspace);
+                     ns = pSMgr->suggest_auto(slst, wspace, ns);
+
+                     mkinitcap(wspace);
+                     ns = pSMgr->suggest_auto(slst, wspace, ns);
+
+                     for (int j=0; j < ns; j++)
+                       mkallcap((*slst)[j]);
+                     break;
+                   }
+  }
+
+  // word reversing wrapper for complex prefixes
+  if (complexprefixes) {
+    for (int j = 0; j < ns; j++) {
+      if (utf8) reverseword_utf((*slst)[j]); else reverseword((*slst)[j]);
+    }
+  }
+
+  // expand suggestions with dot(s)
+  if (abbv && pAMgr && pAMgr->get_sugswithdots()) {
+    for (int j = 0; j < ns; j++) {
+      (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 1 + abbv);
+      strcat((*slst)[j], word + strlen(word) - abbv);
+    }
+  }
+
+  // LANG_hu section: replace '-' with ' ' in Hungarian
+  if (langnum == LANG_hu) {
+      for (int j=0; j < ns; j++) {
+          char * pos = strchr((*slst)[j],'-');
+          if (pos) {
+              int info;
+              char w[MAXWORDUTF8LEN];
+              *pos = '\0';
+              strcpy(w, (*slst)[j]);
+              strcat(w, pos + 1);
+              spell(w, &info, NULL);
+              if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
+                  *pos = ' ';
+              } else *pos = '-';
+          }
+      }
+  }
+  // END OF LANG_hu section  
+  return ns;
+}
+
+// XXX need UTF-8 support
+int Hunspell::stem(char*** slst, const char * word)
+{
+  char cw[MAXWORDUTF8LEN];
+  char wspace[MAXWORDUTF8LEN];
+  if (! pSMgr) return 0;
+  int wl = strlen(word);
+  if (utf8) {
+    if (wl >= MAXWORDUTF8LEN) return 0;
+  } else {
+    if (wl >= MAXWORDLEN) return 0;
+  }
+  int captype = 0;
+  int abbv = 0;
+  wl = cleanword(cw, word, &captype, &abbv);
+  if (wl == 0) return 0;
+  
+  int ns = 0;
+
+  *slst = NULL; // HU, nsug in pSMgr->suggest
+  
+  switch(captype) {
+     case HUHCAP:
+     case NOCAP:   { 
+                     ns = pSMgr->suggest_stems(slst, cw, ns);
+
+                     if ((abbv) && (ns == 0)) {
+                         memcpy(wspace,cw,wl);
+                         *(wspace+wl) = '.';
+                         *(wspace+wl+1) = '\0';
+                         ns = pSMgr->suggest_stems(slst, wspace, ns);
+                     }
+
+                     break;
+                   }
+
+     case INITCAP: { 
+
+                     ns = pSMgr->suggest_stems(slst, cw, ns);
+
+                     if (ns == 0) {
+                        memcpy(wspace,cw,(wl+1));
+                        mkallsmall(wspace);
+                        ns = pSMgr->suggest_stems(slst, wspace, ns);
+
+                     }
+
+                     if ((abbv) && (ns == 0)) {
+                         memcpy(wspace,cw,wl);
+                         mkallsmall(wspace);
+                         *(wspace+wl) = '.';
+                         *(wspace+wl+1) = '\0';
+                         ns = pSMgr->suggest_stems(slst, wspace, ns);
+                     }
+                     
+                     break;
+                     
+                   }
+
+     case ALLCAP: { 
+                     ns = pSMgr->suggest_stems(slst, cw, ns);
+                     if (ns != 0) break;
+                     
+                     memcpy(wspace,cw,(wl+1));
+                     mkallsmall(wspace);
+                     ns = pSMgr->suggest_stems(slst, wspace, ns);
+
+                     if (ns == 0) {
+                         mkinitcap(wspace);
+                         ns = pSMgr->suggest_stems(slst, wspace, ns);
+                     }
+
+                     if ((abbv) && (ns == 0)) {
+                         memcpy(wspace,cw,wl);
+                         mkallsmall(wspace);
+                         *(wspace+wl) = '.';
+                         *(wspace+wl+1) = '\0';
+                         ns = pSMgr->suggest_stems(slst, wspace, ns);
+                     }
+
+
+                     break;
+                   }
+  }
+  
+  return ns;
+}
+
+int Hunspell::suggest_pos_stems(char*** slst, const char * word)
+{
+  char cw[MAXWORDUTF8LEN];
+  char wspace[MAXWORDUTF8LEN];
+  if (! pSMgr) return 0;
+  int wl = strlen(word);
+  if (utf8) {
+    if (wl >= MAXWORDUTF8LEN) return 0;
+  } else {
+    if (wl >= MAXWORDLEN) return 0;
+  }
+  int captype = 0;
+  int abbv = 0;
+  wl = cleanword(cw, word, &captype, &abbv);
+  if (wl == 0) return 0;
+  
+  int ns = 0; // ns=0 = normalized input
+
+  *slst = NULL; // HU, nsug in pSMgr->suggest
+  
+  switch(captype) {
+     case HUHCAP:
+     case NOCAP:   { 
+                     ns = pSMgr->suggest_pos_stems(slst, cw, ns);
+
+                     if ((abbv) && (ns == 0)) {
+                         memcpy(wspace,cw,wl);
+                         *(wspace+wl) = '.';
+                         *(wspace+wl+1) = '\0';
+                         ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
+                     }
+
+                     break;
+                   }
+
+     case INITCAP: { 
+
+                     ns = pSMgr->suggest_pos_stems(slst, cw, ns);
+
+                     if (ns == 0 || ((*slst)[0][0] == '#')) {
+                        memcpy(wspace,cw,(wl+1));
+                        mkallsmall(wspace);
+                        ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
+                     }
+                     
+                     break;
+                     
+                   }
+
+     case ALLCAP: { 
+                     ns = pSMgr->suggest_pos_stems(slst, cw, ns);
+                     if (ns != 0) break;
+                     
+                     memcpy(wspace,cw,(wl+1));
+                     mkallsmall(wspace);
+                     ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
+
+                     if (ns == 0) {
+                         mkinitcap(wspace);
+                         ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
+                     }
+                     break;
+                   }
+  }
+
+  return ns;
+}
+#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+
+const char * Hunspell::get_wordchars()
+{
+  return pAMgr->get_wordchars();
+}
+
+unsigned short * Hunspell::get_wordchars_utf16(int * len)
+{
+  return pAMgr->get_wordchars_utf16(len);
+}
+
+void Hunspell::mkinitcap(char * p)
+{
+  if (!utf8) {
+    if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper;
+  } else {
+      int len;
+      w_char u[MAXWORDLEN];
+      len = u8_u16(u, MAXWORDLEN, p);
+      unsigned short i = unicodetoupper((u[0].h << 8) + u[0].l, langnum);
+      u[0].h = (unsigned char) (i >> 8);
+      u[0].l = (unsigned char) (i & 0x00FF);
+      u16_u8(p, MAXWORDUTF8LEN, u, len);
+  }
+}
+
+int Hunspell::mkinitcap2(char * p, w_char * u, int nc)
+{
+  if (!utf8) {
+    if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper;
+  } else if (nc > 0) {
+      unsigned short i = unicodetoupper((u[0].h << 8) + u[0].l, langnum);
+      u[0].h = (unsigned char) (i >> 8);
+      u[0].l = (unsigned char) (i & 0x00FF);
+      u16_u8(p, MAXWORDUTF8LEN, u, nc);
+      return strlen(p);
+  }
+  return nc;
+}
+
+int Hunspell::mkinitsmall2(char * p, w_char * u, int nc)
+{
+  if (!utf8) {
+    if (*p != '\0') *p = csconv[((unsigned char)*p)].clower;
+  } else if (nc > 0) {
+      unsigned short i = unicodetolower((u[0].h << 8) + u[0].l, langnum);
+      u[0].h = (unsigned char) (i >> 8);
+      u[0].l = (unsigned char) (i & 0x00FF);
+      u16_u8(p, MAXWORDUTF8LEN, u, nc);
+      return strlen(p);
+  }
+  return nc;
+}
+
+int Hunspell::put_word(const char * word)
+{
+    if (pHMgr) return pHMgr->put_word(word, NULL);
+    return 0;
+}
+
+int Hunspell::put_word_pattern(const char * word, const char * pattern)
+{
+    if (pHMgr) return pHMgr->put_word_pattern(word, pattern);
+    return 0;
+}
+
+const char * Hunspell::get_version()
+{
+  return pAMgr->get_version();
+}
+
+struct cs_info * Hunspell::get_csconv()
+{
+  return csconv;
+}
+
+#ifdef HUNSPELL_EXPERIMENTAL
+// XXX need UTF-8 support
+char * Hunspell::morph(const char * word)
+{
+  char cw[MAXWORDUTF8LEN];
+  char wspace[MAXWORDUTF8LEN];
+  if (! pSMgr) return 0;
+  int wl = strlen(word);
+  if (utf8) {
+    if (wl >= MAXWORDUTF8LEN) return 0;
+  } else {
+    if (wl >= MAXWORDLEN) return 0;
+  }
+  int captype = 0;
+  int abbv = 0;
+  wl = cleanword(cw, word, &captype, &abbv);
+  if (wl == 0) {
+      if (abbv) {
+          for (wl = 0; wl < abbv; wl++) cw[wl] = '.';
+          cw[wl] = '\0';
+          abbv = 0;
+      } else return 0;
+  }
+
+  char result[MAXLNLEN];
+  char * st = NULL;
+  
+  *result = '\0';
+
+  int n = 0;
+  int n2 = 0;
+  int n3 = 0;
+
+  // test numbers
+  // LANG_hu section: set dash information for suggestions
+  if (langnum == LANG_hu) {
+  while ((n < wl) && 
+        (((cw[n] <= '9') && (cw[n] >= '0')) || (((cw[n] == '.') || (cw[n] == ',')) && (n > 0)))) {
+        n++;
+        if ((cw[n] == '.') || (cw[n] == ',')) {
+                if (((n2 == 0) && (n > 3)) || 
+                        ((n2 > 0) && ((cw[n-1] == '.') || (cw[n-1] == ',')))) break;
+                n2++;
+                n3 = n;
+        }
+  }
+
+  if ((n == wl) && (n3 > 0) && (n - n3 > 3)) return NULL;
+  if ((n == wl) || ((n>0) && ((cw[n]=='%') || (cw[n]=='\xB0')) && checkword(cw+n, NULL, NULL))) {
+        strcat(result, cw);
+        result[n - 1] = '\0';
+        if (n == wl) {
+                st = pSMgr->suggest_morph(cw + n - 1);
+                if (st) {
+                        strcat(result, st);
+                        free(st);
+                }
+        } else {
+                char sign = cw[n];
+                cw[n] = '\0';
+                st = pSMgr->suggest_morph(cw + n - 1);
+                if (st) {
+                        strcat(result, st);
+                        free(st);
+                }
+                strcat(result, "+"); // XXX SPEC. MORPHCODE
+                cw[n] = sign;
+                st = pSMgr->suggest_morph(cw + n);
+                if (st) {
+                        strcat(result, st);
+                        free(st);
+                }
+        }
+        return mystrdup(result);
+  }
+  }
+  // END OF LANG_hu section
+  
+  switch(captype) {
+     case NOCAP:   { 
+                     st = pSMgr->suggest_morph(cw);
+                     if (st) {
+                        strcat(result, st);
+                        free(st);
+                     }
+                                         if (abbv) {
+                                        memcpy(wspace,cw,wl);
+                         *(wspace+wl) = '.';
+                         *(wspace+wl+1) = '\0';
+                         st = pSMgr->suggest_morph(wspace);
+                         if (st) {
+                            if (*result) strcat(result, "\n");
+                            strcat(result, st);
+                            free(st);
+                                                 }
+                     }
+                                         break;
+                   }
+     case INITCAP: { 
+                     memcpy(wspace,cw,(wl+1));
+                     mkallsmall(wspace);
+                     st = pSMgr->suggest_morph(wspace);
+                     if (st) {
+                        strcat(result, st);
+                        free(st);
+                     }                                   
+                         st = pSMgr->suggest_morph(cw);
+                     if (st) {
+                        if (*result) strcat(result, "\n");
+                        strcat(result, st);
+                        free(st);
+                     }
+                                         if (abbv) {
+                                         memcpy(wspace,cw,wl);
+                         *(wspace+wl) = '.';
+                         *(wspace+wl+1) = '\0';
+                         mkallsmall(wspace);
+                         st = pSMgr->suggest_morph(wspace);
+                         if (st) {
+                            if (*result) strcat(result, "\n");
+                            strcat(result, st);
+                            free(st);
+                                                 }
+                         mkinitcap(wspace);
+                         st = pSMgr->suggest_morph(wspace);
+                         if (st) {
+                            if (*result) strcat(result, "\n");
+                            strcat(result, st);
+                            free(st);
+                                                 }
+                     }
+                     break;
+                   }
+     case HUHCAP: { 
+                     st = pSMgr->suggest_morph(cw);
+                     if (st) {
+                        strcat(result, st);
+                        free(st);
+                     }
+#if 0
+                     memcpy(wspace,cw,(wl+1));
+                     mkallsmall(wspace);
+                     st = pSMgr->suggest_morph(wspace);
+                     if (st) {
+                        if (*result) strcat(result, "\n");
+                        strcat(result, st);
+                        free(st);
+                     }
+#endif
+                     break;
+                 }
+     case ALLCAP: { 
+                     memcpy(wspace,cw,(wl+1));
+                     st = pSMgr->suggest_morph(wspace);
+                     if (st) {
+                        strcat(result, st);
+                        free(st);
+                     }               
+                     mkallsmall(wspace);
+                     st = pSMgr->suggest_morph(wspace);
+                     if (st) {
+                        if (*result) strcat(result, "\n");
+                        strcat(result, st);
+                        free(st);
+                     }
+                             mkinitcap(wspace);
+                             st = pSMgr->suggest_morph(wspace);
+                     if (st) {
+                        if (*result) strcat(result, "\n");
+                        strcat(result, st);
+                        free(st);
+                     }
+                                         if (abbv) {
+                        memcpy(wspace,cw,(wl+1));
+                        *(wspace+wl) = '.';
+                        *(wspace+wl+1) = '\0';
+                        if (*result) strcat(result, "\n");
+                        st = pSMgr->suggest_morph(wspace);
+                        if (st) {
+                                strcat(result, st);
+                                free(st);
+                        }                    
+                        mkallsmall(wspace);
+                        st = pSMgr->suggest_morph(wspace);
+                        if (st) {
+                          if (*result) strcat(result, "\n");
+                          strcat(result, st);
+                          free(st);
+                        }
+                                mkinitcap(wspace);
+                                st = pSMgr->suggest_morph(wspace);
+                        if (st) {
+                          if (*result) strcat(result, "\n");
+                          strcat(result, st);
+                          free(st);
+                        }
+                                         }
+                     break;
+                   }
+  }
+
+  if (result && (*result)) {
+    // word reversing wrapper for complex prefixes
+    if (complexprefixes) {
+      if (utf8) reverseword_utf(result); else reverseword(result);
+    }
+    return mystrdup(result);
+  }
+
+  // compound word with dash (HU) I18n
+  char * dash = NULL;
+  int nresult = 0;
+  // LANG_hu section: set dash information for suggestions
+  if (langnum == LANG_hu) dash = (char *) strchr(cw,'-');
+  if ((langnum == LANG_hu) && dash) {
+      *dash='\0';      
+      // examine 2 sides of the dash
+      if (dash[1] == '\0') { // base word ending with dash
+        if (spell(cw)) return pSMgr->suggest_morph(cw);
+      } else if ((dash[1] == 'e') && (dash[2] == '\0')) { // XXX (HU) -e hat.
+        if (spell(cw) && (spell("-e"))) {
+                        st = pSMgr->suggest_morph(cw);
+                        if (st) {
+                                strcat(result, st);
+                                free(st);
+                        }
+                        strcat(result,"+"); // XXX spec. separator in MORPHCODE
+                        st = pSMgr->suggest_morph("-e");
+                        if (st) {
+                                strcat(result, st);
+                                free(st);
+                        }
+                        return mystrdup(result);
+                }
+      } else {
+      // first word ending with dash: word- XXX ???
+        char r2 = *(dash + 1);
+        dash[0]='-';
+        dash[1]='\0';
+        nresult = spell(cw);
+        dash[1] = r2;
+        dash[0]='\0';
+        if (nresult && spell(dash+1) && ((strlen(dash+1) > 1) ||
+                ((dash[1] > '0') && (dash[1] < '9')))) {
+                            st = morph(cw);
+                            if (st) {
+                                strcat(result, st);
+                                    free(st);
+                                strcat(result,"+"); // XXX spec. separator in MORPHCODE
+                            }
+                            st = morph(dash+1);
+                            if (st) {
+                                    strcat(result, st);
+                                    free(st);
+                            }
+                            return mystrdup(result);                    
+                        }
+      }
+      // affixed number in correct word
+     if (nresult && (dash > cw) && (((*(dash-1)<='9') && 
+                        (*(dash-1)>='0')) || (*(dash-1)=='.'))) {
+         *dash='-';
+         n = 1;
+         if (*(dash - n) == '.') n++;
+         // search first not a number character to left from dash
+         while (((dash - n)>=cw) && ((*(dash - n)=='0') || (n < 3)) && (n < 6)) {
+            n++;
+         }
+         if ((dash - n) < cw) n--;
+         // numbers: valami1000000-hoz
+         // examine 100000-hoz, 10000-hoz 1000-hoz, 10-hoz,
+         // 56-hoz, 6-hoz
+         for(; n >= 1; n--) {
+            if ((*(dash - n) >= '0') && (*(dash - n) <= '9') && checkword(dash - n, NULL, NULL)) {
+                    strcat(result, cw);
+                    result[dash - cw - n] = '\0';
+                        st = pSMgr->suggest_morph(dash - n);
+                        if (st) {
+                        strcat(result, st);
+                                free(st);
+                        }
+                    return mystrdup(result);                    
+            }
+         }
+     }
+  }
+  return NULL;
+}
+
+// XXX need UTF-8 support
+char * Hunspell::morph_with_correction(const char * word)
+{
+  char cw[MAXWORDUTF8LEN];
+  char wspace[MAXWORDUTF8LEN];
+  if (! pSMgr) return 0;
+  int wl = strlen(word);
+  if (utf8) {
+    if (wl >= MAXWORDUTF8LEN) return 0;
+  } else {
+    if (wl >= MAXWORDLEN) return 0;
+  }
+  int captype = 0;
+  int abbv = 0;
+  wl = cleanword(cw, word, &captype, &abbv);
+  if (wl == 0) return 0;
+
+  char result[MAXLNLEN];
+  char * st = NULL;
+  
+  *result = '\0';
+  
+  
+  switch(captype) {
+     case NOCAP:   { 
+                     st = pSMgr->suggest_morph_for_spelling_error(cw);
+                     if (st) {
+                        strcat(result, st);
+                        free(st);
+                     }
+                                         if (abbv) {
+                                        memcpy(wspace,cw,wl);
+                         *(wspace+wl) = '.';
+                         *(wspace+wl+1) = '\0';
+                         st = pSMgr->suggest_morph_for_spelling_error(wspace);
+                         if (st) {
+                            if (*result) strcat(result, "\n");
+                            strcat(result, st);
+                            free(st);
+                                                 }
+                     }
+                                         break;
+                   }
+     case INITCAP: { 
+                     memcpy(wspace,cw,(wl+1));
+                     mkallsmall(wspace);
+                     st = pSMgr->suggest_morph_for_spelling_error(wspace);
+                     if (st) {
+                        strcat(result, st);
+                        free(st);
+                     }                                   
+                         st = pSMgr->suggest_morph_for_spelling_error(cw);
+                     if (st) {
+                        if (*result) strcat(result, "\n");
+                        strcat(result, st);
+                        free(st);
+                     }
+                                         if (abbv) {
+                                         memcpy(wspace,cw,wl);
+                         *(wspace+wl) = '.';
+                         *(wspace+wl+1) = '\0';
+                         mkallsmall(wspace);
+                         st = pSMgr->suggest_morph_for_spelling_error(wspace);
+                         if (st) {
+                            if (*result) strcat(result, "\n");
+                            strcat(result, st);
+                            free(st);
+                                                 }
+                         mkinitcap(wspace);
+                         st = pSMgr->suggest_morph_for_spelling_error(wspace);
+                         if (st) {
+                            if (*result) strcat(result, "\n");
+                            strcat(result, st);
+                            free(st);
+                                                 }
+                     }
+                     break;
+                   }
+     case HUHCAP: { 
+                     st = pSMgr->suggest_morph_for_spelling_error(cw);
+                     if (st) {
+                        strcat(result, st);
+                        free(st);
+                     }
+                     memcpy(wspace,cw,(wl+1));
+                     mkallsmall(wspace);
+                     st = pSMgr->suggest_morph_for_spelling_error(wspace);
+                     if (st) {
+                        if (*result) strcat(result, "\n");
+                        strcat(result, st);
+                        free(st);
+                     }               
+                     break;
+                 }
+     case ALLCAP: { 
+                     memcpy(wspace,cw,(wl+1));
+                     st = pSMgr->suggest_morph_for_spelling_error(wspace);
+                     if (st) {
+                        strcat(result, st);
+                        free(st);
+                     }               
+                     mkallsmall(wspace);
+                     st = pSMgr->suggest_morph_for_spelling_error(wspace);
+                     if (st) {
+                        if (*result) strcat(result, "\n");
+                        strcat(result, st);
+                        free(st);
+                     }
+                             mkinitcap(wspace);
+                             st = pSMgr->suggest_morph_for_spelling_error(wspace);
+                     if (st) {
+                        if (*result) strcat(result, "\n");
+                        strcat(result, st);
+                        free(st);
+                     }
+                                         if (abbv) {
+                        memcpy(wspace,cw,(wl+1));
+                        *(wspace+wl) = '.';
+                        *(wspace+wl+1) = '\0';
+                        if (*result) strcat(result, "\n");
+                        st = pSMgr->suggest_morph_for_spelling_error(wspace);
+                        if (st) {
+                                strcat(result, st);
+                                free(st);
+                        }                    
+                        mkallsmall(wspace);
+                        st = pSMgr->suggest_morph_for_spelling_error(wspace);
+                        if (st) {
+                          if (*result) strcat(result, "\n");
+                          strcat(result, st);
+                          free(st);
+                        }
+                                mkinitcap(wspace);
+                                st = pSMgr->suggest_morph_for_spelling_error(wspace);
+                        if (st) {
+                          if (*result) strcat(result, "\n");
+                          strcat(result, st);
+                          free(st);
+                        }
+                                         }
+                     break;
+                   }
+  }
+
+  if (result) return mystrdup(result);
+  return NULL;
+}
+
+/* analyze word
+ * return line count 
+ * XXX need a better data structure for morphological analysis */
+int Hunspell::analyze(char ***out, const char *word) {
+  int  n = 0;
+  if (!word) return 0;
+  char * m = morph(word);
+  if(!m) return 0;
+  if (!out)
+  {
+     n = line_tok(m, out);
+     free(m);
+     return n;
+  }
+
+  // without memory allocation
+  /* BUG missing buffer size checking */
+  int i, p;
+  for(p = 0, i = 0; m[i]; i++) {
+     if(m[i] == '\n' || !m[i+1]) {
+       n++;
+       strncpy((*out)[n++], m + p, i - p + 1);
+       if (m[i] == '\n') (*out)[n++][i - p] = '\0';
+       if(!m[i+1]) break;
+       p = i + 1;        
+     }
+  }
+  free(m);
+  return n;
+}
+
+#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+
+Hunhandle *Hunspell_create(const char * affpath, const char * dpath)
+{
+        return (Hunhandle*)(new Hunspell(affpath, dpath));
+}
+
+void Hunspell_destroy(Hunhandle *pHunspell)
+{
+        delete (Hunspell*)(pHunspell);
+}
+
+int Hunspell_spell(Hunhandle *pHunspell, const char *word)
+{
+        return ((Hunspell*)pHunspell)->spell(word);
+}
+
+char *Hunspell_get_dic_encoding(Hunhandle *pHunspell)
+{
+        return ((Hunspell*)pHunspell)->get_dic_encoding();
+}
+
+int Hunspell_suggest(Hunhandle *pHunspell, char*** slst, const char * word)
+{
+        return ((Hunspell*)pHunspell)->suggest(slst, word);
+}
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/hunspell.h spellcheck/hunspell/hunspell/hunspell.h
--- spellcheck.old/hunspell/hunspell/hunspell.h	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/hunspell.h	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,89 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef _MYSPELLMGR_H_
+#define _MYSPELLMGR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct Hunhandle Hunhandle;
+
+Hunhandle *Hunspell_create(const char * affpath, const char * dpath);
+void Hunspell_destroy(Hunhandle *pHunspell);
+
+/* spell(word) - spellcheck word
+ * output: 0 = bad word, not 0 = good word
+ */
+int Hunspell_spell(Hunhandle *pHunspell, const char *);
+
+char *Hunspell_get_dic_encoding(Hunhandle *pHunspell);
+
+/* suggest(suggestions, word) - search suggestions
+ * input: pointer to an array of strings pointer and the (bad) word
+ *   array of strings pointer (here *slst) may not be initialized
+ * output: number of suggestions in string array, and suggestions in
+ *   a newly allocated array of strings (*slts will be NULL when number
+ *   of suggestion equals 0.)
+ */
+int Hunspell_suggest(Hunhandle *pHunspell, char*** slst, const char * word);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/hunspell.hxx spellcheck/hunspell/hunspell/hunspell.hxx
--- spellcheck.old/hunspell/hunspell/hunspell.hxx	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/hunspell.hxx	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,195 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#include "hashmgr.hxx"
+#include "affixmgr.hxx"
+#include "suggestmgr.hxx"
+#include "csutil.hxx"
+#include "langnum.hxx"
+
+#define  SPELL_COMPOUND  (1 << 0)
+#define  SPELL_FORBIDDEN (1 << 1)
+#define  SPELL_ALLCAP    (1 << 2)
+#define  SPELL_NOCAP     (1 << 3)
+#define  SPELL_INITCAP   (1 << 4)
+
+#define MAXSUGGESTION 15
+#define MAXSHARPS 5
+
+#ifndef _MYSPELLMGR_HXX_
+#define _MYSPELLMGR_HXX_
+
+#ifdef HUNSPELL_STATIC
+	#define DLLEXPORT
+#else
+	#ifdef HUNSPELL_EXPORTS
+		#define DLLEXPORT  __declspec( dllexport )
+	#else
+		#define DLLEXPORT  __declspec( dllimport )
+	#endif
+#endif
+
+#ifdef W32
+class DLLEXPORT Hunspell
+#else
+class Hunspell
+#endif
+{
+  AffixMgr*       pAMgr;
+  HashMgr*        pHMgr;
+  SuggestMgr*     pSMgr;
+  char *          encoding;
+  struct cs_info * csconv;
+  int             langnum;
+  int             utf8;
+  int             complexprefixes;
+  char**          wordbreak;
+
+public:
+
+  /* Hunspell(aff, dic) - constructor of Hunspell class
+   * input: path of affix file and dictionary file
+   */
+  
+  Hunspell(const char * affpath, const char * dpath);
+
+  ~Hunspell();
+
+  /* spell(word) - spellcheck word
+   * output: 0 = bad word, not 0 = good word
+   *   
+   * plus output:
+   *   info: information bit array, fields:
+   *     SPELL_COMPOUND  = a compound word 
+   *     SPELL_FORBIDDEN = an explicit forbidden word
+   *   root: root (stem), when input is a word with affix(es)
+   */
+   
+  int spell(const char * word, int * info = NULL, char ** root = NULL);
+
+  /* suggest(suggestions, word) - search suggestions
+   * input: pointer to an array of strings pointer and the (bad) word
+   *   array of strings pointer (here *slst) may not be initialized
+   * output: number of suggestions in string array, and suggestions in
+   *   a newly allocated array of strings (*slts will be NULL when number
+   *   of suggestion equals 0.)
+   */
+
+  int suggest(char*** slst, const char * word);
+  char * get_dic_encoding();
+
+  /* handling custom dictionary */
+  
+  int put_word(const char * word);
+
+  /* pattern is a sample dictionary word 
+   * put word into custom dictionary with affix flags of pattern word
+   */
+  
+  int put_word_pattern(const char * word, const char * pattern);
+
+  /* other */
+
+  /* get extra word characters definied in affix file for tokenization */
+  const char * get_wordchars();
+  unsigned short * get_wordchars_utf16(int * len);
+
+  struct cs_info * get_csconv();
+  const char * get_version();
+
+  /* experimental functions */
+
+#ifdef HUNSPELL_EXPERIMENTAL
+  /* suffix is an affix flag string, similarly in dictionary files */
+  
+  int put_word_suffix(const char * word, const char * suffix);
+  
+  /* morphological analysis */
+  
+  char * morph(const char * word);
+  int analyze(char*** out, const char *word);
+
+  char * morph_with_correction(const char * word);
+
+  /* stemmer function */
+  
+  int stem(char*** slst, const char * word);
+
+  /* spec. suggestions */
+  int suggest_auto(char*** slst, const char * word);
+  int suggest_pos_stems(char*** slst, const char * word);
+  char * get_possible_root();
+#endif
+
+private:
+   int    cleanword(char *, const char *, int * pcaptype, int * pabbrev);
+   int    cleanword2(char *, const char *, w_char *, int * w_len, int * pcaptype, int * pabbrev);
+   void   mkinitcap(char *);
+   int    mkinitcap2(char * p, w_char * u, int nc);
+   int    mkinitsmall2(char * p, w_char * u, int nc);
+   void   mkallcap(char *);
+   int    mkallcap2(char * p, w_char * u, int nc);
+   void   mkallsmall(char *);
+   int    mkallsmall2(char * p, w_char * u, int nc);
+   struct hentry * checkword(const char *, int * info, char **root);
+   char * sharps_u8_l1(char * dest, char * source);
+   hentry * spellsharps(char * base, char *, int, int, char * tmp, int * info, char **root);
+   int    is_keepcase(const hentry * rv);
+   int    insert_sug(char ***slst, char * word, int ns);
+
+};
+
+#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/langnum.hxx spellcheck/hunspell/hunspell/langnum.hxx
--- spellcheck.old/hunspell/hunspell/langnum.hxx	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/langnum.hxx	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,94 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef _LANGNUM_HXX_
+#define _LANGNUM_HXX_
+
+/*
+ language numbers for language specific codes
+ see http://l10n.openoffice.org/languages.html
+*/
+
+enum {
+LANG_ar=96,
+LANG_az=100, // custom number
+LANG_bg=41,
+LANG_ca=37,
+LANG_cs=42,
+LANG_da=45,
+LANG_de=49,
+LANG_el=30,
+LANG_en=01,
+LANG_es=34,
+LANG_eu=10,
+LANG_fr=02,
+LANG_gl=38,
+LANG_hr=78,
+LANG_hu=36,
+LANG_it=39,
+LANG_la=99, // custom number
+LANG_lv=101, // custom number
+LANG_nl=31,
+LANG_pl=48,
+LANG_pt=03,
+LANG_ru=07,
+LANG_sv=50,
+LANG_tr=90,
+LANG_uk=80,
+LANG_xx=999
+};
+
+#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/Makefile.in spellcheck/hunspell/hunspell/Makefile.in
--- spellcheck.old/hunspell/hunspell/Makefile.in	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/Makefile.in	2008-04-23 16:44:54.000000000 +0200
@@ -0,0 +1,66 @@
+# ****** BEGIN LICENSE BLOCK ******
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+# 
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+# 
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+# 
+# The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+# and László Németh (Hunspell). Portions created by the Initial Developers
+# are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+# 
+# Contributor(s): David Einstein (deinst@world.std.com)
+#                 László Németh (nemethl@gyorsposta.hu)
+#                 Ryan VanderMeulen (ryanvm@gmail.com)
+# 
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ****** END LICENSE BLOCK ******
+
+DEPTH           = ../../../..
+topsrcdir       = @top_srcdir@
+srcdir          = @srcdir@
+VPATH           = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE           = hunspell
+LIBRARY_NAME     = libhunspell_s
+FORCE_STATIC_LIB = 1
+LIBXUL_LIBRARY   = 1
+
+REQUIRES         = xpcom \
+                   string \
+                   uconv \
+                   unicharutil \
+                   spellchecker \
+                   xulapp \
+                   $(NULL)
+
+CPPSRCS         += affentry.cpp \
+                   affixmgr.cpp \
+                   csutil.cpp \
+                   hashmgr.cpp \
+                   hunspell.cpp \
+                   phonet.cpp \
+                   suggestmgr.cpp \
+                   $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/phonet.cpp spellcheck/hunspell/hunspell/phonet.cpp
--- spellcheck.old/hunspell/hunspell/phonet.cpp	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/phonet.cpp	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,310 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developer of the Original Code is Björn Jacke. Portions created
+ * by the Initial Developers are Copyright (C) 2000-2007 the Initial
+ * Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Björn Jacke (bjoern.jacke@gmx.de)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * Changelog:
+ *  2000-01-05  Björn Jacke <bjoern.jacke AT gmx.de>
+ *              Initial Release insprired by the article about phonetic
+ *              transformations out of c't 25/1999
+ *
+ *  2007-07-26  Björn Jacke <bjoern.jacke AT gmx.de>
+ *              Released under MPL/GPL/LGPL tri-license for Hunspell
+ *
+ *  2007-08-23  László Németh <nemeth at OOo>
+ *              Porting from Aspell to Hunspell using C-like structs
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef MOZILLA_CLIENT
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+#include <cctype>
+#else
+#include <stdlib.h> 
+#include <string.h>
+#include <stdio.h> 
+#include <ctype.h>
+#endif
+
+#include "csutil.hxx"
+#include "phonet.hxx"
+
+void init_phonet_hash(phonetable & parms) 
+  {
+    int i, k;
+
+    for (i = 0; i < parms.hash_size; i++) {
+      parms.hash[i] = -1;
+    }
+
+    for (i = 0; parms.rules[i][0] != '\0'; i += 2) {
+      /**  set hash value  **/
+      k = (unsigned char) parms.rules[i][0];
+
+      if (parms.hash[k] < 0) {
+	parms.hash[k] = i;
+      }
+    }
+  }
+
+  // like strcpy but safe if the strings overlap
+  //   but only if dest < src
+  static inline void strmove(char * dest, char * src) {
+    while (*src) 
+      *dest++ = *src++;
+    *dest = '\0';
+  }
+
+/*  phonetic transcription algorithm                   */
+/*  see: http://aspell.net/man-html/Phonetic-Code.html */
+/*  convert string to uppercase before this call       */
+int phonet (const char * inword, char * target,
+              int len,
+	      phonetable & parms)
+  {
+    /**       Do phonetic transformation.       **/
+    /**  "len" = length of "inword" incl. '\0'. **/
+
+    /**  result:  >= 0:  length of "target"    **/
+    /**            otherwise:  error            **/
+
+    int  i,j,k=0,n,p,z;
+    int  k0,n0,p0=-333,z0;
+    char c, c0;
+    const char * s;
+    typedef unsigned char uchar;    
+    char word[MAXPHONETUTF8LEN + 1];
+    if (len == -1) len = strlen(inword);
+    if (len > MAXPHONETUTF8LEN) return 0;
+    strcpy(word, inword);
+  
+    /**  check word  **/
+    i = j = z = 0;
+    while ((c = word[i]) != '\0') {
+      n = parms.hash[(uchar) c];
+      z0 = 0;
+
+      if (n >= 0) {
+        /**  check all rules for the same letter  **/
+        while (parms.rules[n][0] == c) {
+
+          /**  check whole string  **/
+          k = 1;   /** number of found letters  **/
+          p = 5;   /** default priority  **/
+          s = parms.rules[n];
+          s++;     /**  important for (see below)  "*(s-1)"  **/
+          
+          while (*s != '\0'  &&  word[i+k] == *s
+                 &&  !isdigit (*s)  &&  strchr ("(-<^$", *s) == NULL) {
+            k++;
+            s++;
+          }
+          if (*s == '(') {
+            /**  check letters in "(..)"  **/
+            if (isalpha(word[i+k])  // ...could be implied?
+                && strchr(s+1, word[i+k]) != NULL) {
+              k++;
+              while (*s != ')')
+                s++;
+              s++;
+            }
+          }
+          p0 = (int) *s;
+          k0 = k;
+          while (*s == '-'  &&  k > 1) {
+            k--;
+            s++;
+          }
+          if (*s == '<')
+            s++;
+          if (isdigit (*s)) {
+            /**  determine priority  **/
+            p = *s - '0';
+            s++;
+          }
+          if (*s == '^'  &&  *(s+1) == '^')
+            s++;
+
+          if (*s == '\0'
+              || (*s == '^'  
+                  && (i == 0  ||  ! isalpha(word[i-1]))
+                  && (*(s+1) != '$'
+                      || (! isalpha(word[i+k0]) )))
+              || (*s == '$'  &&  i > 0  
+                  &&  isalpha(word[i-1])
+                  && (! isalpha(word[i+k0]) ))) 
+          {
+            /**  search for followup rules, if:     **/
+            /**  parms.followup and k > 1  and  NO '-' in searchstring **/
+            c0 = word[i+k-1];
+            n0 = parms.hash[(uchar) c0];
+
+//            if (parms.followup  &&  k > 1  &&  n0 >= 0
+            if (k > 1  &&  n0 >= 0
+                &&  p0 != (int) '-'  &&  word[i+k] != '\0') {
+              /**  test follow-up rule for "word[i+k]"  **/
+              while (parms.rules[n0][0] == c0) {
+
+                /**  check whole string  **/
+                k0 = k;
+                p0 = 5;
+                s = parms.rules[n0];
+                s++;
+                while (*s != '\0'  &&  word[i+k0] == *s
+                       && ! isdigit(*s)  &&  strchr("(-<^$",*s) == NULL) {
+                  k0++;
+                  s++;
+                }
+                if (*s == '(') {
+                  /**  check letters  **/
+                  if (isalpha(word[i+k0])
+                      &&  strchr (s+1, word[i+k0]) != NULL) {
+                    k0++;
+                    while (*s != ')'  &&  *s != '\0')
+                      s++;
+                    if (*s == ')')
+                      s++;
+                  }
+                }
+                while (*s == '-') {
+                  /**  "k0" gets NOT reduced   **/
+                  /**  because "if (k0 == k)"  **/
+                  s++;
+                }
+                if (*s == '<')
+                  s++;
+                if (isdigit (*s)) {
+                  p0 = *s - '0';
+                  s++;
+                }
+
+                if (*s == '\0'
+                    /**  *s == '^' cuts  **/
+                    || (*s == '$'  &&  ! isalpha(word[i+k0]))) 
+                {
+                  if (k0 == k) {
+                    /**  this is just a piece of the string  **/
+                    n0 += 2;
+                    continue;
+                  }
+
+                  if (p0 < p) {
+                    /**  priority too low  **/
+                    n0 += 2;
+                    continue;
+                  }
+                  /**  rule fits; stop search  **/
+                  break;
+                }
+                n0 += 2;
+              } /**  End of "while (parms.rules[n0][0] == c0)"  **/
+
+              if (p0 >= p  && parms.rules[n0][0] == c0) {
+                n += 2;
+                continue;
+              }
+            } /** end of follow-up stuff **/
+
+            /**  replace string  **/
+            s = parms.rules[n+1];
+            p0 = (parms.rules[n][0] != '\0'
+                 &&  strchr (parms.rules[n]+1,'<') != NULL) ? 1:0;
+            if (p0 == 1 &&  z == 0) {
+              /**  rule with '<' is used  **/
+              if (j > 0  &&  *s != '\0'
+                 && (target[j-1] == c  ||  target[j-1] == *s)) {
+                j--;
+              }
+              z0 = 1;
+              z = 1;
+              k0 = 0;
+              while (*s != '\0'  &&  word[i+k0] != '\0') {
+                word[i+k0] = *s;
+                k0++;
+                s++;
+              }
+              if (k > k0)
+                strmove (&word[0]+i+k0, &word[0]+i+k);
+
+              /**  new "actual letter"  **/
+              c = word[i];
+            }
+            else { /** no '<' rule used **/
+              i += k - 1;
+              z = 0;
+              while (*s != '\0'
+                     &&  *(s+1) != '\0'  &&  j < len) {
+                if (j == 0  ||  target[j-1] != *s) {
+                  target[j] = *s;
+                  j++;
+                }
+                s++;
+              }
+              /**  new "actual letter"  **/
+              c = *s;
+              if (parms.rules[n][0] != '\0'
+                 &&  strstr (parms.rules[n]+1, "^^") != NULL) {
+                if (c != '\0') {
+                  target[j] = c;
+                  j++;
+                }
+                strmove (&word[0], &word[0]+i+1);
+                i = 0;
+                z0 = 1;
+              }
+            }
+            break;
+          }  /** end of follow-up stuff **/
+          n += 2;
+        } /**  end of while (parms.rules[n][0] == c)  **/
+      } /**  end of if (n >= 0)  **/
+      if (z0 == 0) {
+//        if (k && (assert(p0!=-333),!p0) &&  j < len &&  c != '\0'
+//           && (!parms.collapse_result  ||  j == 0  ||  target[j-1] != c)){
+        if (k && !p0 && j < len &&  c != '\0'
+           && (1 || j == 0  ||  target[j-1] != c)){
+           /**  condense only double letters  **/
+          target[j] = c;
+	  ///printf("\n setting \n");
+          j++;
+        }
+
+        i++;
+        z = 0;
+	k=0;
+      }
+    }  /**  end of   while ((c = word[i]) != '\0')  **/
+
+    target[j] = '\0';
+    return (j);
+
+  }  /**  end of function "phonet"  **/
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/phonet.hxx spellcheck/hunspell/hunspell/phonet.hxx
--- spellcheck.old/hunspell/hunspell/phonet.hxx	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/phonet.hxx	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,66 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developer of the Original Code is Björn Jacke. Portions created
+ * by the Initial Developers are Copyright (C) 2000-2007 the Initial
+ * Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Björn Jacke (bjoern.jacke@gmx.de)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * Changelog:
+ *  2000-01-05  Björn Jacke <bjoern.jacke AT gmx.de>
+ *              Initial Release insprired by the article about phonetic
+ *              transformations out of c't 25/1999
+ *
+ *  2007-07-20  Björn Jacke <bjoern.jacke AT gmx.de>
+ *              Released under MPL/GPL/LGPL tri-license for Hunspell
+ *
+ *  2007-08-22  László Németh <nemeth at OOo>
+ *              Porting from Aspell to Hunspell by little modifications
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef __PHONETHXX__
+#define __PHONETHXX__
+
+#define MAXPHONETLEN      256
+#define MAXPHONETUTF8LEN  (MAXPHONETLEN * 4)
+
+struct phonetable {
+  char utf8;
+  cs_info * lang;
+  int num;
+  char * * rules;
+  static const int hash_size = 256;
+  int hash[hash_size];
+};
+
+void init_phonet_hash(phonetable & parms);
+
+int phonet (const char * inword, char * target,
+              int len, phonetable & phone);
+
+#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/README.hunspell spellcheck/hunspell/hunspell/README.hunspell
--- spellcheck.old/hunspell/hunspell/README.hunspell	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/README.hunspell	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,59 @@
+******* BEGIN LICENSE BLOCK *******
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+* 
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+* 
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+* 
+* The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+* and László Németh (Hunspell). Portions created by the Initial Developers
+* are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+* 
+* Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+*                 David Einstein (deinst@world.std.com)
+*                 László Németh (nemethl@gyorsposta.hu)
+*                 Ryan VanderMeulen (ryanvm@gmail.com)
+* 
+* Alternatively, the contents of this file may be used under the terms of
+* either the GNU General Public License Version 2 or later (the "GPL"), or
+* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+* in which case the provisions of the GPL or the LGPL are applicable instead
+* of those above. If you wish to allow use of your version of this file only
+* under the terms of either the GPL or the LGPL, and not to allow others to
+* use your version of this file under the terms of the MPL, indicate your
+* decision by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL or the LGPL. If you do not delete
+* the provisions above, a recipient may use your version of this file under
+* the terms of any one of the MPL, the GPL or the LGPL.
+*
+******* END LICENSE BLOCK *******
+
+Hunspell Version: 1.1.12
+
+Hunspell Author: László Németh
+MySpell Author: Kevin Hendricks & David Einstein
+
+Hunspell is a spell checker and morphological analyser library. Hunspell
+is based on OpenOffice.org's Myspell. Documentation, tests, and examples
+are available at http://hunspell.sourceforge.net.
+
+A special thanks and credit goes to Geoff Kuenning, the creator of Ispell.
+MySpell's affix algorithms were based on those of Ispell, which should be
+noted is copyright Geoff Kuenning et al and now available under a BSD-style
+license. For more information on Ispell and affix compression in general,
+please see: http://lasr.cs.ucla.edu/geoff/ispell.html (Ispell homepage)
+
+An almost complete rewrite of MySpell for use by the Mozilla project was
+developed by David Einstein. David was a significant help in improving MySpell.
+
+Special thanks also goes to László Németh, who is the author of the Hungarian
+dictionary and who developed and contributed the code to support compound words
+in MySpell and fixed numerous problems with the encoding case conversion tables
+along with rewriting MySpell as Hunspell and ensuring compatibility with the
+Mozilla codebase.
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/suggestmgr.cpp spellcheck/hunspell/hunspell/suggestmgr.cpp
--- spellcheck.old/hunspell/hunspell/suggestmgr.cpp	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/suggestmgr.cpp	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,2036 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef MOZILLA_CLIENT
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+#include <cctype>
+#else
+#include <stdlib.h> 
+#include <string.h>
+#include <stdio.h> 
+#include <ctype.h>
+#endif
+
+#include "suggestmgr.hxx"
+
+#ifndef MOZILLA_CLIENT
+#ifndef W32
+using namespace std;
+#endif
+#endif
+
+const w_char W_VLINE = { '\0', '|' };
+
+SuggestMgr::SuggestMgr(const char * tryme, int maxn, 
+                       AffixMgr * aptr)
+{
+
+  // register affix manager and check in string of chars to 
+  // try when building candidate suggestions
+  pAMgr = aptr;
+
+  ckeyl = 0;
+  ckey = NULL;
+  ckey_utf = NULL;
+
+  ctryl = 0;
+  ctry = NULL;
+  ctry_utf = NULL;
+
+  utf8 = 0;
+  langnum = 0;
+  complexprefixes = 0;  
+  
+  maxSug = maxn;
+  nosplitsugs = 0;
+  maxngramsugs = MAXNGRAMSUGS;
+
+  if (pAMgr) {
+        char * enc = pAMgr->get_encoding();
+        csconv = get_current_cs(enc);
+        free(enc);
+        langnum = pAMgr->get_langnum();
+        ckey = pAMgr->get_key_string();
+        nosplitsugs = pAMgr->get_nosplitsugs();
+        if (pAMgr->get_maxngramsugs() >= 0) maxngramsugs = pAMgr->get_maxngramsugs();
+        utf8 = pAMgr->get_utf8();
+        complexprefixes = pAMgr->get_complexprefixes();
+  }
+
+  if (ckey) {  
+    if (utf8) {
+        w_char t[MAXSWL];    
+        ckeyl = u8_u16(t, MAXSWL, ckey);
+        ckey_utf = (w_char *) malloc(ckeyl * sizeof(w_char));
+        if (ckey_utf) memcpy(ckey_utf, t, ckeyl * sizeof(w_char));
+    } else {
+        ckeyl = strlen(ckey);
+    }
+  }
+  
+  if (tryme) {  
+    if (utf8) {
+        w_char t[MAXSWL];    
+        ctryl = u8_u16(t, MAXSWL, tryme);
+        ctry_utf = (w_char *) malloc(ctryl * sizeof(w_char));
+        if (ctry_utf) memcpy(ctry_utf, t, ctryl * sizeof(w_char));
+    } else {
+        ctry = mystrdup(tryme);
+        ctryl = strlen(ctry);
+    }
+  }
+}
+
+
+SuggestMgr::~SuggestMgr()
+{
+  pAMgr = NULL;
+  if (ckey) free(ckey);
+  ckey = NULL;
+  if (ckey_utf) free(ckey_utf);
+  ckey_utf = NULL;
+  ckeyl = 0;
+  if (ctry) free(ctry);
+  ctry = NULL;
+  if (ctry_utf) free(ctry_utf);
+  ctry_utf = NULL;
+  ctryl = 0;
+  maxSug = 0;
+}
+
+int SuggestMgr::testsug(char** wlst, const char * candidate, int wl, int ns, int cpdsuggest,
+   int * timer, clock_t * timelimit) {
+      int cwrd = 1;
+      if (ns == maxSug) return maxSug;
+      for (int k=0; k < ns; k++) {
+        if (strcmp(candidate,wlst[k]) == 0) cwrd = 0;
+      }
+      if ((cwrd) && checkword(candidate, wl, cpdsuggest, timer, timelimit)) {
+        wlst[ns] = mystrdup(candidate);
+        if (wlst[ns] == NULL) {
+            for (int j=0; j<ns; j++) free(wlst[j]);
+            return -1;
+        }
+        ns++;
+      } 
+      return ns;
+}
+
+// generate suggestions for a mispelled word
+//    pass in address of array of char * pointers
+// onlycompoundsug: probably bad suggestions (need for ngram sugs, too)
+
+int SuggestMgr::suggest(char*** slst, const char * w, int nsug,
+    int * onlycompoundsug)
+{
+  int nocompoundtwowords = 0;
+  char ** wlst;    
+  w_char word_utf[MAXSWL];
+  int wl = 0;
+
+  char w2[MAXWORDUTF8LEN];
+  const char * word = w;
+
+  // word reversing wrapper for complex prefixes
+  if (complexprefixes) {
+    strcpy(w2, w);
+    if (utf8) reverseword_utf(w2); else reverseword(w2);
+    word = w2;
+  }
+    
+    if (*slst) {
+        wlst = *slst;
+    } else {
+        wlst = (char **) malloc(maxSug * sizeof(char *));
+        if (wlst == NULL) return -1;
+        for (int i = 0; i < maxSug; i++) {
+            wlst[i] = NULL;
+        }
+    }
+    
+    if (utf8) {
+        wl = u8_u16(word_utf, MAXSWL, word);
+    }
+
+    for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) {
+
+    // suggestions for an uppercase word (html -> HTML)
+    if ((nsug < maxSug) && (nsug > -1)) {
+        nsug = (utf8) ? capchars_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
+                    capchars(wlst, word, nsug, cpdsuggest);
+    }
+
+    // perhaps we made a typical fault of spelling
+    if ((nsug < maxSug) && (nsug > -1))
+    nsug = replchars(wlst, word, nsug, cpdsuggest);
+
+    // perhaps we made chose the wrong char from a related set
+    if ((nsug < maxSug) && (nsug > -1)) {
+      nsug = mapchars(wlst, word, nsug, cpdsuggest);
+    }
+
+    // did we swap the order of chars by mistake
+    if ((nsug < maxSug) && (nsug > -1)) {
+        nsug = (utf8) ? swapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
+                    swapchar(wlst, word, nsug, cpdsuggest);
+    }
+
+    // did we swap the order of non adjacent chars by mistake
+    if ((nsug < maxSug) && (nsug > -1)) {
+        nsug = (utf8) ? longswapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
+                    longswapchar(wlst, word, nsug, cpdsuggest);
+    }
+
+    // did we just hit the wrong key in place of a good char (case and keyboard)
+    if ((nsug < maxSug) && (nsug > -1)) {
+        nsug = (utf8) ? badcharkey_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
+                    badcharkey(wlst, word, nsug, cpdsuggest);
+    }
+
+    // did we add a char that should not be there
+    if ((nsug < maxSug) && (nsug > -1)) {
+        nsug = (utf8) ? extrachar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
+                    extrachar(wlst, word, nsug, cpdsuggest);
+    }
+
+    // only suggest compound words when no other suggestion
+    if ((cpdsuggest == 0) && (nsug > 0)) nocompoundtwowords=1;
+
+    // did we forgot a char
+    if ((nsug < maxSug) && (nsug > -1)) {
+        nsug = (utf8) ? forgotchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
+                    forgotchar(wlst, word, nsug, cpdsuggest);
+    }
+
+    // did we move a char
+    if ((nsug < maxSug) && (nsug > -1)) {
+        nsug = (utf8) ? movechar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
+                    movechar(wlst, word, nsug, cpdsuggest);
+    }
+
+    // did we just hit the wrong key in place of a good char
+    if ((nsug < maxSug) && (nsug > -1)) {
+        nsug = (utf8) ? badchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
+                    badchar(wlst, word, nsug, cpdsuggest);
+    }
+
+    // did we double two characters
+    if ((nsug < maxSug) && (nsug > -1)) {
+        nsug = (utf8) ? doubletwochars_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
+                    doubletwochars(wlst, word, nsug, cpdsuggest);
+    }
+
+    // perhaps we forgot to hit space and two words ran together
+    if ((!nosplitsugs) && (nsug < maxSug) && (nsug > -1)) {
+                nsug = twowords(wlst, word, nsug, cpdsuggest);
+        }
+
+    } // repeating ``for'' statement compounding support
+
+    if (nsug < 0) {
+     // we ran out of memory - we should free up as much as possible
+       for (int i = 0; i < maxSug; i++)
+         if (wlst[i] != NULL) free(wlst[i]);
+       free(wlst);
+       wlst = NULL;
+    }
+    
+    if (!nocompoundtwowords && (nsug > 0) && onlycompoundsug) *onlycompoundsug = 1;
+
+    *slst = wlst;
+    return nsug;
+}
+
+// generate suggestions for a word with typical mistake
+//    pass in address of array of char * pointers
+#ifdef HUNSPELL_EXPERIMENTAL
+int SuggestMgr::suggest_auto(char*** slst, const char * w, int nsug)
+{
+    int nocompoundtwowords = 0;
+    char ** wlst;
+
+  char w2[MAXWORDUTF8LEN];
+  const char * word = w;
+
+  // word reversing wrapper for complex prefixes
+  if (complexprefixes) {
+    strcpy(w2, w);
+    if (utf8) reverseword_utf(w2); else reverseword(w2);
+    word = w2;
+  }
+
+    if (*slst) {
+        wlst = *slst;
+    } else {
+        wlst = (char **) malloc(maxSug * sizeof(char *));
+        if (wlst == NULL) return -1;
+    }
+
+    for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) {
+
+    // perhaps we made a typical fault of spelling
+    if ((nsug < maxSug) && (nsug > -1))
+    nsug = replchars(wlst, word, nsug, cpdsuggest);
+
+    // perhaps we made chose the wrong char from a related set
+    if ((nsug < maxSug) && (nsug > -1))
+      nsug = mapchars(wlst, word, nsug, cpdsuggest);
+
+    if ((cpdsuggest==0) && (nsug>0)) nocompoundtwowords=1; else *
+
+    // perhaps we forgot to hit space and two words ran together
+
+    if ((nsug < maxSug) && (nsug > -1) && check_forbidden(word, strlen(word))) {
+                nsug = twowords(wlst, word, nsug, cpdsuggest);
+        }
+    
+    } // repeating ``for'' statement compounding support
+
+    if (nsug < 0) {
+       for (int i=0;i<maxSug; i++)
+         if (wlst[i] != NULL) free(wlst[i]);
+       free(wlst);
+       return -1;
+    }
+
+    *slst = wlst;
+    return nsug;
+}
+#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+
+// suggestions for an uppercase word (html -> HTML)
+int SuggestMgr::capchars_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
+{
+  char candidate[MAXSWUTF8L];
+  w_char candidate_utf[MAXSWL];
+  memcpy(candidate_utf, word, wl * sizeof(w_char));
+  mkallcap_utf(candidate_utf, wl, langnum);
+  u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
+  return testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
+}
+
+// suggestions for an uppercase word (html -> HTML)
+int SuggestMgr::capchars(char** wlst, const char * word, int ns, int cpdsuggest)
+{
+  char candidate[MAXSWUTF8L];
+  strcpy(candidate, word);
+  mkallcap(candidate, csconv);
+  return testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
+}
+
+// suggestions for when chose the wrong char out of a related set
+int SuggestMgr::mapchars(char** wlst, const char * word, int ns, int cpdsuggest)
+{
+  clock_t timelimit;
+  int timer;
+  
+  int wl = strlen(word);
+  if (wl < 2 || ! pAMgr) return ns;
+
+  int nummap = pAMgr->get_nummap();
+  struct mapentry* maptable = pAMgr->get_maptable();
+  if (maptable==NULL) return ns;
+
+  timelimit = clock();
+  timer = MINTIMER;
+  if (utf8) {
+    w_char w[MAXSWL];
+    int len = u8_u16(w, MAXSWL, word);
+    ns = map_related_utf(w, len, 0, cpdsuggest, wlst, ns, maptable, nummap, &timer, &timelimit);
+  } else ns = map_related(word, 0, wlst, cpdsuggest, ns, maptable, nummap, &timer, &timelimit);
+  return ns;
+}
+
+int SuggestMgr::map_related(const char * word, int i, char** wlst, 
+    int cpdsuggest,  int ns,
+    const mapentry* maptable, int nummap, int * timer, clock_t * timelimit)
+{
+  char c = *(word + i);  
+  if (c == 0) {
+      int cwrd = 1;
+      int wl = strlen(word);
+      for (int m=0; m < ns; m++)
+          if (strcmp(word,wlst[m]) == 0) cwrd = 0;
+      if ((cwrd) && checkword(word, wl, cpdsuggest, timer, timelimit)) {
+          if (ns < maxSug) {
+              wlst[ns] = mystrdup(word);
+              if (wlst[ns] == NULL) return -1;
+              ns++;
+          }
+      }
+      return ns;
+  } 
+  int in_map = 0;
+  for (int j = 0; j < nummap; j++) {
+    if (strchr(maptable[j].set,c) != 0) {
+      in_map = 1;
+      char * newword = mystrdup(word);
+      for (int k = 0; k < maptable[j].len; k++) {
+        *(newword + i) = *(maptable[j].set + k);
+        ns = map_related(newword, (i+1), wlst, cpdsuggest,
+           ns, maptable, nummap, timer, timelimit);
+        if (!(*timer)) return ns;
+      }
+      free(newword);
+    }
+  }
+  if (!in_map) {
+     i++;
+     ns = map_related(word, i, wlst, cpdsuggest,
+        ns, maptable, nummap, timer, timelimit);
+  }
+  return ns;
+}
+
+int SuggestMgr::map_related_utf(w_char * word, int len, int i, int cpdsuggest,
+    char** wlst, int ns, const mapentry* maptable, int nummap,
+    int * timer, clock_t * timelimit) 
+{
+  if (i == len) {
+      int cwrd = 1;
+      int wl;
+      char s[MAXSWUTF8L];
+      u16_u8(s, MAXSWUTF8L, word, len);
+      wl = strlen(s);
+      for (int m=0; m < ns; m++)
+          if (strcmp(s,wlst[m]) == 0) cwrd = 0;
+      if ((cwrd) && checkword(s, wl, cpdsuggest, timer, timelimit)) {
+          if (ns < maxSug) {
+              wlst[ns] = mystrdup(s);
+              if (wlst[ns] == NULL) return -1;
+              ns++;
+          }
+      }
+      return ns;
+  } 
+  int in_map = 0;
+  unsigned short c = *((unsigned short *) word + i);
+  for (int j = 0; j < nummap; j++) {
+    if (flag_bsearch((unsigned short *) maptable[j].set_utf16, c, maptable[j].len)) {
+      in_map = 1;
+      for (int k = 0; k < maptable[j].len; k++) {
+        *(word + i) = *(maptable[j].set_utf16 + k);
+        ns = map_related_utf(word, len, i + 1, cpdsuggest,
+           wlst, ns, maptable, nummap, timer, timelimit);
+        if (!(*timer)) return ns;
+      }
+      *((unsigned short *) word + i) = c;
+    }
+  }
+  if (!in_map) {
+     i++;
+     ns = map_related_utf(word, len, i, cpdsuggest,
+          wlst, ns, maptable, nummap, timer, timelimit);
+  }
+  return ns;
+}
+
+
+
+// suggestions for a typical fault of spelling, that
+// differs with more, than 1 letter from the right form.
+int SuggestMgr::replchars(char** wlst, const char * word, int ns, int cpdsuggest)
+{
+  char candidate[MAXSWUTF8L];
+  const char * r;
+  int lenr, lenp;
+  int wl = strlen(word);
+  if (wl < 2 || ! pAMgr) return ns;
+  int numrep = pAMgr->get_numrep();
+  struct replentry* reptable = pAMgr->get_reptable();
+  if (reptable==NULL) return ns;
+  for (int i=0; i < numrep; i++ ) {
+      r = word;
+      lenr = strlen(reptable[i].pattern2);
+      lenp = strlen(reptable[i].pattern);
+      // search every occurence of the pattern in the word
+      while ((r=strstr(r, reptable[i].pattern)) != NULL) {
+          strcpy(candidate, word);
+          if (r-word + lenr + strlen(r+lenp) >= MAXSWUTF8L) break;
+          strcpy(candidate+(r-word),reptable[i].pattern2);
+          strcpy(candidate+(r-word)+lenr, r+lenp);
+          ns = testsug(wlst, candidate, wl-lenp+lenr, ns, cpdsuggest, NULL, NULL);
+          if (ns == -1) return -1;
+          // check REP suggestions with space
+          char * sp = strchr(candidate, ' ');
+          if (sp) {
+            *sp = '\0';
+            if (checkword(candidate, strlen(candidate), 0, NULL, NULL)) {
+              int oldns = ns;
+              *sp = ' ';
+              ns = testsug(wlst, sp + 1, strlen(sp + 1), ns, cpdsuggest, NULL, NULL);
+              if (ns == -1) return -1;
+              if (oldns < ns) {
+                free(wlst[ns - 1]);
+                wlst[ns - 1] = mystrdup(candidate);
+              }
+            }            
+            *sp = ' ';
+          }
+          r++; // search for the next letter
+      }
+   }
+   return ns;
+}
+
+// perhaps we doubled two characters (pattern aba -> ababa, for example vacation -> vacacation)
+int SuggestMgr::doubletwochars(char** wlst, const char * word, int ns, int cpdsuggest)
+{
+  char candidate[MAXSWUTF8L];
+  int state=0;
+  int wl = strlen(word);
+  if (wl < 5 || ! pAMgr) return ns;
+  for (int i=2; i < wl; i++ ) {
+      if (word[i]==word[i-2]) {
+          state++;
+          if (state==3) {
+            strcpy(candidate,word);
+            strcpy(candidate+i-1,word+i+1);
+            ns = testsug(wlst, candidate, wl-2, ns, cpdsuggest, NULL, NULL);
+            if (ns == -1) return -1;
+            state=0;
+          }
+      } else {
+            state=0;
+      }
+  }
+  return ns;
+}
+
+// perhaps we doubled two characters (pattern aba -> ababa, for example vacation -> vacacation)
+int SuggestMgr::doubletwochars_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
+{
+  w_char        candidate_utf[MAXSWL];
+  char          candidate[MAXSWUTF8L];
+  int state=0;
+  if (wl < 5 || ! pAMgr) return ns;
+  for (int i=2; i < wl; i++) {
+      if (w_char_eq(word[i], word[i-2]))  {
+          state++;
+          if (state==3) {
+            memcpy(candidate_utf, word, (i - 1) * sizeof(w_char));
+            memcpy(candidate_utf+i-1, word+i+1, (wl-i-1) * sizeof(w_char));
+            u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl-2);
+            ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
+            if (ns == -1) return -1;
+            state=0;
+          }
+      } else {
+            state=0;
+      }
+  }
+  return ns;
+}
+
+// error is wrong char in place of correct one (case and keyboard related version)
+int SuggestMgr::badcharkey(char ** wlst, const char * word, int ns, int cpdsuggest)
+{
+  char  tmpc;
+  char  candidate[MAXSWUTF8L];
+  int wl = strlen(word);
+  strcpy(candidate, word);
+  // swap out each char one by one and try uppercase and neighbor
+  // keyboard chars in its place to see if that makes a good word
+
+  for (int i=0; i < wl; i++) {
+    tmpc = candidate[i];
+    // check with uppercase letters
+    candidate[i] = csconv[((unsigned char)tmpc)].cupper;
+    if (tmpc != candidate[i]) {
+       ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
+       if (ns == -1) return -1;
+       candidate[i] = tmpc;
+    }
+    // check neighbor characters in keyboard string
+    if (!ckey) continue;
+    char * loc = strchr(ckey, tmpc);
+    while (loc) {
+       if ((loc > ckey) && (*(loc - 1) != '|')) {
+          candidate[i] = *(loc - 1);
+          ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
+          if (ns == -1) return -1;
+       }
+       if ((*(loc + 1) != '|') && (*(loc + 1) != '\0')) {
+          candidate[i] = *(loc + 1);
+          ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
+          if (ns == -1) return -1;
+       }
+       loc = strchr(loc + 1, tmpc);
+    }
+    candidate[i] = tmpc;    
+  }
+  return ns;
+}
+
+// error is wrong char in place of correct one (case and keyboard related version)
+int SuggestMgr::badcharkey_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
+{
+  w_char        tmpc;
+  w_char        candidate_utf[MAXSWL];
+  char          candidate[MAXSWUTF8L];
+  memcpy(candidate_utf, word, wl * sizeof(w_char));
+  // swap out each char one by one and try all the tryme
+  // chars in its place to see if that makes a good word
+  for (int i=0; i < wl; i++) {
+    tmpc = candidate_utf[i];
+    // check with uppercase letters
+    mkallcap_utf(candidate_utf + i, 1, langnum);
+    if (!w_char_eq(tmpc, candidate_utf[i])) {
+       u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
+       ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
+       if (ns == -1) return -1;
+       candidate_utf[i] = tmpc;
+    }
+    // check neighbor characters in keyboard string
+    if (!ckey) continue;
+    w_char * loc = ckey_utf;
+    while ((loc < (ckey_utf + ckeyl)) && !w_char_eq(*loc, tmpc)) loc++;
+    while (loc < (ckey_utf + ckeyl)) {
+       if ((loc > ckey_utf) && !w_char_eq(*(loc - 1), W_VLINE)) {
+          candidate_utf[i] = *(loc - 1);
+          u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
+          ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
+          if (ns == -1) return -1;
+       }
+       if (((loc + 1) < (ckey_utf + ckeyl)) && !w_char_eq(*(loc + 1), W_VLINE)) {
+          candidate_utf[i] = *(loc + 1);
+          u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
+          ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
+          if (ns == -1) return -1;
+       }
+       do { loc++; } while ((loc < (ckey_utf + ckeyl)) && !w_char_eq(*loc, tmpc));
+    }
+    candidate_utf[i] = tmpc;    
+  }
+  return ns;
+}
+
+// error is wrong char in place of correct one
+int SuggestMgr::badchar(char ** wlst, const char * word, int ns, int cpdsuggest)
+{
+  char  tmpc;
+  char  candidate[MAXSWUTF8L];
+  clock_t timelimit = clock();
+  int timer = MINTIMER;
+  int wl = strlen(word);
+  strcpy(candidate, word);
+  // swap out each char one by one and try all the tryme
+  // chars in its place to see if that makes a good word
+  for (int i=0; i < wl; i++) {
+    tmpc = candidate[i];
+    for (int j=0; j < ctryl; j++) {
+       if (ctry[j] == tmpc) continue;
+       candidate[i] = ctry[j];
+       ns = testsug(wlst, candidate, wl, ns, cpdsuggest, &timer, &timelimit);
+       if (ns == -1) return -1;
+       if (!timer) return ns;
+       candidate[i] = tmpc;
+    }
+  }
+  return ns;
+}
+
+// error is wrong char in place of correct one
+int SuggestMgr::badchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
+{
+  w_char        tmpc;
+  w_char        candidate_utf[MAXSWL];
+  char          candidate[MAXSWUTF8L];
+  clock_t timelimit = clock();
+  int timer = MINTIMER;  
+  memcpy(candidate_utf, word, wl * sizeof(w_char));
+  // swap out each char one by one and try all the tryme
+  // chars in its place to see if that makes a good word
+  for (int i=0; i < wl; i++) {
+    tmpc = candidate_utf[i];
+    for (int j=0; j < ctryl; j++) {
+       if (w_char_eq(tmpc, ctry_utf[j])) continue;
+       candidate_utf[i] = ctry_utf[j];
+       u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
+       ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, &timer, &timelimit);
+       if (ns == -1) return -1;
+       if (!timer) return ns;
+       candidate_utf[i] = tmpc;
+    }
+  }
+  return ns;
+}
+
+// error is word has an extra letter it does not need 
+int SuggestMgr::extrachar_utf(char** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
+{
+   char candidate[MAXSWUTF8L];
+   w_char candidate_utf[MAXSWL];
+   const w_char * p;
+   w_char * r;
+   if (wl < 2) return ns;
+   // try omitting one char of word at a time
+   memcpy(candidate_utf, word + 1, (wl - 1) * sizeof(w_char));
+   for (p = word, r = candidate_utf;  p < word + wl;  ) {
+       u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl - 1);       
+       ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
+       if (ns == -1) return -1;
+       *r++ = *p++;
+   }
+   return ns;
+}
+
+// error is word has an extra letter it does not need 
+int SuggestMgr::extrachar(char** wlst, const char * word, int ns, int cpdsuggest)
+{
+   char    candidate[MAXSWUTF8L];
+   const char *  p;
+   char *  r;
+   int wl = strlen(word);
+   if (wl < 2) return ns;
+   // try omitting one char of word at a time
+   strcpy (candidate, word + 1);
+   for (p = word, r = candidate;  *p != 0;  ) {
+      ns = testsug(wlst, candidate, wl-1, ns, cpdsuggest, NULL, NULL);
+      if (ns == -1) return -1;
+      *r++ = *p++;
+   }
+   return ns;
+}
+
+
+// error is missing a letter it needs
+int SuggestMgr::forgotchar(char ** wlst, const char * word, int ns, int cpdsuggest)
+{
+   char candidate[MAXSWUTF8L];
+   const char * p;
+   char *       q;
+   clock_t timelimit = clock();
+   int timer = MINTIMER;
+   int wl = strlen(word);
+   // try inserting a tryme character before every letter
+   strcpy(candidate + 1, word);
+   for (p = word, q = candidate;  *p != 0;  )  {
+      for (int i = 0;  i < ctryl;  i++) {
+         *q = ctry[i];
+         ns = testsug(wlst, candidate, wl+1, ns, cpdsuggest, &timer, &timelimit);
+         if (ns == -1) return -1;
+         if (!timer) return ns;
+      }
+      *q++ = *p++;
+   }
+   // now try adding one to end */
+   for (int i = 0;  i < ctryl;  i++) {
+      *q = ctry[i];
+      ns = testsug(wlst, candidate, wl+1, ns, cpdsuggest, NULL, NULL);
+      if (ns == -1) return -1;
+   }
+   return ns;
+}
+
+// error is missing a letter it needs
+int SuggestMgr::forgotchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
+{
+   w_char  candidate_utf[MAXSWL];
+   char    candidate[MAXSWUTF8L];
+   const w_char * p;
+   w_char * q;
+   int cwrd;
+   clock_t timelimit = clock();
+   int timer = MINTIMER;
+   // try inserting a tryme character before every letter
+   memcpy (candidate_utf + 1, word, wl * sizeof(w_char));
+   for (p = word, q = candidate_utf;  p < (word + wl); )  {
+      for (int i = 0;  i < ctryl;  i++) {
+         *q = ctry_utf[i];
+         cwrd = 1;
+         u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl + 1);
+         ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, &timer, &timelimit);
+         if (ns == -1) return -1;
+         if (!timer) return ns;
+       }
+      *q++ = *p++;
+   }
+   // now try adding one to end */
+   for (int i = 0;  i < ctryl;  i++) {
+      *q = ctry_utf[i];
+      cwrd = 1;
+      u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl + 1);
+      ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
+      if (ns == -1) return -1;
+   }
+   return ns;
+}
+
+
+/* error is should have been two words */
+int SuggestMgr::twowords(char ** wlst, const char * word, int ns, int cpdsuggest)
+{
+    char candidate[MAXSWUTF8L];
+    char * p;
+    int c1, c2;
+    int forbidden = 0;
+    int cwrd;
+
+    int wl=strlen(word);
+    if (wl < 3) return ns;
+    
+    if (langnum == LANG_hu) forbidden = check_forbidden(word, wl);
+
+    strcpy(candidate + 1, word);
+    // split the string into two pieces after every char
+    // if both pieces are good words make them a suggestion
+    for (p = candidate + 1;  p[1] != '\0';  p++) {
+       p[-1] = *p;
+       // go to end of the UTF-8 character
+       while (utf8 && ((p[1] & 0xc0) == 0x80)) {
+         *p = p[1];
+         p++;
+       }
+       if (utf8 && p[1] == '\0') break; // last UTF-8 character
+       *p = '\0';
+       c1 = checkword(candidate,strlen(candidate), cpdsuggest, NULL, NULL);
+       if (c1) {
+         c2 = checkword((p+1),strlen(p+1), cpdsuggest, NULL, NULL);
+         if (c2) {
+            *p = ' ';
+
+            // spec. Hungarian code (need a better compound word support)
+            if ((langnum == LANG_hu) && !forbidden &&
+                // if 3 repeating letter, use - instead of space
+                (((p[-1] == p[1]) && (((p>candidate+1) && (p[-1] == p[-2])) || (p[-1] == p[2]))) ||
+                // or multiple compounding, with more, than 6 syllables
+                ((c1 == 3) && (c2 >= 2)))) *p = '-';
+
+            cwrd = 1;
+            for (int k=0; k < ns; k++)
+                if (strcmp(candidate,wlst[k]) == 0) cwrd = 0;
+            if (ns < maxSug) {
+                if (cwrd) {
+                    wlst[ns] = mystrdup(candidate);
+                    if (wlst[ns] == NULL) return -1;
+                    ns++;
+                }
+            } else return ns;
+         }
+       }
+    }
+    return ns;
+}
+
+
+// error is adjacent letter were swapped
+int SuggestMgr::swapchar(char ** wlst, const char * word, int ns, int cpdsuggest)
+{
+   char candidate[MAXSWUTF8L];
+   char * p;
+   char tmpc;
+   int wl=strlen(word);
+   // try swapping adjacent chars one by one
+   strcpy(candidate, word);
+   for (p = candidate;  p[1] != 0;  p++) {
+      tmpc = *p;
+      *p = p[1];
+      p[1] = tmpc;
+      ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
+      if (ns == -1) return -1;
+      p[1] = *p;
+      *p = tmpc;
+   }
+   // try double swaps for short words
+   // ahev -> have, owudl -> would
+   if (wl == 4 || wl == 5) {
+     candidate[0] = word[1];
+     candidate[1] = word[0];
+     candidate[2] = word[2];
+     candidate[wl - 2] = word[wl - 1];
+     candidate[wl - 1] = word[wl - 2];
+     ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
+     if (ns == -1) return -1;
+     if (wl == 5) {
+        candidate[0] = word[0];
+        candidate[1] = word[2];
+        candidate[2] = word[1];
+        ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
+        if (ns == -1) return -1;
+     }
+   }
+   return ns;
+}
+
+// error is adjacent letter were swapped
+int SuggestMgr::swapchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
+{
+   w_char candidate_utf[MAXSWL];
+   char   candidate[MAXSWUTF8L];
+   w_char * p;
+   w_char tmpc;
+   int len = 0;
+   // try swapping adjacent chars one by one
+   memcpy (candidate_utf, word, wl * sizeof(w_char));
+   for (p = candidate_utf;  p < (candidate_utf + wl - 1);  p++) {
+      tmpc = *p;
+      *p = p[1];
+      p[1] = tmpc;
+      u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
+      if (len == 0) len = strlen(candidate);
+      ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL);
+      if (ns == -1) return -1;
+      p[1] = *p;
+      *p = tmpc;
+   }
+   // try double swaps for short words
+   // ahev -> have, owudl -> would, suodn -> sound
+   if (wl == 4 || wl == 5) {
+     candidate_utf[0] = word[1];
+     candidate_utf[1] = word[0];
+     candidate_utf[2] = word[2];
+     candidate_utf[wl - 2] = word[wl - 1];
+     candidate_utf[wl - 1] = word[wl - 2];
+     u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
+     ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL);
+     if (ns == -1) return -1;
+     if (wl == 5) {
+        candidate_utf[0] = word[0];
+        candidate_utf[1] = word[2];
+        candidate_utf[2] = word[1];
+        u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
+	ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL);
+        if (ns == -1) return -1;
+     }
+   }
+   return ns;
+}
+
+// error is not adjacent letter were swapped
+int SuggestMgr::longswapchar(char ** wlst, const char * word, int ns, int cpdsuggest)
+{
+   char candidate[MAXSWUTF8L];
+   char * p;
+   char * q;
+   char tmpc;
+   int wl=strlen(word);
+   // try swapping not adjacent chars one by one
+   strcpy(candidate, word);
+   for (p = candidate;  *p != 0;  p++) {
+    for (q = candidate;  *q != 0;  q++) {
+     if (abs(p-q) > 1) {
+      tmpc = *p;
+      *p = *q;
+      *q = tmpc;
+      ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
+      if (ns == -1) return -1;
+      *q = *p;
+      *p = tmpc;
+     }
+    }
+   }
+   return ns;
+}
+
+
+// error is adjacent letter were swapped
+int SuggestMgr::longswapchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
+{
+   w_char candidate_utf[MAXSWL];
+   char   candidate[MAXSWUTF8L];
+   w_char * p;
+   w_char * q;
+   w_char tmpc;
+   // try swapping not adjacent chars
+   memcpy (candidate_utf, word, wl * sizeof(w_char));
+   for (p = candidate_utf;  p < (candidate_utf + wl);  p++) {
+     for (q = candidate_utf;  q < (candidate_utf + wl);  q++) {
+       if (abs(p-q) > 1) {
+         tmpc = *p;
+         *p = *q;
+         *q = tmpc;
+         u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
+         ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
+         if (ns == -1) return -1;
+         *q = *p;
+         *p = tmpc;
+       }
+     }
+   }
+   return ns;
+}
+
+// error is a letter was moved
+int SuggestMgr::movechar(char ** wlst, const char * word, int ns, int cpdsuggest)
+{
+   char candidate[MAXSWUTF8L];
+   char * p;
+   char * q;
+   char tmpc;
+
+   int wl=strlen(word);
+   // try moving a char
+   strcpy(candidate, word);
+   for (p = candidate;  *p != 0;  p++) {
+     for (q = p + 1;  (*q != 0) && ((q - p) < 10);  q++) {
+      tmpc = *(q-1);
+      *(q-1) = *q;
+      *q = tmpc;
+      if ((q-p) < 2) continue; // omit swap char
+      ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
+      if (ns == -1) return -1;
+    }
+    strcpy(candidate, word);
+   }
+   for (p = candidate + wl - 1;  p > candidate;  p--) {
+     for (q = p - 1;  (q >= candidate) && ((p - q) < 10);  q--) {
+      tmpc = *(q+1);
+      *(q+1) = *q;
+      *q = tmpc;
+      if ((p-q) < 2) continue; // omit swap char
+      ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
+      if (ns == -1) return -1;
+    }
+    strcpy(candidate, word);
+   }   
+   return ns;
+}
+
+// error is a letter was moved
+int SuggestMgr::movechar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
+{
+   w_char candidate_utf[MAXSWL];
+   char   candidate[MAXSWUTF8L];
+   w_char * p;
+   w_char * q;
+   w_char tmpc;
+   // try moving a char
+   memcpy (candidate_utf, word, wl * sizeof(w_char));
+   for (p = candidate_utf;  p < (candidate_utf + wl);  p++) {
+     for (q = p + 1;  (q < (candidate_utf + wl)) && ((q - p) < 10);  q++) {
+         tmpc = *(q-1);
+         *(q-1) = *q;
+         *q = tmpc;
+         if ((q-p) < 2) continue; // omit swap char
+         u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
+         ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
+         if (ns == -1) return -1;
+     }
+     memcpy (candidate_utf, word, wl * sizeof(w_char));
+   }
+   for (p = candidate_utf + wl - 1;  p > candidate_utf;  p--) {
+     for (q = p - 1;  (q >= candidate_utf) && ((p - q) < 10);  q--) {
+         tmpc = *(q+1);
+         *(q+1) = *q;
+         *q = tmpc;
+         if ((p-q) < 2) continue; // omit swap char
+         u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
+         ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
+         if (ns == -1) return -1;
+     }
+     memcpy (candidate_utf, word, wl * sizeof(w_char));
+   }
+   return ns;   
+}
+
+// generate a set of suggestions for very poorly spelled words
+int SuggestMgr::ngsuggest(char** wlst, char * w, int ns, HashMgr* pHMgr)
+{
+
+  int i, j;
+  int lval;
+  int sc, scphon;
+  int lp, lpphon;
+  int nonbmp = 0;
+
+  if (!pHMgr) return ns;
+
+  // exhaustively search through all root words
+  // keeping track of the MAX_ROOTS most similar root words
+  struct hentry * roots[MAX_ROOTS];
+  char * rootsphon[MAX_ROOTS];
+  int scores[MAX_ROOTS];
+  int scoresphon[MAX_ROOTS];
+  for (i = 0; i < MAX_ROOTS; i++) {
+    roots[i] = NULL;
+    scores[i] = -100 * i;
+    rootsphon[i] = NULL;
+    scoresphon[i] = -100 * i;
+  }
+  lp = MAX_ROOTS - 1;
+  lpphon = MAX_ROOTS - 1;
+  scphon = scoresphon[MAX_ROOTS-1];
+  
+  char w2[MAXWORDUTF8LEN];
+  char * word = w;
+
+  // word reversing wrapper for complex prefixes
+  if (complexprefixes) {
+    strcpy(w2, w);
+    if (utf8) reverseword_utf(w2); else reverseword(w2);
+    word = w2;
+  }
+
+  char mw[MAXSWUTF8L];
+  w_char u8[MAXSWL];
+  int nc = strlen(word);
+  int n = (utf8) ? u8_u16(u8, MAXSWL, word) : nc;
+  
+  // set character based ngram suggestion for words with non-BMP Unicode characters
+  if (n == -1) {
+    utf8 = 0;
+    n = nc;
+    nonbmp = 1;
+  }
+
+  struct hentry* hp = NULL;
+  int col = -1;
+  phonetable * ph = (pAMgr) ? pAMgr->get_phonetable() : NULL;
+  char target[MAXSWUTF8L];
+  char candidate[MAXSWUTF8L];
+  if (ph) {
+    strcpy(candidate, word);
+    mkallcap(candidate, csconv);
+    phonet(candidate, target, n, *ph);
+//    fprintf(stderr, "Tip: %s->%s\n", candidate, target);
+  }
+  
+  while ((hp = pHMgr->walk_hashtable(col, hp))) {
+    if ((hp->astr) && (pAMgr) && 
+       (TESTAFF(hp->astr, pAMgr->get_forbiddenword(), hp->alen) ||
+          TESTAFF(hp->astr, ONLYUPCASEFLAG, hp->alen) ||
+          TESTAFF(hp->astr, pAMgr->get_nosuggest(), hp->alen) ||
+          TESTAFF(hp->astr, pAMgr->get_onlyincompound(), hp->alen))) continue;
+
+    sc = ngram(3, word, &(hp->word), NGRAM_LONGER_WORSE + NGRAM_LOWERING) +
+	leftcommonsubstring(word, &(hp->word));
+
+    // check special pronounciation
+    if (hp->var) {
+	int sc2 = ngram(3, word, &(hp->word) + hp->blen + 1, NGRAM_LONGER_WORSE + NGRAM_LOWERING) +
+	leftcommonsubstring(word, &(hp->word) + hp->blen + 1);
+	if (sc2 > sc) sc = sc2;
+    }
+    
+    if (ph && (sc > 2) && (abs(n - (int) hp->clen) <= 3)) {
+	char target2[MAXSWUTF8L];
+        strcpy(candidate, &(hp->word));
+        mkallcap(candidate, csconv);
+        phonet(candidate, target2, -1, *ph);
+        scphon = 2 * ngram(3, target, target2, NGRAM_LONGER_WORSE);
+    }
+
+    if (sc > scores[lp]) {
+      scores[lp] = sc;  
+      roots[lp] = hp;
+      lval = sc;
+      for (j=0; j < MAX_ROOTS; j++)
+        if (scores[j] < lval) {
+          lp = j;
+          lval = scores[j];
+        }
+    }
+
+    if (scphon > scoresphon[lpphon]) {
+      scoresphon[lpphon] = scphon;
+      rootsphon[lpphon] = &(hp->word);
+      lval = scphon;
+      for (j=0; j < MAX_ROOTS; j++)
+        if (scoresphon[j] < lval) {
+          lpphon = j;
+          lval = scoresphon[j];
+        }
+    }
+  }
+
+  // find minimum threshhold for a passable suggestion
+  // mangle original word three differnt ways
+  // and score them to generate a minimum acceptable score
+  int thresh = 0;
+  for (int sp = 1; sp < 4; sp++) {
+     if (utf8) {
+       for (int k=sp; k < n; k+=4) *((unsigned short *) u8 + k) = '*';
+       u16_u8(mw, MAXSWUTF8L, u8, n);
+       thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + NGRAM_LOWERING);
+     } else {
+       strcpy(mw, word);
+       for (int k=sp; k < n; k+=4) *(mw + k) = '*';
+       thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + NGRAM_LOWERING);
+     }
+  }
+  thresh = thresh / 3;
+  thresh--;
+
+  // now expand affixes on each of these root words and
+  // and use length adjusted ngram scores to select
+  // possible suggestions
+  char * guess[MAX_GUESS];
+  char * guessorig[MAX_GUESS];
+  int gscore[MAX_GUESS];
+  for(i=0;i<MAX_GUESS;i++) {
+     guess[i] = NULL;
+     guessorig[i] = NULL;
+     gscore[i] = -100 * i;
+  }
+
+  lp = MAX_GUESS - 1;
+
+  struct guessword * glst;
+  glst = (struct guessword *) calloc(MAX_WORDS,sizeof(struct guessword));
+  if (! glst) {
+    if (nonbmp) utf8 = 1;
+    return ns;
+  }
+
+  for (i = 0; i < MAX_ROOTS; i++) {
+      if (roots[i]) {
+        struct hentry * rp = roots[i];
+        int nw = pAMgr->expand_rootword(glst, MAX_WORDS, &(rp->word), rp->blen,
+            	    rp->astr, rp->alen, word, nc, 
+                    ((rp->var) ? &(rp->word) + rp->blen + 1 : NULL));
+
+        for (int k = 0; k < nw ; k++) {
+           sc = ngram(n, word, glst[k].word, NGRAM_ANY_MISMATCH + NGRAM_LOWERING) +
+               leftcommonsubstring(word, glst[k].word);
+
+           if ((sc > thresh)) {
+              if (sc > gscore[lp]) {
+                 if (guess[lp]) {
+                    free (guess[lp]);
+                    if (guessorig[lp]) {
+                	free(guessorig[lp]);
+                	guessorig[lp] = NULL;
+            	    }
+                 }
+                 gscore[lp] = sc;
+                 guess[lp] = glst[k].word;
+                 guessorig[lp] = glst[k].orig;
+                 lval = sc;
+                 for (j=0; j < MAX_GUESS; j++)
+                    if (gscore[j] < lval) {
+                       lp = j;
+                       lval = gscore[j];
+                    }
+              } else { 
+                free(glst[k].word);
+                if (glst[k].orig) free(glst[k].orig);
+              }
+           } else {
+        	free(glst[k].word);
+                if (glst[k].orig) free(glst[k].orig);
+           }
+        }
+      }
+  }
+  free(glst);
+
+  // now we are done generating guesses
+  // sort in order of decreasing score
+  
+  
+  bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS);
+  if (ph) bubblesort(&rootsphon[0], NULL, &scoresphon[0], MAX_ROOTS);
+
+  // weight suggestions with a similarity index, based on
+  // the longest common subsequent algorithm and resort
+
+  int is_swap;
+  for (i=0; i < MAX_GUESS; i++) {
+      if (guess[i]) {
+        // lowering guess[i]
+        char gl[MAXSWUTF8L];
+        int len;
+        if (utf8) {
+          w_char _w[MAXSWL];
+          len = u8_u16(_w, MAXSWL, guess[i]);
+          mkallsmall_utf(_w, len, langnum);
+          u16_u8(gl, MAXSWUTF8L, _w, len);
+        } else {
+          strcpy(gl, guess[i]);
+          mkallsmall(gl, csconv);
+          len = strlen(guess[i]);
+        }
+
+        int _lcs = lcslen(word, gl);
+
+        // same characters with different casing
+        if ((n == len) && (n == _lcs)) {
+            gscore[i] += 2000;
+            break;
+        }
+        
+        // heuristic weigthing of ngram scores
+        gscore[i] +=
+          // length of longest common subsequent minus length difference
+          2 * _lcs - abs((int) (n - len)) +
+          // weight length of the left common substring
+          leftcommonsubstring(word, gl) +
+          // weight equal character positions
+          ((_lcs == commoncharacterpositions(word, gl, &is_swap)) ? 1: 0) +
+          // swap character (not neighboring)
+          ((is_swap) ? 1000 : 0);
+      }
+  }
+
+  bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS);
+
+// phonetic version
+  if (ph) for (i=0; i < MAX_ROOTS; i++) {
+      if (rootsphon[i]) {
+        // lowering rootphon[i]
+        char gl[MAXSWUTF8L];
+        int len;
+        if (utf8) {
+          w_char _w[MAXSWL];
+          len = u8_u16(_w, MAXSWL, rootsphon[i]);
+          mkallsmall_utf(_w, len, langnum);
+          u16_u8(gl, MAXSWUTF8L, _w, len);
+        } else {
+          strcpy(gl, rootsphon[i]);
+          mkallsmall(gl, csconv);
+          len = strlen(rootsphon[i]);
+        }
+
+        // heuristic weigthing of ngram scores
+        scoresphon[i] += 2 * lcslen(word, gl) - abs((int) (n - len)) +
+          // weight length of the left common substring
+          leftcommonsubstring(word, gl);
+      }
+  }
+
+  if (ph) bubblesort(&rootsphon[0], NULL, &scoresphon[0], MAX_ROOTS);
+
+  // copy over
+  int oldns = ns;
+
+  int same = 0;
+  for (i=0; i < MAX_GUESS; i++) {
+    if (guess[i]) {
+      if ((ns < oldns + maxngramsugs) && (ns < maxSug) && (!same || (gscore[i] > 1000))) {
+        int unique = 1;
+        // leave only excellent suggestions, if exists
+        if (gscore[i] > 1000) same = 1;
+        for (j = 0; j < ns; j++) {
+          // don't suggest previous suggestions or a previous suggestion with prefixes or affixes
+          if ((!guessorig[i] && strstr(guess[i], wlst[j])) ||
+	     (guessorig[i] && strstr(guessorig[i], wlst[j])) ||
+            // check forbidden words
+            !checkword(guess[i], strlen(guess[i]), 0, NULL, NULL)) unique = 0;
+        }
+        if (unique) {
+    	    wlst[ns++] = guess[i];
+    	    if (guessorig[i]) {
+    		free(guess[i]);
+    		wlst[ns-1] = guessorig[i];
+    	    }
+    	} else {
+    	    free(guess[i]);
+    	    if (guessorig[i]) free(guessorig[i]);
+    	}
+      } else {
+        free(guess[i]);
+    	if (guessorig[i]) free(guessorig[i]);
+      }
+    }
+  }
+
+  oldns = ns;
+  if (ph) for (i=0; i < MAX_ROOTS; i++) {
+    if (rootsphon[i]) {
+      if ((ns < oldns + MAXPHONSUGS) && (ns < maxSug)) {
+        int unique = 1;
+        for (j = 0; j < ns; j++) {
+          // don't suggest previous suggestions or a previous suggestion with prefixes or affixes
+          if (strstr(rootsphon[i], wlst[j]) || 
+            // check forbidden words
+            !checkword(rootsphon[i], strlen(rootsphon[i]), 0, NULL, NULL)) unique = 0;
+        }
+        if (unique) wlst[ns++] = mystrdup(rootsphon[i]);
+      }
+    }
+  }
+
+  if (nonbmp) utf8 = 1;
+  return ns;
+}
+
+
+// see if a candidate suggestion is spelled correctly
+// needs to check both root words and words with affixes
+
+// obsolote MySpell-HU modifications:
+// return value 2 and 3 marks compounding with hyphen (-)
+// `3' marks roots without suffix
+int SuggestMgr::checkword(const char * word, int len, int cpdsuggest, int * timer, clock_t * timelimit)
+{
+  struct hentry * rv=NULL;
+  int nosuffix = 0;
+
+  // check time limit
+  if (timer) {
+    (*timer)--;
+    if (!(*timer) && timelimit) {
+      if ((clock() - *timelimit) > TIMELIMIT) return 0;
+      *timer = MAXPLUSTIMER;
+    }
+  }
+  
+  if (pAMgr) { 
+    if (cpdsuggest==1) {
+      if (pAMgr->get_compound()) {
+        rv = pAMgr->compound_check(word,len,0,0,0,0,NULL,0,NULL,NULL,1);
+        if (rv) return 3; // XXX obsolote categorisation
+        }
+        return 0;
+    }
+
+    rv = pAMgr->lookup(word);
+
+    if (rv) {
+        if ((rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen)
+               || TESTAFF(rv->astr,pAMgr->get_nosuggest(),rv->alen))) return 0;
+        while (rv) {
+    	    if (rv->astr && (TESTAFF(rv->astr,pAMgr->get_pseudoroot(),rv->alen) ||
+                  TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
+            TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) {
+        	rv = rv->next_homonym;
+    	    } else break;
+    	}
+    } else rv = pAMgr->prefix_check(word, len, 0); // only prefix, and prefix + suffix XXX
+    
+    if (rv) {
+        nosuffix=1;
+    } else {
+        rv = pAMgr->suffix_check(word, len, 0, NULL, NULL, 0, NULL); // only suffix
+    }
+
+    if (!rv && pAMgr->have_contclass()) {
+        rv = pAMgr->suffix_check_twosfx(word, len, 0, NULL, FLAG_NULL);
+        if (!rv) rv = pAMgr->prefix_check_twosfx(word, len, 1, FLAG_NULL);
+    }
+
+    // check forbidden words
+    if ((rv) && (rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen) ||
+      TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
+      TESTAFF(rv->astr,pAMgr->get_nosuggest(),rv->alen) ||
+      TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) return 0;
+
+    if (rv) { // XXX obsolote    
+      if ((pAMgr->get_compoundflag()) && 
+          TESTAFF(rv->astr, pAMgr->get_compoundflag(), rv->alen)) return 2 + nosuffix; 
+      return 1;
+    }
+  }
+  return 0;
+}
+
+int SuggestMgr::check_forbidden(const char * word, int len)
+{
+  struct hentry * rv = NULL;
+
+  if (pAMgr) { 
+    rv = pAMgr->lookup(word);
+    if (rv && rv->astr && (TESTAFF(rv->astr,pAMgr->get_pseudoroot(),rv->alen) ||
+        TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) rv = NULL;
+    if (!(pAMgr->prefix_check(word,len,1)))
+        rv = pAMgr->suffix_check(word,len, 0, NULL, NULL, 0, NULL); // prefix+suffix, suffix
+    // check forbidden words
+    if ((rv) && (rv->astr) && TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen)) return 1;
+   }
+    return 0;
+}
+
+#ifdef HUNSPELL_EXPERIMENTAL
+// suggest stems, XXX experimental code
+int SuggestMgr::suggest_stems(char*** slst, const char * w, int nsug)
+{
+    char buf[MAXSWUTF8L];
+    char ** wlst;    
+    int prevnsug = nsug;
+
+  char w2[MAXWORDUTF8LEN];
+  const char * word = w;
+
+  // word reversing wrapper for complex prefixes
+  if (complexprefixes) {
+    strcpy(w2, w);
+    if (utf8) reverseword_utf(w2); else reverseword(w2);
+    word = w2;
+  }
+
+    if (*slst) {
+        wlst = *slst;
+    } else {
+        wlst = (char **) calloc(maxSug, sizeof(char *));
+        if (wlst == NULL) return -1;
+    }
+    // perhaps there are a fix stem in the dictionary
+    if ((nsug < maxSug) && (nsug > -1)) {
+    
+    nsug = fixstems(wlst, word, nsug);
+    if (nsug == prevnsug) {
+        char * s = mystrdup(word);
+        char * p = s + strlen(s);
+        while ((*p != '-') && (p != s)) p--;
+        if (*p == '-') {
+            *p = '\0';
+            nsug = fixstems(wlst, s, nsug);
+            if ((nsug == prevnsug) && (nsug < maxSug) && (nsug >= 0)) {
+                char * t;
+                buf[0] = '\0';
+                for (t = s; (t[0] != '\0') && ((t[0] >= '0') || (t[0] <= '9')); t++); // is a number?
+                if (*t != '\0') strcpy(buf, "# ");
+                strcat(buf, s);
+                wlst[nsug] = mystrdup(buf);
+                if (wlst[nsug] == NULL) return -1;
+                nsug++;
+            }
+            p++;
+            nsug = fixstems(wlst, p, nsug);
+        }
+
+        free(s);
+    }
+    }
+    
+    if (nsug < 0) {
+       for (int i=0;i<maxSug; i++)
+         if (wlst[i] != NULL) free(wlst[i]);
+         free(wlst);
+       return -1;
+    }
+
+    *slst = wlst;
+    return nsug;
+}
+
+
+// there are fix stems in dictionary
+int SuggestMgr::fixstems(char ** wlst, const char * word, int ns)
+{
+    char buf[MAXSWUTF8L];
+    char prefix[MAXSWUTF8L] = "";
+
+    int dicstem = 1; // 0 = lookup, 1= affix, 2 = compound
+    int cpdindex = 0;
+    struct hentry * rv = NULL;
+
+    int wl = strlen(word);
+    int cmpdstemnum;
+    int cmpdstem[MAXCOMPOUND];
+
+    if (pAMgr) { 
+        rv = pAMgr->lookup(word);
+        if (rv) {
+            dicstem = 0;
+        } else {
+            // try stripping off affixes 
+            rv = pAMgr->affix_check(word, wl);
+
+            // else try check compound word
+            if (!rv && pAMgr->get_compound()) {
+                rv = pAMgr->compound_check(word, wl,
+                     0, 0, 100, 0, NULL, 0, &cmpdstemnum, cmpdstem,1);
+
+                if (rv) {
+                    dicstem = 2;
+                    for (int j = 0; j < cmpdstemnum; j++) {
+                        cpdindex += cmpdstem[j];
+                    }
+                    if(! (pAMgr->lookup(word + cpdindex)))
+                        pAMgr->affix_check(word + cpdindex, wl - cpdindex); // for prefix
+                }
+            }
+
+
+            if (pAMgr->get_prefix()) {
+                strcpy(prefix, pAMgr->get_prefix());
+            }
+
+            // XXX obsolete, will be a general solution for stemming
+            if ((prefix) && (strncmp(prefix, "leg", 3)==0)) prefix[0] = '\0'; // (HU)       
+        }
+
+    }
+
+
+
+    if ((rv) && (ns < maxSug)) {
+    
+        // check fixstem flag and not_valid_stem flag
+        // first word
+        if ((ns < maxSug) && (dicstem < 2)) { 
+            strcpy(buf, prefix);
+            if ((dicstem > 0) && pAMgr->get_derived()) {
+                // XXX obsolote
+                   if (strlen(prefix) == 1) {
+                        strcat(buf, (pAMgr->get_derived()) + 1);
+                   } else {
+                        strcat(buf, pAMgr->get_derived());
+                   }
+                } else {
+                        // special stem in affix description
+                        const char * wordchars = pAMgr->get_wordchars();
+                        if (rv->description && 
+                           (strchr(wordchars, *(rv->description)))) {
+                           char * desc = (rv->description) + 1;
+                           while (strchr(wordchars, *desc)) desc++;
+                           strncat(buf, rv->description, desc - (rv->description));
+                        } else {
+                            strcat(buf, rv->word);
+                        }
+                }
+            wlst[ns] = mystrdup(buf);
+            if (wlst[ns] == NULL) return -1;
+            ns++;
+        }
+
+        if (dicstem == 2) {
+
+            // compound stem
+
+//          if (rv->astr && (strchr(rv->astr, '0') == NULL)) {
+            if (rv->astr) {
+                strcpy(buf, word);
+                buf[cpdindex] = '\0';
+                if (prefix) strcat(buf, prefix);
+                if (pAMgr->get_derived()) {
+                        strcat(buf, pAMgr->get_derived());
+                } else {
+                        // special stem in affix description
+                        const char * wordchars = pAMgr->get_wordchars();
+                        if (rv->description && 
+                           (strchr(wordchars, *(rv->description)))) {
+                           char * desc = (rv->description) + 1;
+                           while (strchr(wordchars, *desc)) desc++;
+                           strncat(buf, rv->description, desc - (rv->description));
+                        } else {
+                            strcat(buf, rv->word);
+                        }
+                }
+                if (ns < maxSug) {
+                    wlst[ns] = mystrdup(buf);
+                    if (wlst[ns] == NULL) return -1;
+                    ns++;
+                }
+            }
+        }
+    }
+    return ns;
+}
+
+// suggest possible stems
+int SuggestMgr::suggest_pos_stems(char*** slst, const char * w, int nsug)
+{
+    char ** wlst;    
+
+    struct hentry * rv = NULL;
+
+  char w2[MAXSWUTF8L];
+  const char * word = w;
+
+  // word reversing wrapper for complex prefixes
+  if (complexprefixes) {
+    strcpy(w2, w);
+    if (utf8) reverseword_utf(w2); else reverseword(w2);
+    word = w2;
+  }
+
+    int wl = strlen(word);
+
+
+    if (*slst) {
+        wlst = *slst;
+    } else {
+        wlst = (char **) calloc(maxSug, sizeof(char *));
+        if (wlst == NULL) return -1;
+    }
+
+    rv = pAMgr->suffix_check(word, wl, 0, NULL, wlst, maxSug, &nsug);
+
+    // delete dash from end of word
+    if (nsug > 0) {
+        for (int j=0; j < nsug; j++) {
+            if (wlst[j][strlen(wlst[j]) - 1] == '-') wlst[j][strlen(wlst[j]) - 1] = '\0';
+        }
+    }
+
+    *slst = wlst;
+    return nsug;
+}
+
+
+char * SuggestMgr::suggest_morph(const char * w)
+{
+    char result[MAXLNLEN];
+    char * r = (char *) result;
+    char * st;
+
+    struct hentry * rv = NULL;
+
+    *result = '\0';
+
+    if (! pAMgr) return NULL;
+
+  char w2[MAXSWUTF8L];
+  const char * word = w;
+
+  // word reversing wrapper for complex prefixes
+  if (complexprefixes) {
+    strcpy(w2, w);
+    if (utf8) reverseword_utf(w2); else reverseword(w2);
+    word = w2;
+  }
+
+    rv = pAMgr->lookup(word);
+    
+    while (rv) {
+        if ((!rv->astr) || !(TESTAFF(rv->astr, pAMgr->get_forbiddenword(), rv->alen) ||
+            TESTAFF(rv->astr, pAMgr->get_pseudoroot(), rv->alen) ||
+            TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) {
+            if (rv->description && ((!rv->astr) || 
+                !TESTAFF(rv->astr, pAMgr->get_lemma_present(), rv->alen)))
+                    strcat(result, word);
+            if (rv->description) strcat(result, rv->description);
+            strcat(result, "\n");
+        }
+        rv = rv->next_homonym;
+    }
+    
+    st = pAMgr->affix_check_morph(word,strlen(word));
+    if (st) {
+        strcat(result, st);
+        free(st);
+    }
+
+    if (pAMgr->get_compound() && (*result == '\0'))
+        pAMgr->compound_check_morph(word, strlen(word),
+                     0, 0, 100, 0,NULL, 0, &r, NULL);
+    
+    return (*result) ? mystrdup(line_uniq(delete_zeros(result))) : NULL;
+}
+
+char * SuggestMgr::suggest_morph_for_spelling_error(const char * word)
+{
+    char * p = NULL;
+    char ** wlst = (char **) calloc(maxSug, sizeof(char *));
+    if (!**wlst) return NULL;
+    // we will use only the first suggestion
+    for (int i = 0; i < maxSug - 1; i++) wlst[i] = "";
+    int ns = suggest(&wlst, word, maxSug - 1);
+    if (ns == maxSug) {
+        p = suggest_morph(wlst[maxSug - 1]);
+        free(wlst[maxSug - 1]);
+    }
+    if (wlst) free(wlst);
+    return p;
+}
+#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+
+
+// generate an n-gram score comparing s1 and s2
+int SuggestMgr::ngram(int n, char * s1, const char * s2, int opt)
+{
+  int nscore = 0;
+  int ns;
+  int l1;
+  int l2;
+
+  if (utf8) {
+    w_char su1[MAXSWL];
+    w_char su2[MAXSWL];
+    l1 = u8_u16(su1, MAXSWL, s1);
+    l2 = u8_u16(su2, MAXSWL, s2);
+    if ((l2 <= 0) || (l1 == -1)) return 0;
+    // lowering dictionary word
+    if (opt & NGRAM_LOWERING) mkallsmall_utf(su2, l2, langnum);
+    for (int j = 1; j <= n; j++) {
+      ns = 0;
+      for (int i = 0; i <= (l1-j); i++) {
+        for (int l = 0; l <= (l2-j); l++) {
+            int k;
+            for (k = 0; (k < j); k++) {
+              w_char * c1 = su1 + i + k;
+              w_char * c2 = su2 + l + k;
+              if ((c1->l != c2->l) || (c1->h != c2->h)) break;
+            }
+            if (k == j) {
+                ns++;
+                break;
+            }
+        }
+      }
+      nscore = nscore + ns;
+      if (ns < 2) break;
+    }
+  } else {  
+    char t[MAXSWUTF8L];
+    l1 = strlen(s1);
+    l2 = strlen(s2);
+    if (l2 == 0) return 0;
+    strcpy(t, s2);
+    if (opt & NGRAM_LOWERING) mkallsmall(t, csconv);
+    for (int j = 1; j <= n; j++) {
+      ns = 0;
+      for (int i = 0; i <= (l1-j); i++) {
+        char c = *(s1 + i + j);
+        *(s1 + i + j) = '\0';
+        if (strstr(t,(s1+i))) ns++;
+        *(s1 + i + j ) = c;
+      }
+      nscore = nscore + ns;
+      if (ns < 2) break;
+    }
+  }
+  
+  ns = 0;
+  if (opt & NGRAM_LONGER_WORSE) ns = (l2-l1)-2;
+  if (opt & NGRAM_ANY_MISMATCH) ns = abs(l2-l1)-2;
+  ns = (nscore - ((ns > 0) ? ns : 0));
+  return ns;
+}
+
+// length of the left common substring of s1 and (decapitalised) s2
+int SuggestMgr::leftcommonsubstring(char * s1, const char * s2) {
+  if (utf8) {
+    w_char su1[MAXSWL];
+    w_char su2[MAXSWL];
+    // decapitalize dictionary word
+    if (complexprefixes) {
+      int l1 = u8_u16(su1, MAXSWL, s1);
+      int l2 = u8_u16(su2, MAXSWL, s2);
+      if (*((short *)su1+l1-1) == *((short *)su2+l2-1)) return 1;
+    } else {
+      int i;
+      u8_u16(su1, 1, s1);
+      u8_u16(su2, 1, s2);
+      unsigned short idx = (su2->h << 8) + su2->l;
+      if (*((short *)su1) != *((short *)su2) &&
+         (*((unsigned short *)su1) != unicodetolower(idx, langnum))) return 0;
+      int l1 = u8_u16(su1, MAXSWL, s1);
+      int l2 = u8_u16(su2, MAXSWL, s2);
+      for(i = 1; (i < l1) && (i < l2) &&
+         (*((short *)(su1 + i)) == *((short *)(su2 + i))); i++);
+      return i;
+    }
+  } else {
+    if (complexprefixes) {
+      int l1 = strlen(s1);
+      int l2 = strlen(s2);
+      if (*(s2+l1-1) == *(s2+l2-1)) return 1;
+    } else {
+      char * olds = s1;
+      // decapitalise dictionary word
+      if ((*s1 != *s2) && (*s1 != csconv[((unsigned char)*s2)].clower)) return 0;
+      do {
+        s1++; s2++;
+      } while ((*s1 == *s2) && (*s1 != '\0'));
+      return s1 - olds;
+    }
+  }
+  return 0;
+}
+
+int SuggestMgr::commoncharacterpositions(char * s1, const char * s2, int * is_swap) {
+  int num = 0;
+  int diff = 0;
+  int diffpos[2];
+  *is_swap = 0;
+  if (utf8) {
+    w_char su1[MAXSWL];
+    w_char su2[MAXSWL];
+    int l1 = u8_u16(su1, MAXSWL, s1);
+    int l2 = u8_u16(su2, MAXSWL, s2);
+    // decapitalize dictionary word
+    if (complexprefixes) {
+      mkallsmall_utf(su2+l2-1, 1, langnum);
+    } else {
+      mkallsmall_utf(su2, 1, langnum);
+    }
+    for (int i = 0; (i < l1) && (i < l2); i++) {
+      if (((short *) su1)[i] == ((short *) su2)[i]) {
+        num++;
+      } else {
+        if (diff < 2) diffpos[diff] = i;
+        diff++;
+      }
+    }
+    if ((diff == 2) && (l1 == l2) &&
+        (((short *) su1)[diffpos[0]] == ((short *) su2)[diffpos[1]]) &&
+        (((short *) su1)[diffpos[1]] == ((short *) su2)[diffpos[0]])) *is_swap = 1;
+  } else {
+    int i;
+    char t[MAXSWUTF8L];
+    strcpy(t, s2);
+    // decapitalize dictionary word
+    if (complexprefixes) {
+      int l2 = strlen(t);
+      *(t+l2-1) = csconv[((unsigned char)*(t+l2-1))].clower;
+    } else {
+      mkallsmall(t, csconv);
+    }
+    for (i = 0; (*(s1+i) != 0) && (*(t+i) != 0); i++) {
+      if (*(s1+i) == *(t+i)) {
+        num++;
+      } else {
+        if (diff < 2) diffpos[diff] = i;
+        diff++;
+      }
+    }
+    if ((diff == 2) && (*(s1+i) == 0) && (*(t+i) == 0) &&
+      (*(s1+diffpos[0]) == *(t+diffpos[1])) &&
+      (*(s1+diffpos[1]) == *(t+diffpos[0]))) *is_swap = 1;
+  }
+  return num;
+}
+
+int SuggestMgr::mystrlen(const char * word) {
+  if (utf8) {
+    w_char w[MAXSWL];
+    return u8_u16(w, MAXSWL, word);
+  } else return strlen(word);
+}
+
+// sort in decreasing order of score
+void SuggestMgr::bubblesort(char** rword, char** rword2, int* rsc, int n )
+{
+      int m = 1;
+      while (m < n) {
+          int j = m;
+          while (j > 0) {
+            if (rsc[j-1] < rsc[j]) {
+                int sctmp = rsc[j-1];
+                char * wdtmp = rword[j-1];
+                rsc[j-1] = rsc[j];
+                rword[j-1] = rword[j];
+                rsc[j] = sctmp;
+                rword[j] = wdtmp;
+                if (rword2) {
+            	    wdtmp = rword2[j-1];
+            	    rword2[j-1] = rword2[j];
+            	    rword2[j] = wdtmp;
+                }
+                j--;
+            } else break;
+          }
+          m++;
+      }
+      return;
+}
+
+// longest common subsequence
+void SuggestMgr::lcs(const char * s, const char * s2, int * l1, int * l2, char ** result) {
+  int n, m;
+  w_char su[MAXSWL];
+  w_char su2[MAXSWL];
+  char * b;
+  char * c;
+  int i;
+  int j;
+  if (utf8) {
+    m = u8_u16(su, MAXSWL, s);
+    n = u8_u16(su2, MAXSWL, s2);
+  } else {
+    m = strlen(s);
+    n = strlen(s2);
+  }
+  c = (char *) malloc((m + 1) * (n + 1));
+  b = (char *) malloc((m + 1) * (n + 1));
+  if (!c || !b) {
+    if (c) free(c);
+    if (b) free(b);
+    *result = NULL;
+    return;
+  }
+  for (i = 1; i <= m; i++) c[i*(n+1)] = 0;
+  for (j = 0; j <= n; j++) c[j] = 0;
+  for (i = 1; i <= m; i++) {
+    for (j = 1; j <= n; j++) {
+      if ((utf8) && (*((short *) su+i-1) == *((short *)su2+j-1))
+          || (!utf8) && ((*(s+i-1)) == (*(s2+j-1)))) {
+        c[i*(n+1) + j] = c[(i-1)*(n+1) + j-1]+1;
+        b[i*(n+1) + j] = LCS_UPLEFT;
+      } else if (c[(i-1)*(n+1) + j] >= c[i*(n+1) + j-1]) {
+        c[i*(n+1) + j] = c[(i-1)*(n+1) + j];
+        b[i*(n+1) + j] = LCS_UP;
+      } else {
+        c[i*(n+1) + j] = c[i*(n+1) + j-1];
+        b[i*(n+1) + j] = LCS_LEFT;
+      }
+    }
+  }
+  *result = b;
+  free(c);
+  *l1 = m;
+  *l2 = n;
+}
+
+int SuggestMgr::lcslen(const char * s, const char* s2) {
+  int m;
+  int n;
+  int i;
+  int j;
+  char * result;
+  int len = 0;
+  lcs(s, s2, &m, &n, &result);
+  if (!result) return 0;
+  i = m;
+  j = n;
+  while ((i != 0) && (j != 0)) {
+    if (result[i*(n+1) + j] == LCS_UPLEFT) {
+      len++;
+      i--;
+      j--;
+    } else if (result[i*(n+1) + j] == LCS_UP) {
+      i--;
+    } else j--;
+  }
+  free(result);
+  return len;
+}
diff -uprN --exclude=CVS spellcheck.old/hunspell/hunspell/suggestmgr.hxx spellcheck/hunspell/hunspell/suggestmgr.hxx
--- spellcheck.old/hunspell/hunspell/suggestmgr.hxx	1970-01-01 01:00:00.000000000 +0100
+++ spellcheck/hunspell/hunspell/suggestmgr.hxx	2008-04-23 16:42:09.000000000 +0200
@@ -0,0 +1,160 @@
+/******* BEGIN LICENSE BLOCK *******
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+ * and László Németh (Hunspell). Portions created by the Initial Developers
+ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+ * 
+ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+ *                 David Einstein (deinst@world.std.com)
+ *                 László Németh (nemethl@gyorsposta.hu)
+ *                 Davide Prina
+ *                 Giuseppe Modugno
+ *                 Gianluca Turconi
+ *                 Simon Brouwer
+ *                 Noll Janos
+ *                 Biro Arpad
+ *                 Goldman Eleonora
+ *                 Sarlos Tamas
+ *                 Bencsath Boldizsar
+ *                 Halacsy Peter
+ *                 Dvornik Laszlo
+ *                 Gefferth Andras
+ *                 Nagy Viktor
+ *                 Varga Daniel
+ *                 Chris Halls
+ *                 Rene Engelhard
+ *                 Bram Moolenaar
+ *                 Dafydd Jones
+ *                 Harri Pitkanen
+ *                 Andras Timar
+ *                 Tor Lillqvist
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ ******* END LICENSE BLOCK *******/
+
+#ifndef _SUGGESTMGR_HXX_
+#define _SUGGESTMGR_HXX_
+
+#define MAXSWL 100
+#define MAXSWUTF8L (MAXSWL * 4)
+#define MAX_ROOTS 100
+#define MAX_WORDS 100
+#define MAX_GUESS 200
+#define MAXNGRAMSUGS 4
+#define MAXPHONSUGS 2
+
+// timelimit: max ~1/4 sec (process time on Linux) for a time consuming function
+#define TIMELIMIT (CLOCKS_PER_SEC >> 2)
+#define MINTIMER 100
+#define MAXPLUSTIMER 100
+
+#define NGRAM_LONGER_WORSE  (1 << 0)
+#define NGRAM_ANY_MISMATCH  (1 << 1)
+#define NGRAM_LOWERING      (1 << 2)
+
+#include "atypes.hxx"
+#include "affixmgr.hxx"
+#include "hashmgr.hxx"
+#include "langnum.hxx"
+#include <time.h>
+
+enum { LCS_UP, LCS_LEFT, LCS_UPLEFT };
+
+class SuggestMgr
+{
+  char *          ckey;
+  int             ckeyl;
+  w_char *        ckey_utf;
+
+  char *          ctry;
+  int             ctryl;
+  w_char *        ctry_utf;
+
+  AffixMgr*       pAMgr;
+  int             maxSug;
+  struct cs_info * csconv;
+  int             utf8;
+  int             langnum;
+  int             nosplitsugs;
+  int             maxngramsugs;
+  int             complexprefixes;
+
+
+public:
+  SuggestMgr(const char * tryme, int maxn, AffixMgr *aptr);
+  ~SuggestMgr();
+
+  int suggest(char*** slst, const char * word, int nsug, int * onlycmpdsug);
+  int ngsuggest(char ** wlst, char * word, int ns, HashMgr* pHMgr);
+  int suggest_auto(char*** slst, const char * word, int nsug);
+  int suggest_stems(char*** slst, const char * word, int nsug);
+  int suggest_pos_stems(char*** slst, const char * word, int nsug);
+
+  char * suggest_morph(const char * word);
+  char * suggest_morph_for_spelling_error(const char * word);
+
+private:
+   int testsug(char** wlst, const char * candidate, int wl, int ns, int cpdsuggest,
+     int * timer, clock_t * timelimit);
+   int checkword(const char *, int, int, int *, clock_t *);
+   int check_forbidden(const char *, int);
+
+   int capchars(char **, const char *, int, int);
+   int replchars(char**, const char *, int, int);
+   int doubletwochars(char**, const char *, int, int);
+   int forgotchar(char **, const char *, int, int);
+   int swapchar(char **, const char *, int, int);
+   int longswapchar(char **, const char *, int, int);
+   int movechar(char **, const char *, int, int);
+   int extrachar(char **, const char *, int, int);
+   int badcharkey(char **, const char *, int, int);
+   int badchar(char **, const char *, int, int);
+   int twowords(char **, const char *, int, int);
+   int fixstems(char **, const char *, int);
+
+   int capchars_utf(char **, const w_char *, int wl, int, int);
+   int doubletwochars_utf(char**, const w_char *, int wl, int, int);
+   int forgotchar_utf(char**, const w_char *, int wl, int, int);
+   int extrachar_utf(char**, const w_char *, int wl, int, int);
+   int badcharkey_utf(char **, const w_char *, int wl, int, int);
+   int badchar_utf(char **, const w_char *, int wl, int, int);
+   int swapchar_utf(char **, const w_char *, int wl, int, int);
+   int longswapchar_utf(char **, const w_char *, int, int, int);
+   int movechar_utf(char **, const w_char *, int, int, int);
+
+   int mapchars(char**, const char *, int, int);
+   int map_related(const char *, int, char ** wlst, int, int, const mapentry*, int, int *, clock_t *);
+   int map_related_utf(w_char *, int, int, int, char ** wlst, int, const mapentry*, int, int *, clock_t *);
+   int ngram(int n, char * s1, const char * s2, int opt);
+   int mystrlen(const char * word);
+   int leftcommonsubstring(char * s1, const char * s2);
+   int commoncharacterpositions(char * s1, const char * s2, int * is_swap);
+   void bubblesort( char ** rwd, char ** rwd2, int * rsc, int n);
+   void lcs(const char * s, const char * s2, int * l1, int * l2, char ** result);
+   int lcslen(const char * s, const char* s2);
+
+};
+
+#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/Makefile.in spellcheck/hunspell/Makefile.in
--- spellcheck.old/hunspell/Makefile.in	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/Makefile.in	2008-04-23 16:42:09.000000000 +0200
@@ -41,7 +41,13 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= hunspell
-DIRS		= src
+
+ifndef MOZ_NATIVE_HUNSPELL
+DIRS		+= hunspell
+endif
+
+DIRS		+= src
+
 
 include $(topsrcdir)/config/rules.mk
 
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/affentry.cpp spellcheck/hunspell/src/affentry.cpp
--- spellcheck.old/hunspell/src/affentry.cpp	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/affentry.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,924 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef MOZILLA_CLIENT
-#include <cstdlib>
-#include <cstring>
-#include <cctype>
-#include <cstdio>
-#else
-#include <stdlib.h> 
-#include <string.h>
-#include <stdio.h> 
-#include <ctype.h>
-#endif
-
-#include "affentry.hxx"
-#include "csutil.hxx"
-
-#ifndef MOZILLA_CLIENT
-#ifndef W32
-using namespace std;
-#endif
-#endif
-
-
-PfxEntry::PfxEntry(AffixMgr* pmgr, affentry* dp)
-{
-  // register affix manager
-  pmyMgr = pmgr;
-
-  // set up its intial values
- 
-  aflag = dp->aflag;         // flag 
-  strip = dp->strip;         // string to strip
-  appnd = dp->appnd;         // string to append
-  stripl = dp->stripl;       // length of strip string
-  appndl = dp->appndl;       // length of append string
-  numconds = dp->numconds;   // number of conditions to match
-  opts = dp->opts;         // cross product flag
-  // then copy over all of the conditions
-  memcpy(&conds.base[0],&dp->conds.base[0],SETSIZE*sizeof(conds.base[0]));
-  next = NULL;
-  nextne = NULL;
-  nexteq = NULL;
-#ifdef HUNSPELL_EXPERIMENTAL
-  morphcode = dp->morphcode;
-#endif
-  contclass = dp->contclass;
-  contclasslen = dp->contclasslen;
-}
-
-
-PfxEntry::~PfxEntry()
-{
-    aflag = 0;
-    if (appnd) free(appnd);
-    if (strip) free(strip);
-    pmyMgr = NULL;
-    appnd = NULL;
-    strip = NULL;
-    if (opts & aeUTF8) {
-        for (int i = 0; i < numconds; i++) {
-            if (conds.utf8.wchars[i]) free(conds.utf8.wchars[i]);
-        }
-    }
-#ifdef HUNSPELL_EXPERIMENTAL
-    if (morphcode && !(opts & aeALIASM)) free(morphcode);
-#endif
-    if (contclass && !(opts & aeALIASF)) free(contclass);
-}
-
-// add prefix to this word assuming conditions hold
-char * PfxEntry::add(const char * word, int len)
-{
-    char tword[MAXWORDUTF8LEN + 4];
-
-    if ((len > stripl) && (len >= numconds) && test_condition(word) &&
-       (!stripl || (strncmp(word, strip, stripl) == 0)) && 
-       ((MAXWORDUTF8LEN + 4) > (len + appndl - stripl))) {
-    /* we have a match so add prefix */
-              char * pp = tword;
-              if (appndl) {
-                  strcpy(tword,appnd);
-                  pp += appndl;
-               }
-               strcpy(pp, (word + stripl));
-               return mystrdup(tword);
-     }
-     return NULL;    
-}
-
-
-inline int PfxEntry::test_condition(const char * st)
-{
-    int cond;
-    unsigned char * cp = (unsigned char *)st;
-    if (!(opts & aeUTF8)) { // 256-character codepage
-        for (cond = 0;  cond < numconds;  cond++) {
-            if ((conds.base[*cp++] & (1 << cond)) == 0) return 0;
-        }
-    } else { // UTF-8 encoding
-      unsigned short wc;
-      for (cond = 0;  cond < numconds;  cond++) {
-        // a simple 7-bit ASCII character in UTF-8
-        if ((*cp >> 7) == 0) {
-            // also check limit (end of word)
-            if ((!*cp) || ((conds.utf8.ascii[*cp++] & (1 << cond)) == 0)) return 0;
-        // UTF-8 multibyte character
-        } else {
-            // not dot wildcard in rule
-            if (!conds.utf8.all[cond]) {
-                if (conds.utf8.neg[cond]) {
-                    u8_u16((w_char *) &wc, 1, (char *) cp);
-                    if (conds.utf8.wchars[cond] && 
-                        flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
-                            wc, (short) conds.utf8.wlen[cond])) return 0;
-                } else {
-                    if (!conds.utf8.wchars[cond]) return 0;
-                    u8_u16((w_char *) &wc, 1, (char *) cp);
-                    if (!flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
-                         wc, (short)conds.utf8.wlen[cond])) return 0;
-                }
-            }
-            // jump to next UTF-8 character
-            for(cp++; (*cp & 0xc0) == 0x80; cp++);
-        }
-      }
-    }
-    return 1;
-}
-
-
-// check if this prefix entry matches 
-struct hentry * PfxEntry::checkword(const char * word, int len, char in_compound, const FLAG needflag)
-{
-    int                 tmpl;   // length of tmpword
-    struct hentry *     he;     // hash entry of root word or NULL
-    char                tmpword[MAXWORDUTF8LEN + 4];
-
-    // on entry prefix is 0 length or already matches the beginning of the word.
-    // So if the remaining root word has positive length
-    // and if there are enough chars in root word and added back strip chars
-    // to meet the number of characters conditions, then test it
-
-     tmpl = len - appndl;
-
-     if ((tmpl > 0) &&  (tmpl + stripl >= numconds)) {
-
-            // generate new root word by removing prefix and adding
-            // back any characters that would have been stripped
-
-            if (stripl) strcpy (tmpword, strip);
-            strcpy ((tmpword + stripl), (word + appndl));
-
-            // now make sure all of the conditions on characters
-            // are met.  Please see the appendix at the end of
-            // this file for more info on exactly what is being
-            // tested
-
-            // if all conditions are met then check if resulting
-            // root word in the dictionary
-
-            if (test_condition(tmpword)) {
-                tmpl += stripl;
-                if ((he = pmyMgr->lookup(tmpword)) != NULL) {
-                   do {
-                      if (TESTAFF(he->astr, aflag, he->alen) &&
-                        // forbid single prefixes with pseudoroot flag
-                        ! TESTAFF(contclass, pmyMgr->get_pseudoroot(), contclasslen) &&
-                        // needflag
-                        ((!needflag) || TESTAFF(he->astr, needflag, he->alen) ||
-                         (contclass && TESTAFF(contclass, needflag, contclasslen))))
-                            return he;
-                      he = he->next_homonym; // check homonyms
-                   } while (he);
-                }
-                
-                // prefix matched but no root word was found 
-                // if aeXPRODUCT is allowed, try again but now 
-                // ross checked combined with a suffix
-
-                //if ((opts & aeXPRODUCT) && in_compound) {
-                if ((opts & aeXPRODUCT)) {
-                   he = pmyMgr->suffix_check(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, NULL, 
-                        0, NULL, FLAG_NULL, needflag, in_compound);
-                   if (he) return he;
-                }
-            }
-     }
-    return NULL;
-}
-
-// check if this prefix entry matches 
-struct hentry * PfxEntry::check_twosfx(const char * word, int len,
-    char in_compound, const FLAG needflag)
-{
-    int                 tmpl;   // length of tmpword
-    struct hentry *     he;     // hash entry of root word or NULL
-    char                tmpword[MAXWORDUTF8LEN + 4];
-
-    // on entry prefix is 0 length or already matches the beginning of the word.
-    // So if the remaining root word has positive length
-    // and if there are enough chars in root word and added back strip chars
-    // to meet the number of characters conditions, then test it
-
-     tmpl = len - appndl;
-
-     if ((tmpl > 0) &&  (tmpl + stripl >= numconds)) {
-
-            // generate new root word by removing prefix and adding
-            // back any characters that would have been stripped
-
-            if (stripl) strcpy (tmpword, strip);
-            strcpy ((tmpword + stripl), (word + appndl));
-
-            // now make sure all of the conditions on characters
-            // are met.  Please see the appendix at the end of
-            // this file for more info on exactly what is being
-            // tested
-
-            // if all conditions are met then check if resulting
-            // root word in the dictionary
-
-            if (test_condition(tmpword)) {
-                tmpl += stripl;
-
-                // prefix matched but no root word was found 
-                // if aeXPRODUCT is allowed, try again but now 
-                // cross checked combined with a suffix
-
-                if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
-                   he = pmyMgr->suffix_check_twosfx(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, needflag);
-                   if (he) return he;
-                }
-            }
-     }
-    return NULL;
-}
-
-#ifdef HUNSPELL_EXPERIMENTAL
-// check if this prefix entry matches 
-char * PfxEntry::check_twosfx_morph(const char * word, int len,
-         char in_compound, const FLAG needflag)
-{
-    int                 tmpl;   // length of tmpword
-    char                tmpword[MAXWORDUTF8LEN + 4];
-
-    // on entry prefix is 0 length or already matches the beginning of the word.
-    // So if the remaining root word has positive length
-    // and if there are enough chars in root word and added back strip chars
-    // to meet the number of characters conditions, then test it
-
-     tmpl = len - appndl;
-
-     if ((tmpl > 0) &&  (tmpl + stripl >= numconds)) {
-
-            // generate new root word by removing prefix and adding
-            // back any characters that would have been stripped
-
-            if (stripl) strcpy (tmpword, strip);
-            strcpy ((tmpword + stripl), (word + appndl));
-
-            // now make sure all of the conditions on characters
-            // are met.  Please see the appendix at the end of
-            // this file for more info on exactly what is being
-            // tested
-
-            // if all conditions are met then check if resulting
-            // root word in the dictionary
-
-            if (test_condition(tmpword)) {
-                tmpl += stripl;
-
-                // prefix matched but no root word was found 
-                // if aeXPRODUCT is allowed, try again but now 
-                // ross checked combined with a suffix
-
-                if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
-                    return pmyMgr->suffix_check_twosfx_morph(tmpword, tmpl,
-                             aeXPRODUCT, (AffEntry *)this, needflag);
-                }
-            }
-     }
-    return NULL;
-}
-
-// check if this prefix entry matches 
-char * PfxEntry::check_morph(const char * word, int len, char in_compound, const FLAG needflag)
-{
-    int                 tmpl;   // length of tmpword
-    struct hentry *     he;     // hash entry of root word or NULL
-    char                tmpword[MAXWORDUTF8LEN + 4];
-    char                result[MAXLNLEN];
-    char * st;
-    
-    *result = '\0';
-
-    // on entry prefix is 0 length or already matches the beginning of the word.
-    // So if the remaining root word has positive length
-    // and if there are enough chars in root word and added back strip chars
-    // to meet the number of characters conditions, then test it
-
-     tmpl = len - appndl;
-
-     if ((tmpl > 0) &&  (tmpl + stripl >= numconds)) {
-
-            // generate new root word by removing prefix and adding
-            // back any characters that would have been stripped
-
-            if (stripl) strcpy (tmpword, strip);
-            strcpy ((tmpword + stripl), (word + appndl));
-
-            // now make sure all of the conditions on characters
-            // are met.  Please see the appendix at the end of
-            // this file for more info on exactly what is being
-            // tested
-
-            // if all conditions are met then check if resulting
-            // root word in the dictionary
-
-            if (test_condition(tmpword)) {
-                tmpl += stripl;
-                if ((he = pmyMgr->lookup(tmpword)) != NULL) {
-                    do {
-                      if (TESTAFF(he->astr, aflag, he->alen) &&
-                        // forbid single prefixes with pseudoroot flag
-                        ! TESTAFF(contclass, pmyMgr->get_pseudoroot(), contclasslen) &&
-                        // needflag
-                        ((!needflag) || TESTAFF(he->astr, needflag, he->alen) ||
-                         (contclass && TESTAFF(contclass, needflag, contclasslen)))) {
-                            if (morphcode) strcat(result, morphcode); else strcat(result,getKey());
-                            if (he->description) {
-                                if ((*(he->description)=='[')||(*(he->description)=='<')) strcat(result,he->word);
-                                strcat(result,he->description);
-                            }
-                            strcat(result, "\n");
-                      }
-                      he = he->next_homonym;
-                    } while (he);
-                }
-
-                // prefix matched but no root word was found 
-                // if aeXPRODUCT is allowed, try again but now 
-                // ross checked combined with a suffix
-
-                if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
-                   st = pmyMgr->suffix_check_morph(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, 
-                     FLAG_NULL, needflag);
-                   if (st) {
-                        strcat(result, st);
-                        free(st);
-                   }
-                }
-            }
-     }
-     
-    if (*result) return mystrdup(result);
-    return NULL;
-}
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
-SfxEntry::SfxEntry(AffixMgr * pmgr, affentry* dp)
-{
-  // register affix manager
-  pmyMgr = pmgr;
-
-  // set up its intial values
-  aflag = dp->aflag;         // char flag 
-  strip = dp->strip;         // string to strip
-  appnd = dp->appnd;         // string to append
-  stripl = dp->stripl;       // length of strip string
-  appndl = dp->appndl;       // length of append string
-  numconds = dp->numconds;   // number of conditions to match
-  opts = dp->opts;         // cross product flag
-
-  // then copy over all of the conditions
-  memcpy(&conds.base[0],&dp->conds.base[0],SETSIZE*sizeof(conds.base[0]));
-
-  rappnd = myrevstrdup(appnd);
-
-#ifdef HUNSPELL_EXPERIMENTAL
-  morphcode = dp->morphcode;
-#endif
-  contclass = dp->contclass;
-  contclasslen = dp->contclasslen;
-}
-
-
-SfxEntry::~SfxEntry()
-{
-    aflag = 0;
-    if (appnd) free(appnd);
-    if (rappnd) free(rappnd);
-    if (strip) free(strip);
-    pmyMgr = NULL;
-    appnd = NULL;
-    strip = NULL;    
-    if (opts & aeUTF8) {
-        for (int i = 0; i < numconds; i++) {
-            if (conds.utf8.wchars[i]) free(conds.utf8.wchars[i]);  
-        }
-    }
-#ifdef HUNSPELL_EXPERIMENTAL
-    if (morphcode && !(opts & aeALIASM)) free(morphcode);
-#endif
-    if (contclass && !(opts & aeALIASF)) free(contclass);
-}
-
-// add suffix to this word assuming conditions hold
-char * SfxEntry::add(const char * word, int len)
-{
-    char                tword[MAXWORDUTF8LEN + 4];
-
-     /* make sure all conditions match */
-     if ((len > stripl) && (len >= numconds) && test_condition(word + len, word) &&
-        (!stripl || (strcmp(word + len - stripl, strip) == 0)) &&
-        ((MAXWORDUTF8LEN + 4) > (len + appndl - stripl))) {
-              /* we have a match so add suffix */
-              strcpy(tword,word);
-              if (appndl) {
-                  strcpy(tword + len - stripl, appnd);
-              } else {
-                  *(tword + len - stripl) = '\0';
-              }
-              return mystrdup(tword);
-     }
-     return NULL;
-}
-
-
-inline int SfxEntry::test_condition(const char * st, const char * beg)
-{
-    int cond;
-    unsigned char * cp = (unsigned char *) st;
-    if (!(opts & aeUTF8)) { // 256-character codepage
-        // Domolki affix algorithm
-        for (cond = numconds;  --cond >= 0; ) {
-            if ((conds.base[*--cp] & (1 << cond)) == 0) return 0;
-        }
-    } else { // UTF-8 encoding
-      unsigned short wc;
-      for (cond = numconds;  --cond >= 0; ) {
-        // go to next character position and check limit
-        if ((char *) --cp < beg) return 0;
-        // a simple 7-bit ASCII character in UTF-8
-        if ((*cp >> 7) == 0) {
-            if ((conds.utf8.ascii[*cp] & (1 << cond)) == 0) return 0;
-        // UTF-8 multibyte character
-        } else {
-            // go to first character of UTF-8 multibyte character
-            for (; (*cp & 0xc0) == 0x80; cp--);
-            // not dot wildcard in rule
-            if (!conds.utf8.all[cond]) {
-                if (conds.utf8.neg[cond]) {
-                    u8_u16((w_char *) &wc, 1, (char *) cp);
-                    if (conds.utf8.wchars[cond] && 
-                        flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
-                            wc, (short) conds.utf8.wlen[cond])) return 0;
-                } else {
-                    if (!conds.utf8.wchars[cond]) return 0;
-                    u8_u16((w_char *) &wc, 1, (char *) cp);
-                    if (!flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
-                         wc, (short)conds.utf8.wlen[cond])) return 0;
-                }
-            }
-        }
-      }
-    }
-    return 1;
-}
-
-
-
-// see if this suffix is present in the word 
-struct hentry * SfxEntry::checkword(const char * word, int len, int optflags,
-    AffEntry* ppfx, char ** wlst, int maxSug, int * ns, const FLAG cclass, const FLAG needflag,
-    const FLAG badflag)
-{
-    int                 tmpl;            // length of tmpword 
-    struct hentry *     he;              // hash entry pointer
-    unsigned char *     cp;
-    char                tmpword[MAXWORDUTF8LEN + 4];
-    PfxEntry* ep = (PfxEntry *) ppfx;
-
-    // if this suffix is being cross checked with a prefix
-    // but it does not support cross products skip it
-
-    if (((optflags & aeXPRODUCT) != 0) && ((opts & aeXPRODUCT) == 0))
-        return NULL;
-
-    // upon entry suffix is 0 length or already matches the end of the word.
-    // So if the remaining root word has positive length
-    // and if there are enough chars in root word and added back strip chars
-    // to meet the number of characters conditions, then test it
-
-    tmpl = len - appndl;
-    // the second condition is not enough for UTF-8 strings
-    // it checked in test_condition()
-    
-    if ((tmpl > 0)  &&  (tmpl + stripl >= numconds)) {
-
-            // generate new root word by removing suffix and adding
-            // back any characters that would have been stripped or
-            // or null terminating the shorter string
-
-            strcpy (tmpword, word);
-            cp = (unsigned char *)(tmpword + tmpl);
-            if (stripl) {
-                strcpy ((char *)cp, strip);
-                tmpl += stripl;
-                cp = (unsigned char *)(tmpword + tmpl);
-            } else *cp = '\0';
-
-            // now make sure all of the conditions on characters
-            // are met.  Please see the appendix at the end of
-            // this file for more info on exactly what is being            // tested
-
-            // if all conditions are met then check if resulting
-            // root word in the dictionary
-
-            if (test_condition((char *) cp, (char *) tmpword)) {
-
-#ifdef SZOSZABLYA_POSSIBLE_ROOTS
-                fprintf(stdout,"%s %s %c\n", word, tmpword, aflag);
-#endif
-                if ((he = pmyMgr->lookup(tmpword)) != NULL) {
-                    do {
-                        // check conditional suffix (enabled by prefix)
-                        if ((TESTAFF(he->astr, aflag, he->alen) || (ep && ep->getCont() &&
-                                    TESTAFF(ep->getCont(), aflag, ep->getContLen()))) && 
-                            (((optflags & aeXPRODUCT) == 0) || 
-                            TESTAFF(he->astr, ep->getFlag(), he->alen) ||
-                             // enabled by prefix
-                            ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen))
-                            ) &&
-                            // handle cont. class
-                            ((!cclass) || 
-                                ((contclass) && TESTAFF(contclass, cclass, contclasslen))
-                            ) &&
-                            // check only in compound homonyms (bad flags)
-                            (!badflag || !TESTAFF(he->astr, badflag, he->alen)
-                            ) &&                            
-                            // handle required flag
-                            ((!needflag) || 
-                              (TESTAFF(he->astr, needflag, he->alen) ||
-                              ((contclass) && TESTAFF(contclass, needflag, contclasslen)))
-                            )
-                        ) return he;
-                        he = he->next_homonym; // check homonyms
-                    } while (he);
-
-                // obsolote stemming code (used only by the 
-                // experimental SuffixMgr:suggest_pos_stems)
-                // store resulting root in wlst
-                } else if (wlst && (*ns < maxSug)) {
-                    int cwrd = 1;
-                    for (int k=0; k < *ns; k++) 
-                        if (strcmp(tmpword, wlst[k]) == 0) cwrd = 0;
-                    if (cwrd) {
-                        wlst[*ns] = mystrdup(tmpword);
-                        if (wlst[*ns] == NULL) {
-                            for (int j=0; j<*ns; j++) free(wlst[j]);
-                            *ns = -1;
-                            return NULL;
-                        }
-                        (*ns)++;
-                    }
-                }
-            }
-    }
-    return NULL;
-}
-
-// see if two-level suffix is present in the word 
-struct hentry * SfxEntry::check_twosfx(const char * word, int len, int optflags,
-    AffEntry* ppfx, const FLAG needflag)
-{
-    int                 tmpl;            // length of tmpword 
-    struct hentry *     he;              // hash entry pointer
-    unsigned char *     cp;
-    char                tmpword[MAXWORDUTF8LEN + 4];
-    PfxEntry* ep = (PfxEntry *) ppfx;
-
-
-    // if this suffix is being cross checked with a prefix
-    // but it does not support cross products skip it
-
-    if ((optflags & aeXPRODUCT) != 0 &&  (opts & aeXPRODUCT) == 0)
-        return NULL;
-
-    // upon entry suffix is 0 length or already matches the end of the word.
-    // So if the remaining root word has positive length
-    // and if there are enough chars in root word and added back strip chars
-    // to meet the number of characters conditions, then test it
-
-    tmpl = len - appndl;
-
-    if ((tmpl > 0)  &&  (tmpl + stripl >= numconds)) {
-
-            // generate new root word by removing suffix and adding
-            // back any characters that would have been stripped or
-            // or null terminating the shorter string
-
-            strcpy (tmpword, word);
-            cp = (unsigned char *)(tmpword + tmpl);
-            if (stripl) {
-                strcpy ((char *)cp, strip);
-                tmpl += stripl;
-                cp = (unsigned char *)(tmpword + tmpl);
-            } else *cp = '\0';
-
-            // now make sure all of the conditions on characters
-            // are met.  Please see the appendix at the end of
-            // this file for more info on exactly what is being
-            // tested
-
-            // if all conditions are met then recall suffix_check
-
-            if (test_condition((char *) cp, (char *) tmpword)) {
-                if (ppfx) {
-                    // handle conditional suffix
-                    if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) 
-                        he = pmyMgr->suffix_check(tmpword, tmpl, 0, NULL, NULL, 0, NULL, (FLAG) aflag, needflag);
-                    else
-                        he = pmyMgr->suffix_check(tmpword, tmpl, optflags, ppfx, NULL, 0, NULL, (FLAG) aflag, needflag);
-                } else {
-                    he = pmyMgr->suffix_check(tmpword, tmpl, 0, NULL, NULL, 0, NULL, (FLAG) aflag, needflag);
-                }
-                if (he) return he;
-            }
-    }
-    return NULL;
-}
-
-#ifdef HUNSPELL_EXPERIMENTAL
-// see if two-level suffix is present in the word 
-char * SfxEntry::check_twosfx_morph(const char * word, int len, int optflags,
-    AffEntry* ppfx, const FLAG needflag)
-{
-    int                 tmpl;            // length of tmpword 
-    unsigned char *     cp;
-    char                tmpword[MAXWORDUTF8LEN + 4];
-    PfxEntry* ep = (PfxEntry *) ppfx;
-    char * st;
-
-    char result[MAXLNLEN];
-    
-    *result = '\0';
-
-    // if this suffix is being cross checked with a prefix
-    // but it does not support cross products skip it
-
-    if ((optflags & aeXPRODUCT) != 0 &&  (opts & aeXPRODUCT) == 0)
-        return NULL;
-
-    // upon entry suffix is 0 length or already matches the end of the word.
-    // So if the remaining root word has positive length
-    // and if there are enough chars in root word and added back strip chars
-    // to meet the number of characters conditions, then test it
-
-    tmpl = len - appndl;
-
-    if ((tmpl > 0)  &&  (tmpl + stripl >= numconds)) {
-
-            // generate new root word by removing suffix and adding
-            // back any characters that would have been stripped or
-            // or null terminating the shorter string
-
-            strcpy (tmpword, word);
-            cp = (unsigned char *)(tmpword + tmpl);
-            if (stripl) {
-                strcpy ((char *)cp, strip);
-                tmpl += stripl;
-                cp = (unsigned char *)(tmpword + tmpl);
-            } else *cp = '\0';
-
-            // now make sure all of the conditions on characters
-            // are met.  Please see the appendix at the end of
-            // this file for more info on exactly what is being
-            // tested
-
-            // if all conditions are met then recall suffix_check
-
-            if (test_condition((char *) cp, (char *) tmpword)) {
-                if (ppfx) {
-                    // handle conditional suffix
-                    if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) {
-                        st = pmyMgr->suffix_check_morph(tmpword, tmpl, 0, NULL, aflag, needflag);
-                        if (st) {
-                            if (((PfxEntry *) ppfx)->getMorph()) {
-                                strcat(result, ((PfxEntry *) ppfx)->getMorph());
-                            }
-                            strcat(result,st);
-                            free(st);
-                            mychomp(result);
-                        }
-                    } else {
-                        st = pmyMgr->suffix_check_morph(tmpword, tmpl, optflags, ppfx, aflag, needflag);
-                        if (st) {
-                            strcat(result, st);
-                            free(st);
-                            mychomp(result);
-                        }
-                    }
-                } else {
-                        st = pmyMgr->suffix_check_morph(tmpword, tmpl, 0, NULL, aflag, needflag);
-                        if (st) {
-                            strcat(result, st);
-                            free(st);
-                            mychomp(result);
-                        }
-                }
-                if (*result) return mystrdup(result);
-            }
-    }
-    return NULL;
-}
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
-// get next homonym with same affix
-struct hentry * SfxEntry::get_next_homonym(struct hentry * he, int optflags, AffEntry* ppfx, 
-    const FLAG cclass, const FLAG needflag)
-{
-    PfxEntry* ep = (PfxEntry *) ppfx;
-    FLAG eFlag = ep ? ep->getFlag() : FLAG_NULL;
-
-    while (he->next_homonym) {
-        he = he->next_homonym;
-        if ((TESTAFF(he->astr, aflag, he->alen) || (ep && ep->getCont() && TESTAFF(ep->getCont(), aflag, ep->getContLen()))) && 
-                            ((optflags & aeXPRODUCT) == 0 || 
-                            TESTAFF(he->astr, eFlag, he->alen) ||
-                             // handle conditional suffix
-                            ((contclass) && TESTAFF(contclass, eFlag, contclasslen))
-                            ) &&
-                            // handle cont. class
-                            ((!cclass) || 
-                                ((contclass) && TESTAFF(contclass, cclass, contclasslen))
-                            ) &&
-                            // handle required flag
-                            ((!needflag) || 
-                              (TESTAFF(he->astr, needflag, he->alen) ||
-                              ((contclass) && TESTAFF(contclass, needflag, contclasslen)))
-                            )
-                        ) return he;
-    }
-    return NULL;
-}
-
-
-#if 0
-
-Appendix:  Understanding Affix Code
-
-
-An affix is either a  prefix or a suffix attached to root words to make 
-other words.
-
-Basically a Prefix or a Suffix is set of AffEntry objects
-which store information about the prefix or suffix along 
-with supporting routines to check if a word has a particular 
-prefix or suffix or a combination.
-
-The structure affentry is defined as follows:
-
-struct affentry
-{
-   unsigned short aflag;    // ID used to represent the affix
-   char * strip;            // string to strip before adding affix
-   char * appnd;            // the affix string to add
-   unsigned char stripl;    // length of the strip string
-   unsigned char appndl;    // length of the affix string
-   char numconds;           // the number of conditions that must be met
-   char opts;               // flag: aeXPRODUCT- combine both prefix and suffix 
-   char   conds[SETSIZE];   // array which encodes the conditions to be met
-};
-
-
-Here is a suffix borrowed from the en_US.aff file.  This file 
-is whitespace delimited.
-
-SFX D Y 4 
-SFX D   0     e          d
-SFX D   y     ied        [^aeiou]y
-SFX D   0     ed         [^ey]
-SFX D   0     ed         [aeiou]y
-
-This information can be interpreted as follows:
-
-In the first line has 4 fields
-
-Field
------
-1     SFX - indicates this is a suffix
-2     D   - is the name of the character flag which represents this suffix
-3     Y   - indicates it can be combined with prefixes (cross product)
-4     4   - indicates that sequence of 4 affentry structures are needed to
-               properly store the affix information
-
-The remaining lines describe the unique information for the 4 SfxEntry 
-objects that make up this affix.  Each line can be interpreted
-as follows: (note fields 1 and 2 are as a check against line 1 info)
-
-Field
------
-1     SFX         - indicates this is a suffix
-2     D           - is the name of the character flag for this affix
-3     y           - the string of chars to strip off before adding affix
-                         (a 0 here indicates the NULL string)
-4     ied         - the string of affix characters to add
-5     [^aeiou]y   - the conditions which must be met before the affix
-                    can be applied
-
-Field 5 is interesting.  Since this is a suffix, field 5 tells us that
-there are 2 conditions that must be met.  The first condition is that 
-the next to the last character in the word must *NOT* be any of the 
-following "a", "e", "i", "o" or "u".  The second condition is that
-the last character of the word must end in "y".
-
-So how can we encode this information concisely and be able to 
-test for both conditions in a fast manner?  The answer is found
-but studying the wonderful ispell code of Geoff Kuenning, et.al. 
-(now available under a normal BSD license).
-
-If we set up a conds array of 256 bytes indexed (0 to 255) and access it
-using a character (cast to an unsigned char) of a string, we have 8 bits
-of information we can store about that character.  Specifically we
-could use each bit to say if that character is allowed in any of the 
-last (or first for prefixes) 8 characters of the word.
-
-Basically, each character at one end of the word (up to the number 
-of conditions) is used to index into the conds array and the resulting 
-value found there says whether the that character is valid for a 
-specific character position in the word.  
-
-For prefixes, it does this by setting bit 0 if that char is valid 
-in the first position, bit 1 if valid in the second position, and so on. 
-
-If a bit is not set, then that char is not valid for that postion in the
-word.
-
-If working with suffixes bit 0 is used for the character closest 
-to the front, bit 1 for the next character towards the end, ..., 
-with bit numconds-1 representing the last char at the end of the string. 
-
-Note: since entries in the conds[] are 8 bits, only 8 conditions 
-(read that only 8 character positions) can be examined at one
-end of a word (the beginning for prefixes and the end for suffixes.
-
-So to make this clearer, lets encode the conds array values for the 
-first two affentries for the suffix D described earlier.
-
-
-  For the first affentry:    
-     numconds = 1             (only examine the last character)
-
-     conds['e'] =  (1 << 0)   (the word must end in an E)
-     all others are all 0
-
-  For the second affentry:
-     numconds = 2             (only examine the last two characters)     
-
-     conds[X] = conds[X] | (1 << 0)     (aeiou are not allowed)
-         where X is all characters *but* a, e, i, o, or u
-         
-
-     conds['y'] = (1 << 1)     (the last char must be a y)
-     all other bits for all other entries in the conds array are zero
-
-
-#endif
-
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/affentry.hxx spellcheck/hunspell/src/affentry.hxx
--- spellcheck.old/hunspell/src/affentry.hxx	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/affentry.hxx	1970-01-01 01:00:00.000000000 +0100
@@ -1,187 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef _AFFIX_HXX_
-#define _AFFIX_HXX_
-
-#include "atypes.hxx"
-#include "baseaffix.hxx"
-#include "affixmgr.hxx"
-
-/* A Prefix Entry  */
-
-class PfxEntry : public AffEntry
-{
-       AffixMgr*    pmyMgr;
-
-       PfxEntry * next;
-       PfxEntry * nexteq;
-       PfxEntry * nextne;
-       PfxEntry * flgnxt;
-
-public:
-
-  PfxEntry(AffixMgr* pmgr, affentry* dp );
-  ~PfxEntry();
-
-  inline bool          allowCross() { return ((opts & aeXPRODUCT) != 0); }
-  struct hentry *      checkword(const char * word, int len, char in_compound, 
-                            const FLAG needflag = FLAG_NULL);
-
-  struct hentry *      check_twosfx(const char * word, int len, char in_compound, const FLAG needflag = NULL);
-
-  char *      check_morph(const char * word, int len, char in_compound,
-                            const FLAG needflag = FLAG_NULL);
-
-  char *      check_twosfx_morph(const char * word, int len,
-                  char in_compound, const FLAG needflag = FLAG_NULL);
-
-  inline FLAG getFlag()   { return aflag;   }
-  inline const char *  getKey()    { return appnd;  } 
-  char *               add(const char * word, int len);
-
-  inline short getKeyLen() { return appndl; } 
-
-  inline const char *  getMorph()    { return morphcode;  } 
-
-  inline const unsigned short * getCont()    { return contclass;  } 
-  inline short           getContLen()    { return contclasslen;  } 
-
-  inline PfxEntry *    getNext()   { return next;   }
-  inline PfxEntry *    getNextNE() { return nextne; }
-  inline PfxEntry *    getNextEQ() { return nexteq; }
-  inline PfxEntry *    getFlgNxt() { return flgnxt; }
-
-  inline void   setNext(PfxEntry * ptr)   { next = ptr;   }
-  inline void   setNextNE(PfxEntry * ptr) { nextne = ptr; }
-  inline void   setNextEQ(PfxEntry * ptr) { nexteq = ptr; }
-  inline void   setFlgNxt(PfxEntry * ptr) { flgnxt = ptr; }
-  
-  inline int    test_condition(const char * st);
-};
-
-
-
-
-/* A Suffix Entry */
-
-class SfxEntry : public AffEntry
-{
-       AffixMgr*    pmyMgr;
-       char *       rappnd;
-
-       SfxEntry *   next;
-       SfxEntry *   nexteq;
-       SfxEntry *   nextne;
-       SfxEntry *   flgnxt;
-           
-       SfxEntry *   l_morph;
-       SfxEntry *   r_morph;
-       SfxEntry *   eq_morph;
-
-public:
-
-  SfxEntry(AffixMgr* pmgr, affentry* dp );
-  ~SfxEntry();
-
-  inline bool          allowCross() { return ((opts & aeXPRODUCT) != 0); }
-  struct hentry *   checkword(const char * word, int len, int optflags, 
-                    AffEntry* ppfx, char ** wlst, int maxSug, int * ns,
-//                    const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, char in_compound=IN_CPD_NOT);
-                    const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, const FLAG badflag = 0);
-
-  struct hentry *   check_twosfx(const char * word, int len, int optflags, AffEntry* ppfx, const FLAG needflag = NULL);
-
-  char *      check_twosfx_morph(const char * word, int len, int optflags,
-                 AffEntry* ppfx, const FLAG needflag = FLAG_NULL);
-  struct hentry * get_next_homonym(struct hentry * he);
-  struct hentry * get_next_homonym(struct hentry * word, int optflags, AffEntry* ppfx, 
-    const FLAG cclass, const FLAG needflag);
-
-
-  inline FLAG getFlag()   { return aflag;   }
-  inline const char *  getKey()    { return rappnd; } 
-  char *               add(const char * word, int len);
-
-
-  inline const char *  getMorph()    { return morphcode;  } 
-
-  inline const unsigned short * getCont()    { return contclass;  } 
-  inline short           getContLen()    { return contclasslen;  } 
-  inline const char *  getAffix()    { return appnd; } 
-
-  inline short getKeyLen() { return appndl; } 
-
-  inline SfxEntry *    getNext()   { return next;   }
-  inline SfxEntry *    getNextNE() { return nextne; }
-  inline SfxEntry *    getNextEQ() { return nexteq; }
-
-  inline SfxEntry *    getLM() { return l_morph; }
-  inline SfxEntry *    getRM() { return r_morph; }
-  inline SfxEntry *    getEQM() { return eq_morph; }
-  inline SfxEntry *    getFlgNxt() { return flgnxt; }
-
-  inline void   setNext(SfxEntry * ptr)   { next = ptr;   }
-  inline void   setNextNE(SfxEntry * ptr) { nextne = ptr; }
-  inline void   setNextEQ(SfxEntry * ptr) { nexteq = ptr; }
-  inline void   setFlgNxt(SfxEntry * ptr) { flgnxt = ptr; }
-
-  inline int    test_condition(const char * st, const char * begin);
-};
-
-#endif
-
-
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/affixmgr.cpp spellcheck/hunspell/src/affixmgr.cpp
--- spellcheck.old/hunspell/src/affixmgr.cpp	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/affixmgr.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,4155 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef MOZILLA_CLIENT
-#include <cstdlib>
-#include <cstring>
-#include <cctype>
-#include <cstdio>
-#else
-#include <stdlib.h> 
-#include <string.h>
-#include <stdio.h> 
-#include <ctype.h>
-#endif
-
-#include "affixmgr.hxx"
-#include "affentry.hxx"
-#include "langnum.hxx"
-
-#include "csutil.hxx"
-
-#ifndef MOZILLA_CLIENT
-#ifndef W32
-using namespace std;
-#endif
-#endif
-
-AffixMgr::AffixMgr(const char * affpath, HashMgr* ptr) 
-{
-  // register hash manager and load affix data from aff file
-  pHMgr = ptr;
-  keystring = NULL;
-  trystring = NULL;
-  encoding=NULL;
-  utf8 = 0;
-  complexprefixes = 0;
-  maptable = NULL;
-  nummap = 0;
-  breaktable = NULL;
-  numbreak = 0;
-  reptable = NULL;
-  numrep = 0;
-  checkcpdtable = NULL;
-  numcheckcpd = 0;
-  defcpdtable = NULL;
-  numdefcpd = 0;
-  phone = NULL;
-  compoundflag = FLAG_NULL; // permits word in compound forms
-  compoundbegin = FLAG_NULL; // may be first word in compound forms
-  compoundmiddle = FLAG_NULL; // may be middle word in compound forms
-  compoundend = FLAG_NULL; // may be last word in compound forms
-  compoundroot = FLAG_NULL; // compound word signing flag
-  compoundpermitflag = FLAG_NULL; // compound permitting flag for suffixed word
-  compoundforbidflag = FLAG_NULL; // compound fordidden flag for suffixed word
-  checkcompounddup = 0; // forbid double words in compounds
-  checkcompoundrep = 0; // forbid bad compounds (may be non compound word with a REP substitution)
-  checkcompoundcase = 0; // forbid upper and lowercase combinations at word bounds
-  checkcompoundtriple = 0; // forbid compounds with triple letters
-  forbiddenword = FLAG_NULL; // forbidden word signing flag
-  nosuggest = FLAG_NULL; // don't suggest words signed with NOSUGGEST flag
-  lang = NULL; // language
-  langnum = 0; // language code (see http://l10n.openoffice.org/languages.html)
-  pseudoroot = FLAG_NULL; // forbidden root, allowed only with suffixes
-  cpdwordmax = -1; // default: unlimited wordcount in compound words
-  cpdmin = -1;  // undefined
-  cpdmaxsyllable = 0; // default: unlimited syllablecount in compound words
-  cpdvowels=NULL; // vowels (for calculating of Hungarian compounding limit, O(n) search! XXX)
-  cpdvowels_utf16=NULL; // vowels for UTF-8 encoding (bsearch instead of O(n) search)
-  cpdvowels_utf16_len=0; // vowels
-  pfxappnd=NULL; // previous prefix for counting the syllables of prefix BUG
-  sfxappnd=NULL; // previous suffix for counting a special syllables BUG
-  cpdsyllablenum=NULL; // syllable count incrementing flag
-  checknum=0; // checking numbers, and word with numbers
-  wordchars=NULL; // letters + spec. word characters
-  wordchars_utf16=NULL; // letters + spec. word characters
-  wordchars_utf16_len=0; // letters + spec. word characters
-  ignorechars=NULL; // letters + spec. word characters
-  ignorechars_utf16=NULL; // letters + spec. word characters
-  ignorechars_utf16_len=0; // letters + spec. word characters
-  version=NULL; // affix and dictionary file version string
-  havecontclass=0; // flags of possible continuing classes (double affix)
-  // LEMMA_PRESENT: not put root into the morphological output. Lemma presents
-  // in morhological description in dictionary file. It's often combined with PSEUDOROOT.
-  lemma_present = FLAG_NULL; 
-  circumfix = FLAG_NULL; 
-  onlyincompound = FLAG_NULL; 
-  flag_mode = FLAG_CHAR; // default one-character flags in affix and dic file
-  maxngramsugs = -1; // undefined
-  nosplitsugs = 0;
-  sugswithdots = 0;
-  keepcase = 0;
-  checksharps = 0;
-
-  derived = NULL; // XXX not threadsafe variable for experimental stemming
-  sfx = NULL;
-  pfx = NULL;
-
-  for (int i=0; i < SETSIZE; i++) {
-     pStart[i] = NULL;
-     sStart[i] = NULL;
-     pFlag[i] = NULL;
-     sFlag[i] = NULL;
-  }
-
-  for (int j=0; j < CONTSIZE; j++) {
-    contclasses[j] = 0;
-  }
-
-  if (parse_file(affpath)) {
-     HUNSPELL_WARNING(stderr, "Failure loading aff file %s\n",affpath);
-  }
-  
-  if (cpdmin == -1) cpdmin = MINCPDLEN;
-
-}
-
-
-AffixMgr::~AffixMgr() 
-{
- 
-  // pass through linked prefix entries and clean up
-  for (int i=0; i < SETSIZE ;i++) {
-       pFlag[i] = NULL;
-       PfxEntry * ptr = (PfxEntry *)pStart[i];
-       PfxEntry * nptr = NULL;
-       while (ptr) {
-            nptr = ptr->getNext();
-            delete(ptr);
-            ptr = nptr;
-            nptr = NULL;
-       }  
-  }
-
-  // pass through linked suffix entries and clean up
-  for (int j=0; j < SETSIZE ; j++) {
-       sFlag[j] = NULL;
-       SfxEntry * ptr = (SfxEntry *)sStart[j];
-       SfxEntry * nptr = NULL;
-       while (ptr) {
-            nptr = ptr->getNext();
-            delete(ptr);
-            ptr = nptr;
-            nptr = NULL;
-       }
-       sStart[j] = NULL;
-  }
-
-  if (keystring) free(keystring);
-  keystring=NULL;
-  if (trystring) free(trystring);
-  trystring=NULL;
-  if (encoding) free(encoding);
-  encoding=NULL;
-  if (maptable) {  
-     for (int j=0; j < nummap; j++) {
-        if (maptable[j].set) free(maptable[j].set);
-        if (maptable[j].set_utf16) free(maptable[j].set_utf16);
-        maptable[j].set = NULL;
-        maptable[j].len = 0;
-     }
-     free(maptable);  
-     maptable = NULL;
-  }
-  nummap = 0;
-  if (breaktable) {
-     for (int j=0; j < numbreak; j++) {
-        if (breaktable[j]) free(breaktable[j]);
-        breaktable[j] = NULL;
-     }
-     free(breaktable);  
-     breaktable = NULL;
-  }
-  numbreak = 0;
-  if (reptable) {
-     for (int j=0; j < numrep; j++) {
-        free(reptable[j].pattern);
-        free(reptable[j].pattern2);
-     }
-     free(reptable);  
-     reptable = NULL;
-  }
-  if (phone && phone->rules) {
-     for (int j=0; j < phone->num + 1; j++) {
-        free(phone->rules[j * 2]);
-        free(phone->rules[j * 2 + 1]);
-     }
-     free(phone->rules);
-     free(phone);  
-     phone = NULL;
-  }
-
-  if (defcpdtable) {  
-     for (int j=0; j < numdefcpd; j++) {
-        free(defcpdtable[j].def);
-        defcpdtable[j].def = NULL;
-     }
-     free(defcpdtable);  
-     defcpdtable = NULL;
-  }
-  numrep = 0;
-  if (checkcpdtable) {  
-     for (int j=0; j < numcheckcpd; j++) {
-        free(checkcpdtable[j].pattern);
-        free(checkcpdtable[j].pattern2);
-        checkcpdtable[j].pattern = NULL;
-        checkcpdtable[j].pattern2 = NULL;
-     }
-     free(checkcpdtable);  
-     checkcpdtable = NULL;
-  }
-  numcheckcpd = 0;
-  FREE_FLAG(compoundflag);
-  FREE_FLAG(compoundbegin);
-  FREE_FLAG(compoundmiddle);
-  FREE_FLAG(compoundend);
-  FREE_FLAG(compoundpermitflag);
-  FREE_FLAG(compoundforbidflag);
-  FREE_FLAG(compoundroot);
-  FREE_FLAG(forbiddenword);
-  FREE_FLAG(nosuggest);
-  FREE_FLAG(pseudoroot);
-  FREE_FLAG(lemma_present);
-  FREE_FLAG(circumfix);
-  FREE_FLAG(onlyincompound);
-  
-  cpdwordmax = 0;
-  pHMgr = NULL;
-  cpdmin = 0;
-  cpdmaxsyllable = 0;
-  if (cpdvowels) free(cpdvowels);
-  if (cpdvowels_utf16) free(cpdvowels_utf16);
-  if (cpdsyllablenum) free(cpdsyllablenum);
-  free_utf_tbl();
-  if (lang) free(lang);
-  if (wordchars) free(wordchars);
-  if (wordchars_utf16) free(wordchars_utf16);
-  if (ignorechars) free(ignorechars);
-  if (ignorechars_utf16) free(ignorechars_utf16);
-  if (version) free(version);
-  if (derived) free(derived);
-  checknum=0;
-}
-
-
-// read in aff file and build up prefix and suffix entry objects 
-int  AffixMgr::parse_file(const char * affpath)
-{
-
-  // io buffers
-  char line[MAXLNLEN+1];
- 
-  // affix type
-  char ft;
-  
-  // checking flag duplication
-  char dupflags[CONTSIZE];
-  char dupflags_ini = 1;
-
-  // first line indicator for removing byte order mark
-  int firstline = 1;
-  
-  // open the affix file
-  FILE * afflst;
-  afflst = fopen(affpath,"r");
-  if (!afflst) {
-    HUNSPELL_WARNING(stderr, "error: could not open affix description file %s\n",affpath);
-    return 1;
-  }
-
-  // step one is to parse the affix file building up the internal
-  // affix data structures
-
-
-    // read in each line ignoring any that do not
-    // start with a known line type indicator
-    while (fgets(line,MAXLNLEN,afflst)) {
-       mychomp(line);
-
-       /* remove byte order mark */
-       if (firstline) {
-         firstline = 0;
-         if (strncmp(line,"\xEF\xBB\xBF",3) == 0) {
-            memmove(line, line+3, strlen(line+3)+1);
-            HUNSPELL_WARNING(stderr, "warning: affix file begins with byte order mark: possible incompatibility with old Hunspell versions\n");
-         }
-       }
-
-       /* parse in the keyboard string */
-       if (strncmp(line,"KEY",3) == 0) {
-          if (parse_string(line, &keystring, "KEY")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the try string */
-       if (strncmp(line,"TRY",3) == 0) {
-          if (parse_string(line, &trystring, "TRY")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the name of the character set used by the .dict and .aff */
-       if (strncmp(line,"SET",3) == 0) {
-          if (parse_string(line, &encoding, "SET")) {
-             fclose(afflst);
-             return 1;
-          }
-          if (strcmp(encoding, "UTF-8") == 0) {
-             utf8 = 1;
-#ifndef OPENOFFICEORG
-#ifndef MOZILLA_CLIENT
-             if (initialize_utf_tbl()) return 1;
-#endif
-#endif
-          }
-       }
-
-       /* parse COMPLEXPREFIXES for agglutinative languages with right-to-left writing system */
-       if (strncmp(line,"COMPLEXPREFIXES",15) == 0)
-                   complexprefixes = 1;
-
-       /* parse in the flag used by the controlled compound words */
-       if (strncmp(line,"COMPOUNDFLAG",12) == 0) {
-          if (parse_flag(line, &compoundflag, "COMPOUNDFLAG")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag used by compound words */
-       if (strncmp(line,"COMPOUNDBEGIN",13) == 0) {
-          if (complexprefixes) {
-            if (parse_flag(line, &compoundend, "COMPOUNDBEGIN")) {
-              fclose(afflst);
-              return 1;
-            }
-          } else {
-            if (parse_flag(line, &compoundbegin, "COMPOUNDBEGIN")) {
-              fclose(afflst);
-              return 1;
-            }
-          }
-       }
-
-       /* parse in the flag used by compound words */
-       if (strncmp(line,"COMPOUNDMIDDLE",14) == 0) {
-          if (parse_flag(line, &compoundmiddle, "COMPOUNDMIDDLE")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-       /* parse in the flag used by compound words */
-       if (strncmp(line,"COMPOUNDEND",11) == 0) {
-          if (complexprefixes) {
-            if (parse_flag(line, &compoundbegin, "COMPOUNDEND")) {
-              fclose(afflst);
-              return 1;
-            }
-          } else {
-            if (parse_flag(line, &compoundend, "COMPOUNDEND")) {
-              fclose(afflst);
-              return 1;
-            }
-          }
-       }
-
-       /* parse in the data used by compound_check() method */
-       if (strncmp(line,"COMPOUNDWORDMAX",15) == 0) {
-          if (parse_num(line, &cpdwordmax, "COMPOUNDWORDMAX")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag sign compounds in dictionary */
-       if (strncmp(line,"COMPOUNDROOT",12) == 0) {
-          if (parse_flag(line, &compoundroot, "COMPOUNDROOT")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag used by compound_check() method */
-       if (strncmp(line,"COMPOUNDPERMITFLAG",18) == 0) {
-          if (parse_flag(line, &compoundpermitflag, "COMPOUNDPERMITFLAG")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag used by compound_check() method */
-       if (strncmp(line,"COMPOUNDFORBIDFLAG",18) == 0) {
-          if (parse_flag(line, &compoundforbidflag, "COMPOUNDFORBIDFLAG")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       if (strncmp(line,"CHECKCOMPOUNDDUP",16) == 0) {
-                   checkcompounddup = 1;
-       }
-
-       if (strncmp(line,"CHECKCOMPOUNDREP",16) == 0) {
-                   checkcompoundrep = 1;
-       }
-
-       if (strncmp(line,"CHECKCOMPOUNDTRIPLE",19) == 0) {
-                   checkcompoundtriple = 1;
-       }
-
-       if (strncmp(line,"CHECKCOMPOUNDCASE",17) == 0) {
-                   checkcompoundcase = 1;
-       }
-
-       if (strncmp(line,"NOSUGGEST",9) == 0) {
-          if (parse_flag(line, &nosuggest, "NOSUGGEST")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag used by forbidden words */
-       if (strncmp(line,"FORBIDDENWORD",13) == 0) {
-          if (parse_flag(line, &forbiddenword, "FORBIDDENWORD")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag used by forbidden words */
-       if (strncmp(line,"LEMMA_PRESENT",13) == 0) {
-          if (parse_flag(line, &lemma_present, "LEMMA_PRESENT")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag used by circumfixes */
-       if (strncmp(line,"CIRCUMFIX",9) == 0) {
-          if (parse_flag(line, &circumfix, "CIRCUMFIX")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag used by fogemorphemes */
-       if (strncmp(line,"ONLYINCOMPOUND",14) == 0) {
-          if (parse_flag(line, &onlyincompound, "ONLYINCOMPOUND")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag used by `pseudoroots' */
-       if (strncmp(line,"PSEUDOROOT",10) == 0) {
-          if (parse_flag(line, &pseudoroot, "PSEUDOROOT")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag used by `pseudoroots' */
-       if (strncmp(line,"NEEDAFFIX",9) == 0) {
-          if (parse_flag(line, &pseudoroot, "NEEDAFFIX")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the minimal length for words in compounds */
-       if (strncmp(line,"COMPOUNDMIN",11) == 0) {
-          if (parse_num(line, &cpdmin, "COMPOUNDMIN")) {
-             fclose(afflst);
-             return 1;
-          }
-          if (cpdmin < 1) cpdmin = 1;
-       }
-
-       /* parse in the max. words and syllables in compounds */
-       if (strncmp(line,"COMPOUNDSYLLABLE",16) == 0) {
-          if (parse_cpdsyllable(line)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag used by compound_check() method */
-       if (strncmp(line,"SYLLABLENUM",11) == 0) {
-          if (parse_string(line, &cpdsyllablenum, "SYLLABLENUM")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the flag used by the controlled compound words */
-       if (strncmp(line,"CHECKNUM",8) == 0) {
-           checknum=1;
-       }
-
-       /* parse in the extra word characters */
-       if (strncmp(line,"WORDCHARS",9) == 0) {
-          if (parse_array(line, &wordchars, &wordchars_utf16, &wordchars_utf16_len, "WORDCHARS", utf8)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the ignored characters (for example, Arabic optional diacretics charachters */
-       if (strncmp(line,"IGNORE",6) == 0) {
-          if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, "IGNORE", utf8)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the typical fault correcting table */
-       if (strncmp(line,"REP",3) == 0) {
-          if (parse_reptable(line, afflst)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the phonetic translation table */
-       if (strncmp(line,"PHONE",5) == 0) {
-          if (parse_phonetable(line, afflst)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the checkcompoundpattern table */
-       if (strncmp(line,"CHECKCOMPOUNDPATTERN",20) == 0) {
-          if (parse_checkcpdtable(line, afflst)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the defcompound table */
-       if (strncmp(line,"COMPOUNDRULE",12) == 0) {
-          if (parse_defcpdtable(line, afflst)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the related character map table */
-       if (strncmp(line,"MAP",3) == 0) {
-          if (parse_maptable(line, afflst)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the word breakpoints table */
-       if (strncmp(line,"BREAK",5) == 0) {
-          if (parse_breaktable(line, afflst)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       /* parse in the language for language specific codes */
-       if (strncmp(line,"LANG",4) == 0) {
-          if (parse_string(line, &lang, "LANG")) {
-             fclose(afflst);
-             return 1;
-          }
-          langnum = get_lang_num(lang);
-       }
-
-       if (strncmp(line,"VERSION",7) == 0) {
-          if (parse_string(line, &version, "VERSION")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       if (strncmp(line,"MAXNGRAMSUGS",12) == 0) {
-          if (parse_num(line, &maxngramsugs, "MAXNGRAMSUGS")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       if (strncmp(line,"NOSPLITSUGS",11) == 0) {
-                   nosplitsugs=1;
-       }
-
-       if (strncmp(line,"SUGSWITHDOTS",12) == 0) {
-                   sugswithdots=1;
-       }
-
-       /* parse in the flag used by forbidden words */
-       if (strncmp(line,"KEEPCASE",8) == 0) {
-          if (parse_flag(line, &keepcase, "KEEPCASE")) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       if (strncmp(line,"CHECKSHARPS",11) == 0) {
-                   checksharps=1;
-       }
-
-       /* parse this affix: P - prefix, S - suffix */
-       ft = ' ';
-       if (strncmp(line,"PFX",3) == 0) ft = complexprefixes ? 'S' : 'P';
-       if (strncmp(line,"SFX",3) == 0) ft = complexprefixes ? 'P' : 'S';
-       if (ft != ' ') {
-          if (dupflags_ini) {
-            for (int i = 0; i < CONTSIZE; i++) dupflags[i] = 0;
-            dupflags_ini = 0;
-          }
-          if (parse_affix(line, ft, afflst, dupflags)) {
-             fclose(afflst);
-             process_pfx_tree_to_list();
-             process_sfx_tree_to_list();
-             return 1;
-          }
-       }
-
-    }
-    fclose(afflst);
-
-    // convert affix trees to sorted list
-    process_pfx_tree_to_list();
-    process_sfx_tree_to_list();
-
-    // now we can speed up performance greatly taking advantage of the 
-    // relationship between the affixes and the idea of "subsets".
-
-    // View each prefix as a potential leading subset of another and view
-    // each suffix (reversed) as a potential trailing subset of another.
-
-    // To illustrate this relationship if we know the prefix "ab" is found in the
-    // word to examine, only prefixes that "ab" is a leading subset of need be examined.
-    // Furthermore is "ab" is not present then none of the prefixes that "ab" is
-    // is a subset need be examined.
-    // The same argument goes for suffix string that are reversed.
-
-    // Then to top this off why not examine the first char of the word to quickly
-    // limit the set of prefixes to examine (i.e. the prefixes to examine must 
-    // be leading supersets of the first character of the word (if they exist)
- 
-    // To take advantage of this "subset" relationship, we need to add two links
-    // from entry.  One to take next if the current prefix is found (call it nexteq)
-    // and one to take next if the current prefix is not found (call it nextne).
-
-    // Since we have built ordered lists, all that remains is to properly intialize 
-    // the nextne and nexteq pointers that relate them
-
-    process_pfx_order();
-    process_sfx_order();
-
-    /* get encoding for CHECKCOMPOUNDCASE */
-    char * enc = get_encoding();
-    csconv = get_current_cs(enc);
-    free(enc);
-    enc = NULL;
-
-    // temporary BREAK definition for German dash handling (OOo issue 64400)
-    if ((langnum == LANG_de) && (!breaktable)) {
-        breaktable = (char **) malloc(sizeof(char *));
-        if (!breaktable) return 1;
-        breaktable[0] = mystrdup("-");
-        numbreak = 1;
-    }
-    return 0;
-}
-
-
-// we want to be able to quickly access prefix information
-// both by prefix flag, and sorted by prefix string itself 
-// so we need to set up two indexes
-
-int AffixMgr::build_pfxtree(AffEntry* pfxptr)
-{
-  PfxEntry * ptr;
-  PfxEntry * pptr;
-  PfxEntry * ep = (PfxEntry*) pfxptr;
-
-  // get the right starting points
-  const char * key = ep->getKey();
-  const unsigned char flg = (unsigned char) (ep->getFlag() & 0x00FF);
-
-  // first index by flag which must exist
-  ptr = (PfxEntry*)pFlag[flg];
-  ep->setFlgNxt(ptr);
-  pFlag[flg] = (AffEntry *) ep;
-
-
-  // handle the special case of null affix string
-  if (strlen(key) == 0) {
-    // always inset them at head of list at element 0
-     ptr = (PfxEntry*)pStart[0];
-     ep->setNext(ptr);
-     pStart[0] = (AffEntry*)ep;
-     return 0;
-  }
-
-  // now handle the normal case
-  ep->setNextEQ(NULL);
-  ep->setNextNE(NULL);
-
-  unsigned char sp = *((const unsigned char *)key);
-  ptr = (PfxEntry*)pStart[sp];
-  
-  // handle the first insert 
-  if (!ptr) {
-     pStart[sp] = (AffEntry*)ep;
-     return 0;
-  }
-
-
-  // otherwise use binary tree insertion so that a sorted
-  // list can easily be generated later
-  pptr = NULL;
-  for (;;) {
-    pptr = ptr;
-    if (strcmp(ep->getKey(), ptr->getKey() ) <= 0) {
-       ptr = ptr->getNextEQ();
-       if (!ptr) {
-          pptr->setNextEQ(ep);
-          break;
-       }
-    } else {
-       ptr = ptr->getNextNE();
-       if (!ptr) {
-          pptr->setNextNE(ep);
-          break;
-       }
-    }
-  }
-  return 0;
-}
-
-// we want to be able to quickly access suffix information
-// both by suffix flag, and sorted by the reverse of the
-// suffix string itself; so we need to set up two indexes
-int AffixMgr::build_sfxtree(AffEntry* sfxptr)
-{
-  SfxEntry * ptr;
-  SfxEntry * pptr;
-  SfxEntry * ep = (SfxEntry *) sfxptr;
-
-  /* get the right starting point */
-  const char * key = ep->getKey();
-  const unsigned char flg = (unsigned char) (ep->getFlag() & 0x00FF);
-
-  // first index by flag which must exist
-  ptr = (SfxEntry*)sFlag[flg];
-  ep->setFlgNxt(ptr);
-  sFlag[flg] = (AffEntry *) ep;
-
-  // next index by affix string
-
-  // handle the special case of null affix string
-  if (strlen(key) == 0) {
-    // always inset them at head of list at element 0
-     ptr = (SfxEntry*)sStart[0];
-     ep->setNext(ptr);
-     sStart[0] = (AffEntry*)ep;
-     return 0;
-  }
-
-  // now handle the normal case
-  ep->setNextEQ(NULL);
-  ep->setNextNE(NULL);
-
-  unsigned char sp = *((const unsigned char *)key);
-  ptr = (SfxEntry*)sStart[sp];
-  
-  // handle the first insert 
-  if (!ptr) {
-     sStart[sp] = (AffEntry*)ep;
-     return 0;
-  }
-
-  // otherwise use binary tree insertion so that a sorted
-  // list can easily be generated later
-  pptr = NULL;
-  for (;;) {
-    pptr = ptr;
-    if (strcmp(ep->getKey(), ptr->getKey() ) <= 0) {
-       ptr = ptr->getNextEQ();
-       if (!ptr) {
-          pptr->setNextEQ(ep);
-          break;
-       }
-    } else {
-       ptr = ptr->getNextNE();
-       if (!ptr) {
-          pptr->setNextNE(ep);
-          break;
-       }
-    }
-  }
-  return 0;
-}
-
-// convert from binary tree to sorted list
-int AffixMgr::process_pfx_tree_to_list()
-{
-  for (int i=1; i< SETSIZE; i++) {
-    pStart[i] = process_pfx_in_order(pStart[i],NULL);
-  }
-  return 0;
-}
-
-
-AffEntry* AffixMgr::process_pfx_in_order(AffEntry* ptr, AffEntry* nptr)
-{
-  if (ptr) {
-    nptr = process_pfx_in_order(((PfxEntry*) ptr)->getNextNE(), nptr);
-    ((PfxEntry*) ptr)->setNext((PfxEntry*) nptr);
-    nptr = process_pfx_in_order(((PfxEntry*) ptr)->getNextEQ(), ptr);
-  }
-  return nptr;
-}
-
-
-// convert from binary tree to sorted list
-int AffixMgr:: process_sfx_tree_to_list()
-{
-  for (int i=1; i< SETSIZE; i++) {
-    sStart[i] = process_sfx_in_order(sStart[i],NULL);
-  }
-  return 0;
-}
-
-AffEntry* AffixMgr::process_sfx_in_order(AffEntry* ptr, AffEntry* nptr)
-{
-  if (ptr) {
-    nptr = process_sfx_in_order(((SfxEntry*) ptr)->getNextNE(), nptr);
-    ((SfxEntry*) ptr)->setNext((SfxEntry*) nptr);
-    nptr = process_sfx_in_order(((SfxEntry*) ptr)->getNextEQ(), ptr);
-  }
-  return nptr;
-}
-
-
-// reinitialize the PfxEntry links NextEQ and NextNE to speed searching
-// using the idea of leading subsets this time
-int AffixMgr::process_pfx_order()
-{
-    PfxEntry* ptr;
-
-    // loop through each prefix list starting point
-    for (int i=1; i < SETSIZE; i++) {
-
-         ptr = (PfxEntry*)pStart[i];
-
-         // look through the remainder of the list
-         //  and find next entry with affix that 
-         // the current one is not a subset of
-         // mark that as destination for NextNE
-         // use next in list that you are a subset
-         // of as NextEQ
-
-         for (; ptr != NULL; ptr = ptr->getNext()) {
-
-             PfxEntry * nptr = ptr->getNext();
-             for (; nptr != NULL; nptr = nptr->getNext()) {
-                 if (! isSubset( ptr->getKey() , nptr->getKey() )) break;
-             }
-             ptr->setNextNE(nptr);
-             ptr->setNextEQ(NULL);
-             if ((ptr->getNext()) && isSubset(ptr->getKey() , (ptr->getNext())->getKey())) 
-                 ptr->setNextEQ(ptr->getNext());
-         }
-
-         // now clean up by adding smart search termination strings:
-         // if you are already a superset of the previous prefix
-         // but not a subset of the next, search can end here
-         // so set NextNE properly
-
-         ptr = (PfxEntry *) pStart[i];
-         for (; ptr != NULL; ptr = ptr->getNext()) {
-             PfxEntry * nptr = ptr->getNext();
-             PfxEntry * mptr = NULL;
-             for (; nptr != NULL; nptr = nptr->getNext()) {
-                 if (! isSubset(ptr->getKey(),nptr->getKey())) break;
-                 mptr = nptr;
-             }
-             if (mptr) mptr->setNextNE(NULL);
-         }
-    }
-    return 0;
-}
-
-// initialize the SfxEntry links NextEQ and NextNE to speed searching
-// using the idea of leading subsets this time
-int AffixMgr::process_sfx_order()
-{
-    SfxEntry* ptr;
-
-    // loop through each prefix list starting point
-    for (int i=1; i < SETSIZE; i++) {
-
-         ptr = (SfxEntry *) sStart[i];
-
-         // look through the remainder of the list
-         //  and find next entry with affix that 
-         // the current one is not a subset of
-         // mark that as destination for NextNE
-         // use next in list that you are a subset
-         // of as NextEQ
-
-         for (; ptr != NULL; ptr = ptr->getNext()) {
-             SfxEntry * nptr = ptr->getNext();
-             for (; nptr != NULL; nptr = nptr->getNext()) {
-                 if (! isSubset(ptr->getKey(),nptr->getKey())) break;
-             }
-             ptr->setNextNE(nptr);
-             ptr->setNextEQ(NULL);
-             if ((ptr->getNext()) && isSubset(ptr->getKey(),(ptr->getNext())->getKey())) 
-                 ptr->setNextEQ(ptr->getNext());
-         }
-
-
-         // now clean up by adding smart search termination strings:
-         // if you are already a superset of the previous suffix
-         // but not a subset of the next, search can end here
-         // so set NextNE properly
-
-         ptr = (SfxEntry *) sStart[i];
-         for (; ptr != NULL; ptr = ptr->getNext()) {
-             SfxEntry * nptr = ptr->getNext();
-             SfxEntry * mptr = NULL;
-             for (; nptr != NULL; nptr = nptr->getNext()) {
-                 if (! isSubset(ptr->getKey(),nptr->getKey())) break;
-                 mptr = nptr;
-             }
-             if (mptr) mptr->setNextNE(NULL);
-         }
-    }
-    return 0;
-}
-
-
-
-// takes aff file condition string and creates the
-// conds array - please see the appendix at the end of the
-// file affentry.cpp which describes what is going on here
-// in much more detail
-
-int AffixMgr::encodeit(struct affentry * ptr, char * cs)
-{
-  unsigned char c;
-  int i, j, k;
-  unsigned char mbr[MAXLNLEN];
-  w_char wmbr[MAXLNLEN];
-  w_char * wpos = wmbr;
-
-  // now clear the conditions array */
-  for (i=0;i<SETSIZE;i++) ptr->conds.base[i] = (unsigned char) 0;
-
-  // now parse the string to create the conds array */
-  int nc = strlen(cs);
-  unsigned char neg = 0;   // complement indicator
-  int grp = 0;   // group indicator
-  unsigned char n = 0;     // number of conditions
-  int ec = 0;    // end condition indicator
-  int nm = 0;    // number of member in group
-
-  // if no condition just return
-  if (strcmp(cs,".")==0) {
-    ptr->numconds = 0;
-    return 0;
-  }
-
-  i = 0;
-  while (i < nc) {
-    c = *((unsigned char *)(cs + i));
-
-    // start group indicator
-    if (c == '[') {
-       grp = 1;
-       c = 0;
-    }
-
-    // complement flag
-    if ((grp == 1) && (c == '^')) {
-       neg = 1;
-       c = 0;
-    }
-
-    // end goup indicator
-    if (c == ']') {
-       ec = 1;
-       c = 0;
-    }
-
-    // add character of group to list
-    if ((grp == 1) && (c != 0)) {
-      *(mbr + nm) = c;
-      nm++;
-      c = 0;
-    }
-
-    // end of condition 
-    if (c != 0) {
-       ec = 1;
-    }
-
-  if (ec) {    
-    if (!utf8) {
-      if (grp == 1) {
-        if (neg == 0) {
-          // set the proper bits in the condition array vals for those chars
-          for (j=0;j<nm;j++) {
-             k = (unsigned int) mbr[j];
-             ptr->conds.base[k] = ptr->conds.base[k] | ((unsigned char)1 << n);
-          }
-        } else {
-          // complement so set all of them and then unset indicated ones
-           for (j=0;j<SETSIZE;j++) ptr->conds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n);
-           for (j=0;j<nm;j++) {
-             k = (unsigned int) mbr[j];
-             ptr->conds.base[k] = ptr->conds.base[k] & ~((unsigned char)1 << n);
-           }
-        }
-        neg = 0;
-        grp = 0;   
-        nm = 0;
-      } else {
-         // not a group so just set the proper bit for this char
-         // but first handle special case of . inside condition
-         if (c == '.') {
-            // wild card character so set them all
-            for (j=0;j<SETSIZE;j++) ptr->conds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n);
-         } else {  
-            ptr->conds.base[(unsigned int) c] = ptr->conds.base[(unsigned int)c] | ((unsigned char)1 << n);
-         }
-      }
-      n++;
-      ec = 0;
-    } else { // UTF-8 character set
-      if (grp == 1) {
-        ptr->conds.utf8.neg[n] = neg;
-        if (neg == 0) {
-          // set the proper bits in the condition array vals for those chars
-          for (j=0;j<nm;j++) {
-             k = (unsigned int) mbr[j];
-             if (k >> 7) {
-                u8_u16(wpos, 1, (char *) mbr + j);
-                wpos++;
-                if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character
-             } else {
-                ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] | ((unsigned char)1 << n);
-             }
-          }
-        } else { // neg == 1
-          // complement so set all of them and then unset indicated ones
-           for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n);
-           for (j=0;j<nm;j++) {
-             k = (unsigned int) mbr[j];
-             if (k >> 7) {
-                u8_u16(wpos, 1, (char *) mbr + j);
-                wpos++;
-                if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character
-             } else {
-                ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] & ~((unsigned char)1 << n);
-             }
-           }
-        }
-        neg = 0;
-        grp = 0;   
-        nm = 0;
-        ptr->conds.utf8.wlen[n] = wpos - wmbr;
-        if ((wpos - wmbr) != 0) {
-            ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char) * (wpos - wmbr));
-            if (!ptr->conds.utf8.wchars[n]) return 1;
-            memcpy(ptr->conds.utf8.wchars[n], wmbr, sizeof(w_char) * (wpos - wmbr));
-            flag_qsort((unsigned short *) ptr->conds.utf8.wchars[n], 0, ptr->conds.utf8.wlen[n]);
-            wpos = wmbr;
-        }
-      } else { // grp == 0
-         // is UTF-8 character?
-         if (c >> 7) {
-            ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char));
-            if (!ptr->conds.utf8.wchars[n]) return 1;
-            ptr->conds.utf8.wlen[n] = 1;
-            u8_u16(ptr->conds.utf8.wchars[n], 1, cs + i);
-            if ((c & 0xe0) == 0xe0) i+=2; else i++; // 3-byte UFT-8 character
-         } else {
-            ptr->conds.utf8.wchars[n] = NULL;
-            // not a group so just set the proper bit for this char
-            // but first handle special case of . inside condition
-            if (c == '.') {
-                ptr->conds.utf8.all[n] = 1;
-                // wild card character so set them all
-                for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n);
-            } else {
-                ptr->conds.utf8.all[n] = 0;
-                ptr->conds.utf8.ascii[(unsigned int) c] = ptr->conds.utf8.ascii[(unsigned int)c] | ((unsigned char)1 << n);
-            }
-         }
-         neg = 0;
-      }
-      n++;
-      ec = 0;
-      neg = 0;
-    }  
-  }
-
-    i++;
-  }
-  ptr->numconds = n;
-  return 0;
-}
-
- // return 1 if s1 is a leading subset of s2
-/* inline int AffixMgr::isSubset(const char * s1, const char * s2)
- {
-    while ((*s1 == *s2) && *s1) {
-        s1++;
-        s2++;
-    }
-    return (*s1 == '\0');
- }
-*/
-
- // return 1 if s1 is a leading subset of s2 (dots are for infixes)
-inline int AffixMgr::isSubset(const char * s1, const char * s2)
- {
-    while (((*s1 == *s2) || (*s1 == '.')) && (*s1 != '\0')) {
-        s1++;
-        s2++;
-    }
-    return (*s1 == '\0');
- }
-
-
-// check word for prefixes
-struct hentry * AffixMgr::prefix_check(const char * word, int len, char in_compound,
-    const FLAG needflag)
-{
-    struct hentry * rv= NULL;
-
-    pfx = NULL;
-    pfxappnd = NULL;
-    sfxappnd = NULL;
-    
-    // first handle the special case of 0 length prefixes
-    PfxEntry * pe = (PfxEntry *) pStart[0];
-    while (pe) {
-        if (
-            // fogemorpheme
-              ((in_compound != IN_CPD_NOT) || !(pe->getCont() &&
-                  (TESTAFF(pe->getCont(), onlyincompound, pe->getContLen())))) &&
-            // permit prefixes in compounds
-              ((in_compound != IN_CPD_END) || (pe->getCont() &&
-                  (TESTAFF(pe->getCont(), compoundpermitflag, pe->getContLen()))))
-              ) {
-                    // check prefix
-                    rv = pe->checkword(word, len, in_compound, needflag);
-                    if (rv) {
-                        pfx=(AffEntry *)pe; // BUG: pfx not stateless
-                        return rv;
-                    }
-             }
-       pe = pe->getNext();
-    }
-  
-    // now handle the general case
-    unsigned char sp = *((const unsigned char *)word);
-    PfxEntry * pptr = (PfxEntry *)pStart[sp];
-
-    while (pptr) {
-        if (isSubset(pptr->getKey(),word)) {
-             if (
-            // fogemorpheme
-              ((in_compound != IN_CPD_NOT) || !(pptr->getCont() &&
-                  (TESTAFF(pptr->getCont(), onlyincompound, pptr->getContLen())))) &&
-            // permit prefixes in compounds
-              ((in_compound != IN_CPD_END) || (pptr->getCont() &&
-                  (TESTAFF(pptr->getCont(), compoundpermitflag, pptr->getContLen()))))
-              ) {
-            // check prefix
-                  rv = pptr->checkword(word, len, in_compound, needflag);
-                  if (rv) {
-                    pfx=(AffEntry *)pptr; // BUG: pfx not stateless
-                    return rv;
-                  }
-             }
-             pptr = pptr->getNextEQ();
-        } else {
-             pptr = pptr->getNextNE();
-        }
-    }
-    
-    return NULL;
-}
-
-// check word for prefixes
-struct hentry * AffixMgr::prefix_check_twosfx(const char * word, int len,
-    char in_compound, const FLAG needflag)
-{
-    struct hentry * rv= NULL;
-
-    pfx = NULL;
-    sfxappnd = NULL;
-    
-    // first handle the special case of 0 length prefixes
-    PfxEntry * pe = (PfxEntry *) pStart[0];
-    
-    while (pe) {
-        rv = pe->check_twosfx(word, len, in_compound, needflag);
-        if (rv) return rv;
-        pe = pe->getNext();
-    }
-  
-    // now handle the general case
-    unsigned char sp = *((const unsigned char *)word);
-    PfxEntry * pptr = (PfxEntry *)pStart[sp];
-
-    while (pptr) {
-        if (isSubset(pptr->getKey(),word)) {
-            rv = pptr->check_twosfx(word, len, in_compound, needflag);
-            if (rv) {
-                pfx = (AffEntry *)pptr;
-                return rv;
-            }
-            pptr = pptr->getNextEQ();
-        } else {
-             pptr = pptr->getNextNE();
-        }
-    }
-    
-    return NULL;
-}
-
-#ifdef HUNSPELL_EXPERIMENTAL
-// check word for prefixes
-char * AffixMgr::prefix_check_morph(const char * word, int len, char in_compound,
-    const FLAG needflag)
-{
-    char * st;
-
-    char result[MAXLNLEN];
-    result[0] = '\0';
-
-    pfx = NULL;
-    sfxappnd = NULL;
-    
-    // first handle the special case of 0 length prefixes
-    PfxEntry * pe = (PfxEntry *) pStart[0];
-    while (pe) {
-       st = pe->check_morph(word,len,in_compound, needflag);
-       if (st) {
-            strcat(result, st);
-            free(st);
-       }
-       // if (rv) return rv;
-       pe = pe->getNext();
-    }
-  
-    // now handle the general case
-    unsigned char sp = *((const unsigned char *)word);
-    PfxEntry * pptr = (PfxEntry *)pStart[sp];
-
-    while (pptr) {
-        if (isSubset(pptr->getKey(),word)) {
-            st = pptr->check_morph(word,len,in_compound, needflag);
-            if (st) {
-              // fogemorpheme
-              if ((in_compound != IN_CPD_NOT) || !((pptr->getCont() && 
-                        (TESTAFF(pptr->getCont(), onlyincompound, pptr->getContLen()))))) {
-                    strcat(result, st);
-                    pfx = (AffEntry *)pptr;
-                }
-                free(st);
-            }
-            pptr = pptr->getNextEQ();
-        } else {
-            pptr = pptr->getNextNE();
-        }
-    }
-    
-    if (*result) return mystrdup(result);
-    return NULL;
-}
-
-
-// check word for prefixes
-char * AffixMgr::prefix_check_twosfx_morph(const char * word, int len,
-    char in_compound, const FLAG needflag)
-{
-    char * st;
-
-    char result[MAXLNLEN];
-    result[0] = '\0';
-
-    pfx = NULL;
-    sfxappnd = NULL;
-    
-    // first handle the special case of 0 length prefixes
-    PfxEntry * pe = (PfxEntry *) pStart[0];
-    while (pe) {
-        st = pe->check_twosfx_morph(word,len,in_compound, needflag);
-        if (st) {
-            strcat(result, st);
-            free(st);
-        }
-        pe = pe->getNext();
-    }
-  
-    // now handle the general case
-    unsigned char sp = *((const unsigned char *)word);
-    PfxEntry * pptr = (PfxEntry *)pStart[sp];
-
-    while (pptr) {
-        if (isSubset(pptr->getKey(),word)) {
-            st = pptr->check_twosfx_morph(word, len, in_compound, needflag);
-            if (st) {
-                strcat(result, st);
-                free(st);
-                pfx = (AffEntry *)pptr;
-            }
-            pptr = pptr->getNextEQ();
-        } else {
-            pptr = pptr->getNextNE();
-        }
-    }
-    
-    if (*result) return mystrdup(result);
-    return NULL;
-}
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
-
-// Is word a non compound with a REP substitution (see checkcompoundrep)?
-int AffixMgr::cpdrep_check(const char * word, int wl)
-{
-  char candidate[MAXLNLEN];
-  const char * r;
-  int lenr, lenp;
-
-  if ((wl < 2) || !numrep) return 0;
-
-  for (int i=0; i < numrep; i++ ) {
-      r = word;
-      lenr = strlen(reptable[i].pattern2);
-      lenp = strlen(reptable[i].pattern);
-      // search every occurence of the pattern in the word
-      while ((r=strstr(r, reptable[i].pattern)) != NULL) {
-          strcpy(candidate, word);
-          if (r-word + lenr + strlen(r+lenp) >= MAXLNLEN) break;
-          strcpy(candidate+(r-word),reptable[i].pattern2);
-          strcpy(candidate+(r-word)+lenr, r+lenp);
-          if (candidate_check(candidate,strlen(candidate))) return 1;
-          r++; // search for the next letter
-      }
-   }
-   return 0;
-}
-
-// forbid compoundings when there are special patterns at word bound
-int AffixMgr::cpdpat_check(const char * word, int pos)
-{
-  int len;
-  for (int i = 0; i < numcheckcpd; i++) {
-      if (isSubset(checkcpdtable[i].pattern2, word + pos) &&
-        (len = strlen(checkcpdtable[i].pattern)) && (pos > len) &&
-        (strncmp(word + pos - len, checkcpdtable[i].pattern, len) == 0)) return 1;
-  }
-  return 0;
-}
-
-// forbid compounding with neighbouring upper and lower case characters at word bounds
-int AffixMgr::cpdcase_check(const char * word, int pos)
-{
-  if (utf8) {
-      w_char u, w;
-      const char * p;
-      u8_u16(&u, 1, word + pos);
-      for (p = word + pos - 1; (*p & 0xc0) == 0x80; p--);
-      u8_u16(&w, 1, p);
-      unsigned short a = (u.h << 8) + u.l;
-      unsigned short b = (w.h << 8) + w.l;
-      if (((unicodetoupper(a, langnum) == a) || (unicodetoupper(b, langnum) == b))) return 1;
-  } else {
-      unsigned char a = *(word + pos - 1);
-      unsigned char b = *(word + pos);
-      if ((csconv[a].ccase || csconv[b].ccase) && (a != '-') && (b != '-')) return 1;
-  }
-  return 0;
-}
-
-// check compound patterns
-int AffixMgr::defcpd_check(hentry *** words, short wnum, hentry * rv, hentry ** def, char all)
-{
-  signed short btpp[MAXWORDLEN]; // metacharacter (*, ?) positions for backtracking
-  signed short btwp[MAXWORDLEN]; // word positions for metacharacters
-  int btnum[MAXWORDLEN]; // number of matched characters in metacharacter positions
-  short bt = 0;  
-  int i;
-  int ok;
-  int w = 0;
-  if (!*words) {
-    w = 1;
-    *words = def;
-  }
-  (*words)[wnum] = rv;
-
-  for (i = 0; i < numdefcpd; i++) {
-    signed short pp = 0; // pattern position
-    signed short wp = 0; // "words" position
-    int ok2;
-    ok = 1;
-    ok2 = 1;
-    do {
-      while ((pp < defcpdtable[i].len) && (wp <= wnum)) {
-        if (((pp+1) < defcpdtable[i].len) &&
-          ((defcpdtable[i].def[pp+1] == '*') || (defcpdtable[i].def[pp+1] == '?'))) {
-            int wend = (defcpdtable[i].def[pp+1] == '?') ? wp : wnum;
-            ok2 = 1;
-            pp+=2;
-            btpp[bt] = pp;
-            btwp[bt] = wp;
-            while (wp <= wend) {
-                if (!(*words)[wp]->alen || 
-                  !TESTAFF((*words)[wp]->astr, defcpdtable[i].def[pp-2], (*words)[wp]->alen)) {
-                    ok2 = 0;
-                    break;
-                }
-                wp++;
-            }
-            if (wp <= wnum) ok2 = 0;
-            btnum[bt] = wp - btwp[bt];
-            if (btnum[bt] > 0) bt++;
-            if (ok2) break;
-        } else {
-            ok2 = 1;
-            if (!(*words)[wp] || !(*words)[wp]->alen || 
-              !TESTAFF((*words)[wp]->astr, defcpdtable[i].def[pp], (*words)[wp]->alen)) {
-                ok = 0;
-                break;
-            }
-            pp++;
-            wp++;
-            if ((defcpdtable[i].len == pp) && !(wp > wnum)) ok = 0;
-        }
-      }
-    if (ok && ok2) { 
-        int r = pp;
-        while ((defcpdtable[i].len > r) && ((r+1) < defcpdtable[i].len) &&
-            ((defcpdtable[i].def[r+1] == '*') || (defcpdtable[i].def[r+1] == '?'))) r+=2;
-        if (defcpdtable[i].len <= r) return 1;
-    }    
-    // backtrack
-    if (bt) do {
-        ok = 1;
-        btnum[bt - 1]--;
-        pp = btpp[bt - 1];
-        wp = btwp[bt - 1] + btnum[bt - 1];
-    } while ((btnum[bt - 1] < 0) && --bt);
-  } while (bt);
-
-  if (ok && ok2 && (!all || (defcpdtable[i].len <= pp))) return 1; 
-  // check zero ending
-  while (ok && ok2 && (defcpdtable[i].len > pp) && ((pp+1) < defcpdtable[i].len) &&
-    ((defcpdtable[i].def[pp+1] == '*') || (defcpdtable[i].def[pp+1] == '?'))) pp+=2;
-  if (ok && ok2 && (defcpdtable[i].len <= pp)) return 1;
-  }
-  (*words)[wnum] = NULL;
-  if (w) *words = NULL;
-  return 0;
-}
-
-inline int AffixMgr::candidate_check(const char * word, int len)
-{
-  struct hentry * rv=NULL;
-  
-  rv = lookup(word);
-  if (rv) return 1;
-
-//  rv = prefix_check(word,len,1);
-//  if (rv) return 1;
-  
-  rv = affix_check(word,len);
-  if (rv) return 1;
-  return 0;
-}
-
-// calculate number of syllable for compound-checking
-short AffixMgr::get_syllable(const char * word, int wlen)
-{
-    if (cpdmaxsyllable==0) return 0;
-    
-    short num=0;
-
-    if (!utf8) {
-        for (int i=0; i<wlen; i++) {
-            if (strchr(cpdvowels, word[i])) num++;
-        }
-    } else if (cpdvowels_utf16) {
-        w_char w[MAXWORDUTF8LEN];
-        int i = u8_u16(w, MAXWORDUTF8LEN, word);
-        for (; i > 0; i--) {
-            if (flag_bsearch((unsigned short *) cpdvowels_utf16,
-                ((unsigned short *) w)[i - 1], cpdvowels_utf16_len)) num++;
-        }
-    }
-    return num;
-}
-
-// check if compound word is correctly spelled
-// hu_mov_rule = spec. Hungarian rule (XXX)
-struct hentry * AffixMgr::compound_check(const char * word, int len, 
-    short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words = NULL,
-    char hu_mov_rule = 0, int * cmpdstemnum = NULL, int * cmpdstem = NULL, char is_sug = 0)
-{
-    int i; 
-    short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
-    int oldcmpdstemnum = 0;
-    struct hentry * rv = NULL;
-    struct hentry * rv_first;
-    struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking
-    char st [MAXWORDUTF8LEN + 4];
-    char ch;
-    int cmin;
-    int cmax;
-    
-    int checked_prefix;
-
-#ifdef HUNSTEM
-    if (cmpdstemnum) {
-        if (wordnum == 0) {
-            *cmpdstemnum = 1;
-        } else {
-            (*cmpdstemnum)++;
-        }
-    }
-#endif
-    if (utf8) {
-        for (cmin = 0, i = 0; (i < cpdmin) && word[cmin]; i++) {
-          cmin++;
-          for (; (word[cmin] & 0xc0) == 0x80; cmin++);
-        }
-        for (cmax = len, i = 0; (i < (cpdmin - 1)) && cmax; i++) {
-          cmax--;
-          for (; (word[cmax] & 0xc0) == 0x80; cmax--);
-        }
-    } else {
-        cmin = cpdmin;
-        cmax = len - cpdmin + 1;
-    }
-
-    strcpy(st, word);
-
-    for (i = cmin; i < cmax; i++) {
-
-        oldnumsyllable = numsyllable;
-        oldwordnum = wordnum;
-        checked_prefix = 0;
-
-        // go to end of the UTF-8 character
-        if (utf8) {
-            for (; (st[i] & 0xc0) == 0x80; i++);
-            if (i >= cmax) return NULL;
-        }
-
-        
-        ch = st[i];
-        st[i] = '\0';
-
-        sfx = NULL;
-        pfx = NULL;
-        
-        // FIRST WORD
-        
-        rv = lookup(st); // perhaps without prefix
-
-        // search homonym with compound flag
-        while ((rv) && !hu_mov_rule &&
-            ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
-                !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-                  (compoundbegin && !wordnum &&
-                        TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
-                  (compoundmiddle && wordnum && !words &&
-                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
-                  (numdefcpd &&
-                    ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) ||
-                    (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))))
-                  ))) {
-            rv = rv->next_homonym;
-        }
-
-        if (!rv) {
-            if (compoundflag && 
-             !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) {
-                if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL,
-                        FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule &&
-                    ((SfxEntry*)sfx)->getCont() &&
-                        ((compoundforbidflag && TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
-                            ((SfxEntry*)sfx)->getContLen())) || (compoundend &&
-                        TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, 
-                            ((SfxEntry*)sfx)->getContLen())))) {
-                        rv = NULL;
-                }
-            }
-            if (rv ||
-              (((wordnum == 0) && compoundbegin &&
-                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
-                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundbegin)))) ||
-              ((wordnum > 0) && compoundmiddle &&
-                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
-                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle)))))
-              ) checked_prefix = 1;
-        // else check forbiddenwords and pseudoroot
-        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
-            TESTAFF(rv->astr, pseudoroot, rv->alen) || 
-            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen))
-             )) {
-                st[i] = ch;
-                continue;
-        }
-
-            // check non_compound flag in suffix and prefix
-            if ((rv) && !hu_mov_rule &&
-                ((pfx && ((PfxEntry*)pfx)->getCont() &&
-                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, 
-                        ((PfxEntry*)pfx)->getContLen())) ||
-                (sfx && ((SfxEntry*)sfx)->getCont() &&
-                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
-                        ((SfxEntry*)sfx)->getContLen())))) {
-                    rv = NULL;
-            }
-
-            // check compoundend flag in suffix and prefix
-            if ((rv) && !checked_prefix && compoundend && !hu_mov_rule &&
-                ((pfx && ((PfxEntry*)pfx)->getCont() &&
-                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundend, 
-                        ((PfxEntry*)pfx)->getContLen())) ||
-                (sfx && ((SfxEntry*)sfx)->getCont() &&
-                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, 
-                        ((SfxEntry*)sfx)->getContLen())))) {
-                    rv = NULL;
-            }
-            
-            // check compoundmiddle flag in suffix and prefix
-            if ((rv) && !checked_prefix && (wordnum==0) && compoundmiddle && !hu_mov_rule &&
-                ((pfx && ((PfxEntry*)pfx)->getCont() &&
-                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundmiddle, 
-                        ((PfxEntry*)pfx)->getContLen())) ||
-                (sfx && ((SfxEntry*)sfx)->getCont() &&
-                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundmiddle, 
-                        ((SfxEntry*)sfx)->getContLen())))) {
-                    rv = NULL;
-            }       
-
-        // check forbiddenwords
-        if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
-            (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) {
-                return NULL;
-            }
-
-        // increment word number, if the second root has a compoundroot flag
-        if ((rv) && compoundroot && 
-            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
-                wordnum++;
-        }
-
-        // first word is acceptable in compound words?
-        if (((rv) && 
-          ( checked_prefix || (words && words[wnum]) ||
-            (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-            ((oldwordnum == 0) && compoundbegin && TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
-            ((oldwordnum > 0) && compoundmiddle && TESTAFF(rv->astr, compoundmiddle, rv->alen))// ||
-//            (numdefcpd && )
-
-// LANG_hu section: spec. Hungarian rule
-            || ((langnum == LANG_hu) && hu_mov_rule && (
-                    TESTAFF(rv->astr, 'F', rv->alen) || // XXX hardwired Hungarian dictionary codes
-                    TESTAFF(rv->astr, 'G', rv->alen) ||
-                    TESTAFF(rv->astr, 'H', rv->alen)
-                )
-              )
-// END of LANG_hu section
-          )
-          && ! (( checkcompoundtriple && // test triple letters
-                   (word[i-1]==word[i]) && (
-                      ((i>1) && (word[i-1]==word[i-2])) || 
-                      ((word[i-1]==word[i+1])) // may be word[i+1] == '\0'
-                   )
-               ) ||
-               ( 
-                 // test CHECKCOMPOUNDPATTERN
-                 numcheckcpd && cpdpat_check(word, i)
-               ) ||
-               ( 
-                 checkcompoundcase && cpdcase_check(word, i)
-               ))
-         )
-// LANG_hu section: spec. Hungarian rule
-         || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) &&
-              (sfx && ((SfxEntry*)sfx)->getCont() && ( // XXX hardwired Hungarian dic. codes
-                        TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) 'x', ((SfxEntry*)sfx)->getContLen()) ||
-                        TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) '%', ((SfxEntry*)sfx)->getContLen())
-                    )                
-               )
-             )
-// END of LANG_hu section
-         ) {
-
-// LANG_hu section: spec. Hungarian rule
-            if (langnum == LANG_hu) {
-                // calculate syllable number of the word            
-                numsyllable += get_syllable(st, i);
-
-                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
-                if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++;
-            }
-// END of LANG_hu section
-
-#ifdef HUNSTEM
-            if (cmpdstem) cmpdstem[*cmpdstemnum - 1] = i;
-#endif
-
-            // NEXT WORD(S)
-            rv_first = rv;
-            rv = lookup((word+i)); // perhaps without prefix
-
-        // search homonym with compound flag
-        while ((rv) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
-                        !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-                          (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) ||
-                           (numdefcpd && words && defcpd_check(&words, wnum + 1, rv, NULL,1))))) {
-            rv = rv->next_homonym;
-        }
-
-            if (rv && words && words[wnum + 1]) return rv;
-
-            oldnumsyllable2 = numsyllable;
-            oldwordnum2 = wordnum;
-
-// LANG_hu section: spec. Hungarian rule, XXX hardwired dictionary code
-            if ((rv) && (langnum == LANG_hu) && (TESTAFF(rv->astr, 'I', rv->alen)) && !(TESTAFF(rv->astr, 'J', rv->alen))) {
-                numsyllable--;
-            }
-// END of LANG_hu section
-
-            // increment word number, if the second root has a compoundroot flag
-            if ((rv) && (compoundroot) && 
-                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
-                    wordnum++;
-            }
-
-            // check forbiddenwords
-            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
-               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
-
-            // second word is acceptable, as a root?
-            // hungarian conventions: compounding is acceptable,
-            // when compound forms consist of 2 words, or if more,
-            // then the syllable number of root words must be 6, or lesser.
-
-            if ((rv) && (
-                      (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-                      (compoundend && TESTAFF(rv->astr, compoundend, rv->alen))
-                    )
-                && (
-                      ((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || 
-                      ((cpdmaxsyllable==0) || 
-                          (numsyllable + get_syllable(&(rv->word), rv->clen)<=cpdmaxsyllable))
-                    )
-                && (
-                     (!checkcompounddup || (rv != rv_first))
-                   )
-                )
-                 {
-                      // forbid compound word, if it is a non compound word with typical fault
-                      if (checkcompoundrep && cpdrep_check(word,len)) return NULL;
-                      return rv;
-            }
-
-            numsyllable = oldnumsyllable2 ;
-            wordnum = oldwordnum2;
-
-            // perhaps second word has prefix or/and suffix
-            sfx = NULL;
-            sfxflag = FLAG_NULL;
-            rv = (compoundflag) ? affix_check((word+i),strlen(word+i), compoundflag, IN_CPD_END) : NULL;
-            if (!rv && compoundend) {
-                sfx = NULL;
-                pfx = NULL;
-                rv = affix_check((word+i),strlen(word+i), compoundend, IN_CPD_END);
-            }
-            
-            if (!rv && numdefcpd && words) {
-                rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END);
-                if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1)) return rv;
-                rv = NULL;
-            }
-
-            // check non_compound flag in suffix and prefix
-            if ((rv) && 
-                ((pfx && ((PfxEntry*)pfx)->getCont() &&
-                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, 
-                        ((PfxEntry*)pfx)->getContLen())) ||
-                (sfx && ((SfxEntry*)sfx)->getCont() &&
-                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
-                        ((SfxEntry*)sfx)->getContLen())))) {
-                    rv = NULL;
-            }
-
-            // check forbiddenwords
-            if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
-               (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL;
-
-            // pfxappnd = prefix of word+i, or NULL
-            // calculate syllable number of prefix.
-            // hungarian convention: when syllable number of prefix is more,
-            // than 1, the prefix+word counts as two words.
-
-            if (langnum == LANG_hu) {
-                // calculate syllable number of the word
-                numsyllable += get_syllable(word + i, strlen(word + i));
-                
-                // - affix syllable num.
-                // XXX only second suffix (inflections, not derivations)
-                if (sfxappnd) {
-                    char * tmp = myrevstrdup(sfxappnd);
-                    numsyllable -= get_syllable(tmp, strlen(tmp));
-                    free(tmp);
-                }
-                
-                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
-                if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++;
-
-                // increment syllable num, if last word has a SYLLABLENUM flag
-                // and the suffix is beginning `s'
-            
-                if (cpdsyllablenum) {
-                    switch (sfxflag) {
-                        case 'c': { numsyllable+=2; break; }
-                        case 'J': { numsyllable += 1; break; }
-                        case 'I': { if (TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; }
-                    }
-                }
-            }
-            
-            // increment word number, if the second word has a compoundroot flag
-            if ((rv) && (compoundroot) && 
-                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
-                    wordnum++;
-            }
-
-            // second word is acceptable, as a word with prefix or/and suffix?
-            // hungarian conventions: compounding is acceptable,
-            // when compound forms consist 2 word, otherwise
-            // the syllable number of root words is 6, or lesser.
-            if ((rv) && 
-                    (
-                      ((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) || 
-                      ((cpdmaxsyllable == 0) || 
-                          (numsyllable <= cpdmaxsyllable))
-                    )
-                && (
-                   (!checkcompounddup || (rv != rv_first))
-                   )) {
-                    // forbid compound word, if it is a non compound word with typical fault
-                    if (checkcompoundrep && cpdrep_check(word, len)) return NULL;
-                    return rv;
-            }
-
-            numsyllable = oldnumsyllable2;
-            wordnum = oldwordnum2;
-#ifdef HUNSTEM
-            if (cmpdstemnum) oldcmpdstemnum = *cmpdstemnum;
-#endif
-            // perhaps second word is a compound word (recursive call)
-            if (wordnum < maxwordnum) {
-                rv = compound_check((word+i),strlen(word+i), wordnum+1,
-                     numsyllable, maxwordnum, wnum + 1, words,
-                     0, cmpdstemnum, cmpdstem, is_sug);
-            } else {
-                rv=NULL;
-            }
-            if (rv) {
-                // forbid compound word, if it is a non compound word with typical fault
-                if (checkcompoundrep && cpdrep_check(word, len)) return NULL;
-                return rv;
-            } else {
-#ifdef HUNSTEM
-            if (cmpdstemnum) *cmpdstemnum = oldcmpdstemnum;
-#endif
-            }
-        }
-        st[i] = ch;
-        wordnum = oldwordnum;
-        numsyllable = oldnumsyllable;
-    }
-    
-    return NULL;
-}    
-
-#ifdef HUNSPELL_EXPERIMENTAL
-// check if compound word is correctly spelled
-// hu_mov_rule = spec. Hungarian rule (XXX)
-int AffixMgr::compound_check_morph(const char * word, int len, 
-    short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words,
-    char hu_mov_rule = 0, char ** result = NULL, char * partresult = NULL)
-{
-    int i;
-    short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
-    int ok = 0;
-
-    struct hentry * rv = NULL;
-    struct hentry * rv_first;
-    struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking
-    char st [MAXWORDUTF8LEN + 4];
-    char ch;
-    
-    int checked_prefix;
-    char presult[MAXLNLEN];
-
-    int cmin;
-    int cmax;
-    
-    if (utf8) {
-        for (cmin = 0, i = 0; (i < cpdmin) && word[cmin]; i++) {
-          cmin++;
-          for (; (word[cmin] & 0xc0) == 0x80; cmin++);
-        }
-        for (cmax = len, i = 0; (i < (cpdmin - 1)) && cmax; i++) {
-          cmax--;
-          for (; (word[cmax] & 0xc0) == 0x80; cmax--);
-        }
-    } else {
-        cmin = cpdmin;
-        cmax = len - cpdmin + 1;
-    }
-
-    strcpy(st, word);
-
-    for (i = cmin; i < cmax; i++) {
-        oldnumsyllable = numsyllable;
-        oldwordnum = wordnum;
-        checked_prefix = 0;
-
-        // go to end of the UTF-8 character
-        if (utf8) {
-            for (; (st[i] & 0xc0) == 0x80; i++);
-            if (i >= cmax) return 0;
-        }
-        
-        ch = st[i];
-        st[i] = '\0';
-        sfx = NULL;
-
-        // FIRST WORD
-        *presult = '\0';
-        if (partresult) strcat(presult, partresult);
-        
-        rv = lookup(st); // perhaps without prefix
-
-        // search homonym with compound flag
-        while ((rv) && !hu_mov_rule && 
-            ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
-                !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-                (compoundbegin && !wordnum &&
-                        TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
-                (compoundmiddle && wordnum && !words &&
-                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
-                  (numdefcpd &&
-                    ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) ||
-                    (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))))
-                  ))) {
-            rv = rv->next_homonym;
-        }
-
-        if (rv)  {
-            if (rv->description) {
-                if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen))
-                                        strcat(presult, st);
-                strcat(presult, rv->description);
-            }
-        }
-        
-        if (!rv) {
-            if (compoundflag && 
-             !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) {
-                if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL,
-                        FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule &&
-                    ((SfxEntry*)sfx)->getCont() &&
-                        ((compoundforbidflag && TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
-                            ((SfxEntry*)sfx)->getContLen())) || (compoundend &&
-                        TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, 
-                            ((SfxEntry*)sfx)->getContLen())))) {
-                        rv = NULL;
-                }
-            }
-            
-            if (rv ||
-              (((wordnum == 0) && compoundbegin &&
-                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
-                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundbegin)))) ||
-              ((wordnum > 0) && compoundmiddle &&
-                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
-                (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle)))))
-              ) {
-                //char * p = prefix_check_morph(st, i, 0, compound);
-                char * p = NULL;
-                if (compoundflag) p = affix_check_morph(st, i, compoundflag);
-                if (!p || (*p == '\0')) {
-                   if ((wordnum == 0) && compoundbegin) {
-                     p = affix_check_morph(st, i, compoundbegin);
-                   } else if ((wordnum > 0) && compoundmiddle) {
-                     p = affix_check_morph(st, i, compoundmiddle);                   
-                   }
-                }
-                if (*p != '\0') {
-                    line_uniq(p);
-                    if (strchr(p, '\n')) {
-                        strcat(presult, "(");
-                        strcat(presult, line_join(p, '|'));
-                        strcat(presult, ")");
-                      } else {
-                        strcat(presult, p);
-                      }
-                }
-                if (presult[strlen(presult) - 1] == '\n') {
-                    presult[strlen(presult) - 1] = '\0';
-                }
-                checked_prefix = 1;
-                //strcat(presult, "+");
-            }
-        // else check forbiddenwords
-        } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
-            TESTAFF(rv->astr, pseudoroot, rv->alen))) {
-                st[i] = ch;
-                continue;
-        }
-
-            // check non_compound flag in suffix and prefix
-            if ((rv) && !hu_mov_rule &&
-                ((pfx && ((PfxEntry*)pfx)->getCont() &&
-                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, 
-                        ((PfxEntry*)pfx)->getContLen())) ||
-                (sfx && ((SfxEntry*)sfx)->getCont() &&
-                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
-                        ((SfxEntry*)sfx)->getContLen())))) {
-                    continue;
-            }
-
-            // check compoundend flag in suffix and prefix
-            if ((rv) && !checked_prefix && compoundend && !hu_mov_rule &&
-                ((pfx && ((PfxEntry*)pfx)->getCont() &&
-                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundend, 
-                        ((PfxEntry*)pfx)->getContLen())) ||
-                (sfx && ((SfxEntry*)sfx)->getCont() &&
-                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, 
-                        ((SfxEntry*)sfx)->getContLen())))) {
-                    continue;
-            }
-
-            // check compoundmiddle flag in suffix and prefix
-            if ((rv) && !checked_prefix && (wordnum==0) && compoundmiddle && !hu_mov_rule &&
-                ((pfx && ((PfxEntry*)pfx)->getCont() &&
-                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundmiddle, 
-                        ((PfxEntry*)pfx)->getContLen())) ||
-                (sfx && ((SfxEntry*)sfx)->getCont() &&
-                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundmiddle, 
-                        ((SfxEntry*)sfx)->getContLen())))) {
-                    rv = NULL;
-            }       
-
-        // check forbiddenwords
-        if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) continue;
-
-        // increment word number, if the second root has a compoundroot flag
-        if ((rv) && (compoundroot) && 
-            (TESTAFF(rv->astr, compoundroot, rv->alen))) {
-                wordnum++;
-        }
-
-        // first word is acceptable in compound words?
-        if (((rv) && 
-          ( checked_prefix || (words && words[wnum]) ||
-            (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-            ((oldwordnum == 0) && compoundbegin && TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
-            ((oldwordnum > 0) && compoundmiddle && TESTAFF(rv->astr, compoundmiddle, rv->alen)) 
-// LANG_hu section: spec. Hungarian rule
-            || ((langnum == LANG_hu) && // hu_mov_rule
-                hu_mov_rule && (
-                    TESTAFF(rv->astr, 'F', rv->alen) ||
-                    TESTAFF(rv->astr, 'G', rv->alen) ||
-                    TESTAFF(rv->astr, 'H', rv->alen)
-                )
-              )
-// END of LANG_hu section
-          )
-          && ! (( checkcompoundtriple && // test triple letters
-                   (word[i-1]==word[i]) && (
-                      ((i>1) && (word[i-1]==word[i-2])) || 
-                      ((word[i-1]==word[i+1])) // may be word[i+1] == '\0'
-                   )
-               ) ||
-               (
-                   // test CHECKCOMPOUNDPATTERN
-                   numcheckcpd && cpdpat_check(word, i)
-               ) ||
-               ( 
-                 checkcompoundcase && cpdcase_check(word, i)
-               ))
-         )
-// LANG_hu section: spec. Hungarian rule
-         || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) &&
-              (sfx && ((SfxEntry*)sfx)->getCont() && (
-                        TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) 'x', ((SfxEntry*)sfx)->getContLen()) ||
-                        TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) '%', ((SfxEntry*)sfx)->getContLen())
-                    )                
-               )
-             )
-// END of LANG_hu section
-         ) {
-
-// LANG_hu section: spec. Hungarian rule
-            if (langnum == LANG_hu) {
-                // calculate syllable number of the word
-                numsyllable += get_syllable(st, i);
-
-                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
-                if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++;
-            }
-// END of LANG_hu section
-
-            // NEXT WORD(S)
-            rv_first = rv;
-            rv = lookup((word+i)); // perhaps without prefix
-
-        // search homonym with compound flag
-        while ((rv) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
-                        !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-                          (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) ||
-                           (numdefcpd && defcpd_check(&words, wnum + 1, rv, NULL,1))))) {
-            rv = rv->next_homonym;
-        }
-
-            if (rv && words && words[wnum + 1]) {
-                  strcat(*result, presult);
-                  if (complexprefixes && rv->description) strcat(*result, rv->description);
-                  if (rv->description && ((!rv->astr) || 
-                     !TESTAFF(rv->astr, lemma_present, rv->alen)))
-                        strcat(*result, &(rv->word));
-                  if (!complexprefixes && rv->description) strcat(*result, rv->description);
-                  strcat(*result, "\n");
-                  ok = 1;
-                  return 0;
-            }
-
-            oldnumsyllable2 = numsyllable;
-            oldwordnum2 = wordnum;
-
-// LANG_hu section: spec. Hungarian rule
-            if ((rv) && (langnum == LANG_hu) && (TESTAFF(rv->astr, 'I', rv->alen)) && !(TESTAFF(rv->astr, 'J', rv->alen))) {
-                numsyllable--;
-            }
-// END of LANG_hu section
-            // increment word number, if the second root has a compoundroot flag
-            if ((rv) && (compoundroot) && 
-                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
-                    wordnum++;
-            }
-
-            // check forbiddenwords
-            if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) {
-                st[i] = ch;
-                continue;
-            }
-                    
-            // second word is acceptable, as a root?
-            // hungarian conventions: compounding is acceptable,
-            // when compound forms consist of 2 words, or if more,
-            // then the syllable number of root words must be 6, or lesser.
-            if ((rv) && (
-                      (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-                      (compoundend && TESTAFF(rv->astr, compoundend, rv->alen))
-                    )
-                && (
-                      ((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || 
-                      ((cpdmaxsyllable==0) || 
-                          (numsyllable+get_syllable(&(rv->word),rv->wlen)<=cpdmaxsyllable))
-                    )
-                && (
-                     (!checkcompounddup || (rv != rv_first))
-                   )
-                )
-                 {
-                      // bad compound word
-                      strcat(*result, presult);
-                                          
-                      if (rv->description) {
-                        if (complexprefixes) strcat(*result, rv->description);
-                        if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen))
-                                               strcat(*result, &(rv->word));
-                        if (!complexprefixes) strcat(*result, rv->description);
-                      }
-                      strcat(*result, "\n");
-                              ok = 1;
-            }
-
-            numsyllable = oldnumsyllable2 ;
-            wordnum = oldwordnum2;
-
-            // perhaps second word has prefix or/and suffix
-            sfx = NULL;
-            sfxflag = FLAG_NULL;
-
-            if (compoundflag) rv = affix_check((word+i),strlen(word+i), compoundflag); else rv = NULL;
-
-            if (!rv && compoundend) {
-                sfx = NULL;
-                pfx = NULL;
-                rv = affix_check((word+i),strlen(word+i), compoundend);
-            }
-
-            if (!rv && numdefcpd && words) {
-                rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END);
-                if (rv && words && defcpd_check(&words, wnum + 1, rv, NULL, 1)) {
-                      char * m = NULL;
-                      if (compoundflag) m = affix_check_morph((word+i),strlen(word+i), compoundflag);
-                      if ((!m || *m == '\0') && compoundend)
-                            m = affix_check_morph((word+i),strlen(word+i), compoundend);
-                      strcat(*result, presult);
-                      if (m) {
-                        line_uniq(m);
-                        if (strchr(m, '\n')) {
-                            strcat(*result, "(");
-                            strcat(*result, line_join(m, '|'));
-                            strcat(*result, ")");
-                        } else {
-                            strcat(*result, m);
-                        }
-                        free(m);
-                      }
-                      strcat(*result, "\n");
-                      ok = 1;
-                }
-            }
-
-            // check non_compound flag in suffix and prefix
-            if ((rv) && 
-                ((pfx && ((PfxEntry*)pfx)->getCont() &&
-                    TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, 
-                        ((PfxEntry*)pfx)->getContLen())) ||
-                (sfx && ((SfxEntry*)sfx)->getCont() &&
-                    TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
-                        ((SfxEntry*)sfx)->getContLen())))) {
-                    rv = NULL;
-            }
-
-            // check forbiddenwords
-            if ((rv) && (rv->astr) && (TESTAFF(rv->astr,forbiddenword,rv->alen))
-                    && (! TESTAFF(rv->astr, pseudoroot, rv->alen))) {
-                        st[i] = ch;
-                        continue;
-                    }
-
-            if (langnum == LANG_hu) {
-                // calculate syllable number of the word
-                numsyllable += get_syllable(word + i, strlen(word + i));
-
-                // - affix syllable num.
-                // XXX only second suffix (inflections, not derivations)
-                if (sfxappnd) {
-                    char * tmp = myrevstrdup(sfxappnd);
-                    numsyllable -= get_syllable(tmp, strlen(tmp));
-                    free(tmp);
-                }
-
-                // + 1 word, if syllable number of the prefix > 1 (hungarian convention)
-                if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++;
-
-                // increment syllable num, if last word has a SYLLABLENUM flag
-                // and the suffix is beginning `s'
-
-                if (cpdsyllablenum) {
-                    switch (sfxflag) {
-                        case 'c': { numsyllable+=2; break; }
-                        case 'J': { numsyllable += 1; break; }
-                        case 'I': { if (rv && TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; }
-                    }
-                }
-            }
-
-            // increment word number, if the second word has a compoundroot flag
-            if ((rv) && (compoundroot) && 
-                (TESTAFF(rv->astr, compoundroot, rv->alen))) {
-                    wordnum++;
-            }
-            // second word is acceptable, as a word with prefix or/and suffix?
-            // hungarian conventions: compounding is acceptable,
-            // when compound forms consist 2 word, otherwise
-            // the syllable number of root words is 6, or lesser.
-            if ((rv) && 
-                    (
-                      ((cpdwordmax==-1) || (wordnum+1<cpdwordmax)) || 
-                      ((cpdmaxsyllable==0) || 
-                          (numsyllable <= cpdmaxsyllable))
-                    )
-                && (
-                   (!checkcompounddup || (rv != rv_first))
-                   )) {
-                      char * m = NULL;
-                      if (compoundflag) m = affix_check_morph((word+i),strlen(word+i), compoundflag);
-                      if ((!m || *m == '\0') && compoundend)
-                            m = affix_check_morph((word+i),strlen(word+i), compoundend);
-                      strcat(*result, presult);
-                      if (m) {
-                        line_uniq(m);
-                        if (strchr(m, '\n')) {
-                            strcat(*result, "(");
-                            strcat(*result, line_join(m, '|'));
-                            strcat(*result, ")");
-                        } else {
-                            strcat(*result, m);
-                        }
-                        free(m);
-                      }
-                      strcat(*result, "\n");
-                      ok = 1;
-            }
-
-            numsyllable = oldnumsyllable2;
-            wordnum = oldwordnum2;
-
-            // perhaps second word is a compound word (recursive call)
-            if ((wordnum < maxwordnum) && (ok == 0)) {
-                        compound_check_morph((word+i),strlen(word+i), wordnum+1, 
-                             numsyllable, maxwordnum, wnum + 1, words, 0, result, presult);
-            } else {
-                rv=NULL;
-            }
-        }
-        st[i] = ch;
-        wordnum = oldwordnum;
-        numsyllable = oldnumsyllable;
-    }
-    return 0;
-}    
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
- // return 1 if s1 (reversed) is a leading subset of end of s2
-/* inline int AffixMgr::isRevSubset(const char * s1, const char * end_of_s2, int len)
- {
-    while ((len > 0) && *s1 && (*s1 == *end_of_s2)) {
-        s1++;
-        end_of_s2--;
-        len--;
-    }
-    return (*s1 == '\0');
- }
- */
-
-inline int AffixMgr::isRevSubset(const char * s1, const char * end_of_s2, int len)
- {
-    while ((len > 0) && (*s1 != '\0') && ((*s1 == *end_of_s2) || (*s1 == '.'))) {
-        s1++;
-        end_of_s2--;
-        len--;
-    }
-    return (*s1 == '\0');
- }
-
-// check word for suffixes
-
-struct hentry * AffixMgr::suffix_check (const char * word, int len, 
-       int sfxopts, AffEntry * ppfx, char ** wlst, int maxSug, int * ns, 
-       const FLAG cclass, const FLAG needflag, char in_compound)
-{
-    struct hentry * rv = NULL;
-    char result[MAXLNLEN];
-
-    PfxEntry* ep = (PfxEntry *) ppfx;
-
-    // first handle the special case of 0 length suffixes
-    SfxEntry * se = (SfxEntry *) sStart[0];
-
-    while (se) {
-        if (!cclass || se->getCont()) {
-            // suffixes are not allowed in beginning of compounds
-            if ((((in_compound != IN_CPD_BEGIN)) || // && !cclass
-             // except when signed with compoundpermitflag flag
-             (se->getCont() && compoundpermitflag &&
-                TESTAFF(se->getCont(),compoundpermitflag,se->getContLen()))) && (!circumfix ||
-              // no circumfix flag in prefix and suffix
-              ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(),
-                   circumfix, ep->getContLen())) &&
-               (!se->getCont() || !(TESTAFF(se->getCont(),circumfix,se->getContLen())))) ||
-              // circumfix flag in prefix AND suffix
-              ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(),
-                   circumfix, ep->getContLen())) &&
-               (se->getCont() && (TESTAFF(se->getCont(),circumfix,se->getContLen())))))  &&
-            // fogemorpheme
-              (in_compound || 
-                 !((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) &&
-            // pseudoroot on prefix or first suffix
-              (cclass || 
-                   !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) ||
-                   (ppfx && !((ep->getCont()) &&
-                     TESTAFF(ep->getCont(), pseudoroot,
-                       ep->getContLen())))
-              )
-            ) {
-                rv = se->checkword(word,len, sfxopts, ppfx, wlst, maxSug, ns, (FLAG) cclass, 
-                    needflag, (in_compound ? 0 : onlyincompound));
-                if (rv) {
-                    sfx=(AffEntry *)se; // BUG: sfx not stateless
-                    return rv;
-                }
-            }
-        }
-       se = se->getNext();
-    }
-  
-    // now handle the general case
-    unsigned char sp = *((const unsigned char *)(word + len - 1));
-    SfxEntry * sptr = (SfxEntry *) sStart[sp];
-
-    while (sptr) {
-        if (isRevSubset(sptr->getKey(), word + len - 1, len)
-        ) {
-            // suffixes are not allowed in beginning of compounds
-            if ((((in_compound != IN_CPD_BEGIN)) || // && !cclass
-             // except when signed with compoundpermitflag flag
-             (sptr->getCont() && compoundpermitflag &&
-                TESTAFF(sptr->getCont(),compoundpermitflag,sptr->getContLen()))) && (!circumfix ||
-              // no circumfix flag in prefix and suffix
-              ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(),
-                   circumfix, ep->getContLen())) &&
-               (!sptr->getCont() || !(TESTAFF(sptr->getCont(),circumfix,sptr->getContLen())))) ||
-              // circumfix flag in prefix AND suffix
-              ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(),
-                   circumfix, ep->getContLen())) &&
-               (sptr->getCont() && (TESTAFF(sptr->getCont(),circumfix,sptr->getContLen())))))  &&
-            // fogemorpheme
-              (in_compound || 
-                 !((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) &&
-            // pseudoroot on prefix or first suffix
-              (cclass || 
-                  !(sptr->getCont() && TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())) ||
-                  (ppfx && !((ep->getCont()) &&
-                     TESTAFF(ep->getCont(), pseudoroot,
-                       ep->getContLen())))
-              )
-            ) {
-                rv = sptr->checkword(word,len, sfxopts, ppfx, wlst,
-                    maxSug, ns, cclass, needflag, (in_compound ? 0 : onlyincompound));
-                if (rv) {
-                    sfx=(AffEntry *)sptr; // BUG: sfx not stateless
-                    sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless
-                    if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless
-                    if (cclass || sptr->getCont()) {
-                                if (!derived) {
-                                        derived = mystrdup(word);
-                                } else {
-                                        strcpy(result, derived); // XXX check size
-                                        strcat(result, "\n");
-                                        strcat(result, word);
-                                        free(derived);
-                                        derived = mystrdup(result);
-                                }
-                    }
-                    return rv;
-                }
-             }
-             sptr = sptr->getNextEQ();
-        } else {
-             sptr = sptr->getNextNE();
-        }
-    }
-
-    return NULL;
-}
-
-// check word for two-level suffixes
-
-struct hentry * AffixMgr::suffix_check_twosfx(const char * word, int len, 
-       int sfxopts, AffEntry * ppfx, const FLAG needflag)
-{
-    struct hentry * rv = NULL;
-
-    // first handle the special case of 0 length suffixes
-    SfxEntry * se = (SfxEntry *) sStart[0];
-    while (se) {
-        if (contclasses[se->getFlag()])
-        {
-            rv = se->check_twosfx(word,len, sfxopts, ppfx, needflag);
-            if (rv) return rv;
-        }
-        se = se->getNext();
-    }
-  
-    // now handle the general case
-    unsigned char sp = *((const unsigned char *)(word + len - 1));
-    SfxEntry * sptr = (SfxEntry *) sStart[sp];
-
-    while (sptr) {
-        if (isRevSubset(sptr->getKey(), word + len - 1, len)) {
-            if (contclasses[sptr->getFlag()])
-            {
-                rv = sptr->check_twosfx(word,len, sfxopts, ppfx, needflag);
-                if (rv) {
-                    sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless
-                    if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless
-                    return rv;
-                }
-            }
-            sptr = sptr->getNextEQ();
-        } else {
-             sptr = sptr->getNextNE();
-        }
-    }
-
-    return NULL;
-}
-
-#ifdef HUNSPELL_EXPERIMENTAL
-char * AffixMgr::suffix_check_twosfx_morph(const char * word, int len, 
-       int sfxopts, AffEntry * ppfx, const FLAG needflag)
-{
-    char result[MAXLNLEN];
-    char result2[MAXLNLEN];
-    char result3[MAXLNLEN];
-    
-    char * st;
-
-    result[0] = '\0';
-    result2[0] = '\0';
-    result3[0] = '\0';
-
-    // first handle the special case of 0 length suffixes
-    SfxEntry * se = (SfxEntry *) sStart[0];
-    while (se) {
-        if (contclasses[se->getFlag()])
-        {
-            st = se->check_twosfx_morph(word,len, sfxopts, ppfx, needflag);
-            if (st) {
-                if (ppfx) {
-                    if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph());
-                }
-                strcat(result, st);
-                free(st);
-                if (se->getMorph()) strcat(result, se->getMorph());
-                strcat(result, "\n");
-            }
-        }
-        se = se->getNext();
-    }
-  
-    // now handle the general case
-    unsigned char sp = *((const unsigned char *)(word + len - 1));
-    SfxEntry * sptr = (SfxEntry *) sStart[sp];
-
-    while (sptr) {
-        if (isRevSubset(sptr->getKey(), word + len - 1, len)) {
-            if (contclasses[sptr->getFlag()]) 
-            {
-                st = sptr->check_twosfx_morph(word,len, sfxopts, ppfx, needflag);
-                if (st) {
-                    sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless
-                    if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless
-                    strcpy(result2, st);
-                    free(st);
-
-                result3[0] = '\0';
-#ifdef DEBUG
-                unsigned short flag = sptr->getFlag();
-                if (flag_mode == FLAG_NUM) {
-                    sprintf(result3, "<%d>", sptr->getKey());
-                } else if (flag_mode == FLAG_LONG) {
-                    sprintf(result3, "<%c%c>", flag >> 8, (flag << 8) >>8);
-                } else sprintf(result3, "<%c>", flag);
-                strcat(result3, ":");
-#endif
-                if (sptr->getMorph()) strcat(result3, sptr->getMorph());
-                strlinecat(result2, result3);
-                strcat(result2, "\n");
-                strcat(result,  result2);
-                }
-            }
-            sptr = sptr->getNextEQ();
-        } else {
-             sptr = sptr->getNextNE();
-        }
-    }
-    if (result) return mystrdup(result);
-    return NULL;
-}
-
-char * AffixMgr::suffix_check_morph(const char * word, int len, 
-       int sfxopts, AffEntry * ppfx, const FLAG cclass, const FLAG needflag, char in_compound)
-{
-    char result[MAXLNLEN];
-    
-    struct hentry * rv = NULL;
-
-    result[0] = '\0';
-
-    PfxEntry* ep = (PfxEntry *) ppfx;
-
-    // first handle the special case of 0 length suffixes
-    SfxEntry * se = (SfxEntry *) sStart[0];
-    while (se) {
-        if (!cclass || se->getCont()) {
-            // suffixes are not allowed in beginning of compounds
-            if (((((in_compound != IN_CPD_BEGIN)) || // && !cclass
-             // except when signed with compoundpermitflag flag
-             (se->getCont() && compoundpermitflag &&
-                TESTAFF(se->getCont(),compoundpermitflag,se->getContLen()))) && (!circumfix ||
-              // no circumfix flag in prefix and suffix
-              ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(),
-                   circumfix, ep->getContLen())) &&
-               (!se->getCont() || !(TESTAFF(se->getCont(),circumfix,se->getContLen())))) ||
-              // circumfix flag in prefix AND suffix
-              ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(),
-                   circumfix, ep->getContLen())) &&
-               (se->getCont() && (TESTAFF(se->getCont(),circumfix,se->getContLen())))))  &&
-            // fogemorpheme
-              (in_compound || 
-                 !((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) &&
-            // pseudoroot on prefix or first suffix
-              (cclass || 
-                   !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) ||
-                   (ppfx && !((ep->getCont()) &&
-                     TESTAFF(ep->getCont(), pseudoroot,
-                       ep->getContLen())))
-              )
-            ))
-            rv = se->checkword(word,len, sfxopts, ppfx, NULL, 0, 0, cclass, needflag);
-         while (rv) {
-           if (ppfx) {
-                if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph());
-            }
-            if (complexprefixes && rv->description) strcat(result, rv->description);
-            if (rv->description && ((!rv->astr) || 
-                                        !TESTAFF(rv->astr, lemma_present, rv->alen)))
-                                               strcat(result, &(rv->word));
-            if (!complexprefixes && rv->description) strcat(result, rv->description);
-            if (se->getMorph()) strcat(result, se->getMorph());
-            strcat(result, "\n");
-            rv = se->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag);
-         }
-       }
-       se = se->getNext();
-    }
-  
-    // now handle the general case
-    unsigned char sp = *((const unsigned char *)(word + len - 1));
-    SfxEntry * sptr = (SfxEntry *) sStart[sp];
-
-    while (sptr) {
-        if (isRevSubset(sptr->getKey(), word + len - 1, len)
-        ) {
-            // suffixes are not allowed in beginning of compounds
-            if (((((in_compound != IN_CPD_BEGIN)) || // && !cclass
-             // except when signed with compoundpermitflag flag
-             (sptr->getCont() && compoundpermitflag &&
-                TESTAFF(sptr->getCont(),compoundpermitflag,sptr->getContLen()))) && (!circumfix ||
-              // no circumfix flag in prefix and suffix
-              ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(),
-                   circumfix, ep->getContLen())) &&
-               (!sptr->getCont() || !(TESTAFF(sptr->getCont(),circumfix,sptr->getContLen())))) ||
-              // circumfix flag in prefix AND suffix
-              ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(),
-                   circumfix, ep->getContLen())) &&
-               (sptr->getCont() && (TESTAFF(sptr->getCont(),circumfix,sptr->getContLen())))))  &&
-            // fogemorpheme
-              (in_compound || 
-                 !((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) &&
-            // pseudoroot on first suffix
-              (cclass || !(sptr->getCont() && 
-                   TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())))
-            )) rv = sptr->checkword(word,len, sfxopts, ppfx, NULL, 0, 0, cclass, needflag);
-            while (rv) {
-                    if (ppfx) {
-                        if (((PfxEntry *) ppfx)->getMorph()) strcat(result, ((PfxEntry *) ppfx)->getMorph());
-                    }    
-                    if (complexprefixes && rv->description) strcat(result, rv->description);
-                    if (rv->description && ((!rv->astr) || 
-                        !TESTAFF(rv->astr, lemma_present, rv->alen))) strcat(result, &(rv->word));
-                    if (!complexprefixes && rv->description) strcat(result, rv->description);
-#ifdef DEBUG
-                unsigned short flag = sptr->getFlag();
-                if (flag_mode == FLAG_NUM) {
-                    sprintf(result, "<%d>", sptr->getKey());
-                } else if (flag_mode == FLAG_LONG) {
-                    sprintf(result, "<%c%c>", flag >> 8, (flag << 8) >>8);
-                } else sprintf(result, "<%c>", flag);
-                strcat(result, ":");
-#endif
-
-                if (sptr->getMorph()) strcat(result, sptr->getMorph());
-                strcat(result, "\n");
-                rv = sptr->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag);
-            }
-             sptr = sptr->getNextEQ();
-        } else {
-             sptr = sptr->getNextNE();
-        }
-    }
-
-    if (*result) return mystrdup(result);
-    return NULL;
-}
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
-
-// check if word with affixes is correctly spelled
-struct hentry * AffixMgr::affix_check (const char * word, int len, const FLAG needflag, char in_compound)
-{
-    struct hentry * rv= NULL;
-    if (derived) free(derived);
-    derived =  NULL;
-
-    // check all prefixes (also crossed with suffixes if allowed) 
-    rv = prefix_check(word, len, in_compound, needflag);
-    if (rv) return rv;
-
-    // if still not found check all suffixes
-    rv = suffix_check(word, len, 0, NULL, NULL, 0, NULL, FLAG_NULL, needflag, in_compound);
-
-    if (havecontclass) {
-        sfx = NULL;
-        pfx = NULL;
-        if (rv) return rv;
-        // if still not found check all two-level suffixes
-        rv = suffix_check_twosfx(word, len, 0, NULL, needflag);
-        if (rv) return rv;
-        // if still not found check all two-level suffixes
-        rv = prefix_check_twosfx(word, len, IN_CPD_NOT, needflag);
-    }
-    return rv;
-}
-
-#ifdef HUNSPELL_EXPERIMENTAL
-// check if word with affixes is correctly spelled
-char * AffixMgr::affix_check_morph(const char * word, int len, const FLAG needflag, char in_compound)
-{
-    char result[MAXLNLEN];
-    char * st = NULL;
-
-    *result = '\0';
-    
-    // check all prefixes (also crossed with suffixes if allowed) 
-    st = prefix_check_morph(word, len, in_compound);
-    if (st) {
-        strcat(result, st);
-        free(st);
-    }
-
-    // if still not found check all suffixes    
-    st = suffix_check_morph(word, len, 0, NULL, '\0', needflag, in_compound);
-    if (st) {
-        strcat(result, st);
-        free(st);
-    }
-
-    if (havecontclass) {
-        sfx = NULL;
-        pfx = NULL;
-        // if still not found check all two-level suffixes
-        st = suffix_check_twosfx_morph(word, len, 0, NULL, needflag);
-        if (st) {
-            strcat(result, st);
-            free(st);
-        }
-
-        // if still not found check all two-level suffixes
-        st = prefix_check_twosfx_morph(word, len, IN_CPD_NOT, needflag);
-        if (st) {
-            strcat(result, st);
-            free(st);
-        }
-    }
-    
-    return mystrdup(result);
-}
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
-
-int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts,
-    int wl, const unsigned short * ap, unsigned short al, char * bad, int badl,
-    char * phone)
-{
-
-    int nh=0;
-    // first add root word to list
-    if ((nh < maxn) && !(al && ((pseudoroot && TESTAFF(ap, pseudoroot, al)) ||
-         (onlyincompound && TESTAFF(ap, onlyincompound, al))))) {
-       wlst[nh].word = mystrdup(ts);
-       wlst[nh].allow = (1 == 0);
-       wlst[nh].orig = NULL;
-       nh++;
-       // add special phonetic version
-       if (phone && (nh < maxn)) {
-    	    wlst[nh].word = mystrdup(phone);
-    	    wlst[nh].allow = (1 == 0);
-    	    wlst[nh].orig = mystrdup(ts);
-    	    nh++;
-       }
-    }
-
-    // handle suffixes
-    for (int i = 0; i < al; i++) {
-       const unsigned char c = (unsigned char) (ap[i] & 0x00FF);
-       SfxEntry * sptr = (SfxEntry *)sFlag[c];
-       while (sptr) {
-         if ((sptr->getFlag() == ap[i]) && (!sptr->getKeyLen() || ((badl > sptr->getKeyLen()) &&
-                (strcmp(sptr->getAffix(), bad + badl - sptr->getKeyLen()) == 0))) &&
-                // check pseudoroot flag
-                !(sptr->getCont() && ((pseudoroot && 
-                      TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())) ||
-                  (circumfix && 
-                      TESTAFF(sptr->getCont(), circumfix, sptr->getContLen())) ||
-                  (onlyincompound && 
-                      TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))
-                ) {
-            char * newword = sptr->add(ts, wl);
-            if (newword) {
-                if (nh < maxn) {
-                    wlst[nh].word = newword;
-                    wlst[nh].allow = sptr->allowCross();
-                    wlst[nh].orig = NULL;
-                    nh++;
-                    // add special phonetic version
-    		    if (phone && (nh < maxn)) {
-    			char st[MAXWORDUTF8LEN];
-    			strcpy(st, phone);
-    			strcat(st, sptr->getKey());
-    			reverseword(st + strlen(phone));
-    			wlst[nh].word = mystrdup(st);
-    			wlst[nh].allow = (1 == 0);
-    			wlst[nh].orig = mystrdup(newword);
-    			nh++;
-    		    }
-                } else {
-                    free(newword);
-                }
-            }
-         }
-         sptr = (SfxEntry *)sptr ->getFlgNxt();
-       }
-    }
-
-    int n = nh;
-
-    // handle cross products of prefixes and suffixes
-    for (int j=1;j<n ;j++)
-       if (wlst[j].allow) {
-          for (int k = 0; k < al; k++) {
-    	     const unsigned char c = (unsigned char) (ap[k] & 0x00FF);
-             PfxEntry * cptr = (PfxEntry *) pFlag[c];
-             while (cptr) {
-                if ((cptr->getFlag() == ap[k]) && cptr->allowCross() && (!cptr->getKeyLen() || ((badl > cptr->getKeyLen()) &&
-                        (strncmp(cptr->getKey(), bad, cptr->getKeyLen()) == 0)))) {
-                    int l1 = strlen(wlst[j].word);
-                    char * newword = cptr->add(wlst[j].word, l1);
-                    if (newword) {
-                       if (nh < maxn) {
-                          wlst[nh].word = newword;
-                          wlst[nh].allow = cptr->allowCross();
-                	  wlst[nh].orig = NULL;
-                          nh++;
-                       } else {
-                          free(newword);
-                       }
-                    }
-                }
-                cptr = (PfxEntry *)cptr ->getFlgNxt();
-             }
-          }
-       }
-
-
-    // now handle pure prefixes
-    for (int m = 0; m < al; m ++) {
-       const unsigned char c = (unsigned char) (ap[m] & 0x00FF);
-       PfxEntry * ptr = (PfxEntry *) pFlag[c];
-       while (ptr) {
-         if ((ptr->getFlag() == ap[m]) && (!ptr->getKeyLen() || ((badl > ptr->getKeyLen()) &&
-                (strncmp(ptr->getKey(), bad, ptr->getKeyLen()) == 0))) &&
-                // check pseudoroot flag
-                !(ptr->getCont() && ((pseudoroot && 
-                      TESTAFF(ptr->getCont(), pseudoroot, ptr->getContLen())) ||
-                     (circumfix && 
-                      TESTAFF(ptr->getCont(), circumfix, ptr->getContLen())) ||                      
-                  (onlyincompound && 
-                      TESTAFF(ptr->getCont(), onlyincompound, ptr->getContLen()))))
-                ) {
-            char * newword = ptr->add(ts, wl);
-            if (newword) {
-                if (nh < maxn) {
-                    wlst[nh].word = newword;
-                    wlst[nh].allow = ptr->allowCross();
-                    wlst[nh].orig = NULL;
-                    nh++;
-                } else {
-                    free(newword);
-                } 
-            }
-         }
-         ptr = (PfxEntry *)ptr ->getFlgNxt();
-       }
-    }
-
-    return nh;
-}
-
-
-
-// return length of replacing table
-int AffixMgr::get_numrep()
-{
-  return numrep;
-}
-
-// return replacing table
-struct replentry * AffixMgr::get_reptable()
-{
-  if (! reptable ) return NULL;
-  return reptable;
-}
-
-// return replacing table
-struct phonetable * AffixMgr::get_phonetable()
-{
-  if (! phone ) return NULL;
-  return phone;
-}
-
-// return length of character map table
-int AffixMgr::get_nummap()
-{
-  return nummap;
-}
-
-// return character map table
-struct mapentry * AffixMgr::get_maptable()
-{
-  if (! maptable ) return NULL;
-  return maptable;
-}
-
-// return length of word break table
-int AffixMgr::get_numbreak()
-{
-  return numbreak;
-}
-
-// return character map table
-char ** AffixMgr::get_breaktable()
-{
-  if (! breaktable ) return NULL;
-  return breaktable;
-}
-
-// return text encoding of dictionary
-char * AffixMgr::get_encoding()
-{
-  if (! encoding ) {
-      encoding = mystrdup("ISO8859-1");
-  }
-  return mystrdup(encoding);
-}
-
-// return text encoding of dictionary
-int AffixMgr::get_langnum()
-{
-  return langnum;
-}
-
-// return double prefix option
-int AffixMgr::get_complexprefixes()
-{
-  return complexprefixes;
-}
-
-FLAG AffixMgr::get_keepcase()
-{
-  return keepcase;
-}
-
-int AffixMgr::get_checksharps()
-{
-  return checksharps;
-}
-
-// return the preferred ignore string for suggestions
-char * AffixMgr::get_ignore()
-{
-  if (!ignorechars) return NULL;
-  return ignorechars;
-}
-
-// return the preferred ignore string for suggestions
-unsigned short * AffixMgr::get_ignore_utf16(int * len)
-{
-  *len = ignorechars_utf16_len;
-  return ignorechars_utf16;
-}
-
-// return the keyboard string for suggestions
-char * AffixMgr::get_key_string()
-{
-  if (! keystring ) return NULL;
-  return mystrdup(keystring);
-}
-
-// return the preferred try string for suggestions
-char * AffixMgr::get_try_string()
-{
-  if (! trystring ) return NULL;
-  return mystrdup(trystring);
-}
-
-// return the preferred try string for suggestions
-const char * AffixMgr::get_wordchars()
-{
-  return wordchars;
-}
-
-unsigned short * AffixMgr::get_wordchars_utf16(int * len)
-{
-  *len = wordchars_utf16_len;
-  return wordchars_utf16;
-}
-
-// is there compounding?
-int AffixMgr::get_compound()
-{
-  return compoundflag || compoundbegin || numdefcpd;
-}
-
-// return the compound words control flag
-FLAG AffixMgr::get_compoundflag()
-{
-  return compoundflag;
-}
-
-// return the forbidden words control flag
-FLAG AffixMgr::get_forbiddenword()
-{
-  return forbiddenword;
-}
-
-// return the forbidden words control flag
-FLAG AffixMgr::get_nosuggest()
-{
-  return nosuggest;
-}
-
-// return the forbidden words flag modify flag
-FLAG AffixMgr::get_pseudoroot()
-{
-  return pseudoroot;
-}
-
-// return the onlyincompound flag
-FLAG AffixMgr::get_onlyincompound()
-{
-  return onlyincompound;
-}
-
-// return the compound word signal flag
-FLAG AffixMgr::get_compoundroot()
-{
-  return compoundroot;
-}
-
-// return the compound begin signal flag
-FLAG AffixMgr::get_compoundbegin()
-{
-  return compoundbegin;
-}
-
-// return the value of checknum
-int AffixMgr::get_checknum()
-{
-  return checknum;
-}
-
-// return the value of prefix
-const char * AffixMgr::get_prefix()
-{
-  if (pfx) return ((PfxEntry *)pfx)->getKey();
-  return NULL;
-}
-
-// return the value of suffix
-const char * AffixMgr::get_suffix()
-{
-  return sfxappnd;
-}
-
-// return the value of derived form (base word with first suffix).
-const char * AffixMgr::get_derived()
-{
-  return derived;
-}
-
-// return the value of suffix
-const char * AffixMgr::get_version()
-{
-  return version;
-}
-
-// return lemma_present flag
-FLAG AffixMgr::get_lemma_present()
-{
-  return lemma_present;
-}
-
-// utility method to look up root words in hash table
-struct hentry * AffixMgr::lookup(const char * word)
-{
-  if (! pHMgr) return NULL;
-  return pHMgr->lookup(word);
-}
-
-// return the value of suffix
-const int AffixMgr::have_contclass()
-{
-  return havecontclass;
-}
-
-// return utf8
-int AffixMgr::get_utf8()
-{
-  return utf8;
-}
-
-// return nosplitsugs
-int AffixMgr::get_maxngramsugs(void)
-{
-  return maxngramsugs;
-}
-
-// return nosplitsugs
-int AffixMgr::get_nosplitsugs(void)
-{
-  return nosplitsugs;
-}
-
-// return sugswithdots
-int AffixMgr::get_sugswithdots(void)
-{
-  return sugswithdots;
-}
-
-/* parse flag */
-int AffixMgr::parse_flag(char * line, unsigned short * out, const char * name) {
-   char * s = NULL;
-   if (*out != FLAG_NULL) {
-      HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", name);
-      return 1;
-   }
-   if (parse_string(line, &s, name)) return 1;
-   *out = pHMgr->decode_flag(s);
-   free(s);
-   return 0;
-}
-
-/* parse num */
-int AffixMgr::parse_num(char * line, int * out, const char * name) {
-   char * s = NULL;
-   if (*out != -1) {
-      HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", name);
-      return 1;
-   }
-   if (parse_string(line, &s, name)) return 1;
-   *out = atoi(s);
-   free(s);
-   return 0;
-}
-
-/* parse in the max syllablecount of compound words and  */
-int  AffixMgr::parse_cpdsyllable(char * line)
-{
-   char * tp = line;
-   char * piece;
-   int i = 0;
-   int np = 0;
-   w_char w[MAXWORDLEN];
-   piece = mystrsep(&tp, 0);
-   while (piece) {
-      if (*piece != '\0') {
-          switch(i) {
-             case 0: { np++; break; }
-             case 1: { cpdmaxsyllable = atoi(piece); np++; break; }
-             case 2: {
-                if (!utf8) {
-                    cpdvowels = mystrdup(piece);
-                } else {
-                    int n = u8_u16(w, MAXWORDLEN, piece);
-                    if (n > 0) {
-                        flag_qsort((unsigned short *) w, 0, n);
-                        cpdvowels_utf16 = (w_char *) malloc(n * sizeof(w_char));
-                        if (!cpdvowels_utf16) return 1;
-                        memcpy(cpdvowels_utf16, w, n * sizeof(w_char));
-                    }
-                    cpdvowels_utf16_len = n;
-                }
-                np++;
-                break;
-             }
-             default: break;
-          }
-          i++;
-      }
-      free(piece);
-      piece = mystrsep(&tp, 0);
-   }
-   if (np < 2) {
-      HUNSPELL_WARNING(stderr, "error: missing compoundsyllable information\n");
-      return 1;
-   }
-   if (np == 2) cpdvowels = mystrdup("aeiouAEIOU");
-   return 0;
-}
-
-/* parse in the typical fault correcting table */
-int  AffixMgr::parse_reptable(char * line, FILE * af)
-{
-   if (numrep != 0) {
-      HUNSPELL_WARNING(stderr, "error: duplicate REP tables used\n");
-      return 1;
-   }
-   char * tp = line;
-   char * piece;
-   int i = 0;
-   int np = 0;
-   piece = mystrsep(&tp, 0);
-   while (piece) {
-       if (*piece != '\0') {
-          switch(i) {
-             case 0: { np++; break; }
-             case 1: { 
-                       numrep = atoi(piece);
-                       if (numrep < 1) {
-                          HUNSPELL_WARNING(stderr, "incorrect number of entries in replacement table\n");
-                          free(piece);
-                          return 1;
-                       }
-                       reptable = (replentry *) malloc(numrep * sizeof(struct replentry));
-                       if (!reptable) return 1;
-                       np++;
-                       break;
-                     }
-             default: break;
-          }
-          i++;
-       }
-       free(piece);
-       piece = mystrsep(&tp, 0);
-   }
-   if (np != 2) {
-      HUNSPELL_WARNING(stderr, "error: missing replacement table information\n");
-      return 1;
-   } 
- 
-   /* now parse the numrep lines to read in the remainder of the table */
-   char * nl = line;
-   for (int j=0; j < numrep; j++) {
-        if (!fgets(nl,MAXLNLEN,af)) return 1;
-        mychomp(nl);
-        tp = nl;
-        i = 0;
-        reptable[j].pattern = NULL;
-        reptable[j].pattern2 = NULL;
-        piece = mystrsep(&tp, 0);
-        while (piece) {
-           if (*piece != '\0') {
-               switch(i) {
-                  case 0: {
-                             if (strncmp(piece,"REP",3) != 0) {
-                                 HUNSPELL_WARNING(stderr, "error: replacement table is corrupt\n");
-                                 numrep = 0;
-                                 free(piece);
-                                 return 1;
-                             }
-                             break;
-                          }
-                  case 1: { reptable[j].pattern = mystrrep(mystrdup(piece),"_"," "); break; }
-                  case 2: { reptable[j].pattern2 = mystrrep(mystrdup(piece),"_"," "); break; }
-                  default: break;
-               }
-               i++;
-           }
-           free(piece);
-           piece = mystrsep(&tp, 0);
-        }
-        if ((!(reptable[j].pattern)) || (!(reptable[j].pattern2))) {
-             HUNSPELL_WARNING(stderr, "error: replacement table is corrupt\n");
-             numrep = 0;
-             return 1;
-        }
-   }
-   return 0;
-}
-
-/* parse in the typical fault correcting table */
-int  AffixMgr::parse_phonetable(char * line, FILE * af)
-{
-   if (phone) {
-      HUNSPELL_WARNING(stderr, "error: duplicate PHONE tables used\n");
-      return 1;
-   }
-   char * tp = line;
-   char * piece;
-   int i = 0;
-   int np = 0;
-   piece = mystrsep(&tp, 0);
-   while (piece) {
-       if (*piece != '\0') {
-          switch(i) {
-             case 0: { np++; break; }
-             case 1: { 
-            	       phone = (phonetable *) malloc(sizeof(struct phonetable));
-            	       phone->num = atoi(piece);
-            	       phone->rules = NULL;
-            	       phone->utf8 = utf8;
-                       if (!phone) return 1;
-                       if (phone->num < 1) {
-                          HUNSPELL_WARNING(stderr, "incorrect number of entries in phonelacement table\n");
-                          free(piece);
-                          return 1;
-                       }
-                       phone->rules = (char * *) malloc(2 * (phone->num + 1) * sizeof(char *));
-                       if (!phone->rules) return 1;
-                       np++;
-                       break;
-                     }
-             default: break;
-          }
-          i++;
-       }
-       free(piece);
-       piece = mystrsep(&tp, 0);
-   }
-   if (np != 2) {
-      HUNSPELL_WARNING(stderr, "error: missing PHONE table information\n");
-      return 1;
-   } 
- 
-   /* now parse the phone->num lines to read in the remainder of the table */
-   char * nl = line;
-   for (int j=0; j < phone->num; j++) {
-        if (!fgets(nl,MAXLNLEN,af)) return 1;
-        mychomp(nl);
-        tp = nl;
-        i = 0;
-        phone->rules[j * 2] = NULL;
-        phone->rules[j * 2 + 1] = NULL;
-        piece = mystrsep(&tp, 0);
-        while (piece) {
-           if (*piece != '\0') {
-               switch(i) {
-                  case 0: {
-                             if (strncmp(piece,"PHONE",5) != 0) {
-                                 HUNSPELL_WARNING(stderr, "error: PHONE table is corrupt\n");
-                                 phone->num = 0;
-                                 free(piece);
-                                 return 1;
-                             }
-                             break;
-                          }
-                  case 1: { phone->rules[j * 2] = mystrrep(mystrdup(piece),"_",""); break; }
-                  case 2: { phone->rules[j * 2 + 1] = mystrrep(mystrdup(piece),"_",""); break; }
-                  default: break;
-               }
-               i++;
-           }
-           free(piece);
-           piece = mystrsep(&tp, 0);
-        }
-        if ((!(phone->rules[j * 2])) || (!(phone->rules[j * 2 + 1]))) {
-             HUNSPELL_WARNING(stderr, "error: PHONE table is corrupt\n");
-             phone->num = 0;
-             return 1;
-        }
-   }
-   phone->rules[phone->num * 2] = mystrdup("");
-   phone->rules[phone->num * 2 + 1] = mystrdup("");
-   init_phonet_hash(*phone);
-   return 0;
-}
-
-/* parse in the checkcompoundpattern table */
-int  AffixMgr::parse_checkcpdtable(char * line, FILE * af)
-{
-   if (numcheckcpd != 0) {
-      HUNSPELL_WARNING(stderr, "error: duplicate compound pattern tables used\n");
-      return 1;
-   }
-   char * tp = line;
-   char * piece;
-   int i = 0;
-   int np = 0;
-   piece = mystrsep(&tp, 0);
-   while (piece) {
-       if (*piece != '\0') {
-          switch(i) {
-             case 0: { np++; break; }
-             case 1: { 
-                       numcheckcpd = atoi(piece);
-                       if (numcheckcpd < 1) {
-                          HUNSPELL_WARNING(stderr, "incorrect number of entries in compound pattern table\n");
-                          free(piece);
-                          return 1;
-                       }
-                       checkcpdtable = (replentry *) malloc(numcheckcpd * sizeof(struct replentry));
-                       if (!checkcpdtable) return 1;
-                       np++;
-                       break;
-                     }
-             default: break;
-          }
-          i++;
-       }
-       free(piece);
-       piece = mystrsep(&tp, 0);
-   }
-   if (np != 2) {
-      HUNSPELL_WARNING(stderr, "error: missing compound pattern table information\n");
-      return 1;
-   } 
- 
-   /* now parse the numcheckcpd lines to read in the remainder of the table */
-   char * nl = line;
-   for (int j=0; j < numcheckcpd; j++) {
-        if (!fgets(nl,MAXLNLEN,af)) return 1;
-        mychomp(nl);
-        tp = nl;
-        i = 0;
-        checkcpdtable[j].pattern = NULL;
-        checkcpdtable[j].pattern2 = NULL;
-        piece = mystrsep(&tp, 0);
-        while (piece) {
-           if (*piece != '\0') {
-               switch(i) {
-                  case 0: {
-                             if (strncmp(piece,"CHECKCOMPOUNDPATTERN",20) != 0) {
-                                 HUNSPELL_WARNING(stderr, "error: compound pattern table is corrupt\n");
-                                 numcheckcpd = 0;
-                                 free(piece);
-                                 return 1;
-                             }
-                             break;
-                          }
-                  case 1: { checkcpdtable[j].pattern = mystrdup(piece); break; }
-                  case 2: { checkcpdtable[j].pattern2 = mystrdup(piece); break; }
-                  default: break;
-               }
-               i++;
-           }
-           free(piece);
-           piece = mystrsep(&tp, 0);
-        }
-        if ((!(checkcpdtable[j].pattern)) || (!(checkcpdtable[j].pattern2))) {
-             HUNSPELL_WARNING(stderr, "error: compound pattern table is corrupt\n");
-	     numcheckcpd = 0;
-	     return 1;
-        }
-   }
-   return 0;
-}
-
-/* parse in the compound rule table */
-int  AffixMgr::parse_defcpdtable(char * line, FILE * af)
-{
-   if (numdefcpd != 0) {
-      HUNSPELL_WARNING(stderr, "error: duplicate compound rule tables used\n");
-      return 1;
-   }
-   char * tp = line;
-   char * piece;
-   int i = 0;
-   int np = 0;
-   piece = mystrsep(&tp, 0);
-   while (piece) {
-       if (*piece != '\0') {
-          switch(i) {
-             case 0: { np++; break; }
-             case 1: { 
-                       numdefcpd = atoi(piece);
-                       if (numdefcpd < 1) {
-                          HUNSPELL_WARNING(stderr, "incorrect number of entries in compound rule table\n");
-                          free(piece);
-                          return 1;
-                       }
-                       defcpdtable = (flagentry *) malloc(numdefcpd * sizeof(flagentry));
-                       if (!defcpdtable) return 1;
-                       np++;
-                       break;
-                     }
-             default: break;
-          }
-          i++;
-       }
-       free(piece);
-       piece = mystrsep(&tp, 0);
-   }
-   if (np != 2) {
-      HUNSPELL_WARNING(stderr, "error: missing compound rule table information\n");
-      return 1;
-   } 
- 
-   /* now parse the numdefcpd lines to read in the remainder of the table */
-   char * nl = line;
-   for (int j=0; j < numdefcpd; j++) {
-        if (!fgets(nl,MAXLNLEN,af)) return 1;
-        mychomp(nl);
-        tp = nl;
-        i = 0;
-        defcpdtable[j].def = NULL;
-        piece = mystrsep(&tp, 0);
-        while (piece) {
-           if (*piece != '\0') {
-               switch(i) {
-                  case 0: {
-                             if (strncmp(piece, "COMPOUNDRULE", 12) != 0) {
-                                 HUNSPELL_WARNING(stderr, "error: compound rule table is corrupt\n");
-                                 free(piece);
-                                 numdefcpd = 0;
-                                 return 1;
-                             }
-                             break;
-                          }
-                  case 1: { 
-                            defcpdtable[j].len = 
-                                pHMgr->decode_flags(&(defcpdtable[j].def), piece);
-                            break; 
-                           }
-                  default: break;
-               }
-               i++;
-           }
-           free(piece);
-           piece = mystrsep(&tp, 0);
-        }
-        if (!defcpdtable[j].len) {
-             HUNSPELL_WARNING(stderr, "error: compound rule table is corrupt\n");
-             numdefcpd = 0;
-             return 1;
-        }
-   }
-   return 0;
-}
-
-
-/* parse in the character map table */
-int  AffixMgr::parse_maptable(char * line, FILE * af)
-{
-   if (nummap != 0) {
-      HUNSPELL_WARNING(stderr, "error: duplicate MAP tables used\n");
-      return 1;
-   }
-   char * tp = line;
-   char * piece;
-   int i = 0;
-   int np = 0;
-   piece = mystrsep(&tp, 0);
-   while (piece) {
-       if (*piece != '\0') {
-          switch(i) {
-             case 0: { np++; break; }
-             case 1: { 
-                       nummap = atoi(piece);
-                       if (nummap < 1) {
-                          HUNSPELL_WARNING(stderr, "incorrect number of entries in map table\n");
-                          free(piece);
-                          return 1;
-                       }
-                       maptable = (mapentry *) malloc(nummap * sizeof(struct mapentry));
-                       if (!maptable) return 1;
-                       np++;
-                       break;
-                     }
-             default: break;
-          }
-          i++;
-       }
-       free(piece);
-       piece = mystrsep(&tp, 0);
-   }
-   if (np != 2) {
-      HUNSPELL_WARNING(stderr, "error: missing map table information\n");
-      return 1;
-   } 
- 
-   /* now parse the nummap lines to read in the remainder of the table */
-   char * nl = line;
-   for (int j=0; j < nummap; j++) {
-        if (!fgets(nl,MAXLNLEN,af)) return 1;
-        mychomp(nl);
-        tp = nl;
-        i = 0;
-        maptable[j].set = NULL;
-        maptable[j].len = 0;
-        piece = mystrsep(&tp, 0);
-        while (piece) {
-           if (*piece != '\0') {
-               switch(i) {
-                  case 0: {
-                             if (strncmp(piece,"MAP",3) != 0) {
-                                 HUNSPELL_WARNING(stderr, "error: map table is corrupt\n");
-                                 nummap = 0;
-                                 free(piece);
-                                 return 1;
-                             }
-                             break;
-                          }
-                  case 1: {
-                            maptable[j].len = 0;
-                            maptable[j].set = NULL;
-                            maptable[j].set_utf16 = NULL;
-                            if (!utf8) {
-                                maptable[j].set = mystrdup(piece); 
-                                maptable[j].len = strlen(maptable[j].set);
-                            } else {
-                                w_char w[MAXWORDLEN];
-                                int n = u8_u16(w, MAXWORDLEN, piece);
-                                if (n > 0) {
-                                    flag_qsort((unsigned short *) w, 0, n);
-                                    maptable[j].set_utf16 = (w_char *) malloc(n * sizeof(w_char));
-                                    if (!maptable[j].set_utf16) return 1;
-                                    memcpy(maptable[j].set_utf16, w, n * sizeof(w_char));
-                                }
-                                maptable[j].len = n;
-                            }
-                            break; }
-                  default: break;
-               }
-               i++;
-           }
-           free(piece);
-           piece = mystrsep(&tp, 0);
-        }
-        if ((!(maptable[j].set || maptable[j].set_utf16)) || (!(maptable[j].len))) {
-             HUNSPELL_WARNING(stderr, "error: map table is corrupt\n");
-             nummap = 0;
-             return 1;
-        }
-   }
-   return 0;
-}
-
-/* parse in the word breakpoint table */
-int  AffixMgr::parse_breaktable(char * line, FILE * af)
-{
-   if (numbreak != 0) {
-      HUNSPELL_WARNING(stderr, "error: duplicate word breakpoint tables used\n");
-      return 1;
-   }
-   char * tp = line;
-   char * piece;
-   int i = 0;
-   int np = 0;
-   piece = mystrsep(&tp, 0);
-   while (piece) {
-       if (*piece != '\0') {
-          switch(i) {
-             case 0: { np++; break; }
-             case 1: { 
-                       numbreak = atoi(piece);
-                       if (numbreak < 1) {
-                          HUNSPELL_WARNING(stderr, "incorrect number of entries in BREAK table\n");
-                          free(piece);
-                          return 1;
-                       }
-                       breaktable = (char **) malloc(numbreak * sizeof(char *));
-                       if (!breaktable) return 1;
-                       np++;
-                       break;
-                     }
-             default: break;
-          }
-          i++;
-       }
-       free(piece);
-       piece = mystrsep(&tp, 0);
-   }
-   if (np != 2) {
-      HUNSPELL_WARNING(stderr, "error: missing word breakpoint table information\n");
-      return 1;
-   } 
- 
-   /* now parse the numbreak lines to read in the remainder of the table */
-   char * nl = line;
-   for (int j=0; j < numbreak; j++) {
-        if (!fgets(nl,MAXLNLEN,af)) return 1;
-        mychomp(nl);
-        tp = nl;
-        i = 0;
-        piece = mystrsep(&tp, 0);
-        while (piece) {
-           if (*piece != '\0') {
-               switch(i) {
-                  case 0: {
-                             if (strncmp(piece,"BREAK",5) != 0) {
-                                 HUNSPELL_WARNING(stderr, "error: BREAK table is corrupt\n");
-                                 free(piece);
-                                 numbreak = 0;
-                                 return 1;
-                             }
-                             break;
-                          }
-                  case 1: {
-                            breaktable[j] = mystrdup(piece);
-                            break;
-                          }
-                  default: break;
-               }
-               i++;
-           }
-           free(piece);
-           piece = mystrsep(&tp, 0);
-        }
-        if (!breaktable) {
-             HUNSPELL_WARNING(stderr, "error: BREAK table is corrupt\n");
-             numbreak = 0;
-             return 1;
-        }
-   }
-   return 0;
-}
-
-int  AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflags)
-{
-   int numents = 0;      // number of affentry structures to parse
-
-   unsigned short aflag = 0;      // affix char identifier
-
-   char ff=0;
-   struct affentry * ptr= NULL;
-   struct affentry * nptr= NULL;
-
-   char * tp = line;
-   char * nl = line;
-   char * piece;
-   int i = 0;
-
-   // checking lines with bad syntax
-#ifdef DEBUG
-   int basefieldnum = 0;
-#endif
-
-   // split affix header line into pieces
-
-   int np = 0;
-   piece = mystrsep(&tp, 0);
-   while (piece) {
-      if (*piece != '\0') {
-          switch(i) {
-             // piece 1 - is type of affix
-             case 0: { np++; break; }
-          
-             // piece 2 - is affix char
-             case 1: { 
-                    np++;
-                    aflag = pHMgr->decode_flag(piece);
-                    if (((at == 'S') && (dupflags[aflag] & dupSFX)) ||
-                        ((at == 'P') && (dupflags[aflag] & dupPFX))) {
-                        HUNSPELL_WARNING(stderr, "error: duplicate affix flag %s in line %s\n", piece, nl);
-                        // return 1; XXX permissive mode for bad dictionaries
-                    }
-                    dupflags[aflag] += ((at == 'S') ? dupSFX : dupPFX);
-                    break; 
-                    }
-             // piece 3 - is cross product indicator 
-             case 2: { np++; if (*piece == 'Y') ff = aeXPRODUCT; break; }
-
-             // piece 4 - is number of affentries
-             case 3: { 
-                       np++;
-                       numents = atoi(piece); 
-                       if (numents == 0) {
-                           char * err = pHMgr->encode_flag(aflag);
-                           HUNSPELL_WARNING(stderr, "error: affix %s header has incorrect entry count in line %s\n",
-                                   err, nl);
-                           free(err);
-                           return 1;
-                       }
-                       ptr = (struct affentry *) malloc(numents * sizeof(struct affentry));
-                       if (!ptr) return 1;
-                       ptr->opts = ff;
-                       if (utf8) ptr->opts += aeUTF8;
-                       if (pHMgr->is_aliasf()) ptr->opts += aeALIASF;
-#ifdef HUNSPELL_EXPERIMENTAL
-                       if (pHMgr->is_aliasm()) ptr->opts += aeALIASM;
-#endif
-                       ptr->aflag = aflag;
-                     }
-
-             default: break;
-          }
-          i++;
-      }
-      free(piece);
-      piece = mystrsep(&tp, 0);
-   }
-   // check to make sure we parsed enough pieces
-   if (np != 4) {
-       char * err = pHMgr->encode_flag(aflag); 
-       HUNSPELL_WARNING(stderr, "error: affix %s header has insufficient data in line %s\n", err, nl);
-       free(err);
-       free(ptr);
-       return 1;
-   }
- 
-   // store away ptr to first affentry
-   nptr = ptr;
-
-   // now parse numents affentries for this affix
-   for (int j=0; j < numents; j++) {
-      if (!fgets(nl,MAXLNLEN,af)) return 1;
-      mychomp(nl);
-      tp = nl;
-      i = 0;
-      np = 0;
-
-      // split line into pieces
-      piece = mystrsep(&tp, 0);
-      while (piece) {
-         if (*piece != '\0') {
-             switch(i) {
-                // piece 1 - is type
-                case 0: { 
-                          np++;
-                          if (nptr != ptr) nptr->opts = ptr->opts;
-                          break;
-                        }
-
-                // piece 2 - is affix char
-                case 1: { 
-                          np++;
-                          if (pHMgr->decode_flag(piece) != aflag) {
-                              char * err = pHMgr->encode_flag(aflag);
-                              HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl);
-                              HUNSPELL_WARNING(stderr, "error: possible incorrect count\n");
-                              free(err);
-                              free(piece);
-                              return 1;
-                          }
-
-                          if (nptr != ptr) nptr->aflag = ptr->aflag;
-                          break;
-                        }
-
-                // piece 3 - is string to strip or 0 for null 
-                case 2: { 
-                          np++;
-                          if (complexprefixes) {
-                            if (utf8) reverseword_utf(piece); else reverseword(piece);
-                          }
-                          nptr->strip = mystrdup(piece);
-                          nptr->stripl = (unsigned char) strlen(nptr->strip);
-                          if (strcmp(nptr->strip,"0") == 0) {
-                              free(nptr->strip);
-                              nptr->strip=mystrdup("");
-                              nptr->stripl = 0;
-                          }   
-                          break; 
-                        }
-
-                // piece 4 - is affix string or 0 for null
-                case 3: { 
-                          char * dash;  
-#ifdef HUNSPELL_EXPERIMENTAL
-                          nptr->morphcode = NULL;
-#endif
-                          nptr->contclass = NULL;
-                          nptr->contclasslen = 0;
-                          np++;
-                          dash = strchr(piece, '/');
-                          if (dash) {
-                            *dash = '\0';
-
-                            if (ignorechars) {
-                              if (utf8) {
-                                remove_ignored_chars_utf(piece, ignorechars_utf16, ignorechars_utf16_len);
-                              } else {
-                                remove_ignored_chars(piece,ignorechars);
-                              }
-                            }
-                            
-                            if (complexprefixes) {
-                                if (utf8) reverseword_utf(piece); else reverseword(piece);
-                            }
-                            nptr->appnd = mystrdup(piece);
-                            
-                            if (pHMgr->is_aliasf()) {
-                                int index = atoi(dash + 1);
-                                nptr->contclasslen = (unsigned short) pHMgr->get_aliasf(index, &(nptr->contclass));
-                            } else {
-                                nptr->contclasslen = (unsigned short) pHMgr->decode_flags(&(nptr->contclass), dash + 1);
-                                flag_qsort(nptr->contclass, 0, nptr->contclasslen);
-                            }
-                            *dash = '/';
-
-                            havecontclass = 1;
-                            for (unsigned short _i = 0; _i < nptr->contclasslen; _i++) {
-                              contclasses[(nptr->contclass)[_i]] = 1;
-                            }
-                          } else {
-                            if (ignorechars) {
-                              if (utf8) {
-                                remove_ignored_chars_utf(piece, ignorechars_utf16, ignorechars_utf16_len);
-                              } else {
-                                remove_ignored_chars(piece,ignorechars);
-                              }
-                            }
-
-                            if (complexprefixes) {
-                                if (utf8) reverseword_utf(piece); else reverseword(piece);
-                            }
-                            nptr->appnd = mystrdup(piece);       
-                          }
-                          
-                          nptr->appndl = (unsigned char) strlen(nptr->appnd);
-                          if (strcmp(nptr->appnd,"0") == 0) {
-                              free(nptr->appnd);
-                              nptr->appnd=mystrdup("");
-                              nptr->appndl = 0;
-                          }   
-                          break; 
-                        }
-
-                // piece 5 - is the conditions descriptions
-                case 4: { 
-                          np++;
-                          if (complexprefixes) {
-                            int neg = 0;
-                            if (utf8) reverseword_utf(piece); else reverseword(piece);
-                            // reverse condition
-                            for (char * k = piece + strlen(piece) - 1; k >= piece; k--) {
-                                switch(*k) {
-                                  case '[': {
-                                        if (neg) *(k+1) = '['; else *k = ']';
-                                        break;
-                                    }
-                                  case ']': {
-                                        *k = '[';
-                                        if (neg) *(k+1) = '^';
-                                        neg = 0;
-                                        break;
-                                    }
-                                  case '^': {
-                                       if (*(k+1) == ']') neg = 1; else *(k+1) = *k;
-                                       break;
-                                    }
-                                  default: {
-                                    if (neg) *(k+1) = *k;
-                                  }
-                               }
-                            }
-                          }
-                          if (nptr->stripl && (strcmp(piece, ".") != 0) &&
-                            redundant_condition(at, nptr->strip, nptr->stripl, piece, nl))
-                                strcpy(piece, ".");
-                          if (encodeit(nptr,piece)) return 1;
-                         break;
-                }
-                
-#ifdef HUNSPELL_EXPERIMENTAL
-                case 5: {
-                          np++;
-                          if (pHMgr->is_aliasm()) {
-                            int index = atoi(piece);
-                            nptr->morphcode = pHMgr->get_aliasm(index);
-                          } else {
-                            if (complexprefixes) {
-                                if (utf8) reverseword_utf(piece); else reverseword(piece);
-                            }
-                            nptr->morphcode = mystrdup(piece);
-                          }
-                          break; 
-                }
-#endif
-
-                default: break;
-             }
-             i++;
-         }
-         free(piece);
-         piece = mystrsep(&tp, 0);
-      }
-      // check to make sure we parsed enough pieces
-      if (np < 4) {
-          char * err = pHMgr->encode_flag(aflag);
-          HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl);
-          free(err);
-          free(ptr);
-          return 1;
-      }
-
-#ifdef DEBUG
-#ifdef HUNSPELL_EXPERIMENTAL
-      // detect unnecessary fields, excepting comments
-      if (basefieldnum) {
-        int fieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6);
-          if (fieldnum != basefieldnum) 
-            HUNSPELL_WARNING(stderr, "warning: bad field number:\n%s\n", nl);
-      } else {
-        basefieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6);
-      }
-#endif
-#endif
-      nptr++;
-   }
- 
-   // now create SfxEntry or PfxEntry objects and use links to
-   // build an ordered (sorted by affix string) list
-   nptr = ptr;
-   for (int k = 0; k < numents; k++) {
-      if (at == 'P') {
-          PfxEntry * pfxptr = new PfxEntry(this,nptr);
-          build_pfxtree((AffEntry *)pfxptr);
-      } else {
-          SfxEntry * sfxptr = new SfxEntry(this,nptr);
-          build_sfxtree((AffEntry *)sfxptr); 
-      }
-      nptr++;
-   }      
-   free(ptr);
-   return 0;
-}
-
-int AffixMgr::redundant_condition(char ft, char * strip, int stripl, const char * cond, char * warnvar) {
-  int condl = strlen(cond);
-  int i;
-  int j;
-  int neg;
-  int in;
-  if (ft == 'P') { // prefix
-    if (strncmp(strip, cond, condl) == 0) return 1;
-    if (utf8) {
-    } else {
-      for (i = 0, j = 0; (i < stripl) && (j < condl); i++, j++) {
-        if (cond[j] != '[') {
-          if (cond[j] != strip[i]) {
-            HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar);
-          }
-        } else {
-          neg = (cond[j+1] == '^') ? 1 : 0;
-          in = 0;
-          do {
-            j++;
-            if (strip[i] == cond[j]) in = 1;
-          } while ((j < (condl - 1)) && (cond[j] != ']'));
-          if (j == (condl - 1) && (cond[j] != ']')) {
-            HUNSPELL_WARNING(stderr, "error: missing ] in condition:\n%s\n", warnvar);
-            return 0;
-          }
-          if ((!neg && !in) || (neg && in)) {
-            HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar);
-            return 0;          
-          }
-        }
-      }
-      if (j >= condl) return 1;
-    }
-  } else { // suffix
-    if ((stripl >= condl) && strcmp(strip + stripl - condl, cond) == 0) return 1;
-    if (utf8) {
-    } else {
-      for (i = stripl - 1, j = condl - 1; (i >= 0) && (j >= 0); i--, j--) {
-        if (cond[j] != ']') {
-          if (cond[j] != strip[i]) {
-            HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar);
-          }
-        } else {
-          in = 0;
-          do {
-            j--;
-            if (strip[i] == cond[j]) in = 1;
-          } while ((j > 0) && (cond[j] != '['));
-          if ((j == 0) && (cond[j] != '[')) {
-            HUNSPELL_WARNING(stderr, "error: missing ] in condition:\n%s\n", warnvar);
-            return 0;
-          }
-          neg = (cond[j+1] == '^') ? 1 : 0;
-          if ((!neg && !in) || (neg && in)) {
-            HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar);
-            return 0;          
-          }
-        }
-      }
-      if (j < 0) return 1;
-    }    
-  }
-  return 0;
-}
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/affixmgr.hxx spellcheck/hunspell/src/affixmgr.hxx
--- spellcheck.old/hunspell/src/affixmgr.hxx	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/affixmgr.hxx	1970-01-01 01:00:00.000000000 +0100
@@ -1,272 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef _AFFIXMGR_HXX_
-#define _AFFIXMGR_HXX_
-
-#ifdef MOZILLA_CLIENT
-#ifdef __SUNPRO_CC // for SunONE Studio compiler
-using namespace std;
-#endif
-#include <stdio.h>
-#else
-#include <cstdio>
-#endif
-
-#include "atypes.hxx"
-#include "baseaffix.hxx"
-#include "hashmgr.hxx"
-#include "phonet.hxx"
-
-// check flag duplication
-#define dupSFX        (1 << 0)
-#define dupPFX        (1 << 1)
-
-class AffixMgr
-{
-
-  AffEntry *          pStart[SETSIZE];
-  AffEntry *          sStart[SETSIZE];
-  AffEntry *          pFlag[CONTSIZE];
-  AffEntry *          sFlag[CONTSIZE];
-  HashMgr *           pHMgr;
-  char *              keystring;
-  char *              trystring;
-  char *              encoding;
-  struct cs_info *    csconv;
-  int                 utf8;
-  int                 complexprefixes;
-  FLAG                compoundflag;
-  FLAG                compoundbegin;
-  FLAG                compoundmiddle;
-  FLAG                compoundend;
-  FLAG                compoundroot;
-  FLAG                compoundforbidflag;
-  FLAG                compoundpermitflag;
-  int                 checkcompounddup;
-  int                 checkcompoundrep;
-  int                 checkcompoundcase;
-  int                 checkcompoundtriple;
-  FLAG                forbiddenword;
-  FLAG                nosuggest;
-  FLAG                pseudoroot;
-  int                 cpdmin;
-  int                 numrep;
-  replentry *         reptable;
-  int                 nummap;
-  mapentry *          maptable;
-  int                 numbreak;
-  char **             breaktable;
-  int                 numcheckcpd;
-  replentry *         checkcpdtable;
-  int                 numdefcpd;
-  flagentry *         defcpdtable;
-  phonetable *        phone;
-  int                 maxngramsugs;
-  int                 nosplitsugs;
-  int                 sugswithdots;
-  int                 cpdwordmax;
-  int                 cpdmaxsyllable;
-  char *              cpdvowels;
-  w_char *            cpdvowels_utf16;
-  int                 cpdvowels_utf16_len;
-  char *              cpdsyllablenum;
-  const char *        pfxappnd; // BUG: not stateless
-  const char *        sfxappnd; // BUG: not stateless
-  FLAG                sfxflag;  // BUG: not stateless
-  char *              derived;  // BUG: not stateless
-  AffEntry *          sfx;      // BUG: not stateless
-  AffEntry *          pfx;      // BUG: not stateless
-  int                 checknum;
-  char *              wordchars;
-  unsigned short *    wordchars_utf16;
-  int                 wordchars_utf16_len;
-  char *              ignorechars;
-  unsigned short *    ignorechars_utf16;
-  int                 ignorechars_utf16_len;
-  char *              version;
-  char *              lang;
-  int                 langnum;
-  FLAG                lemma_present;
-  FLAG                circumfix;
-  FLAG                onlyincompound;
-  FLAG                keepcase;
-  int                 checksharps;
-
-  int                 havecontclass; // boolean variable
-  char                contclasses[CONTSIZE]; // flags of possible continuing classes (twofold affix)
-  flag                flag_mode;
-  
-public:
- 
-  AffixMgr(const char * affpath, HashMgr * ptr);
-  ~AffixMgr();
-  struct hentry *     affix_check(const char * word, int len,
-            const unsigned short needflag = (unsigned short) 0, char in_compound = IN_CPD_NOT);
-  struct hentry *     prefix_check(const char * word, int len,
-            char in_compound, const FLAG needflag = FLAG_NULL);
-  inline int isSubset(const char * s1, const char * s2);
-  struct hentry *     prefix_check_twosfx(const char * word, int len,
-            char in_compound, const FLAG needflag = FLAG_NULL);
-  inline int isRevSubset(const char * s1, const char * end_of_s2, int len);
-  struct hentry *     suffix_check(const char * word, int len, int sfxopts, AffEntry* ppfx,
-                        char ** wlst, int maxSug, int * ns, const FLAG cclass = FLAG_NULL,
-                        const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT);
-  struct hentry *     suffix_check_twosfx(const char * word, int len,
-            int sfxopts, AffEntry* ppfx, const FLAG needflag = FLAG_NULL);
-
-  char * affix_check_morph(const char * word, int len,
-                    const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT);
-  char * prefix_check_morph(const char * word, int len,
-                    char in_compound, const FLAG needflag = FLAG_NULL);
-  char * suffix_check_morph (const char * word, int len, int sfxopts, AffEntry * ppfx,
-            const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT);
-
-  char * prefix_check_twosfx_morph(const char * word, int len,
-            char in_compound, const FLAG needflag = FLAG_NULL);
-  char * suffix_check_twosfx_morph(const char * word, int len,
-            int sfxopts, AffEntry * ppfx, const FLAG needflag = FLAG_NULL);
-
-  int                 expand_rootword(struct guessword * wlst, int maxn, const char * ts,
-                        int wl, const unsigned short * ap, unsigned short al, char * bad, int,
-                        char *);
-
-  short               get_syllable (const char * word, int wlen);
-  int                 cpdrep_check(const char * word, int len);
-  int                 cpdpat_check(const char * word, int len);
-  int                 defcpd_check(hentry *** words, short wnum, hentry * rv, hentry ** rwords, char all);
-  int                 cpdcase_check(const char * word, int len);
-  inline int                 candidate_check(const char * word, int len);
-  struct hentry *     compound_check(const char * word, int len,
-                              short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words,
-                              char hu_mov_rule, int * cmpdstemnum, int * cmpdstem, char is_sug);
-
-  int compound_check_morph(const char * word, int len,
-                              short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words,
-                              char hu_mov_rule, char ** result, char * partresult);
-
-  struct hentry *     lookup(const char * word);
-  int                 get_numrep();
-  struct replentry *  get_reptable();
-  struct phonetable * get_phonetable();
-  int                 get_nummap();
-  struct mapentry *   get_maptable();
-  int                 get_numbreak();
-  char **             get_breaktable();
-  char *              get_encoding();
-  int                 get_langnum();
-  char *              get_key_string();
-  char *              get_try_string();
-  const char *        get_wordchars();
-  unsigned short *    get_wordchars_utf16(int * len);
-  char *              get_ignore();
-  unsigned short *    get_ignore_utf16(int * len);
-  int                 get_compound();
-  FLAG                get_compoundflag();
-  FLAG                get_compoundbegin();
-  FLAG                get_forbiddenword();
-  FLAG                get_nosuggest();
-//  FLAG                get_circumfix();
-  FLAG                get_pseudoroot();
-  FLAG                get_onlyincompound();
-  FLAG                get_compoundroot();
-  FLAG                get_lemma_present();
-  int                 get_checknum();
-  char *              get_possible_root();
-  const char *        get_prefix();
-  const char *        get_suffix();
-  const char *        get_derived();
-  const char *        get_version();
-  const int           have_contclass();
-  int                 get_utf8();
-  int                 get_complexprefixes();
-  char *              get_suffixed(char );
-  int                 get_maxngramsugs();
-  int                 get_nosplitsugs();
-  int                 get_sugswithdots(void);
-  FLAG                get_keepcase(void);
-  int                 get_checksharps(void);
-
-private:
-  int  parse_file(const char * affpath);
-//  int  parse_string(char * line, char ** out, const char * name);
-  int  parse_flag(char * line, unsigned short * out, const char * name);
-  int  parse_num(char * line, int * out, const char * name);
-//  int  parse_array(char * line, char ** out, unsigned short ** out_utf16,
-//            int * out_utf16_len, const char * name);
-  int  parse_cpdsyllable(char * line);
-  int  parse_reptable(char * line, FILE * af);
-  int  parse_phonetable(char * line, FILE * af);
-  int  parse_maptable(char * line, FILE * af);
-  int  parse_breaktable(char * line, FILE * af);
-  int  parse_checkcpdtable(char * line, FILE * af);
-  int  parse_defcpdtable(char * line, FILE * af);
-  int  parse_affix(char * line, const char at, FILE * af, char * dupflags);
-
-  int encodeit(struct affentry * ptr, char * cs);
-  int build_pfxtree(AffEntry* pfxptr);
-  int build_sfxtree(AffEntry* sfxptr);
-  int process_pfx_order();
-  int process_sfx_order();
-  AffEntry * process_pfx_in_order(AffEntry * ptr, AffEntry * nptr);
-  AffEntry * process_sfx_in_order(AffEntry * ptr, AffEntry * nptr);
-  int process_pfx_tree_to_list();
-  int process_sfx_tree_to_list();
-  int redundant_condition(char, char * strip, int stripl, const char * cond, char *);
-};
-
-#endif
-
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/atypes.hxx spellcheck/hunspell/src/atypes.hxx
--- spellcheck.old/hunspell/src/atypes.hxx	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/atypes.hxx	1970-01-01 01:00:00.000000000 +0100
@@ -1,154 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef _ATYPES_HXX_
-#define _ATYPES_HXX_
-
-#ifndef HUNSPELL_WARNING
-#ifdef HUNSPELL_WARNING_ON
-#define HUNSPELL_WARNING fprintf
-#else
-// empty inline function to switch off warnings (instead of the C99 standard variadic macros)
-static inline void HUNSPELL_WARNING(FILE *, const char *, ...) {}
-#endif
-#endif
-
-// HUNSTEM def.
-#define HUNSTEM
-
-#include "csutil.hxx"
-#include "hashmgr.hxx"
-
-#define SETSIZE         256
-#define CONTSIZE        65536
-#define MAXWORDLEN      100
-#define MAXWORDUTF8LEN  256
-
-// affentry options
-#define aeXPRODUCT      (1 << 0)
-#define aeUTF8          (1 << 1)
-#define aeALIASF        (1 << 2)
-#define aeALIASM        (1 << 3)
-#define aeINFIX         (1 << 4)
-
-// compound options
-#define IN_CPD_NOT   0
-#define IN_CPD_BEGIN 1
-#define IN_CPD_END   2
-#define IN_CPD_OTHER 3
-
-#define MAXLNLEN        8192
-
-#define MINCPDLEN       3
-#define MAXCOMPOUND     10
-
-#define MAXACC          1000
-
-#define FLAG unsigned short
-#define FLAG_NULL 0x00
-#define FREE_FLAG(a) a = 0
-
-#define TESTAFF( a, b , c ) flag_bsearch((unsigned short *) a, (unsigned short) b, c)
-
-struct affentry
-{
-   char * strip;
-   char * appnd;
-   unsigned char stripl;
-   unsigned char appndl;
-   char  numconds;
-   char  opts;
-   unsigned short aflag;
-   union {
-        char   base[SETSIZE];
-        struct {
-                char ascii[SETSIZE/2];
-                char neg[8];
-                char all[8];
-                w_char * wchars[8];
-                int wlen[8];
-        } utf8;
-   } conds;
-#ifdef HUNSPELL_EXPERIMENTAL
-   char *       morphcode;
-#endif
-   unsigned short * contclass;
-   short        contclasslen;
-};
-
-struct mapentry {
-  char * set;
-  w_char * set_utf16;
-  int len;
-};
-
-struct flagentry {
-  FLAG * def;
-  int len;
-};
-
-struct guessword {
-  char * word;
-  bool allow;
-  char * orig;
-};
-
-#endif
-
-
-
-
-
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/baseaffix.hxx spellcheck/hunspell/src/baseaffix.hxx
--- spellcheck.old/hunspell/src/baseaffix.hxx	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/baseaffix.hxx	1970-01-01 01:00:00.000000000 +0100
@@ -1,87 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef _BASEAFF_HXX_
-#define _BASEAFF_HXX_
-
-class AffEntry
-{
-public:
-
-protected:
-       char *       appnd;
-       char *       strip;
-       unsigned char  appndl;
-       unsigned char  stripl;
-       char         numconds;
-       char  opts;
-       unsigned short aflag;
-       union {
-         char   base[SETSIZE];
-         struct {
-                char  ascii[SETSIZE/2];
-                char neg[8];
-                char all[8];
-                w_char * wchars[8];
-                int wlen[8];
-         } utf8;
-       } conds;
-       char *       morphcode;
-       unsigned short * contclass;
-       short        contclasslen;
-};
-
-#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/csutil.cpp spellcheck/hunspell/src/csutil.cpp
--- spellcheck.old/hunspell/src/csutil.cpp	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/csutil.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,5400 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef MOZILLA_CLIENT
-#include <cstdlib>
-#include <cstring>
-#include <cstdio>
-#include <cctype>
-#else
-#include <stdlib.h> 
-#include <string.h>
-#include <stdio.h> 
-#include <ctype.h>
-#endif
-
-#include "csutil.hxx"
-#include "atypes.hxx"
-#include "langnum.hxx"
-
-#ifdef OPENOFFICEORG
-#  include <unicode/uchar.h>
-#else
-#  ifndef MOZILLA_CLIENT
-#    include "utf_info.cxx"
-#    define UTF_LST_LEN (sizeof(utf_lst) / (sizeof(unicode_info)))
-#  endif
-#endif
-
-#ifdef MOZILLA_CLIENT
-#include "nsCOMPtr.h"
-#include "nsServiceManagerUtils.h"
-#include "nsIUnicodeEncoder.h"
-#include "nsIUnicodeDecoder.h"
-#include "nsICaseConversion.h"
-#include "nsICharsetConverterManager.h"
-#include "nsUnicharUtilCIID.h"
-#include "nsUnicharUtils.h"
-
-static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
-static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
-#endif
-
-#ifdef MOZILLA_CLIENT
-#ifdef __SUNPRO_CC // for SunONE Studio compiler
-using namespace std;
-#endif
-#else
-#ifndef W32
-using namespace std;
-#endif
-#endif
-
-static struct unicode_info2 * utf_tbl = NULL;
-static int utf_tbl_count = 0; // utf_tbl can be used by multiple Hunspell instances
-
-/* only UTF-16 (BMP) implementation */
-char * u16_u8(char * dest, int size, const w_char * src, int srclen) {
-    char * u8 = dest;
-    char * u8_max = u8 + size;
-    const w_char * u2 = src;
-    const w_char * u2_max = src + srclen;
-    while ((u2 < u2_max) && (u8 < u8_max)) {
-        if (u2->h) { // > 0xFF
-            // XXX 4-byte haven't implemented yet.
-            if (u2->h >= 0x08) {   // >= 0x800 (3-byte UTF-8 character)
-                *u8 = 0xe0 + (u2->h >> 4);
-                u8++;
-                if (u8 < u8_max) {
-                    *u8 = 0x80 + ((u2->h & 0xf) << 2) + (u2->l >> 6);
-                    u8++;
-                    if (u8 < u8_max) {
-                        *u8 = 0x80 + (u2->l & 0x3f);
-                        u8++;
-                    }
-                }
-            } else { // < 0x800 (2-byte UTF-8 character)
-                *u8 = 0xc0 + (u2->h << 2) + (u2->l >> 6);
-                u8++;
-                if (u8 < u8_max) {
-                    *u8 = 0x80 + (u2->l & 0x3f);
-                    u8++;
-                }
-            }
-        } else { // <= 0xFF
-            if (u2->l & 0x80) { // >0x80 (2-byte UTF-8 character)
-                *u8 = 0xc0 + (u2->l >> 6);
-                u8++;
-                if (u8 < u8_max) {
-                    *u8 = 0x80 + (u2->l & 0x3f);
-                    u8++;
-                }
-            } else { // < 0x80 (1-byte UTF-8 character)
-                *u8 = u2->l;
-                u8++;
-            }
-        }
-        u2++;
-    }
-    *u8 = '\0';
-    return dest;
-}
-
-
-/* only UTF-16 (BMP) implementation */
-int u8_u16(w_char * dest, int size, const char * src) {
-    const char * u8 = src;
-    w_char * u2 = dest;
-    w_char * u2_max = u2 + size;
-    
-    while ((u2 < u2_max) && *u8) {
-    switch ((*u8) & 0xf0) {
-        case 0x00:
-        case 0x10:
-        case 0x20:
-        case 0x30:
-        case 0x40:
-        case 0x50:
-        case 0x60:
-        case 0x70: {
-            u2->h = 0;
-            u2->l = *u8;
-            break;
-        }
-        case 0x80:
-        case 0x90:
-        case 0xa0:
-        case 0xb0: {
-            HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Unexpected continuation bytes in %d. character position\n%s\n", u8 - src, src);    
-            u2->h = 0xff;
-            u2->l = 0xfd;
-            break;
-        }
-        case 0xc0:
-        case 0xd0: {    // 2-byte UTF-8 codes
-            if ((*(u8+1) & 0xc0) == 0x80) {
-                u2->h = (*u8 & 0x1f) >> 2;
-                u2->l = (*u8 << 6) + (*(u8+1) & 0x3f);
-                u8++;
-            } else {
-                HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %d. character position:\n%s\n", u8 - src, src);
-                u2->h = 0xff;
-                u2->l = 0xfd;
-            }
-            break;
-        }
-        case 0xe0: {    // 3-byte UTF-8 codes
-            if ((*(u8+1) & 0xc0) == 0x80) {
-                u2->h = ((*u8 & 0x0f) << 4) + ((*(u8+1) & 0x3f) >> 2);
-                u8++;
-                if ((*(u8+1) & 0xc0) == 0x80) {
-                    u2->l = (*u8 << 6) + (*(u8+1) & 0x3f);
-                    u8++;
-                } else {
-                    HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %d. character position:\n%s\n", u8 - src, src);
-                    u2->h = 0xff;
-                    u2->l = 0xfd;
-                }
-            } else {
-                HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %d. character position:\n%s\n", u8 - src, src);
-                u2->h = 0xff;
-                u2->l = 0xfd;
-            }
-            break;
-        }
-        case 0xf0: {    // 4 or more byte UTF-8 codes
-            HUNSPELL_WARNING(stderr, "This UTF-8 encoding can't convert to UTF-16:\n%s\n", src);
-            u2->h = 0xff;
-            u2->l = 0xfd;
-            return -1;
-        }
-    }
-    u8++;
-    u2++;
-    }
-    return u2 - dest;
-}
-
-void flag_qsort(unsigned short flags[], int begin, int end) {
-    unsigned short reg;
-    if (end > begin) {
-        unsigned short pivot = flags[begin];
-        int l = begin + 1;
-        int r = end;
-        while(l < r) {
-            if (flags[l] <= pivot) {
-                l++;
-            } else {
-             r--;
-             reg = flags[l];
-             flags[l] = flags[r];
-             flags[r] = reg;
-          }
-       }
-       l--;
-       reg = flags[begin];
-       flags[begin] = flags[l];
-       flags[l] = reg;
-
-       flag_qsort(flags, begin, l);
-       flag_qsort(flags, r, end);
-    }
- }
-
-int flag_bsearch(unsigned short flags[], unsigned short flag, int length) {
-   int mid;
-   int left = 0;
-   int right = length - 1;
-   while (left <= right) {
-      mid = (left + right) / 2;
-      if (flags[mid] == flag) return 1;
-      if (flag < flags[mid]) right = mid - 1;
-      else left = mid + 1;
-   }
-   return 0;
-}
-
- // strip strings into token based on single char delimiter
- // acts like strsep() but only uses a delim char and not
- // a delim string
- // default delimiter: white space characters
- 
- char * mystrsep(char ** stringp, const char delim)
- {
-   char * rv = NULL;
-   char * mp = *stringp;
-   int n = strlen(mp);
-   if (n > 0) {
-      char * dp;
-      if (delim) {
-        dp = (char *)memchr(mp,(int)((unsigned char)delim),n);
-      } else {
-        // don't use isspace() here, the string can be in some random charset
-        // that's way different than the locale's
-        for (dp = mp; (*dp && *dp != ' ' && *dp != '\t'); dp++);
-        if (!*dp) dp = NULL;
-      }
-      if (dp) {
-         *stringp = dp+1;
-         int nc = (int)((unsigned long)dp - (unsigned long)mp);
-         rv = (char *) malloc(nc+1);
-	 if (rv) {
-            memcpy(rv,mp,nc);
-            *(rv+nc) = '\0';
-            return rv;
-	 }
-      } else {
-         rv = (char *) malloc(n+1);
-         if (rv) {
-    	    memcpy(rv, mp, n);
-            *(rv+n) = '\0';
-            *stringp = mp + n;
-            return rv;
-         }
-      }
-   }
-   return NULL;
- }
-
- 
- // replaces strdup with ansi version
- char * mystrdup(const char * s)
- {
-   char * d = NULL;
-   if (s) {
-      int sl = strlen(s);
-      d = (char *) malloc(((sl+1) * sizeof(char)));
-      if (d) memcpy(d,s,((sl+1)*sizeof(char)));
-   }
-   return d;
- }
- 
- 
- // remove cross-platform text line end characters
- void mychomp(char * s)
- {
-   int k = strlen(s);
-   if ((k > 0) && ((*(s+k-1)=='\r') || (*(s+k-1)=='\n'))) *(s+k-1) = '\0';
-   if ((k > 1) && (*(s+k-2) == '\r')) *(s+k-2) = '\0';
- }
- 
- 
- //  does an ansi strdup of the reverse of a string
- char * myrevstrdup(const char * s)
- {
-     char * d = NULL;
-     if (s) {
-        int sl = strlen(s);
-        d = (char *) malloc((sl+1) * sizeof(char));
-        if (d) {
-          const char * p = s + sl - 1;
-          char * q = d;
-          while (p >= s) *q++ = *p--;
-          *q = '\0';
-        }
-     }
-     return d;
- }
-
-#ifdef HUNSPELL_EXPERIMENTAL
- // append s to ends of every lines in text
- void strlinecat(char * dest, const char * s)
- {
-    char * dup = mystrdup(dest);
-    char * source = dup;
-    int len = strlen(s);
-    while (*source) {
-        if (*source == '\n') {
-            strncpy(dest, s, len);
-            dest += len;
-        }
-        *dest = *source;
-        source++; dest++;
-    }
-    strcpy(dest, s);
-    free(dup);
- }
-
-// break text to lines
-// return number of lines
-int line_tok(const char * text, char *** lines) {
-    int linenum = 0;
-    char * dup = mystrdup(text);
-    char * p = strchr(dup, '\n');
-    while (p) {
-        linenum++;
-        *p = '\0';
-        p++;
-        p = strchr(p, '\n');
-    }
-    *lines = (char **) calloc(linenum + 1, sizeof(char *));
-    if (!(*lines)) return -1;
-
-    p = dup; 
-    for (int i = 0; i < linenum + 1; i++) {
-        (*lines)[i] = mystrdup(p);
-        p += strlen(p) + 1;
-    }
-    free(dup);
-    return linenum;
-}
-
-// uniq line in place
-char * line_uniq(char * text) {
-    char ** lines;
-    int linenum = line_tok(text, &lines);
-    int i;
-    strcpy(text, lines[0]);
-    for ( i = 1; i<=linenum; i++ ) {
-        int dup = 0;
-        for (int j = 0; j < i; j++) {
-            if (strcmp(lines[i], lines[j]) == 0) dup = 1;
-        }
-        if (!dup) {
-            if ((i > 1) || (*(lines[0]) != '\0')) strcat(text, "\n");
-            strcat(text, lines[i]);
-        }
-    }
-    for ( i = 0; i<=linenum; i++ ) {
-        if (lines[i]) free(lines[i]);
-    }
-    if (lines) free(lines);
-    return text;
-}
-
-// change \n to char c
-char * line_join(char * text, char c) {
-    char * p;
-    for (p = text; *p; p++) if (*p == '\n') *p = c;
-    return text;
-}
-
-// leave only last {[^}]*} substring for handling zero morphemes
-char * delete_zeros(char * morphout) {
-    char * p = morphout;
-    char * q = p;
-    char * q2 = NULL;
-    int suffix = 0;
-    
-    for (;*p && *(p+1);) {
-        switch (*p) {
-            case '{': 
-                q2 = q;
-                q--;
-                break;
-            case '}':
-                if (q2) {
-                    suffix = 1;
-                    q--;
-                }
-                break; 
-            default:
-                if (suffix) {
-                    q = q2;
-                }
-                suffix = 0;
-                *q = *p;
-        }
-        p++;
-        q++;
-    }
-    *q = '\0';
-    return morphout;
-}
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
-char * mystrrep(char * word, const char * pat, const char * rep) {
-    char * pos = strstr(word, pat);
-    if (pos) {
-        int replen = strlen(rep);
-        int patlen = strlen(pat);
-        if (replen < patlen) {
-            char * end = word + strlen(word);
-            char * next = pos + replen;
-            char * prev = pos + strlen(pat);
-            for (; prev < end; *next = *prev, prev++, next++);
-            *next = '\0';
-        } else if (replen > patlen) {
-            char * end = pos + patlen;
-            char * next = word + strlen(word) + replen - patlen;
-            char * prev = next - replen + patlen;
-            for (; prev >= end; *next = *prev, prev--, next--);
-        }
-        strncpy(pos, rep, replen);
-    }
-    return word;
-}
-
- // reverse word 
- int reverseword(char * word) {
-   char r;
-   for (char * dest = word + strlen(word) - 1; word < dest; word++, dest--) {
-     r=*word;
-     *word = *dest;
-     *dest = r;
-   }
-   return 0;
- }
-
- // reverse word (error: 1)
- int reverseword_utf(char * word) {
-   w_char w[MAXWORDLEN];
-   w_char * p;
-   w_char r;
-   int l = u8_u16(w, MAXWORDLEN, word);
-   if (l == -1) return 1;
-   p = w;
-   for (w_char * dest = w + l - 1; p < dest; p++, dest--) {
-     r=*p;
-     *p = *dest;
-     *dest = r;
-   }
-   u16_u8(word, MAXWORDUTF8LEN, w, l);
-   return 0;
- }
- 
- // convert null terminated string to all caps
- void mkallcap(char * p, const struct cs_info * csconv)
- {
-   while (*p != '\0') {
-     *p = csconv[((unsigned char) *p)].cupper;
-     p++;
-   }
- }
-  
- // convert null terminated string to all little
- void mkallsmall(char * p, const struct cs_info * csconv)
- {
-   while (*p != '\0') {
-     *p = csconv[((unsigned char) *p)].clower;
-     p++;
-   }
- }
-
-void mkallsmall_utf(w_char * u, int nc, int langnum) {
-    for (int i = 0; i < nc; i++) {
-        unsigned short idx = (u[i].h << 8) + u[i].l;
-        if (idx != unicodetolower(idx, langnum)) {
-            u[i].h = (unsigned char) (unicodetolower(idx, langnum) >> 8);
-            u[i].l = (unsigned char) (unicodetolower(idx, langnum) & 0x00FF);
-        }
-    }
-}
-
-void mkallcap_utf(w_char * u, int nc, int langnum) {
-    for (int i = 0; i < nc; i++) {
-        unsigned short idx = (u[i].h << 8) + u[i].l;
-        if (idx != unicodetoupper(idx, langnum)) {
-            u[i].h = (unsigned char) (unicodetoupper(idx, langnum) >> 8);
-            u[i].l = (unsigned char) (unicodetoupper(idx, langnum) & 0x00FF);
-        }
-    }
-}
- 
- // convert null terminated string to have intial capital
- void mkinitcap(char * p, const struct cs_info * csconv)
- {
-   if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper;
- }
-
-#ifndef MOZILLA_CLIENT
- // convert null terminated string to all caps using encoding
- void enmkallcap(char * d, const char * p, const char * encoding)
- 
- {
-   struct cs_info * csconv = get_current_cs(encoding);
-   while (*p != '\0') {
-     *d++ = csconv[((unsigned char) *p)].cupper;
-     p++;
-   }
-   *d = '\0';
- }
-
- // convert null terminated string to all little using encoding
- void enmkallsmall(char * d, const char * p, const char * encoding)
- {
-   struct cs_info * csconv = get_current_cs(encoding);
-   while (*p != '\0') {
-     *d++ = csconv[((unsigned char) *p)].clower;
-     p++;
-   }
-   *d = '\0';
- }
-
- // convert null terminated string to have intial capital using encoding
- void enmkinitcap(char * d, const char * p, const char * encoding)
- {
-   struct cs_info * csconv = get_current_cs(encoding);
-   memcpy(d,p,(strlen(p)+1));
-   if (*p != '\0') *d= csconv[((unsigned char)*p)].cupper;
- }
-
-// these are simple character mappings for the 
-// encodings supported
-// supplying isupper, tolower, and toupper
-
-struct cs_info iso1_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x00, 0xa1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x00, 0xa3, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x00, 0xa5, 0xa5 },
-{ 0x00, 0xa6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa8 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x00, 0xaa, 0xaa },
-{ 0x00, 0xab, 0xab },
-{ 0x00, 0xac, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x00, 0xaf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xb1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x00, 0xb3, 0xb3 },
-{ 0x00, 0xb4, 0xb4 },
-{ 0x00, 0xb5, 0xb5 },
-{ 0x00, 0xb6, 0xb6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xb8 },
-{ 0x00, 0xb9, 0xb9 },
-{ 0x00, 0xba, 0xba },
-{ 0x00, 0xbb, 0xbb },
-{ 0x00, 0xbc, 0xbc },
-{ 0x00, 0xbd, 0xbd },
-{ 0x00, 0xbe, 0xbe },
-{ 0x00, 0xbf, 0xbf },
-{ 0x01, 0xe0, 0xc0 },
-{ 0x01, 0xe1, 0xc1 },
-{ 0x01, 0xe2, 0xc2 },
-{ 0x01, 0xe3, 0xc3 },
-{ 0x01, 0xe4, 0xc4 },
-{ 0x01, 0xe5, 0xc5 },
-{ 0x01, 0xe6, 0xc6 },
-{ 0x01, 0xe7, 0xc7 },
-{ 0x01, 0xe8, 0xc8 },
-{ 0x01, 0xe9, 0xc9 },
-{ 0x01, 0xea, 0xca },
-{ 0x01, 0xeb, 0xcb },
-{ 0x01, 0xec, 0xcc },
-{ 0x01, 0xed, 0xcd },
-{ 0x01, 0xee, 0xce },
-{ 0x01, 0xef, 0xcf },
-{ 0x01, 0xf0, 0xd0 },
-{ 0x01, 0xf1, 0xd1 },
-{ 0x01, 0xf2, 0xd2 },
-{ 0x01, 0xf3, 0xd3 },
-{ 0x01, 0xf4, 0xd4 },
-{ 0x01, 0xf5, 0xd5 },
-{ 0x01, 0xf6, 0xd6 },
-{ 0x00, 0xd7, 0xd7 },
-{ 0x01, 0xf8, 0xd8 },
-{ 0x01, 0xf9, 0xd9 },
-{ 0x01, 0xfa, 0xda },
-{ 0x01, 0xfb, 0xdb },
-{ 0x01, 0xfc, 0xdc },
-{ 0x01, 0xfd, 0xdd },
-{ 0x01, 0xfe, 0xde },
-{ 0x00, 0xdf, 0xdf },
-{ 0x00, 0xe0, 0xc0 },
-{ 0x00, 0xe1, 0xc1 },
-{ 0x00, 0xe2, 0xc2 },
-{ 0x00, 0xe3, 0xc3 },
-{ 0x00, 0xe4, 0xc4 },
-{ 0x00, 0xe5, 0xc5 },
-{ 0x00, 0xe6, 0xc6 },
-{ 0x00, 0xe7, 0xc7 },
-{ 0x00, 0xe8, 0xc8 },
-{ 0x00, 0xe9, 0xc9 },
-{ 0x00, 0xea, 0xca },
-{ 0x00, 0xeb, 0xcb },
-{ 0x00, 0xec, 0xcc },
-{ 0x00, 0xed, 0xcd },
-{ 0x00, 0xee, 0xce },
-{ 0x00, 0xef, 0xcf },
-{ 0x00, 0xf0, 0xd0 },
-{ 0x00, 0xf1, 0xd1 },
-{ 0x00, 0xf2, 0xd2 },
-{ 0x00, 0xf3, 0xd3 },
-{ 0x00, 0xf4, 0xd4 },
-{ 0x00, 0xf5, 0xd5 },
-{ 0x00, 0xf6, 0xd6 },
-{ 0x00, 0xf7, 0xf7 },
-{ 0x00, 0xf8, 0xd8 },
-{ 0x00, 0xf9, 0xd9 },
-{ 0x00, 0xfa, 0xda },
-{ 0x00, 0xfb, 0xdb },
-{ 0x00, 0xfc, 0xdc },
-{ 0x00, 0xfd, 0xdd },
-{ 0x00, 0xfe, 0xde },
-{ 0x00, 0xff, 0xff },
-};
-
-
-struct cs_info iso2_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x01, 0xb1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x01, 0xb3, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x01, 0xb5, 0xa5 },
-{ 0x01, 0xb6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa8 },
-{ 0x01, 0xb9, 0xa9 },
-{ 0x01, 0xba, 0xaa },
-{ 0x01, 0xbb, 0xab },
-{ 0x01, 0xbc, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x01, 0xbe, 0xae },
-{ 0x01, 0xbf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xa1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x00, 0xb3, 0xa3 },
-{ 0x00, 0xb4, 0xb4 },
-{ 0x00, 0xb5, 0xa5 },
-{ 0x00, 0xb6, 0xa6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xb8 },
-{ 0x00, 0xb9, 0xa9 },
-{ 0x00, 0xba, 0xaa },
-{ 0x00, 0xbb, 0xab },
-{ 0x00, 0xbc, 0xac },
-{ 0x00, 0xbd, 0xbd },
-{ 0x00, 0xbe, 0xae },
-{ 0x00, 0xbf, 0xaf },
-{ 0x01, 0xe0, 0xc0 },
-{ 0x01, 0xe1, 0xc1 },
-{ 0x01, 0xe2, 0xc2 },
-{ 0x01, 0xe3, 0xc3 },
-{ 0x01, 0xe4, 0xc4 },
-{ 0x01, 0xe5, 0xc5 },
-{ 0x01, 0xe6, 0xc6 },
-{ 0x01, 0xe7, 0xc7 },
-{ 0x01, 0xe8, 0xc8 },
-{ 0x01, 0xe9, 0xc9 },
-{ 0x01, 0xea, 0xca },
-{ 0x01, 0xeb, 0xcb },
-{ 0x01, 0xec, 0xcc },
-{ 0x01, 0xed, 0xcd },
-{ 0x01, 0xee, 0xce },
-{ 0x01, 0xef, 0xcf },
-{ 0x01, 0xf0, 0xd0 },
-{ 0x01, 0xf1, 0xd1 },
-{ 0x01, 0xf2, 0xd2 },
-{ 0x01, 0xf3, 0xd3 },
-{ 0x01, 0xf4, 0xd4 },
-{ 0x01, 0xf5, 0xd5 },
-{ 0x01, 0xf6, 0xd6 },
-{ 0x00, 0xd7, 0xd7 },
-{ 0x01, 0xf8, 0xd8 },
-{ 0x01, 0xf9, 0xd9 },
-{ 0x01, 0xfa, 0xda },
-{ 0x01, 0xfb, 0xdb },
-{ 0x01, 0xfc, 0xdc },
-{ 0x01, 0xfd, 0xdd },
-{ 0x01, 0xfe, 0xde },
-{ 0x00, 0xdf, 0xdf },
-{ 0x00, 0xe0, 0xc0 },
-{ 0x00, 0xe1, 0xc1 },
-{ 0x00, 0xe2, 0xc2 },
-{ 0x00, 0xe3, 0xc3 },
-{ 0x00, 0xe4, 0xc4 },
-{ 0x00, 0xe5, 0xc5 },
-{ 0x00, 0xe6, 0xc6 },
-{ 0x00, 0xe7, 0xc7 },
-{ 0x00, 0xe8, 0xc8 },
-{ 0x00, 0xe9, 0xc9 },
-{ 0x00, 0xea, 0xca },
-{ 0x00, 0xeb, 0xcb },
-{ 0x00, 0xec, 0xcc },
-{ 0x00, 0xed, 0xcd },
-{ 0x00, 0xee, 0xce },
-{ 0x00, 0xef, 0xcf },
-{ 0x00, 0xf0, 0xd0 },
-{ 0x00, 0xf1, 0xd1 },
-{ 0x00, 0xf2, 0xd2 },
-{ 0x00, 0xf3, 0xd3 },
-{ 0x00, 0xf4, 0xd4 },
-{ 0x00, 0xf5, 0xd5 },
-{ 0x00, 0xf6, 0xd6 },
-{ 0x00, 0xf7, 0xf7 },
-{ 0x00, 0xf8, 0xd8 },
-{ 0x00, 0xf9, 0xd9 },
-{ 0x00, 0xfa, 0xda },
-{ 0x00, 0xfb, 0xdb },
-{ 0x00, 0xfc, 0xdc },
-{ 0x00, 0xfd, 0xdd },
-{ 0x00, 0xfe, 0xde },
-{ 0x00, 0xff, 0xff },
-};
-
-
-struct cs_info iso3_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x01, 0xb1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x00, 0xa3, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x00, 0xa5, 0xa5 },
-{ 0x01, 0xb6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa8 },
-{ 0x01, 0x69, 0xa9 },
-{ 0x01, 0xba, 0xaa },
-{ 0x01, 0xbb, 0xab },
-{ 0x01, 0xbc, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x01, 0xbf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xa1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x00, 0xb3, 0xb3 },
-{ 0x00, 0xb4, 0xb4 },
-{ 0x00, 0xb5, 0xb5 },
-{ 0x00, 0xb6, 0xa6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xb8 },
-{ 0x00, 0xb9, 0x49 },
-{ 0x00, 0xba, 0xaa },
-{ 0x00, 0xbb, 0xab },
-{ 0x00, 0xbc, 0xac },
-{ 0x00, 0xbd, 0xbd },
-{ 0x00, 0xbe, 0xbe },
-{ 0x00, 0xbf, 0xaf },
-{ 0x01, 0xe0, 0xc0 },
-{ 0x01, 0xe1, 0xc1 },
-{ 0x01, 0xe2, 0xc2 },
-{ 0x00, 0xc3, 0xc3 },
-{ 0x01, 0xe4, 0xc4 },
-{ 0x01, 0xe5, 0xc5 },
-{ 0x01, 0xe6, 0xc6 },
-{ 0x01, 0xe7, 0xc7 },
-{ 0x01, 0xe8, 0xc8 },
-{ 0x01, 0xe9, 0xc9 },
-{ 0x01, 0xea, 0xca },
-{ 0x01, 0xeb, 0xcb },
-{ 0x01, 0xec, 0xcc },
-{ 0x01, 0xed, 0xcd },
-{ 0x01, 0xee, 0xce },
-{ 0x01, 0xef, 0xcf },
-{ 0x00, 0xd0, 0xd0 },
-{ 0x01, 0xf1, 0xd1 },
-{ 0x01, 0xf2, 0xd2 },
-{ 0x01, 0xf3, 0xd3 },
-{ 0x01, 0xf4, 0xd4 },
-{ 0x01, 0xf5, 0xd5 },
-{ 0x01, 0xf6, 0xd6 },
-{ 0x00, 0xd7, 0xd7 },
-{ 0x01, 0xf8, 0xd8 },
-{ 0x01, 0xf9, 0xd9 },
-{ 0x01, 0xfa, 0xda },
-{ 0x01, 0xfb, 0xdb },
-{ 0x01, 0xfc, 0xdc },
-{ 0x01, 0xfd, 0xdd },
-{ 0x01, 0xfe, 0xde },
-{ 0x00, 0xdf, 0xdf },
-{ 0x00, 0xe0, 0xc0 },
-{ 0x00, 0xe1, 0xc1 },
-{ 0x00, 0xe2, 0xc2 },
-{ 0x00, 0xe3, 0xe3 },
-{ 0x00, 0xe4, 0xc4 },
-{ 0x00, 0xe5, 0xc5 },
-{ 0x00, 0xe6, 0xc6 },
-{ 0x00, 0xe7, 0xc7 },
-{ 0x00, 0xe8, 0xc8 },
-{ 0x00, 0xe9, 0xc9 },
-{ 0x00, 0xea, 0xca },
-{ 0x00, 0xeb, 0xcb },
-{ 0x00, 0xec, 0xcc },
-{ 0x00, 0xed, 0xcd },
-{ 0x00, 0xee, 0xce },
-{ 0x00, 0xef, 0xcf },
-{ 0x00, 0xf0, 0xf0 },
-{ 0x00, 0xf1, 0xd1 },
-{ 0x00, 0xf2, 0xd2 },
-{ 0x00, 0xf3, 0xd3 },
-{ 0x00, 0xf4, 0xd4 },
-{ 0x00, 0xf5, 0xd5 },
-{ 0x00, 0xf6, 0xd6 },
-{ 0x00, 0xf7, 0xf7 },
-{ 0x00, 0xf8, 0xd8 },
-{ 0x00, 0xf9, 0xd9 },
-{ 0x00, 0xfa, 0xda },
-{ 0x00, 0xfb, 0xdb },
-{ 0x00, 0xfc, 0xdc },
-{ 0x00, 0xfd, 0xdd },
-{ 0x00, 0xfe, 0xde },
-{ 0x00, 0xff, 0xff },
-};
-
-struct cs_info iso4_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x01, 0xb1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x01, 0xb3, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x01, 0xb5, 0xa5 },
-{ 0x01, 0xb6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa8 },
-{ 0x01, 0xb9, 0xa9 },
-{ 0x01, 0xba, 0xaa },
-{ 0x01, 0xbb, 0xab },
-{ 0x01, 0xbc, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x01, 0xbe, 0xae },
-{ 0x00, 0xaf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xa1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x00, 0xb3, 0xa3 },
-{ 0x00, 0xb4, 0xb4 },
-{ 0x00, 0xb5, 0xa5 },
-{ 0x00, 0xb6, 0xa6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xb8 },
-{ 0x00, 0xb9, 0xa9 },
-{ 0x00, 0xba, 0xaa },
-{ 0x00, 0xbb, 0xab },
-{ 0x00, 0xbc, 0xac },
-{ 0x00, 0xbd, 0xbd },
-{ 0x00, 0xbe, 0xae },
-{ 0x00, 0xbf, 0xbf },
-{ 0x01, 0xe0, 0xc0 },
-{ 0x01, 0xe1, 0xc1 },
-{ 0x01, 0xe2, 0xc2 },
-{ 0x01, 0xe3, 0xc3 },
-{ 0x01, 0xe4, 0xc4 },
-{ 0x01, 0xe5, 0xc5 },
-{ 0x01, 0xe6, 0xc6 },
-{ 0x01, 0xe7, 0xc7 },
-{ 0x01, 0xe8, 0xc8 },
-{ 0x01, 0xe9, 0xc9 },
-{ 0x01, 0xea, 0xca },
-{ 0x01, 0xeb, 0xcb },
-{ 0x01, 0xec, 0xcc },
-{ 0x01, 0xed, 0xcd },
-{ 0x01, 0xee, 0xce },
-{ 0x01, 0xef, 0xcf },
-{ 0x01, 0xf0, 0xd0 },
-{ 0x01, 0xf1, 0xd1 },
-{ 0x01, 0xf2, 0xd2 },
-{ 0x01, 0xf3, 0xd3 },
-{ 0x01, 0xf4, 0xd4 },
-{ 0x01, 0xf5, 0xd5 },
-{ 0x01, 0xf6, 0xd6 },
-{ 0x00, 0xd7, 0xd7 },
-{ 0x01, 0xf8, 0xd8 },
-{ 0x01, 0xf9, 0xd9 },
-{ 0x01, 0xfa, 0xda },
-{ 0x01, 0xfb, 0xdb },
-{ 0x01, 0xfc, 0xdc },
-{ 0x01, 0xfd, 0xdd },
-{ 0x01, 0xfe, 0xde },
-{ 0x00, 0xdf, 0xdf },
-{ 0x00, 0xe0, 0xc0 },
-{ 0x00, 0xe1, 0xc1 },
-{ 0x00, 0xe2, 0xc2 },
-{ 0x00, 0xe3, 0xc3 },
-{ 0x00, 0xe4, 0xc4 },
-{ 0x00, 0xe5, 0xc5 },
-{ 0x00, 0xe6, 0xc6 },
-{ 0x00, 0xe7, 0xc7 },
-{ 0x00, 0xe8, 0xc8 },
-{ 0x00, 0xe9, 0xc9 },
-{ 0x00, 0xea, 0xca },
-{ 0x00, 0xeb, 0xcb },
-{ 0x00, 0xec, 0xcc },
-{ 0x00, 0xed, 0xcd },
-{ 0x00, 0xee, 0xce },
-{ 0x00, 0xef, 0xcf },
-{ 0x00, 0xf0, 0xd0 },
-{ 0x00, 0xf1, 0xd1 },
-{ 0x00, 0xf2, 0xd2 },
-{ 0x00, 0xf3, 0xd3 },
-{ 0x00, 0xf4, 0xd4 },
-{ 0x00, 0xf5, 0xd5 },
-{ 0x00, 0xf6, 0xd6 },
-{ 0x00, 0xf7, 0xf7 },
-{ 0x00, 0xf8, 0xd8 },
-{ 0x00, 0xf9, 0xd9 },
-{ 0x00, 0xfa, 0xda },
-{ 0x00, 0xfb, 0xdb },
-{ 0x00, 0xfc, 0xdc },
-{ 0x00, 0xfd, 0xdd },
-{ 0x00, 0xfe, 0xde },
-{ 0x00, 0xff, 0xff },
-};
-
-struct cs_info iso5_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x01, 0xf1, 0xa1 },
-{ 0x01, 0xf2, 0xa2 },
-{ 0x01, 0xf3, 0xa3 },
-{ 0x01, 0xf4, 0xa4 },
-{ 0x01, 0xf5, 0xa5 },
-{ 0x01, 0xf6, 0xa6 },
-{ 0x01, 0xf7, 0xa7 },
-{ 0x01, 0xf8, 0xa8 },
-{ 0x01, 0xf9, 0xa9 },
-{ 0x01, 0xfa, 0xaa },
-{ 0x01, 0xfb, 0xab },
-{ 0x01, 0xfc, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x01, 0xfe, 0xae },
-{ 0x01, 0xff, 0xaf },
-{ 0x01, 0xd0, 0xb0 },
-{ 0x01, 0xd1, 0xb1 },
-{ 0x01, 0xd2, 0xb2 },
-{ 0x01, 0xd3, 0xb3 },
-{ 0x01, 0xd4, 0xb4 },
-{ 0x01, 0xd5, 0xb5 },
-{ 0x01, 0xd6, 0xb6 },
-{ 0x01, 0xd7, 0xb7 },
-{ 0x01, 0xd8, 0xb8 },
-{ 0x01, 0xd9, 0xb9 },
-{ 0x01, 0xda, 0xba },
-{ 0x01, 0xdb, 0xbb },
-{ 0x01, 0xdc, 0xbc },
-{ 0x01, 0xdd, 0xbd },
-{ 0x01, 0xde, 0xbe },
-{ 0x01, 0xdf, 0xbf },
-{ 0x01, 0xe0, 0xc0 },
-{ 0x01, 0xe1, 0xc1 },
-{ 0x01, 0xe2, 0xc2 },
-{ 0x01, 0xe3, 0xc3 },
-{ 0x01, 0xe4, 0xc4 },
-{ 0x01, 0xe5, 0xc5 },
-{ 0x01, 0xe6, 0xc6 },
-{ 0x01, 0xe7, 0xc7 },
-{ 0x01, 0xe8, 0xc8 },
-{ 0x01, 0xe9, 0xc9 },
-{ 0x01, 0xea, 0xca },
-{ 0x01, 0xeb, 0xcb },
-{ 0x01, 0xec, 0xcc },
-{ 0x01, 0xed, 0xcd },
-{ 0x01, 0xee, 0xce },
-{ 0x01, 0xef, 0xcf },
-{ 0x00, 0xd0, 0xb0 },
-{ 0x00, 0xd1, 0xb1 },
-{ 0x00, 0xd2, 0xb2 },
-{ 0x00, 0xd3, 0xb3 },
-{ 0x00, 0xd4, 0xb4 },
-{ 0x00, 0xd5, 0xb5 },
-{ 0x00, 0xd6, 0xb6 },
-{ 0x00, 0xd7, 0xb7 },
-{ 0x00, 0xd8, 0xb8 },
-{ 0x00, 0xd9, 0xb9 },
-{ 0x00, 0xda, 0xba },
-{ 0x00, 0xdb, 0xbb },
-{ 0x00, 0xdc, 0xbc },
-{ 0x00, 0xdd, 0xbd },
-{ 0x00, 0xde, 0xbe },
-{ 0x00, 0xdf, 0xbf },
-{ 0x00, 0xe0, 0xc0 },
-{ 0x00, 0xe1, 0xc1 },
-{ 0x00, 0xe2, 0xc2 },
-{ 0x00, 0xe3, 0xc3 },
-{ 0x00, 0xe4, 0xc4 },
-{ 0x00, 0xe5, 0xc5 },
-{ 0x00, 0xe6, 0xc6 },
-{ 0x00, 0xe7, 0xc7 },
-{ 0x00, 0xe8, 0xc8 },
-{ 0x00, 0xe9, 0xc9 },
-{ 0x00, 0xea, 0xca },
-{ 0x00, 0xeb, 0xcb },
-{ 0x00, 0xec, 0xcc },
-{ 0x00, 0xed, 0xcd },
-{ 0x00, 0xee, 0xce },
-{ 0x00, 0xef, 0xcf },
-{ 0x00, 0xf0, 0xf0 },
-{ 0x00, 0xf1, 0xa1 },
-{ 0x00, 0xf2, 0xa2 },
-{ 0x00, 0xf3, 0xa3 },
-{ 0x00, 0xf4, 0xa4 },
-{ 0x00, 0xf5, 0xa5 },
-{ 0x00, 0xf6, 0xa6 },
-{ 0x00, 0xf7, 0xa7 },
-{ 0x00, 0xf8, 0xa8 },
-{ 0x00, 0xf9, 0xa9 },
-{ 0x00, 0xfa, 0xaa },
-{ 0x00, 0xfb, 0xab },
-{ 0x00, 0xfc, 0xac },
-{ 0x00, 0xfd, 0xfd },
-{ 0x00, 0xfe, 0xae },
-{ 0x00, 0xff, 0xaf },
-};
-
-struct cs_info iso6_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x00, 0xa1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x00, 0xa3, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x00, 0xa5, 0xa5 },
-{ 0x00, 0xa6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa8 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x00, 0xaa, 0xaa },
-{ 0x00, 0xab, 0xab },
-{ 0x00, 0xac, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x00, 0xaf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xb1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x00, 0xb3, 0xb3 },
-{ 0x00, 0xb4, 0xb4 },
-{ 0x00, 0xb5, 0xb5 },
-{ 0x00, 0xb6, 0xb6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xb8 },
-{ 0x00, 0xb9, 0xb9 },
-{ 0x00, 0xba, 0xba },
-{ 0x00, 0xbb, 0xbb },
-{ 0x00, 0xbc, 0xbc },
-{ 0x00, 0xbd, 0xbd },
-{ 0x00, 0xbe, 0xbe },
-{ 0x00, 0xbf, 0xbf },
-{ 0x00, 0xc0, 0xc0 },
-{ 0x00, 0xc1, 0xc1 },
-{ 0x00, 0xc2, 0xc2 },
-{ 0x00, 0xc3, 0xc3 },
-{ 0x00, 0xc4, 0xc4 },
-{ 0x00, 0xc5, 0xc5 },
-{ 0x00, 0xc6, 0xc6 },
-{ 0x00, 0xc7, 0xc7 },
-{ 0x00, 0xc8, 0xc8 },
-{ 0x00, 0xc9, 0xc9 },
-{ 0x00, 0xca, 0xca },
-{ 0x00, 0xcb, 0xcb },
-{ 0x00, 0xcc, 0xcc },
-{ 0x00, 0xcd, 0xcd },
-{ 0x00, 0xce, 0xce },
-{ 0x00, 0xcf, 0xcf },
-{ 0x00, 0xd0, 0xd0 },
-{ 0x00, 0xd1, 0xd1 },
-{ 0x00, 0xd2, 0xd2 },
-{ 0x00, 0xd3, 0xd3 },
-{ 0x00, 0xd4, 0xd4 },
-{ 0x00, 0xd5, 0xd5 },
-{ 0x00, 0xd6, 0xd6 },
-{ 0x00, 0xd7, 0xd7 },
-{ 0x00, 0xd8, 0xd8 },
-{ 0x00, 0xd9, 0xd9 },
-{ 0x00, 0xda, 0xda },
-{ 0x00, 0xdb, 0xdb },
-{ 0x00, 0xdc, 0xdc },
-{ 0x00, 0xdd, 0xdd },
-{ 0x00, 0xde, 0xde },
-{ 0x00, 0xdf, 0xdf },
-{ 0x00, 0xe0, 0xe0 },
-{ 0x00, 0xe1, 0xe1 },
-{ 0x00, 0xe2, 0xe2 },
-{ 0x00, 0xe3, 0xe3 },
-{ 0x00, 0xe4, 0xe4 },
-{ 0x00, 0xe5, 0xe5 },
-{ 0x00, 0xe6, 0xe6 },
-{ 0x00, 0xe7, 0xe7 },
-{ 0x00, 0xe8, 0xe8 },
-{ 0x00, 0xe9, 0xe9 },
-{ 0x00, 0xea, 0xea },
-{ 0x00, 0xeb, 0xeb },
-{ 0x00, 0xec, 0xec },
-{ 0x00, 0xed, 0xed },
-{ 0x00, 0xee, 0xee },
-{ 0x00, 0xef, 0xef },
-{ 0x00, 0xf0, 0xf0 },
-{ 0x00, 0xf1, 0xf1 },
-{ 0x00, 0xf2, 0xf2 },
-{ 0x00, 0xf3, 0xf3 },
-{ 0x00, 0xf4, 0xf4 },
-{ 0x00, 0xf5, 0xf5 },
-{ 0x00, 0xf6, 0xf6 },
-{ 0x00, 0xf7, 0xf7 },
-{ 0x00, 0xf8, 0xf8 },
-{ 0x00, 0xf9, 0xf9 },
-{ 0x00, 0xfa, 0xfa },
-{ 0x00, 0xfb, 0xfb },
-{ 0x00, 0xfc, 0xfc },
-{ 0x00, 0xfd, 0xfd },
-{ 0x00, 0xfe, 0xfe },
-{ 0x00, 0xff, 0xff },
-};
-
-struct cs_info iso7_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x00, 0xa1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x00, 0xa3, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x00, 0xa5, 0xa5 },
-{ 0x00, 0xa6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa8 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x00, 0xaa, 0xaa },
-{ 0x00, 0xab, 0xab },
-{ 0x00, 0xac, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x00, 0xaf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xb1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x00, 0xb3, 0xb3 },
-{ 0x00, 0xb4, 0xb4 },
-{ 0x00, 0xb5, 0xb5 },
-{ 0x01, 0xdc, 0xb6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x01, 0xdd, 0xb8 },
-{ 0x01, 0xde, 0xb9 },
-{ 0x01, 0xdf, 0xba },
-{ 0x00, 0xbb, 0xbb },
-{ 0x01, 0xfc, 0xbc },
-{ 0x00, 0xbd, 0xbd },
-{ 0x01, 0xfd, 0xbe },
-{ 0x01, 0xfe, 0xbf },
-{ 0x00, 0xc0, 0xc0 },
-{ 0x01, 0xe1, 0xc1 },
-{ 0x01, 0xe2, 0xc2 },
-{ 0x01, 0xe3, 0xc3 },
-{ 0x01, 0xe4, 0xc4 },
-{ 0x01, 0xe5, 0xc5 },
-{ 0x01, 0xe6, 0xc6 },
-{ 0x01, 0xe7, 0xc7 },
-{ 0x01, 0xe8, 0xc8 },
-{ 0x01, 0xe9, 0xc9 },
-{ 0x01, 0xea, 0xca },
-{ 0x01, 0xeb, 0xcb },
-{ 0x01, 0xec, 0xcc },
-{ 0x01, 0xed, 0xcd },
-{ 0x01, 0xee, 0xce },
-{ 0x01, 0xef, 0xcf },
-{ 0x01, 0xf0, 0xd0 },
-{ 0x01, 0xf1, 0xd1 },
-{ 0x00, 0xd2, 0xd2 },
-{ 0x01, 0xf3, 0xd3 },
-{ 0x01, 0xf4, 0xd4 },
-{ 0x01, 0xf5, 0xd5 },
-{ 0x01, 0xf6, 0xd6 },
-{ 0x01, 0xf7, 0xd7 },
-{ 0x01, 0xf8, 0xd8 },
-{ 0x01, 0xf9, 0xd9 },
-{ 0x01, 0xfa, 0xda },
-{ 0x01, 0xfb, 0xdb },
-{ 0x00, 0xdc, 0xb6 },
-{ 0x00, 0xdd, 0xb8 },
-{ 0x00, 0xde, 0xb9 },
-{ 0x00, 0xdf, 0xba },
-{ 0x00, 0xe0, 0xe0 },
-{ 0x00, 0xe1, 0xc1 },
-{ 0x00, 0xe2, 0xc2 },
-{ 0x00, 0xe3, 0xc3 },
-{ 0x00, 0xe4, 0xc4 },
-{ 0x00, 0xe5, 0xc5 },
-{ 0x00, 0xe6, 0xc6 },
-{ 0x00, 0xe7, 0xc7 },
-{ 0x00, 0xe8, 0xc8 },
-{ 0x00, 0xe9, 0xc9 },
-{ 0x00, 0xea, 0xca },
-{ 0x00, 0xeb, 0xcb },
-{ 0x00, 0xec, 0xcc },
-{ 0x00, 0xed, 0xcd },
-{ 0x00, 0xee, 0xce },
-{ 0x00, 0xef, 0xcf },
-{ 0x00, 0xf0, 0xd0 },
-{ 0x00, 0xf1, 0xd1 },
-{ 0x00, 0xf2, 0xd3 },
-{ 0x00, 0xf3, 0xd3 },
-{ 0x00, 0xf4, 0xd4 },
-{ 0x00, 0xf5, 0xd5 },
-{ 0x00, 0xf6, 0xd6 },
-{ 0x00, 0xf7, 0xd7 },
-{ 0x00, 0xf8, 0xd8 },
-{ 0x00, 0xf9, 0xd9 },
-{ 0x00, 0xfa, 0xda },
-{ 0x00, 0xfb, 0xdb },
-{ 0x00, 0xfc, 0xbc },
-{ 0x00, 0xfd, 0xbe },
-{ 0x00, 0xfe, 0xbf },
-{ 0x00, 0xff, 0xff },
-};
-
-struct cs_info iso8_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x00, 0xa1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x00, 0xa3, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x00, 0xa5, 0xa5 },
-{ 0x00, 0xa6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa8 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x00, 0xaa, 0xaa },
-{ 0x00, 0xab, 0xab },
-{ 0x00, 0xac, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x00, 0xaf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xb1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x00, 0xb3, 0xb3 },
-{ 0x00, 0xb4, 0xb4 },
-{ 0x00, 0xb5, 0xb5 },
-{ 0x00, 0xb6, 0xb6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xb8 },
-{ 0x00, 0xb9, 0xb9 },
-{ 0x00, 0xba, 0xba },
-{ 0x00, 0xbb, 0xbb },
-{ 0x00, 0xbc, 0xbc },
-{ 0x00, 0xbd, 0xbd },
-{ 0x00, 0xbe, 0xbe },
-{ 0x00, 0xbf, 0xbf },
-{ 0x00, 0xc0, 0xc0 },
-{ 0x00, 0xc1, 0xc1 },
-{ 0x00, 0xc2, 0xc2 },
-{ 0x00, 0xc3, 0xc3 },
-{ 0x00, 0xc4, 0xc4 },
-{ 0x00, 0xc5, 0xc5 },
-{ 0x00, 0xc6, 0xc6 },
-{ 0x00, 0xc7, 0xc7 },
-{ 0x00, 0xc8, 0xc8 },
-{ 0x00, 0xc9, 0xc9 },
-{ 0x00, 0xca, 0xca },
-{ 0x00, 0xcb, 0xcb },
-{ 0x00, 0xcc, 0xcc },
-{ 0x00, 0xcd, 0xcd },
-{ 0x00, 0xce, 0xce },
-{ 0x00, 0xcf, 0xcf },
-{ 0x00, 0xd0, 0xd0 },
-{ 0x00, 0xd1, 0xd1 },
-{ 0x00, 0xd2, 0xd2 },
-{ 0x00, 0xd3, 0xd3 },
-{ 0x00, 0xd4, 0xd4 },
-{ 0x00, 0xd5, 0xd5 },
-{ 0x00, 0xd6, 0xd6 },
-{ 0x00, 0xd7, 0xd7 },
-{ 0x00, 0xd8, 0xd8 },
-{ 0x00, 0xd9, 0xd9 },
-{ 0x00, 0xda, 0xda },
-{ 0x00, 0xdb, 0xdb },
-{ 0x00, 0xdc, 0xdc },
-{ 0x00, 0xdd, 0xdd },
-{ 0x00, 0xde, 0xde },
-{ 0x00, 0xdf, 0xdf },
-{ 0x00, 0xe0, 0xe0 },
-{ 0x00, 0xe1, 0xe1 },
-{ 0x00, 0xe2, 0xe2 },
-{ 0x00, 0xe3, 0xe3 },
-{ 0x00, 0xe4, 0xe4 },
-{ 0x00, 0xe5, 0xe5 },
-{ 0x00, 0xe6, 0xe6 },
-{ 0x00, 0xe7, 0xe7 },
-{ 0x00, 0xe8, 0xe8 },
-{ 0x00, 0xe9, 0xe9 },
-{ 0x00, 0xea, 0xea },
-{ 0x00, 0xeb, 0xeb },
-{ 0x00, 0xec, 0xec },
-{ 0x00, 0xed, 0xed },
-{ 0x00, 0xee, 0xee },
-{ 0x00, 0xef, 0xef },
-{ 0x00, 0xf0, 0xf0 },
-{ 0x00, 0xf1, 0xf1 },
-{ 0x00, 0xf2, 0xf2 },
-{ 0x00, 0xf3, 0xf3 },
-{ 0x00, 0xf4, 0xf4 },
-{ 0x00, 0xf5, 0xf5 },
-{ 0x00, 0xf6, 0xf6 },
-{ 0x00, 0xf7, 0xf7 },
-{ 0x00, 0xf8, 0xf8 },
-{ 0x00, 0xf9, 0xf9 },
-{ 0x00, 0xfa, 0xfa },
-{ 0x00, 0xfb, 0xfb },
-{ 0x00, 0xfc, 0xfc },
-{ 0x00, 0xfd, 0xfd },
-{ 0x00, 0xfe, 0xfe },
-{ 0x00, 0xff, 0xff },
-};
-
-struct cs_info iso9_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0xfd, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0xdd },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x00, 0xa1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x00, 0xa3, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x00, 0xa5, 0xa5 },
-{ 0x00, 0xa6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa8 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x00, 0xaa, 0xaa },
-{ 0x00, 0xab, 0xab },
-{ 0x00, 0xac, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x00, 0xaf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xb1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x00, 0xb3, 0xb3 },
-{ 0x00, 0xb4, 0xb4 },
-{ 0x00, 0xb5, 0xb5 },
-{ 0x00, 0xb6, 0xb6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xb8 },
-{ 0x00, 0xb9, 0xb9 },
-{ 0x00, 0xba, 0xba },
-{ 0x00, 0xbb, 0xbb },
-{ 0x00, 0xbc, 0xbc },
-{ 0x00, 0xbd, 0xbd },
-{ 0x00, 0xbe, 0xbe },
-{ 0x00, 0xbf, 0xbf },
-{ 0x01, 0xe0, 0xc0 },
-{ 0x01, 0xe1, 0xc1 },
-{ 0x01, 0xe2, 0xc2 },
-{ 0x01, 0xe3, 0xc3 },
-{ 0x01, 0xe4, 0xc4 },
-{ 0x01, 0xe5, 0xc5 },
-{ 0x01, 0xe6, 0xc6 },
-{ 0x01, 0xe7, 0xc7 },
-{ 0x01, 0xe8, 0xc8 },
-{ 0x01, 0xe9, 0xc9 },
-{ 0x01, 0xea, 0xca },
-{ 0x01, 0xeb, 0xcb },
-{ 0x01, 0xec, 0xcc },
-{ 0x01, 0xed, 0xcd },
-{ 0x01, 0xee, 0xce },
-{ 0x01, 0xef, 0xcf },
-{ 0x01, 0xf0, 0xd0 },
-{ 0x01, 0xf1, 0xd1 },
-{ 0x01, 0xf2, 0xd2 },
-{ 0x01, 0xf3, 0xd3 },
-{ 0x01, 0xf4, 0xd4 },
-{ 0x01, 0xf5, 0xd5 },
-{ 0x01, 0xf6, 0xd6 },
-{ 0x00, 0xd7, 0xd7 },
-{ 0x01, 0xf8, 0xd8 },
-{ 0x01, 0xf9, 0xd9 },
-{ 0x01, 0xfa, 0xda },
-{ 0x01, 0xfb, 0xdb },
-{ 0x01, 0xfc, 0xdc },
-{ 0x01, 0x69, 0xdd },
-{ 0x01, 0xfe, 0xde },
-{ 0x00, 0xdf, 0xdf },
-{ 0x00, 0xe0, 0xc0 },
-{ 0x00, 0xe1, 0xc1 },
-{ 0x00, 0xe2, 0xc2 },
-{ 0x00, 0xe3, 0xc3 },
-{ 0x00, 0xe4, 0xc4 },
-{ 0x00, 0xe5, 0xc5 },
-{ 0x00, 0xe6, 0xc6 },
-{ 0x00, 0xe7, 0xc7 },
-{ 0x00, 0xe8, 0xc8 },
-{ 0x00, 0xe9, 0xc9 },
-{ 0x00, 0xea, 0xca },
-{ 0x00, 0xeb, 0xcb },
-{ 0x00, 0xec, 0xcc },
-{ 0x00, 0xed, 0xcd },
-{ 0x00, 0xee, 0xce },
-{ 0x00, 0xef, 0xcf },
-{ 0x00, 0xf0, 0xd0 },
-{ 0x00, 0xf1, 0xd1 },
-{ 0x00, 0xf2, 0xd2 },
-{ 0x00, 0xf3, 0xd3 },
-{ 0x00, 0xf4, 0xd4 },
-{ 0x00, 0xf5, 0xd5 },
-{ 0x00, 0xf6, 0xd6 },
-{ 0x00, 0xf7, 0xf7 },
-{ 0x00, 0xf8, 0xd8 },
-{ 0x00, 0xf9, 0xd9 },
-{ 0x00, 0xfa, 0xda },
-{ 0x00, 0xfb, 0xdb },
-{ 0x00, 0xfc, 0xdc },
-{ 0x00, 0xfd, 0x49 },
-{ 0x00, 0xfe, 0xde },
-{ 0x00, 0xff, 0xff },
-};
-
-struct cs_info iso10_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x00, 0xa1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x00, 0xa3, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x00, 0xa5, 0xa5 },
-{ 0x00, 0xa6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa8 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x00, 0xaa, 0xaa },
-{ 0x00, 0xab, 0xab },
-{ 0x00, 0xac, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x00, 0xaf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xb1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x00, 0xb3, 0xb3 },
-{ 0x00, 0xb4, 0xb4 },
-{ 0x00, 0xb5, 0xb5 },
-{ 0x00, 0xb6, 0xb6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xb8 },
-{ 0x00, 0xb9, 0xb9 },
-{ 0x00, 0xba, 0xba },
-{ 0x00, 0xbb, 0xbb },
-{ 0x00, 0xbc, 0xbc },
-{ 0x00, 0xbd, 0xbd },
-{ 0x00, 0xbe, 0xbe },
-{ 0x00, 0xbf, 0xbf },
-{ 0x00, 0xc0, 0xc0 },
-{ 0x00, 0xc1, 0xc1 },
-{ 0x00, 0xc2, 0xc2 },
-{ 0x00, 0xc3, 0xc3 },
-{ 0x00, 0xc4, 0xc4 },
-{ 0x00, 0xc5, 0xc5 },
-{ 0x00, 0xc6, 0xc6 },
-{ 0x00, 0xc7, 0xc7 },
-{ 0x00, 0xc8, 0xc8 },
-{ 0x00, 0xc9, 0xc9 },
-{ 0x00, 0xca, 0xca },
-{ 0x00, 0xcb, 0xcb },
-{ 0x00, 0xcc, 0xcc },
-{ 0x00, 0xcd, 0xcd },
-{ 0x00, 0xce, 0xce },
-{ 0x00, 0xcf, 0xcf },
-{ 0x00, 0xd0, 0xd0 },
-{ 0x00, 0xd1, 0xd1 },
-{ 0x00, 0xd2, 0xd2 },
-{ 0x00, 0xd3, 0xd3 },
-{ 0x00, 0xd4, 0xd4 },
-{ 0x00, 0xd5, 0xd5 },
-{ 0x00, 0xd6, 0xd6 },
-{ 0x00, 0xd7, 0xd7 },
-{ 0x00, 0xd8, 0xd8 },
-{ 0x00, 0xd9, 0xd9 },
-{ 0x00, 0xda, 0xda },
-{ 0x00, 0xdb, 0xdb },
-{ 0x00, 0xdc, 0xdc },
-{ 0x00, 0xdd, 0xdd },
-{ 0x00, 0xde, 0xde },
-{ 0x00, 0xdf, 0xdf },
-{ 0x00, 0xe0, 0xe0 },
-{ 0x00, 0xe1, 0xe1 },
-{ 0x00, 0xe2, 0xe2 },
-{ 0x00, 0xe3, 0xe3 },
-{ 0x00, 0xe4, 0xe4 },
-{ 0x00, 0xe5, 0xe5 },
-{ 0x00, 0xe6, 0xe6 },
-{ 0x00, 0xe7, 0xe7 },
-{ 0x00, 0xe8, 0xe8 },
-{ 0x00, 0xe9, 0xe9 },
-{ 0x00, 0xea, 0xea },
-{ 0x00, 0xeb, 0xeb },
-{ 0x00, 0xec, 0xec },
-{ 0x00, 0xed, 0xed },
-{ 0x00, 0xee, 0xee },
-{ 0x00, 0xef, 0xef },
-{ 0x00, 0xf0, 0xf0 },
-{ 0x00, 0xf1, 0xf1 },
-{ 0x00, 0xf2, 0xf2 },
-{ 0x00, 0xf3, 0xf3 },
-{ 0x00, 0xf4, 0xf4 },
-{ 0x00, 0xf5, 0xf5 },
-{ 0x00, 0xf6, 0xf6 },
-{ 0x00, 0xf7, 0xf7 },
-{ 0x00, 0xf8, 0xf8 },
-{ 0x00, 0xf9, 0xf9 },
-{ 0x00, 0xfa, 0xfa },
-{ 0x00, 0xfb, 0xfb },
-{ 0x00, 0xfc, 0xfc },
-{ 0x00, 0xfd, 0xfd },
-{ 0x00, 0xfe, 0xfe },
-{ 0x00, 0xff, 0xff },
-};
-
-struct cs_info koi8r_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x00, 0xa1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x00, 0xa3, 0xb3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x00, 0xa5, 0xa5 },
-{ 0x00, 0xa6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa8 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x00, 0xaa, 0xaa },
-{ 0x00, 0xab, 0xab },
-{ 0x00, 0xac, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x00, 0xaf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xb1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x01, 0xa3, 0xb3 },
-{ 0x00, 0xb4, 0xb4 },
-{ 0x00, 0xb5, 0xb5 },
-{ 0x00, 0xb6, 0xb6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xb8 },
-{ 0x00, 0xb9, 0xb9 },
-{ 0x00, 0xba, 0xba },
-{ 0x00, 0xbb, 0xbb },
-{ 0x00, 0xbc, 0xbc },
-{ 0x00, 0xbd, 0xbd },
-{ 0x00, 0xbe, 0xbe },
-{ 0x00, 0xbf, 0xbf },
-{ 0x00, 0xc0, 0xe0 },
-{ 0x00, 0xc1, 0xe1 },
-{ 0x00, 0xc2, 0xe2 },
-{ 0x00, 0xc3, 0xe3 },
-{ 0x00, 0xc4, 0xe4 },
-{ 0x00, 0xc5, 0xe5 },
-{ 0x00, 0xc6, 0xe6 },
-{ 0x00, 0xc7, 0xe7 },
-{ 0x00, 0xc8, 0xe8 },
-{ 0x00, 0xc9, 0xe9 },
-{ 0x00, 0xca, 0xea },
-{ 0x00, 0xcb, 0xeb },
-{ 0x00, 0xcc, 0xec },
-{ 0x00, 0xcd, 0xed },
-{ 0x00, 0xce, 0xee },
-{ 0x00, 0xcf, 0xef },
-{ 0x00, 0xd0, 0xf0 },
-{ 0x00, 0xd1, 0xf1 },
-{ 0x00, 0xd2, 0xf2 },
-{ 0x00, 0xd3, 0xf3 },
-{ 0x00, 0xd4, 0xf4 },
-{ 0x00, 0xd5, 0xf5 },
-{ 0x00, 0xd6, 0xf6 },
-{ 0x00, 0xd7, 0xf7 },
-{ 0x00, 0xd8, 0xf8 },
-{ 0x00, 0xd9, 0xf9 },
-{ 0x00, 0xda, 0xfa },
-{ 0x00, 0xdb, 0xfb },
-{ 0x00, 0xdc, 0xfc },
-{ 0x00, 0xdd, 0xfd },
-{ 0x00, 0xde, 0xfe },
-{ 0x00, 0xdf, 0xff },
-{ 0x01, 0xc0, 0xe0 },
-{ 0x01, 0xc1, 0xe1 },
-{ 0x01, 0xc2, 0xe2 },
-{ 0x01, 0xc3, 0xe3 },
-{ 0x01, 0xc4, 0xe4 },
-{ 0x01, 0xc5, 0xe5 },
-{ 0x01, 0xc6, 0xe6 },
-{ 0x01, 0xc7, 0xe7 },
-{ 0x01, 0xc8, 0xe8 },
-{ 0x01, 0xc9, 0xe9 },
-{ 0x01, 0xca, 0xea },
-{ 0x01, 0xcb, 0xeb },
-{ 0x01, 0xcc, 0xec },
-{ 0x01, 0xcd, 0xed },
-{ 0x01, 0xce, 0xee },
-{ 0x01, 0xcf, 0xef },
-{ 0x01, 0xd0, 0xf0 },
-{ 0x01, 0xd1, 0xf1 },
-{ 0x01, 0xd2, 0xf2 },
-{ 0x01, 0xd3, 0xf3 },
-{ 0x01, 0xd4, 0xf4 },
-{ 0x01, 0xd5, 0xf5 },
-{ 0x01, 0xd6, 0xf6 },
-{ 0x01, 0xd7, 0xf7 },
-{ 0x01, 0xd8, 0xf8 },
-{ 0x01, 0xd9, 0xf9 },
-{ 0x01, 0xda, 0xfa },
-{ 0x01, 0xdb, 0xfb },
-{ 0x01, 0xdc, 0xfc },
-{ 0x01, 0xdd, 0xfd },
-{ 0x01, 0xde, 0xfe },
-{ 0x01, 0xdf, 0xff },
-};
-
-struct cs_info koi8u_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x00, 0xa1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x00, 0xa3, 0xb3 },
-{ 0x00, 0xa4, 0xb4 }, /* ie */
-{ 0x00, 0xa5, 0xa5 },
-{ 0x00, 0xa6, 0xb6 }, /* i */
-{ 0x00, 0xa7, 0xb7 }, /* ii */
-{ 0x00, 0xa8, 0xa8 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x00, 0xaa, 0xaa },
-{ 0x00, 0xab, 0xab },
-{ 0x00, 0xac, 0xac },
-{ 0x00, 0xad, 0xbd }, /* g'' */
-{ 0x00, 0xae, 0xae },
-{ 0x00, 0xaf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xb1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x01, 0xa3, 0xb3 },
-{ 0x00, 0xb4, 0xb4 }, /* IE */
-{ 0x00, 0xb5, 0xb5 },
-{ 0x00, 0xb6, 0xb6 }, /* I */
-{ 0x00, 0xb7, 0xb7 }, /* II */
-{ 0x00, 0xb8, 0xb8 },
-{ 0x00, 0xb9, 0xb9 },
-{ 0x00, 0xba, 0xba },
-{ 0x00, 0xbb, 0xbb },
-{ 0x00, 0xbc, 0xbc },
-{ 0x00, 0xbd, 0xbd },
-{ 0x00, 0xbe, 0xbe },
-{ 0x00, 0xbf, 0xbf },
-{ 0x00, 0xc0, 0xe0 },
-{ 0x00, 0xc1, 0xe1 },
-{ 0x00, 0xc2, 0xe2 },
-{ 0x00, 0xc3, 0xe3 },
-{ 0x00, 0xc4, 0xe4 },
-{ 0x00, 0xc5, 0xe5 },
-{ 0x00, 0xc6, 0xe6 },
-{ 0x00, 0xc7, 0xe7 },
-{ 0x00, 0xc8, 0xe8 },
-{ 0x00, 0xc9, 0xe9 },
-{ 0x00, 0xca, 0xea },
-{ 0x00, 0xcb, 0xeb },
-{ 0x00, 0xcc, 0xec },
-{ 0x00, 0xcd, 0xed },
-{ 0x00, 0xce, 0xee },
-{ 0x00, 0xcf, 0xef },
-{ 0x00, 0xd0, 0xf0 },
-{ 0x00, 0xd1, 0xf1 },
-{ 0x00, 0xd2, 0xf2 },
-{ 0x00, 0xd3, 0xf3 },
-{ 0x00, 0xd4, 0xf4 },
-{ 0x00, 0xd5, 0xf5 },
-{ 0x00, 0xd6, 0xf6 },
-{ 0x00, 0xd7, 0xf7 },
-{ 0x00, 0xd8, 0xf8 },
-{ 0x00, 0xd9, 0xf9 },
-{ 0x00, 0xda, 0xfa },
-{ 0x00, 0xdb, 0xfb },
-{ 0x00, 0xdc, 0xfc },
-{ 0x00, 0xdd, 0xfd },
-{ 0x00, 0xde, 0xfe },
-{ 0x00, 0xdf, 0xff },
-{ 0x01, 0xc0, 0xe0 },
-{ 0x01, 0xc1, 0xe1 },
-{ 0x01, 0xc2, 0xe2 },
-{ 0x01, 0xc3, 0xe3 },
-{ 0x01, 0xc4, 0xe4 },
-{ 0x01, 0xc5, 0xe5 },
-{ 0x01, 0xc6, 0xe6 },
-{ 0x01, 0xc7, 0xe7 },
-{ 0x01, 0xc8, 0xe8 },
-{ 0x01, 0xc9, 0xe9 },
-{ 0x01, 0xca, 0xea },
-{ 0x01, 0xcb, 0xeb },
-{ 0x01, 0xcc, 0xec },
-{ 0x01, 0xcd, 0xed },
-{ 0x01, 0xce, 0xee },
-{ 0x01, 0xcf, 0xef },
-{ 0x01, 0xd0, 0xf0 },
-{ 0x01, 0xd1, 0xf1 },
-{ 0x01, 0xd2, 0xf2 },
-{ 0x01, 0xd3, 0xf3 },
-{ 0x01, 0xd4, 0xf4 },
-{ 0x01, 0xd5, 0xf5 },
-{ 0x01, 0xd6, 0xf6 },
-{ 0x01, 0xd7, 0xf7 },
-{ 0x01, 0xd8, 0xf8 },
-{ 0x01, 0xd9, 0xf9 },
-{ 0x01, 0xda, 0xfa },
-{ 0x01, 0xdb, 0xfb },
-{ 0x01, 0xdc, 0xfc },
-{ 0x01, 0xdd, 0xfd },
-{ 0x01, 0xde, 0xfe },
-{ 0x01, 0xdf, 0xff },
-};
-
-struct cs_info cp1251_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x01, 0x90, 0x80 },
-{ 0x01, 0x83, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x81 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x01, 0x9a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x01, 0x9c, 0x8c },
-{ 0x01, 0x9d, 0x8d },
-{ 0x01, 0x9e, 0x8e },
-{ 0x01, 0x9f, 0x8f },
-{ 0x00, 0x90, 0x80 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x8a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x8c },
-{ 0x00, 0x9d, 0x8d },
-{ 0x00, 0x9e, 0x8e },
-{ 0x00, 0x9f, 0x8f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x01, 0xa2, 0xa1 },
-{ 0x00, 0xa2, 0xa1 },
-{ 0x01, 0xbc, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x01, 0xb4, 0xa5 },
-{ 0x00, 0xa6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x01, 0xb8, 0xa8 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x01, 0xba, 0xaa },
-{ 0x00, 0xab, 0xab },
-{ 0x00, 0xac, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x01, 0xbf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xb1 },
-{ 0x01, 0xb3, 0xb2 },
-{ 0x00, 0xb3, 0xb2 },
-{ 0x00, 0xb4, 0xa5 },
-{ 0x00, 0xb5, 0xb5 },
-{ 0x00, 0xb6, 0xb6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xa8 },
-{ 0x00, 0xb9, 0xb9 },
-{ 0x00, 0xba, 0xaa },
-{ 0x00, 0xbb, 0xbb },
-{ 0x00, 0xbc, 0xa3 },
-{ 0x01, 0xbe, 0xbd },
-{ 0x00, 0xbe, 0xbd },
-{ 0x00, 0xbf, 0xaf },
-{ 0x01, 0xe0, 0xc0 },
-{ 0x01, 0xe1, 0xc1 },
-{ 0x01, 0xe2, 0xc2 },
-{ 0x01, 0xe3, 0xc3 },
-{ 0x01, 0xe4, 0xc4 },
-{ 0x01, 0xe5, 0xc5 },
-{ 0x01, 0xe6, 0xc6 },
-{ 0x01, 0xe7, 0xc7 },
-{ 0x01, 0xe8, 0xc8 },
-{ 0x01, 0xe9, 0xc9 },
-{ 0x01, 0xea, 0xca },
-{ 0x01, 0xeb, 0xcb },
-{ 0x01, 0xec, 0xcc },
-{ 0x01, 0xed, 0xcd },
-{ 0x01, 0xee, 0xce },
-{ 0x01, 0xef, 0xcf },
-{ 0x01, 0xf0, 0xd0 },
-{ 0x01, 0xf1, 0xd1 },
-{ 0x01, 0xf2, 0xd2 },
-{ 0x01, 0xf3, 0xd3 },
-{ 0x01, 0xf4, 0xd4 },
-{ 0x01, 0xf5, 0xd5 },
-{ 0x01, 0xf6, 0xd6 },
-{ 0x01, 0xf7, 0xd7 },
-{ 0x01, 0xf8, 0xd8 },
-{ 0x01, 0xf9, 0xd9 },
-{ 0x01, 0xfa, 0xda },
-{ 0x01, 0xfb, 0xdb },
-{ 0x01, 0xfc, 0xdc },
-{ 0x01, 0xfd, 0xdd },
-{ 0x01, 0xfe, 0xde },
-{ 0x01, 0xff, 0xdf },
-{ 0x00, 0xe0, 0xc0 },
-{ 0x00, 0xe1, 0xc1 },
-{ 0x00, 0xe2, 0xc2 },
-{ 0x00, 0xe3, 0xc3 },
-{ 0x00, 0xe4, 0xc4 },
-{ 0x00, 0xe5, 0xc5 },
-{ 0x00, 0xe6, 0xc6 },
-{ 0x00, 0xe7, 0xc7 },
-{ 0x00, 0xe8, 0xc8 },
-{ 0x00, 0xe9, 0xc9 },
-{ 0x00, 0xea, 0xca },
-{ 0x00, 0xeb, 0xcb },
-{ 0x00, 0xec, 0xcc },
-{ 0x00, 0xed, 0xcd },
-{ 0x00, 0xee, 0xce },
-{ 0x00, 0xef, 0xcf },
-{ 0x00, 0xf0, 0xd0 },
-{ 0x00, 0xf1, 0xd1 },
-{ 0x00, 0xf2, 0xd2 },
-{ 0x00, 0xf3, 0xd3 },
-{ 0x00, 0xf4, 0xd4 },
-{ 0x00, 0xf5, 0xd5 },
-{ 0x00, 0xf6, 0xd6 },
-{ 0x00, 0xf7, 0xd7 },
-{ 0x00, 0xf8, 0xd8 },
-{ 0x00, 0xf9, 0xd9 },
-{ 0x00, 0xfa, 0xda },
-{ 0x00, 0xfb, 0xdb },
-{ 0x00, 0xfc, 0xdc },
-{ 0x00, 0xfd, 0xdd },
-{ 0x00, 0xfe, 0xde },
-{ 0x00, 0xff, 0xdf },
-};
-
-struct cs_info iso13_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0A, 0x0A },
-{ 0x00, 0x0B, 0x0B },
-{ 0x00, 0x0C, 0x0C },
-{ 0x00, 0x0D, 0x0D },
-{ 0x00, 0x0E, 0x0E },
-{ 0x00, 0x0F, 0x0F },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1A, 0x1A },
-{ 0x00, 0x1B, 0x1B },
-{ 0x00, 0x1C, 0x1C },
-{ 0x00, 0x1D, 0x1D },
-{ 0x00, 0x1E, 0x1E },
-{ 0x00, 0x1F, 0x1F },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2A, 0x2A },
-{ 0x00, 0x2B, 0x2B },
-{ 0x00, 0x2C, 0x2C },
-{ 0x00, 0x2D, 0x2D },
-{ 0x00, 0x2E, 0x2E },
-{ 0x00, 0x2F, 0x2F },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3A, 0x3A },
-{ 0x00, 0x3B, 0x3B },
-{ 0x00, 0x3C, 0x3C },
-{ 0x00, 0x3D, 0x3D },
-{ 0x00, 0x3E, 0x3E },
-{ 0x00, 0x3F, 0x3F },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6A, 0x4A },
-{ 0x01, 0x6B, 0x4B },
-{ 0x01, 0x6C, 0x4C },
-{ 0x01, 0x6D, 0x4D },
-{ 0x01, 0x6E, 0x4E },
-{ 0x01, 0x6F, 0x4F },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7A, 0x5A },
-{ 0x00, 0x5B, 0x5B },
-{ 0x00, 0x5C, 0x5C },
-{ 0x00, 0x5D, 0x5D },
-{ 0x00, 0x5E, 0x5E },
-{ 0x00, 0x5F, 0x5F },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6A, 0x4A },
-{ 0x00, 0x6B, 0x4B },
-{ 0x00, 0x6C, 0x4C },
-{ 0x00, 0x6D, 0x4D },
-{ 0x00, 0x6E, 0x4E },
-{ 0x00, 0x6F, 0x4F },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7A, 0x5A },
-{ 0x00, 0x7B, 0x7B },
-{ 0x00, 0x7C, 0x7C },
-{ 0x00, 0x7D, 0x7D },
-{ 0x00, 0x7E, 0x7E },
-{ 0x00, 0x7F, 0x7F },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8A, 0x8A },
-{ 0x00, 0x8B, 0x8B },
-{ 0x00, 0x8C, 0x8C },
-{ 0x00, 0x8D, 0x8D },
-{ 0x00, 0x8E, 0x8E },
-{ 0x00, 0x8F, 0x8F },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9A, 0x9A },
-{ 0x00, 0x9B, 0x9B },
-{ 0x00, 0x9C, 0x9C },
-{ 0x00, 0x9D, 0x9D },
-{ 0x00, 0x9E, 0x9E },
-{ 0x00, 0x9F, 0x9F },
-{ 0x00, 0xA0, 0xA0 },
-{ 0x00, 0xA1, 0xA1 },
-{ 0x00, 0xA2, 0xA2 },
-{ 0x00, 0xA3, 0xA3 },
-{ 0x00, 0xA4, 0xA4 },
-{ 0x00, 0xA5, 0xA5 },
-{ 0x00, 0xA6, 0xA6 },
-{ 0x00, 0xA7, 0xA7 },
-{ 0x01, 0xB8, 0xA8 },
-{ 0x00, 0xA9, 0xA9 },
-{ 0x01, 0xBA, 0xAA },
-{ 0x00, 0xAB, 0xAB },
-{ 0x00, 0xAC, 0xAC },
-{ 0x00, 0xAD, 0xAD },
-{ 0x00, 0xAE, 0xAE },
-{ 0x01, 0xBF, 0xAF },
-{ 0x00, 0xB0, 0xB0 },
-{ 0x00, 0xB1, 0xB1 },
-{ 0x00, 0xB2, 0xB2 },
-{ 0x00, 0xB3, 0xB3 },
-{ 0x00, 0xB4, 0xB4 },
-{ 0x00, 0xB5, 0xB5 },
-{ 0x00, 0xB6, 0xB6 },
-{ 0x00, 0xB7, 0xB7 },
-{ 0x00, 0xB8, 0xA8 },
-{ 0x00, 0xB9, 0xB9 },
-{ 0x00, 0xBA, 0xAA },
-{ 0x00, 0xBB, 0xBB },
-{ 0x00, 0xBC, 0xBC },
-{ 0x00, 0xBD, 0xBD },
-{ 0x00, 0xBE, 0xBE },
-{ 0x00, 0xBF, 0xAF },
-{ 0x01, 0xE0, 0xC0 },
-{ 0x01, 0xE1, 0xC1 },
-{ 0x01, 0xE2, 0xC2 },
-{ 0x01, 0xE3, 0xC3 },
-{ 0x01, 0xE4, 0xC4 },
-{ 0x01, 0xE5, 0xC5 },
-{ 0x01, 0xE6, 0xC6 },
-{ 0x01, 0xE7, 0xC7 },
-{ 0x01, 0xE8, 0xC8 },
-{ 0x01, 0xE9, 0xC9 },
-{ 0x01, 0xEA, 0xCA },
-{ 0x01, 0xEB, 0xCB },
-{ 0x01, 0xEC, 0xCC },
-{ 0x01, 0xED, 0xCD },
-{ 0x01, 0xEE, 0xCE },
-{ 0x01, 0xEF, 0xCF },
-{ 0x01, 0xF0, 0xD0 },
-{ 0x01, 0xF1, 0xD1 },
-{ 0x01, 0xF2, 0xD2 },
-{ 0x01, 0xF3, 0xD3 },
-{ 0x01, 0xF4, 0xD4 },
-{ 0x01, 0xF5, 0xD5 },
-{ 0x01, 0xF6, 0xD6 },
-{ 0x00, 0xD7, 0xD7 },
-{ 0x01, 0xF8, 0xD8 },
-{ 0x01, 0xF9, 0xD9 },
-{ 0x01, 0xFA, 0xDA },
-{ 0x01, 0xFB, 0xDB },
-{ 0x01, 0xFC, 0xDC },
-{ 0x01, 0xFD, 0xDD },
-{ 0x01, 0xFE, 0xDE },
-{ 0x00, 0xDF, 0xDF },
-{ 0x00, 0xE0, 0xC0 },
-{ 0x00, 0xE1, 0xC1 },
-{ 0x00, 0xE2, 0xC2 },
-{ 0x00, 0xE3, 0xC3 },
-{ 0x00, 0xE4, 0xC4 },
-{ 0x00, 0xE5, 0xC5 },
-{ 0x00, 0xE6, 0xC6 },
-{ 0x00, 0xE7, 0xC7 },
-{ 0x00, 0xE8, 0xC8 },
-{ 0x00, 0xE9, 0xC9 },
-{ 0x00, 0xEA, 0xCA },
-{ 0x00, 0xEB, 0xCB },
-{ 0x00, 0xEC, 0xCC },
-{ 0x00, 0xED, 0xCD },
-{ 0x00, 0xEE, 0xCE },
-{ 0x00, 0xEF, 0xCF },
-{ 0x00, 0xF0, 0xD0 },
-{ 0x00, 0xF1, 0xD1 },
-{ 0x00, 0xF2, 0xD2 },
-{ 0x00, 0xF3, 0xD3 },
-{ 0x00, 0xF4, 0xD4 },
-{ 0x00, 0xF5, 0xD5 },
-{ 0x00, 0xF6, 0xD6 },
-{ 0x00, 0xF7, 0xF7 },
-{ 0x00, 0xF8, 0xD8 },
-{ 0x00, 0xF9, 0xD9 },
-{ 0x00, 0xFA, 0xDA },
-{ 0x00, 0xFB, 0xDB },
-{ 0x00, 0xFC, 0xDC },
-{ 0x00, 0xFD, 0xDD },
-{ 0x00, 0xFE, 0xDE },
-{ 0x00, 0xFF, 0xFF },
-};
-
-
-struct cs_info iso14_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x01, 0xa2, 0xa1 },
-{ 0x00, 0xa2, 0xa1 },
-{ 0x00, 0xa3, 0xa3 },
-{ 0x01, 0xa5, 0xa4 },
-{ 0x00, 0xa5, 0xa4 },
-{ 0x01, 0xa6, 0xab },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x01, 0xb8, 0xa8 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x01, 0xba, 0xaa },
-{ 0x00, 0xab, 0xa6 },
-{ 0x01, 0xbc, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x01, 0xff, 0xaf },
-{ 0x01, 0xb1, 0xb0 },
-{ 0x00, 0xb1, 0xb0 },
-{ 0x01, 0xb3, 0xb2 },
-{ 0x00, 0xb3, 0xb2 },
-{ 0x01, 0xb5, 0xb4 },
-{ 0x00, 0xb5, 0xb4 },
-{ 0x00, 0xb6, 0xb6 },
-{ 0x01, 0xb9, 0xb7 },
-{ 0x00, 0xb8, 0xa8 },
-{ 0x00, 0xb9, 0xb6 },
-{ 0x00, 0xba, 0xaa },
-{ 0x01, 0xbf, 0xbb },
-{ 0x00, 0xbc, 0xac },
-{ 0x01, 0xbe, 0xbd },
-{ 0x00, 0xbe, 0xbd },
-{ 0x00, 0xbf, 0xbb },
-{ 0x01, 0xe0, 0xc0 },
-{ 0x01, 0xe1, 0xc1 },
-{ 0x01, 0xe2, 0xc2 },
-{ 0x01, 0xe3, 0xc3 },
-{ 0x01, 0xe4, 0xc4 },
-{ 0x01, 0xe5, 0xc5 },
-{ 0x01, 0xe6, 0xc6 },
-{ 0x01, 0xe7, 0xc7 },
-{ 0x01, 0xe8, 0xc8 },
-{ 0x01, 0xe9, 0xc9 },
-{ 0x01, 0xea, 0xca },
-{ 0x01, 0xeb, 0xcb },
-{ 0x01, 0xec, 0xcc },
-{ 0x01, 0xed, 0xcd },
-{ 0x01, 0xee, 0xce },
-{ 0x01, 0xef, 0xcf },
-{ 0x01, 0xf0, 0xd0 },
-{ 0x01, 0xf1, 0xd1 },
-{ 0x01, 0xf2, 0xd2 },
-{ 0x01, 0xf3, 0xd3 },
-{ 0x01, 0xf4, 0xd4 },
-{ 0x01, 0xf5, 0xd5 },
-{ 0x01, 0xf6, 0xd6 },
-{ 0x01, 0xf7, 0xd7 },
-{ 0x01, 0xf8, 0xd8 },
-{ 0x01, 0xf9, 0xd9 },
-{ 0x01, 0xfa, 0xda },
-{ 0x01, 0xfb, 0xdb },
-{ 0x01, 0xfc, 0xdc },
-{ 0x01, 0xfd, 0xdd },
-{ 0x01, 0xfe, 0xde },
-{ 0x00, 0xdf, 0xdf },
-{ 0x00, 0xe0, 0xc0 },
-{ 0x00, 0xe1, 0xc1 },
-{ 0x00, 0xe2, 0xc2 },
-{ 0x00, 0xe3, 0xc3 },
-{ 0x00, 0xe4, 0xc4 },
-{ 0x00, 0xe5, 0xc5 },
-{ 0x00, 0xe6, 0xc6 },
-{ 0x00, 0xe7, 0xc7 },
-{ 0x00, 0xe8, 0xc8 },
-{ 0x00, 0xe9, 0xc9 },
-{ 0x00, 0xea, 0xca },
-{ 0x00, 0xeb, 0xcb },
-{ 0x00, 0xec, 0xcc },
-{ 0x00, 0xed, 0xcd },
-{ 0x00, 0xee, 0xce },
-{ 0x00, 0xef, 0xcf },
-{ 0x00, 0xf0, 0xd0 },
-{ 0x00, 0xf1, 0xd1 },
-{ 0x00, 0xf2, 0xd2 },
-{ 0x00, 0xf3, 0xd3 },
-{ 0x00, 0xf4, 0xd4 },
-{ 0x00, 0xf5, 0xd5 },
-{ 0x00, 0xf6, 0xd6 },
-{ 0x00, 0xf7, 0xd7 },
-{ 0x00, 0xf8, 0xd8 },
-{ 0x00, 0xf9, 0xd9 },
-{ 0x00, 0xfa, 0xda },
-{ 0x00, 0xfb, 0xdb },
-{ 0x00, 0xfc, 0xdc },
-{ 0x00, 0xfd, 0xdd },
-{ 0x00, 0xfe, 0xde },
-{ 0x00, 0xff, 0xff },
-};
-
-struct cs_info iso15_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x00, 0xa1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x00, 0xa3, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x00, 0xa5, 0xa5 },
-{ 0x01, 0xa8, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa6 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x00, 0xaa, 0xaa },
-{ 0x00, 0xab, 0xab },
-{ 0x00, 0xac, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x00, 0xaf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xb1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x00, 0xb3, 0xb3 },
-{ 0x01, 0xb8, 0xb4 },
-{ 0x00, 0xb5, 0xb5 },
-{ 0x00, 0xb6, 0xb6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xb4 },
-{ 0x00, 0xb9, 0xb9 },
-{ 0x00, 0xba, 0xba },
-{ 0x00, 0xbb, 0xbb },
-{ 0x01, 0xbd, 0xbc },
-{ 0x00, 0xbd, 0xbc },
-{ 0x01, 0xff, 0xbe },
-{ 0x00, 0xbf, 0xbf },
-{ 0x01, 0xe0, 0xc0 },
-{ 0x01, 0xe1, 0xc1 },
-{ 0x01, 0xe2, 0xc2 },
-{ 0x01, 0xe3, 0xc3 },
-{ 0x01, 0xe4, 0xc4 },
-{ 0x01, 0xe5, 0xc5 },
-{ 0x01, 0xe6, 0xc6 },
-{ 0x01, 0xe7, 0xc7 },
-{ 0x01, 0xe8, 0xc8 },
-{ 0x01, 0xe9, 0xc9 },
-{ 0x01, 0xea, 0xca },
-{ 0x01, 0xeb, 0xcb },
-{ 0x01, 0xec, 0xcc },
-{ 0x01, 0xed, 0xcd },
-{ 0x01, 0xee, 0xce },
-{ 0x01, 0xef, 0xcf },
-{ 0x01, 0xf0, 0xd0 },
-{ 0x01, 0xf1, 0xd1 },
-{ 0x01, 0xf2, 0xd2 },
-{ 0x01, 0xf3, 0xd3 },
-{ 0x01, 0xf4, 0xd4 },
-{ 0x01, 0xf5, 0xd5 },
-{ 0x01, 0xf6, 0xd6 },
-{ 0x00, 0xd7, 0xd7 },
-{ 0x01, 0xf8, 0xd8 },
-{ 0x01, 0xf9, 0xd9 },
-{ 0x01, 0xfa, 0xda },
-{ 0x01, 0xfb, 0xdb },
-{ 0x01, 0xfc, 0xdc },
-{ 0x01, 0xfd, 0xdd },
-{ 0x01, 0xfe, 0xde },
-{ 0x00, 0xdf, 0xdf },
-{ 0x00, 0xe0, 0xc0 },
-{ 0x00, 0xe1, 0xc1 },
-{ 0x00, 0xe2, 0xc2 },
-{ 0x00, 0xe3, 0xc3 },
-{ 0x00, 0xe4, 0xc4 },
-{ 0x00, 0xe5, 0xc5 },
-{ 0x00, 0xe6, 0xc6 },
-{ 0x00, 0xe7, 0xc7 },
-{ 0x00, 0xe8, 0xc8 },
-{ 0x00, 0xe9, 0xc9 },
-{ 0x00, 0xea, 0xca },
-{ 0x00, 0xeb, 0xcb },
-{ 0x00, 0xec, 0xcc },
-{ 0x00, 0xed, 0xcd },
-{ 0x00, 0xee, 0xce },
-{ 0x00, 0xef, 0xcf },
-{ 0x00, 0xf0, 0xd0 },
-{ 0x00, 0xf1, 0xd1 },
-{ 0x00, 0xf2, 0xd2 },
-{ 0x00, 0xf3, 0xd3 },
-{ 0x00, 0xf4, 0xd4 },
-{ 0x00, 0xf5, 0xd5 },
-{ 0x00, 0xf6, 0xd6 },
-{ 0x00, 0xf7, 0xf7 },
-{ 0x00, 0xf8, 0xd8 },
-{ 0x00, 0xf9, 0xd9 },
-{ 0x00, 0xfa, 0xda },
-{ 0x00, 0xfb, 0xdb },
-{ 0x00, 0xfc, 0xdc },
-{ 0x00, 0xfd, 0xdd },
-{ 0x00, 0xfe, 0xde },
-{ 0x00, 0xff, 0xbe },
-};
-
-struct cs_info iscii_devanagari_tbl[] = {
-{ 0x00, 0x00, 0x00 },
-{ 0x00, 0x01, 0x01 },
-{ 0x00, 0x02, 0x02 },
-{ 0x00, 0x03, 0x03 },
-{ 0x00, 0x04, 0x04 },
-{ 0x00, 0x05, 0x05 },
-{ 0x00, 0x06, 0x06 },
-{ 0x00, 0x07, 0x07 },
-{ 0x00, 0x08, 0x08 },
-{ 0x00, 0x09, 0x09 },
-{ 0x00, 0x0a, 0x0a },
-{ 0x00, 0x0b, 0x0b },
-{ 0x00, 0x0c, 0x0c },
-{ 0x00, 0x0d, 0x0d },
-{ 0x00, 0x0e, 0x0e },
-{ 0x00, 0x0f, 0x0f },
-{ 0x00, 0x10, 0x10 },
-{ 0x00, 0x11, 0x11 },
-{ 0x00, 0x12, 0x12 },
-{ 0x00, 0x13, 0x13 },
-{ 0x00, 0x14, 0x14 },
-{ 0x00, 0x15, 0x15 },
-{ 0x00, 0x16, 0x16 },
-{ 0x00, 0x17, 0x17 },
-{ 0x00, 0x18, 0x18 },
-{ 0x00, 0x19, 0x19 },
-{ 0x00, 0x1a, 0x1a },
-{ 0x00, 0x1b, 0x1b },
-{ 0x00, 0x1c, 0x1c },
-{ 0x00, 0x1d, 0x1d },
-{ 0x00, 0x1e, 0x1e },
-{ 0x00, 0x1f, 0x1f },
-{ 0x00, 0x20, 0x20 },
-{ 0x00, 0x21, 0x21 },
-{ 0x00, 0x22, 0x22 },
-{ 0x00, 0x23, 0x23 },
-{ 0x00, 0x24, 0x24 },
-{ 0x00, 0x25, 0x25 },
-{ 0x00, 0x26, 0x26 },
-{ 0x00, 0x27, 0x27 },
-{ 0x00, 0x28, 0x28 },
-{ 0x00, 0x29, 0x29 },
-{ 0x00, 0x2a, 0x2a },
-{ 0x00, 0x2b, 0x2b },
-{ 0x00, 0x2c, 0x2c },
-{ 0x00, 0x2d, 0x2d },
-{ 0x00, 0x2e, 0x2e },
-{ 0x00, 0x2f, 0x2f },
-{ 0x00, 0x30, 0x30 },
-{ 0x00, 0x31, 0x31 },
-{ 0x00, 0x32, 0x32 },
-{ 0x00, 0x33, 0x33 },
-{ 0x00, 0x34, 0x34 },
-{ 0x00, 0x35, 0x35 },
-{ 0x00, 0x36, 0x36 },
-{ 0x00, 0x37, 0x37 },
-{ 0x00, 0x38, 0x38 },
-{ 0x00, 0x39, 0x39 },
-{ 0x00, 0x3a, 0x3a },
-{ 0x00, 0x3b, 0x3b },
-{ 0x00, 0x3c, 0x3c },
-{ 0x00, 0x3d, 0x3d },
-{ 0x00, 0x3e, 0x3e },
-{ 0x00, 0x3f, 0x3f },
-{ 0x00, 0x40, 0x40 },
-{ 0x01, 0x61, 0x41 },
-{ 0x01, 0x62, 0x42 },
-{ 0x01, 0x63, 0x43 },
-{ 0x01, 0x64, 0x44 },
-{ 0x01, 0x65, 0x45 },
-{ 0x01, 0x66, 0x46 },
-{ 0x01, 0x67, 0x47 },
-{ 0x01, 0x68, 0x48 },
-{ 0x01, 0x69, 0x49 },
-{ 0x01, 0x6a, 0x4a },
-{ 0x01, 0x6b, 0x4b },
-{ 0x01, 0x6c, 0x4c },
-{ 0x01, 0x6d, 0x4d },
-{ 0x01, 0x6e, 0x4e },
-{ 0x01, 0x6f, 0x4f },
-{ 0x01, 0x70, 0x50 },
-{ 0x01, 0x71, 0x51 },
-{ 0x01, 0x72, 0x52 },
-{ 0x01, 0x73, 0x53 },
-{ 0x01, 0x74, 0x54 },
-{ 0x01, 0x75, 0x55 },
-{ 0x01, 0x76, 0x56 },
-{ 0x01, 0x77, 0x57 },
-{ 0x01, 0x78, 0x58 },
-{ 0x01, 0x79, 0x59 },
-{ 0x01, 0x7a, 0x5a },
-{ 0x00, 0x5b, 0x5b },
-{ 0x00, 0x5c, 0x5c },
-{ 0x00, 0x5d, 0x5d },
-{ 0x00, 0x5e, 0x5e },
-{ 0x00, 0x5f, 0x5f },
-{ 0x00, 0x60, 0x60 },
-{ 0x00, 0x61, 0x41 },
-{ 0x00, 0x62, 0x42 },
-{ 0x00, 0x63, 0x43 },
-{ 0x00, 0x64, 0x44 },
-{ 0x00, 0x65, 0x45 },
-{ 0x00, 0x66, 0x46 },
-{ 0x00, 0x67, 0x47 },
-{ 0x00, 0x68, 0x48 },
-{ 0x00, 0x69, 0x49 },
-{ 0x00, 0x6a, 0x4a },
-{ 0x00, 0x6b, 0x4b },
-{ 0x00, 0x6c, 0x4c },
-{ 0x00, 0x6d, 0x4d },
-{ 0x00, 0x6e, 0x4e },
-{ 0x00, 0x6f, 0x4f },
-{ 0x00, 0x70, 0x50 },
-{ 0x00, 0x71, 0x51 },
-{ 0x00, 0x72, 0x52 },
-{ 0x00, 0x73, 0x53 },
-{ 0x00, 0x74, 0x54 },
-{ 0x00, 0x75, 0x55 },
-{ 0x00, 0x76, 0x56 },
-{ 0x00, 0x77, 0x57 },
-{ 0x00, 0x78, 0x58 },
-{ 0x00, 0x79, 0x59 },
-{ 0x00, 0x7a, 0x5a },
-{ 0x00, 0x7b, 0x7b },
-{ 0x00, 0x7c, 0x7c },
-{ 0x00, 0x7d, 0x7d },
-{ 0x00, 0x7e, 0x7e },
-{ 0x00, 0x7f, 0x7f },
-{ 0x00, 0x80, 0x80 },
-{ 0x00, 0x81, 0x81 },
-{ 0x00, 0x82, 0x82 },
-{ 0x00, 0x83, 0x83 },
-{ 0x00, 0x84, 0x84 },
-{ 0x00, 0x85, 0x85 },
-{ 0x00, 0x86, 0x86 },
-{ 0x00, 0x87, 0x87 },
-{ 0x00, 0x88, 0x88 },
-{ 0x00, 0x89, 0x89 },
-{ 0x00, 0x8a, 0x8a },
-{ 0x00, 0x8b, 0x8b },
-{ 0x00, 0x8c, 0x8c },
-{ 0x00, 0x8d, 0x8d },
-{ 0x00, 0x8e, 0x8e },
-{ 0x00, 0x8f, 0x8f },
-{ 0x00, 0x90, 0x90 },
-{ 0x00, 0x91, 0x91 },
-{ 0x00, 0x92, 0x92 },
-{ 0x00, 0x93, 0x93 },
-{ 0x00, 0x94, 0x94 },
-{ 0x00, 0x95, 0x95 },
-{ 0x00, 0x96, 0x96 },
-{ 0x00, 0x97, 0x97 },
-{ 0x00, 0x98, 0x98 },
-{ 0x00, 0x99, 0x99 },
-{ 0x00, 0x9a, 0x9a },
-{ 0x00, 0x9b, 0x9b },
-{ 0x00, 0x9c, 0x9c },
-{ 0x00, 0x9d, 0x9d },
-{ 0x00, 0x9e, 0x9e },
-{ 0x00, 0x9f, 0x9f },
-{ 0x00, 0xa0, 0xa0 },
-{ 0x00, 0xa1, 0xa1 },
-{ 0x00, 0xa2, 0xa2 },
-{ 0x00, 0xa3, 0xa3 },
-{ 0x00, 0xa4, 0xa4 },
-{ 0x00, 0xa5, 0xa5 },
-{ 0x00, 0xa6, 0xa6 },
-{ 0x00, 0xa7, 0xa7 },
-{ 0x00, 0xa8, 0xa8 },
-{ 0x00, 0xa9, 0xa9 },
-{ 0x00, 0xaa, 0xaa },
-{ 0x00, 0xab, 0xab },
-{ 0x00, 0xac, 0xac },
-{ 0x00, 0xad, 0xad },
-{ 0x00, 0xae, 0xae },
-{ 0x00, 0xaf, 0xaf },
-{ 0x00, 0xb0, 0xb0 },
-{ 0x00, 0xb1, 0xb1 },
-{ 0x00, 0xb2, 0xb2 },
-{ 0x00, 0xb3, 0xb3 },
-{ 0x00, 0xb4, 0xb4 },
-{ 0x00, 0xb5, 0xb5 },
-{ 0x00, 0xb6, 0xb6 },
-{ 0x00, 0xb7, 0xb7 },
-{ 0x00, 0xb8, 0xb8 },
-{ 0x00, 0xb9, 0xb9 },
-{ 0x00, 0xba, 0xba },
-{ 0x00, 0xbb, 0xbb },
-{ 0x00, 0xbc, 0xbc },
-{ 0x00, 0xbd, 0xbd },
-{ 0x00, 0xbe, 0xbe },
-{ 0x00, 0xbf, 0xbf },
-{ 0x00, 0xc0, 0xc0 },
-{ 0x00, 0xc1, 0xc1 },
-{ 0x00, 0xc2, 0xc2 },
-{ 0x00, 0xc3, 0xc3 },
-{ 0x00, 0xc4, 0xc4 },
-{ 0x00, 0xc5, 0xc5 },
-{ 0x00, 0xc6, 0xc6 },
-{ 0x00, 0xc7, 0xc7 },
-{ 0x00, 0xc8, 0xc8 },
-{ 0x00, 0xc9, 0xc9 },
-{ 0x00, 0xca, 0xca },
-{ 0x00, 0xcb, 0xcb },
-{ 0x00, 0xcc, 0xcc },
-{ 0x00, 0xcd, 0xcd },
-{ 0x00, 0xce, 0xce },
-{ 0x00, 0xcf, 0xcf },
-{ 0x00, 0xd0, 0xd0 },
-{ 0x00, 0xd1, 0xd1 },
-{ 0x00, 0xd2, 0xd2 },
-{ 0x00, 0xd3, 0xd3 },
-{ 0x00, 0xd4, 0xd4 },
-{ 0x00, 0xd5, 0xd5 },
-{ 0x00, 0xd6, 0xd6 },
-{ 0x00, 0xd7, 0xd7 },
-{ 0x00, 0xd8, 0xd8 },
-{ 0x00, 0xd9, 0xd9 },
-{ 0x00, 0xda, 0xda },
-{ 0x00, 0xdb, 0xdb },
-{ 0x00, 0xdc, 0xdc },
-{ 0x00, 0xdd, 0xdd },
-{ 0x00, 0xde, 0xde },
-{ 0x00, 0xdf, 0xdf },
-{ 0x00, 0xe0, 0xe0 },
-{ 0x00, 0xe1, 0xe1 },
-{ 0x00, 0xe2, 0xe2 },
-{ 0x00, 0xe3, 0xe3 },
-{ 0x00, 0xe4, 0xe4 },
-{ 0x00, 0xe5, 0xe5 },
-{ 0x00, 0xe6, 0xe6 },
-{ 0x00, 0xe7, 0xe7 },
-{ 0x00, 0xe8, 0xe8 },
-{ 0x00, 0xe9, 0xe9 },
-{ 0x00, 0xea, 0xea },
-{ 0x00, 0xeb, 0xeb },
-{ 0x00, 0xec, 0xec },
-{ 0x00, 0xed, 0xed },
-{ 0x00, 0xee, 0xee },
-{ 0x00, 0xef, 0xef },
-{ 0x00, 0xf0, 0xf0 },
-{ 0x00, 0xf1, 0xf1 },
-{ 0x00, 0xf2, 0xf2 },
-{ 0x00, 0xf3, 0xf3 },
-{ 0x00, 0xf4, 0xf4 },
-{ 0x00, 0xf5, 0xf5 },
-{ 0x00, 0xf6, 0xf6 },
-{ 0x00, 0xf7, 0xf7 },
-{ 0x00, 0xf8, 0xf8 },
-{ 0x00, 0xf9, 0xf9 },
-{ 0x00, 0xfa, 0xfa },
-{ 0x00, 0xfb, 0xfb },
-{ 0x00, 0xfc, 0xfc },
-{ 0x00, 0xfd, 0xfd },
-{ 0x00, 0xfe, 0xfe },
-{ 0x00, 0xff, 0xff },
-};
-
-struct enc_entry encds[] = {
-{"ISO8859-1",iso1_tbl},
-{"ISO8859-2",iso2_tbl},
-{"ISO8859-3",iso3_tbl},
-{"ISO8859-4",iso4_tbl},
-{"ISO8859-5",iso5_tbl},
-{"ISO8859-6",iso6_tbl},
-{"ISO8859-7",iso7_tbl},
-{"ISO8859-8",iso8_tbl},
-{"ISO8859-9",iso9_tbl},
-{"ISO8859-10",iso10_tbl},
-{"KOI8-R",koi8r_tbl},
-{"KOI8-U",koi8u_tbl},
-{"microsoft-cp1251",cp1251_tbl},
-{"ISO8859-13", iso13_tbl},
-{"ISO8859-14", iso14_tbl},
-{"ISO8859-15", iso15_tbl},
-{"ISCII-DEVANAGARI", iscii_devanagari_tbl},
-};
-
-struct cs_info * get_current_cs(const char * es) {
-  struct cs_info * ccs = encds[0].cs_table;
-  int n = sizeof(encds) / sizeof(encds[0]);
-  for (int i = 0; i < n; i++) {
-    if (strcmp(es,encds[i].enc_name) == 0) {
-      ccs = encds[i].cs_table;
-    }
-  }
-  return ccs;
-}
-#else
-// XXX This function was rewritten for mozilla. Instead of storing the
-// conversion tables static in this file, create them when needed
-// with help the mozilla backend.
-struct cs_info * get_current_cs(const char * es) {
-  struct cs_info *ccs;
-
-  nsCOMPtr<nsIUnicodeEncoder> encoder; 
-  nsCOMPtr<nsIUnicodeDecoder> decoder; 
-  nsCOMPtr<nsICaseConversion> caseConv;
-
-  nsresult rv;
-  nsCOMPtr<nsICharsetConverterManager> ccm = do_GetService(kCharsetConverterManagerCID, &rv);
-  if (NS_FAILED(rv))
-    return nsnull;
-
-  rv = ccm->GetUnicodeEncoder(es, getter_AddRefs(encoder));
-  if (encoder && NS_SUCCEEDED(rv))
-    encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?');
-  if (NS_FAILED(rv))
-    return nsnull;
-  rv = ccm->GetUnicodeDecoder(es, getter_AddRefs(decoder));
-
-  caseConv = do_GetService(kUnicharUtilCID, &rv);
-  if (NS_FAILED(rv))
-    return nsnull;
-
-  ccs = (struct cs_info *) malloc(256 * sizeof(cs_info));
-
-  PRInt32 charLength = 256;
-  PRInt32 uniLength = 512;
-  char *source = (char *)malloc(charLength * sizeof(char));
-  PRUnichar *uni = (PRUnichar *)malloc(uniLength * sizeof(PRUnichar));
-  char *lower = (char *)malloc(charLength * sizeof(char));
-  char *upper = (char *)malloc(charLength * sizeof(char));
-
-  // Create a long string of all chars.
-  unsigned int i;
-  for (i = 0x00; i <= 0xff ; ++i) {
-    source[i] = i;
-  }
-
-  // Convert this long string to unicode
-  rv = decoder->Convert(source, &charLength, uni, &uniLength);
-
-  // Do case conversion stuff, and convert back.
-  caseConv->ToUpper(uni, uni, uniLength);
-  encoder->Convert(uni, &uniLength, upper, &charLength);
-
-  uniLength = 512;
-  charLength = 256;
-  rv = decoder->Convert(source, &charLength, uni, &uniLength);
-  caseConv->ToLower(uni, uni, uniLength);
-  encoder->Convert(uni, &uniLength, lower, &charLength);
-
-  // Store
-  for (i = 0x00; i <= 0xff ; ++i) {
-    ccs[i].cupper = upper[i];
-    ccs[i].clower = lower[i];
-    
-    if (ccs[i].clower != (unsigned char)i)
-      ccs[i].ccase = true;
-    else
-      ccs[i].ccase = false;
-      
-  }
-
-  free(source);
-  free(uni);
-  free(lower);
-  free(upper);
-
-  return ccs;
-}
-#endif
-
-// primitive isalpha() replacement for tokenization
-char * get_casechars(const char * enc) {
-    struct cs_info * csconv = get_current_cs(enc);
-    char expw[MAXLNLEN];
-    char * p =  expw;
-    for (int i = 0; i <= 255; i++) {
-        if ((csconv[i].cupper != csconv[i].clower)) {
-    	    *p = (char) i;
-    	    p++;
-        }
-    }
-    *p = '\0';
-#ifdef MOZILLA_CLIENT
-    delete csconv;
-#endif
-    return mystrdup(expw);
-}
-
-
-
-struct lang_map lang2enc[] = {
-{"ar", "UTF-8", LANG_ar},
-{"az", "UTF-8", LANG_az},
-{"bg", "microsoft-cp1251", LANG_bg},
-{"ca", "ISO8859-1", LANG_ca},
-{"cs", "ISO8859-2", LANG_cs},
-{"da", "ISO8859-1", LANG_da},
-{"de", "ISO8859-1", LANG_de},
-{"el", "ISO8859-7", LANG_el},
-{"en", "ISO8859-1", LANG_en},
-{"es", "ISO8859-1", LANG_es},
-{"eu", "ISO8859-1", LANG_eu},
-{"gl", "ISO8859-1", LANG_gl},
-{"fr", "ISO8859-15", LANG_fr},
-{"hr", "ISO8859-2", LANG_hr},
-{"hu", "ISO8859-2", LANG_hu},
-{"it", "ISO8859-1", LANG_it},
-{"la", "ISO8859-1", LANG_la},
-{"lv", "ISO8859-13", LANG_lv},
-{"nl", "ISO8859-1", LANG_nl},
-{"pl", "ISO8859-2", LANG_pl},
-{"pt", "ISO8859-1", LANG_pt},
-{"sv", "ISO8859-1", LANG_sv},
-{"tr", "UTF-8", LANG_tr},
-{"ru", "KOI8-R", LANG_ru},
-{"uk", "KOI8-U", LANG_uk}
-};
-
-
-const char * get_default_enc(const char * lang) {
-  int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
-  for (int i = 0; i < n; i++) {
-    if (strcmp(lang,lang2enc[i].lang) == 0) {
-      return lang2enc[i].def_enc;
-    }
-  }
-  return NULL;
-}
-
-int get_lang_num(const char * lang) {
-  int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
-  for (int i = 0; i < n; i++) {
-    if (strncmp(lang,lang2enc[i].lang,2) == 0) {
-      return lang2enc[i].num;
-    }
-  }
-  return LANG_xx;
-}
-
-#ifndef OPENOFFICEORG
-#ifndef MOZILLA_CLIENT
-int initialize_utf_tbl() {
-  utf_tbl_count++;
-  if (utf_tbl) return 0;
-  utf_tbl = (unicode_info2 *) malloc(CONTSIZE * sizeof(unicode_info2));
-  if (utf_tbl) {
-    int j;
-    for (j = 0; j < CONTSIZE; j++) {
-      utf_tbl[j].cletter = 0;
-      utf_tbl[j].clower = (unsigned short) j;
-      utf_tbl[j].cupper = (unsigned short) j;
-    }
-    for (j = 0; j < UTF_LST_LEN; j++) {
-      utf_tbl[utf_lst[j].c].cletter = 1;
-      utf_tbl[utf_lst[j].c].clower = utf_lst[j].clower;
-      utf_tbl[utf_lst[j].c].cupper = utf_lst[j].cupper;
-    }
-  } else return 1;
-  return 0;
-}
-#endif
-#endif
-
-void free_utf_tbl() {
-  if (utf_tbl_count > 0) utf_tbl_count--;
-  if (utf_tbl && (utf_tbl_count == 0)) {
-    free(utf_tbl);
-    utf_tbl = NULL;
-  }
-}
-
-#ifdef MOZILLA_CLIENT
-static nsCOMPtr<nsICaseConversion>& getcaseConv()
-{
-  nsresult rv;
-  static nsCOMPtr<nsICaseConversion> caseConv = do_GetService(kUnicharUtilCID, &rv);
-  return caseConv;
-}
-#endif
-
-unsigned short unicodetoupper(unsigned short c, int langnum)
-{
-  // In Azeri and Turkish, I and i dictinct letters:
-  // There are a dotless lower case i pair of upper `I',
-  // and an upper I with dot pair of lower `i'. 
-  if (c == 0x0069 && ((langnum == LANG_az) || (langnum == LANG_tr)))
-    return 0x0130;
-#ifdef OPENOFFICEORG
-  return u_toupper(c);
-#else
-#ifdef MOZILLA_CLIENT
-  PRUnichar ch2;
-  getcaseConv()->ToUpper((PRUnichar) c, &ch2);
-  return ch2;
-#else
-  return (utf_tbl) ? utf_tbl[c].cupper : c;
-#endif
-#endif
-}
-
-unsigned short unicodetolower(unsigned short c, int langnum)
-{
-  // In Azeri and Turkish, I and i dictinct letters:
-  // There are a dotless lower case i pair of upper `I',
-  // and an upper I with dot pair of lower `i'. 
-  if (c == 0x0049 && ((langnum == LANG_az) || (langnum == LANG_tr)))
-    return 0x0131;
-#ifdef OPENOFFICEORG
-  return u_tolower(c);
-#else
-#ifdef MOZILLA_CLIENT
-  PRUnichar ch2;
-  getcaseConv()->ToLower((PRUnichar) c, &ch2);
-  return ch2;
-#else
-  return (utf_tbl) ? utf_tbl[c].clower : c;
-#endif
-#endif
-}
-
-int unicodeisalpha(unsigned short c)
-{
-#ifdef OPENOFFICEORG
-  return u_isalpha(c);
-#else
-  return (utf_tbl) ? utf_tbl[c].cletter : 0;
-#endif
-}
-
-/* get type of capitalization */
-int get_captype(char * word, int nl, cs_info * csconv) {
-   // now determine the capitalization type of the first nl letters
-   int ncap = 0;
-   int nneutral = 0;
-   int firstcap = 0;
-
-      for (char * q = word; *q != '\0'; q++) {
-         if (csconv[*((unsigned char *)q)].ccase) ncap++;
-         if (csconv[*((unsigned char *)q)].cupper == csconv[*((unsigned char *)q)].clower) nneutral++;
-      }
-      if (ncap) {
-        firstcap = csconv[*((unsigned char *) word)].ccase;
-      }
-
-   // now finally set the captype
-   if (ncap == 0) {
-        return NOCAP;
-   } else if ((ncap == 1) && firstcap) {
-        return INITCAP;
-   } else if ((ncap == nl) || ((ncap + nneutral) == nl)) {
-        return ALLCAP;
-   } else if ((ncap > 1) && firstcap) {
-        return HUHINITCAP;
-   }
-   return HUHCAP;
-}
-
-int get_captype_utf8(w_char * word, int nl, int langnum) {
-   // now determine the capitalization type of the first nl letters
-   int ncap = 0;
-   int nneutral = 0;
-   int firstcap = 0;
-   unsigned short idx;
-   // don't check too long words
-   if (nl >= MAXWORDLEN) return 0;
-   // big Unicode character (non BMP area)
-   if (nl == -1) return NOCAP;
-   for (int i = 0; i < nl; i++) {
-     idx = (word[i].h << 8) + word[i].l;
-     if (idx != unicodetolower(idx, langnum)) ncap++;
-     if (unicodetoupper(idx, langnum) == unicodetolower(idx, langnum)) nneutral++;
-   }
-   if (ncap) {
-      idx = (word[0].h << 8) + word[0].l;
-      firstcap = (idx != unicodetolower(idx, langnum));
-  }
-
-   // now finally set the captype
-   if (ncap == 0) {
-        return NOCAP;
-   } else if ((ncap == 1) && firstcap) {
-        return INITCAP;
-   } else if ((ncap == nl) || ((ncap + nneutral) == nl)) {
-        return ALLCAP;
-   } else if ((ncap > 1) && firstcap) {
-        return HUHINITCAP;
-   }
-   return HUHCAP;
-}
-
-
-// strip all ignored characters in the string
-void remove_ignored_chars_utf(char * word, unsigned short ignored_chars[], int ignored_len)
-{
-   w_char w[MAXWORDLEN];
-   w_char w2[MAXWORDLEN];
-   int i;
-   int j;
-   int len = u8_u16(w, MAXWORDLEN, word);
-   for (i = 0, j = 0; i < len; i++) {
-      if (!flag_bsearch(ignored_chars, ((unsigned short *) w)[i], ignored_len)) {
-         w2[j] = w[i];
-         j++;
-      }
-   }
-   if (j < i) u16_u8(word, MAXWORDUTF8LEN, w2, j);
-}
-
-// strip all ignored characters in the string
-void remove_ignored_chars(char * word, char * ignored_chars)
-{
-   for (char * p = word; *p != '\0'; p++) {
-      if (!strchr(ignored_chars, *p)) {
-        *word = *p;
-        word++;
-      }
-   }
-   *word = '\0';
-}
-
-int parse_string(char * line, char ** out, const char * warnvar)
-{
-   char * tp = line;
-   char * piece;
-   int i = 0;
-   int np = 0;
-   if (*out) {
-      HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", warnvar);
-      return 1;
-   }
-   piece = mystrsep(&tp, 0);
-   while (piece) {
-      if (*piece != '\0') {
-          switch(i) {
-              case 0: { np++; break; }
-              case 1: { 
-                *out = mystrdup(piece);
-                np++;
-                break;
-              }
-              default: break;
-          }
-          i++;
-      }
-      free(piece);
-      piece = mystrsep(&tp, 0);
-   }
-   if (np != 2) {
-      HUNSPELL_WARNING(stderr, "error: missing %s information\n", warnvar);
-      return 1;
-   } 
-   return 0;
-}
-
-int parse_array(char * line, char ** out,
-        unsigned short ** out_utf16, int * out_utf16_len, const char * name, int utf8) {
-   if (parse_string(line, out, name)) return 1;
-   if (utf8) {
-        w_char w[MAXWORDLEN];
-        int n = u8_u16(w, MAXWORDLEN, *out);
-        if (n > 0) {
-            flag_qsort((unsigned short *) w, 0, n);
-            *out_utf16 = (unsigned short *) malloc(n * sizeof(unsigned short));
-            if (!*out_utf16) return 1;
-            memcpy(*out_utf16, w, n * sizeof(unsigned short));
-        }
-        *out_utf16_len = n;
-   }
-   return 0;
-}
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/csutil.hxx spellcheck/hunspell/src/csutil.hxx
--- spellcheck.old/hunspell/src/csutil.hxx	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/csutil.hxx	1970-01-01 01:00:00.000000000 +0100
@@ -1,233 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef __CSUTILHXX__
-#define __CSUTILHXX__
-
-// First some base level utility routines
-
-#define NOCAP   0
-#define INITCAP 1
-#define ALLCAP  2
-#define HUHCAP  3
-#define HUHINITCAP  4
-
-#define FIELD_STEM  "st:"
-#define FIELD_POS   "po:"
-#define FIELD_SUFF  "su:"
-#define FIELD_PREF  "pr:"
-#define FIELD_FREQ  "fr:"
-#define FIELD_PHON  "ph:"
-#define FIELD_HYPH  "hy:"
-#define FIELD_COMP  "co:"
-
-// default flags
-#define ONLYUPCASEFLAG 65535
-
-typedef struct {
-    unsigned char l;
-    unsigned char h;
-} w_char;
-
-#define w_char_eq(a,b) (((a).l == (b).l) && ((a).h == (b).h))
-
-// convert UTF-16 characters to UTF-8
-char * u16_u8(char * dest, int size, const w_char * src, int srclen);
-
-// convert UTF-8 characters to UTF-16
-int u8_u16(w_char * dest, int size, const char * src);
-
-// sort 2-byte vector
-void flag_qsort(unsigned short flags[], int begin, int end);
-
-// binary search in 2-byte vector
-int flag_bsearch(unsigned short flags[], unsigned short flag, int right);
-
-// remove end of line char(s)
-void   mychomp(char * s);
-
-// duplicate string
-char * mystrdup(const char * s);
-
-// duplicate reverse of string
-char * myrevstrdup(const char * s);
-
-// parse into tokens with char delimiter
-char * mystrsep(char ** sptr, const char delim);
-// parse into tokens with char delimiter
-char * mystrsep2(char ** sptr, const char delim);
-
-// parse into tokens with char delimiter
-char * mystrrep(char *, const char *, const char *);
-
-// append s to ends of every lines in text
-void strlinecat(char * lines, const char * s);
-
-// tokenize into lines with new line
-   int line_tok(const char * text, char *** lines);
-
-// tokenize into lines with new line and uniq in place
-   char * line_uniq(char * text);
-
-// change \n to c in place
-   char * line_join(char * text, char c);
-
-// leave only last {[^}]*} pattern in string
-   char * delete_zeros(char * morphout);
-
-// reverse word
-   int reverseword(char *);
-
-// reverse word
-   int reverseword_utf(char *);
-
-// character encoding information
-struct cs_info {
-  unsigned char ccase;
-  unsigned char clower;
-  unsigned char cupper;
-};
-
-// two character arrays
-struct replentry {
-  char * pattern;
-  char * pattern2;
-};
-
-// Unicode character encoding information
-struct unicode_info {
-  unsigned short c;
-  unsigned short cupper;
-  unsigned short clower;
-};
-
-struct unicode_info2 {
-  char cletter;
-  unsigned short cupper;
-  unsigned short clower;
-};
-
-int initialize_utf_tbl();
-void free_utf_tbl();
-unsigned short unicodetoupper(unsigned short c, int langnum);
-unsigned short unicodetolower(unsigned short c, int langnum);
-int unicodeisalpha(unsigned short c);
-
-struct enc_entry {
-  const char * enc_name;
-  struct cs_info * cs_table;
-};
-
-// language to encoding default map
-
-struct lang_map {
-  const char * lang;
-  const char * def_enc;
-  int num;
-};
-
-struct cs_info * get_current_cs(const char * es);
-
-const char * get_default_enc(const char * lang);
-
-// get language identifiers of language codes
-int get_lang_num(const char * lang);
-
-// get characters of the given 8bit encoding with lower- and uppercase forms
-char * get_casechars(const char * enc);
-
-// convert null terminated string to all caps using encoding
-void enmkallcap(char * d, const char * p, const char * encoding);
-
-// convert null terminated string to all little using encoding
-void enmkallsmall(char * d, const char * p, const char * encoding);
-
-// convert null terminated string to have intial capital using encoding
-void enmkinitcap(char * d, const char * p, const char * encoding);
-
-// convert null terminated string to all caps
-void mkallcap(char * p, const struct cs_info * csconv);
-
-// convert null terminated string to all little
-void mkallsmall(char * p, const struct cs_info * csconv);
-
-// convert null terminated string to have intial capital
-void mkinitcap(char * p, const struct cs_info * csconv);
-
-// convert first nc characters of UTF-8 string to little
-void mkallsmall_utf(w_char * u, int nc, int langnum);
-
-// convert first nc characters of UTF-8 string to capital
-void mkallcap_utf(w_char * u, int nc, int langnum);
-
-// get type of capitalization
-int get_captype(char * q, int nl, cs_info *);
-
-// get type of capitalization (UTF-8)
-int get_captype_utf8(w_char * q, int nl, int langnum);
-
-// strip all ignored characters in the string
-void remove_ignored_chars_utf(char * word, unsigned short ignored_chars[], int ignored_len);
-
-// strip all ignored characters in the string
-void remove_ignored_chars(char * word, char * ignored_chars);
-
-int parse_string(char * line, char ** out, const char * name);
-
-int parse_array(char * line, char ** out,
-        unsigned short ** out_utf16, int * out_utf16_len, const char * name, int utf8);
-
-#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/hashmgr.cpp spellcheck/hunspell/src/hashmgr.cpp
--- spellcheck.old/hunspell/src/hashmgr.cpp	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/hashmgr.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,941 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef MOZILLA_CLIENT
-#include <cstdlib>
-#include <cstring>
-#include <cstdio>
-#include <cctype>
-#else
-#include <stdlib.h> 
-#include <string.h>
-#include <stdio.h> 
-#include <ctype.h>
-#endif
-
-#include "hashmgr.hxx"
-#include "csutil.hxx"
-#include "atypes.hxx"
-
-#ifdef MOZILLA_CLIENT
-#ifdef __SUNPRO_CC // for SunONE Studio compiler
-using namespace std;
-#endif
-#else
-#ifndef W32
-using namespace std;
-#endif
-#endif
-
-// build a hash table from a munched word list
-
-HashMgr::HashMgr(const char * tpath, const char * apath)
-{
-  tablesize = 0;
-  tableptr = NULL;
-  flag_mode = FLAG_CHAR;
-  complexprefixes = 0;
-  utf8 = 0;
-  langnum = 0;
-  lang = NULL;
-  enc = NULL;
-  csconv = 0;
-  ignorechars = NULL;
-  ignorechars_utf16 = NULL;
-  ignorechars_utf16_len = 0;
-  numaliasf = 0;
-  aliasf = NULL;
-  numaliasm = 0;
-  aliasm = NULL;
-  forbiddenword = FLAG_NULL; // forbidden word signing flag
-  load_config(apath);  
-  int ec = load_tables(tpath);
-  if (ec) {
-    /* error condition - what should we do here */
-    HUNSPELL_WARNING(stderr, "Hash Manager Error : %d\n",ec);
-    if (tableptr) {
-      free(tableptr);
-      tableptr = NULL;
-    }
-    tablesize = 0;
-  }
-}
-
-
-HashMgr::~HashMgr()
-{
-  if (tableptr) {
-    // now pass through hash table freeing up everything
-    // go through column by column of the table
-    for (int i=0; i < tablesize; i++) {
-      struct hentry * pt = tableptr[i];
-      struct hentry * nt = NULL;
-/*      if (pt) {
-        if (pt->astr && (!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen))) free(pt->astr);
-#ifdef HUNSPELL_EXPERIMENTAL
-        if (pt->description && !aliasm) free(pt->description);
-#endif
-        pt = pt->next;
-      }
-*/
-      while(pt) {
-        nt = pt->next;
-        if (pt->astr && (!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen))) free(pt->astr);
-#ifdef HUNSPELL_EXPERIMENTAL
-        if (pt->description && !aliasm) free(pt->description);
-#endif
-        free(pt);
-        pt = nt;
-      }
-    }
-    free(tableptr);
-  }
-  tablesize = 0;
-
-  if (aliasf) {
-    for (int j = 0; j < (numaliasf); j++) free(aliasf[j]);
-    free(aliasf);
-    aliasf = NULL;
-    if (aliasflen) {
-      free(aliasflen);
-      aliasflen = NULL;
-    }
-  }
-  if (aliasm) {
-    for (int j = 0; j < (numaliasm); j++) free(aliasm[j]);
-    free(aliasm);
-    aliasm = NULL;
-  }  
-
-#ifndef OPENOFFICEORG
-#ifndef MOZILLA_CLIENT
-  if (utf8) free_utf_tbl();
-#endif
-#endif
-
-  if (enc) free(enc);
-  if (lang) free(lang);
-  
-  if (ignorechars) free(ignorechars);
-  if (ignorechars_utf16) free(ignorechars_utf16);
-}
-
-// lookup a root word in the hashtable
-
-struct hentry * HashMgr::lookup(const char *word) const
-{
-    struct hentry * dp;
-    if (tableptr) {
-       dp = tableptr[hash(word)];
-       if (!dp) return NULL;
-       for (  ;  dp != NULL;  dp = dp->next) {
-          if (strcmp(word,&(dp->word)) == 0) return dp;
-       }
-    }
-    return NULL;
-}
-
-// add a word to the hash table (private)
-int HashMgr::add_word(const char * word, int wbl, int wcl, unsigned short * aff,
-    int al, const char * desc, bool onlyupcase)
-{
-    bool upcasehomonym = false;
-    int descl = (desc) ? strlen(desc) : 0;
-    // variable-length hash record with word and optional fields
-    // instead of mmap implementation temporarily
-    struct hentry* hp = 
-	(struct hentry *) malloc (sizeof(struct hentry) + wbl + descl + 1);
-    if (!hp) return 1;
-    char * hpw = &(hp->word);
-    strcpy(hpw, word);
-    if (desc && strncmp(desc, FIELD_PHON, strlen(FIELD_PHON)) == 0) {
-	strcpy(hpw + wbl + 1, desc + strlen(FIELD_PHON));
-	hp->var = 1;
-    } else {
-	hp->var = 0;
-    }
-    if (ignorechars != NULL) {
-      if (utf8) {
-        remove_ignored_chars_utf(hpw, ignorechars_utf16, ignorechars_utf16_len);
-      } else {
-        remove_ignored_chars(hpw, ignorechars);
-      }
-    }
-    if (complexprefixes) {
-        if (utf8) reverseword_utf(hpw); else reverseword(hpw);
-    }
-
-    int i = hash(hpw);
-
-       hp->blen = (unsigned char) wbl;
-       hp->clen = (unsigned char) wcl;
-       hp->alen = (short) al;
-       hp->astr = aff;
-       hp->next = NULL;      
-       hp->next_homonym = NULL;
-#ifdef HUNSPELL_EXPERIMENTAL       
-       if (aliasm) {
-            hp->description = (desc) ? get_aliasm(atoi(desc)) : mystrdup(desc);
-       } else {
-            hp->description = mystrdup(desc);
-            if (desc && !hp->description)
-            {
-                free(hp->astr);
-                free(hp);
-                return 1;
-            }
-            if (hp->description && complexprefixes) {
-                if (utf8) reverseword_utf(hp->description); else reverseword(hp->description);
-            }
-       }
-#endif
-       
-       struct hentry * dp = tableptr[i];
-       if (!dp) {
-         tableptr[i] = hp;
-         return 0;
-       }
-       while (dp->next != NULL) {
-         if ((!dp->next_homonym) && (strcmp(&(hp->word), &(dp->word)) == 0)) {
-    	    // remove hidden onlyupcase homonym
-            if (!onlyupcase) {
-		if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) {
-		    free(dp->astr);
-		    dp->astr = hp->astr;
-		    dp->alen = hp->alen;
-		    free(hp);
-		    return 0;
-		} else {
-    		    dp->next_homonym = hp;
-    		}
-            } else {
-        	upcasehomonym = true;
-            }
-         }
-         dp=dp->next;
-       }
-       if (strcmp(&(hp->word), &(dp->word)) == 0) {
-    	    // remove hidden onlyupcase homonym
-            if (!onlyupcase) {
-		if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) {
-		    free(dp->astr);
-		    dp->astr = hp->astr;
-		    dp->alen = hp->alen;
-		    free(hp);
-		    return 0;
-		} else {
-    		    dp->next_homonym = hp;
-    		}
-            } else {
-        	upcasehomonym = true;
-            }
-       }
-       if (!upcasehomonym) {
-    	    dp->next = hp;
-       } else {
-    	    // remove hidden onlyupcase homonym
-    	    if (hp->astr) free(hp->astr);
-    	    free(hp);
-       }
-    return 0;
-}     
-
-int HashMgr::add_hidden_capitalized_word(char * word, int wbl, int wcl,
-    unsigned short * flags, int al, char * dp, int captype)
-{
-    // add inner capitalized forms to handle the following allcap forms:
-    // Mixed caps: OpenOffice.org -> OPENOFFICE.ORG
-    // Allcaps with suffixes: CIA's -> CIA'S    
-    if (((captype == HUHCAP) || (captype == HUHINITCAP) ||
-      ((captype == ALLCAP) && (flags != NULL))) &&
-      !((flags != NULL) && TESTAFF(flags, forbiddenword, al))) {
-          unsigned short * flags2 = (unsigned short *) malloc (sizeof(unsigned short) * (al+1));
-	  if (!flags2) return 1;
-          if (al) memcpy(flags2, flags, al * sizeof(unsigned short));
-          flags2[al] = ONLYUPCASEFLAG;
-          if (utf8) {
-              char st[MAXDELEN];
-              w_char w[MAXDELEN];
-              int wlen = u8_u16(w, MAXDELEN, word);
-              mkallsmall_utf(w, wlen, langnum);
-              mkallcap_utf(w, 1, langnum);
-              u16_u8(st, MAXDELEN, w, wlen);
-              return add_word(st,wbl,wcl,flags2,al+1,dp, true);
-           } else {
-               mkallsmall(word, csconv);
-               mkinitcap(word, csconv);
-               return add_word(word,wbl,wcl,flags2,al+1,dp, true);
-           }
-    }
-    return 0;
-}
-
-// detect captype and modify word length for UTF-8 encoding
-int HashMgr::get_clen_and_captype(const char * word, int wbl, int * captype) {
-    int len;
-    if (utf8) {
-      w_char dest_utf[MAXDELEN];
-      len = u8_u16(dest_utf, MAXDELEN, word);
-      *captype = get_captype_utf8(dest_utf, len, langnum);
-    } else {
-      len = wbl;
-      *captype = get_captype((char *) word, len, csconv);
-    }
-    return len;
-}
-
-// add a custom dic. word to the hash table (public)
-int HashMgr::put_word(const char * word, char * aff)
-{
-    unsigned short * flags;
-    int al = 0;
-    if (aff) {
-        al = decode_flags(&flags, aff);
-        flag_qsort(flags, 0, al);
-    } else {
-        flags = NULL;
-    }
-
-    int captype;
-    int wbl = strlen(word);
-    int wcl = get_clen_and_captype(word, wbl, &captype);
-    add_word(word, wbl, wcl, flags, al, NULL, false);
-    return add_hidden_capitalized_word((char *) word, wbl, wcl, flags, al, NULL, captype);
-}
-
-int HashMgr::put_word_pattern(const char * word, const char * pattern)
-{
-    // detect captype and modify word length for UTF-8 encoding
-    struct hentry * dp = lookup(pattern);
-    if (dp && dp->astr) {
-        int captype;
-        int wbl = strlen(word);
-        int wcl = get_clen_and_captype(word, wbl, &captype);
-	if (aliasf) {
-	    add_word(word, wbl, wcl, dp->astr, dp->alen, NULL, false);	
-	} else {
-    	    unsigned short * flags = (unsigned short *) malloc (dp->alen * sizeof(short));
-	    if (flags) {
-		memcpy((void *) flags, (void *) dp->astr, dp->alen * sizeof(short));
-		add_word(word, wbl, wcl, flags, dp->alen, NULL, false);
-	    } else return 1;
-	}
-    	return add_hidden_capitalized_word((char *) word, wbl, wcl, dp->astr, dp->alen, NULL, captype);
-    }
-    return 1;
-}
-
-// walk the hash table entry by entry - null at end
-// initialize: col=-1; hp = NULL; hp = walk_hashtable(&col, hp);
-struct hentry * HashMgr::walk_hashtable(int &col, struct hentry * hp) const
-{  
-  if (hp && hp->next != NULL) return hp->next;
-  for (col++; col < tablesize; col++) {
-    if (tableptr[col]) return tableptr[col];
-  }
-  // null at end and reset to start
-  col = -1;
-  return NULL;
-}
-
-// load a munched word list and build a hash table on the fly
-int HashMgr::load_tables(const char * tpath)
-{
-  int al;
-  char * ap;
-  char * dp;
-  unsigned short * flags;
-
-  // raw dictionary - munched file
-  FILE * rawdict = fopen(tpath, "r");
-  if (rawdict == NULL) return 1;
-
-  // first read the first line of file to get hash table size */
-  char ts[MAXDELEN];
-  if (! fgets(ts, MAXDELEN-1,rawdict)) {
-    HUNSPELL_WARNING(stderr, "error: empty dic file\n");
-    fclose(rawdict);
-    return 2;
-  }
-  mychomp(ts);
-  
-  /* remove byte order mark */
-  if (strncmp(ts,"\xEF\xBB\xBF",3) == 0) {
-    memmove(ts, ts+3, strlen(ts+3)+1);
-    HUNSPELL_WARNING(stderr, "warning: dic file begins with byte order mark: possible incompatibility with old Hunspell versions\n");
-  }
-  
-  if ((*ts < '1') || (*ts > '9')) HUNSPELL_WARNING(stderr, "error - missing word count in dictionary file\n");
-  tablesize = atoi(ts);
-  if (!tablesize) {
-    fclose(rawdict);
-    return 4;
-  }
-  tablesize = tablesize + 5 + USERWORD;
-  if ((tablesize %2) == 0) tablesize++;
-
-  // allocate the hash table
-  tableptr = (struct hentry **) malloc(tablesize * sizeof(struct hentry *));
-  if (! tableptr) {
-    fclose(rawdict);
-    return 3;
-  }
-  for (int i=0; i<tablesize; i++) tableptr[i] = NULL;
-
-  // loop through all words on much list and add to hash
-  // table and create word and affix strings
-
-  while (fgets(ts,MAXDELEN-1,rawdict)) {
-    mychomp(ts);
-    // split each line into word and morphological description
-    dp = strchr(ts,'\t');
-
-    if (dp) {
-      *dp = '\0';
-      dp++;
-    } else {
-      dp = NULL;
-    }
-
-    // split each line into word and affix char strings
-    // "\/" signs slash in words (not affix separator)
-    // "/" at beginning of the line is word character (not affix separator)
-    ap = strchr(ts,'/');
-    while (ap) {
-        if (ap == ts) {
-            ap++;
-            continue;
-        } else if (*(ap - 1) != '\\') break;
-        // replace "\/" with "/"
-        for (char * sp = ap - 1; *sp; *sp = *(sp + 1), sp++);
-        ap = strchr(ap,'/');
-    }
-
-    if (ap) {
-      *ap = '\0';
-      if (aliasf) {
-        int index = atoi(ap + 1);
-        al = get_aliasf(index, &flags);
-        if (!al) {
-            HUNSPELL_WARNING(stderr, "error - bad flag vector alias: %s\n", ts);
-            *ap = '\0';
-        }
-      } else {
-        al = decode_flags(&flags, ap + 1);
-        flag_qsort(flags, 0, al);
-      }
-    } else {
-      al = 0;
-      ap = NULL;
-      flags = NULL;
-    }
-
-    int captype;
-    int wbl = strlen(ts);
-    int wcl = get_clen_and_captype(ts, wbl, &captype);
-    // add the word and its index plus its capitalized form optionally
-    if (add_word(ts,wbl,wcl,flags,al,dp, false) ||
-	add_hidden_capitalized_word(ts, wbl, wcl, flags, al, dp, captype)) {
-	fclose(rawdict);
-	return 5;
-    }
-  }
-
-  fclose(rawdict);
-  return 0;
-}
-
-
-// the hash function is a simple load and rotate
-// algorithm borrowed
-
-int HashMgr::hash(const char * word) const
-{
-    long  hv = 0;
-    for (int i=0; i < 4  &&  *word != 0; i++)
-        hv = (hv << 8) | (*word++);
-    while (*word != 0) {
-      ROTATE(hv,ROTATE_LEN);
-      hv ^= (*word++);
-    }
-    return (unsigned long) hv % tablesize;
-}
-
-int HashMgr::decode_flags(unsigned short ** result, char * flags) {
-    int len;
-    switch (flag_mode) {
-      case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz)
-        len = strlen(flags);
-        if (len%2 == 1) HUNSPELL_WARNING(stderr, "error: length of FLAG_LONG flagvector is odd: %s\n", flags);
-        len /= 2;
-        *result = (unsigned short *) malloc(len * sizeof(short));
-        if (!*result) return -1;
-        for (int i = 0; i < len; i++) {
-            (*result)[i] = (((unsigned short) flags[i * 2]) << 8) + (unsigned short) flags[i * 2 + 1]; 
-        }
-        break;
-      }
-      case FLAG_NUM: { // decimal numbers separated by comma (4521,23,233 -> 4521 23 233)
-        len = 1;
-        char * src = flags; 
-        unsigned short * dest;
-        char * p;
-        for (p = flags; *p; p++) {
-          if (*p == ',') len++;
-        }
-        *result = (unsigned short *) malloc(len * sizeof(short));
-        if (!*result) return -1;
-        dest = *result;
-        for (p = flags; *p; p++) {
-          if (*p == ',') {
-            *dest = (unsigned short) atoi(src);
-            if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
-            src = p + 1;
-            dest++;
-          }
-        }
-        *dest = (unsigned short) atoi(src);
-        if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
-        break;
-      }    
-      case FLAG_UNI: { // UTF-8 characters
-        w_char w[MAXDELEN/2];
-        len = u8_u16(w, MAXDELEN/2, flags);
-        *result = (unsigned short *) malloc(len * sizeof(short));
-        if (!*result) return -1;
-        memcpy(*result, w, len * sizeof(short));
-        break;
-      }
-      default: { // Ispell's one-character flags (erfg -> e r f g)
-        unsigned short * dest;
-        len = strlen(flags);
-        *result = (unsigned short *) malloc(len * sizeof(short));
-        if (!*result) return -1;
-        dest = *result;
-        for (unsigned char * p = (unsigned char *) flags; *p; p++) {
-          *dest = (unsigned short) *p;
-          dest++;
-        }
-      }
-    }      
-    return len;
-}
-
-unsigned short HashMgr::decode_flag(const char * f) {
-    unsigned short s = 0;
-    switch (flag_mode) {
-      case FLAG_LONG:
-        s = ((unsigned short) f[0] << 8) + (unsigned short) f[1];
-        break;
-      case FLAG_NUM:
-        s = (unsigned short) atoi(f);
-        break;
-      case FLAG_UNI:
-        u8_u16((w_char *) &s, 1, f);
-        break;
-      default:
-        s = (unsigned short) *((unsigned char *)f);
-    }
-    if (!s) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
-    return s;
-}
-
-char * HashMgr::encode_flag(unsigned short f) {
-    unsigned char ch[10];
-    if (f==0) return mystrdup("(NULL)");
-    if (flag_mode == FLAG_LONG) {
-        ch[0] = (unsigned char) (f >> 8);
-        ch[1] = (unsigned char) (f - ((f >> 8) << 8));
-        ch[2] = '\0';
-    } else if (flag_mode == FLAG_NUM) {
-        sprintf((char *) ch, "%d", f);
-    } else if (flag_mode == FLAG_UNI) {
-        u16_u8((char *) &ch, 10, (w_char *) &f, 1);
-    } else {
-        ch[0] = (unsigned char) (f);
-        ch[1] = '\0';
-    }
-    return mystrdup((char *) ch);
-}
-
-// read in aff file and set flag mode
-int  HashMgr::load_config(const char * affpath)
-{
-  int firstline = 1;
-  
-  // io buffers
-  char line[MAXDELEN+1];
- 
-  // open the affix file
-  FILE * afflst;
-  afflst = fopen(affpath,"r");
-  if (!afflst) {
-    HUNSPELL_WARNING(stderr, "Error - could not open affix description file %s\n",affpath);
-    return 1;
-  }
-
-    // read in each line ignoring any that do not
-    // start with a known line type indicator
-
-    while (fgets(line,MAXDELEN,afflst)) {
-        mychomp(line);
-
-       /* remove byte order mark */
-       if (firstline) {
-         firstline = 0;
-         if (strncmp(line,"\xEF\xBB\xBF",3) == 0) memmove(line, line+3, strlen(line+3)+1);
-       }
-
-        /* parse in the try string */
-        if ((strncmp(line,"FLAG",4) == 0) && isspace(line[4])) {
-            if (flag_mode != FLAG_CHAR) {
-                HUNSPELL_WARNING(stderr, "error: duplicate FLAG parameter\n");
-            }
-            if (strstr(line, "long")) flag_mode = FLAG_LONG;
-            if (strstr(line, "num")) flag_mode = FLAG_NUM;
-            if (strstr(line, "UTF-8")) flag_mode = FLAG_UNI;
-            if (flag_mode == FLAG_CHAR) {
-                HUNSPELL_WARNING(stderr, "error: FLAG need `num', `long' or `UTF-8' parameter: %s\n", line);
-            }
-        }
-        if (strncmp(line,"FORBIDDENWORD",13) == 0) {
-          char * st = NULL;
-          if (parse_string(line, &st, "FORBIDDENWORD")) {
-             fclose(afflst);
-             return 1;
-          }
-          forbiddenword = decode_flag(st);
-          free(st);
-        }
-        if (strncmp(line, "SET", 3) == 0) {
-    	  if (parse_string(line, &enc, "SET")) {
-             fclose(afflst);
-             return 1;
-          }    	    
-    	  if (strcmp(enc, "UTF-8") == 0) {
-    	    utf8 = 1;
-#ifndef OPENOFFICEORG
-#ifndef MOZILLA_CLIENT
-    	    initialize_utf_tbl();
-#endif
-#endif
-    	  } else csconv = get_current_cs(enc);
-    	}
-        if (strncmp(line, "LANG", 4) == 0) {    	
-    	  if (parse_string(line, &lang, "LANG")) {
-             fclose(afflst);
-             return 1;
-          }    	    
-    	  langnum = get_lang_num(lang);
-    	}
-
-       /* parse in the ignored characters (for example, Arabic optional diacritics characters */
-       if (strncmp(line,"IGNORE",6) == 0) {
-          if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, "IGNORE", utf8)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-       if ((strncmp(line,"AF",2) == 0) && isspace(line[2])) {
-          if (parse_aliasf(line, afflst)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-
-#ifdef HUNSPELL_EXPERIMENTAL
-       if ((strncmp(line,"AM",2) == 0) && isspace(line[2])) {
-          if (parse_aliasm(line, afflst)) {
-             fclose(afflst);
-             return 1;
-          }
-       }
-#endif
-        if (strncmp(line,"COMPLEXPREFIXES",15) == 0) complexprefixes = 1;
-        if (((strncmp(line,"SFX",3) == 0) || (strncmp(line,"PFX",3) == 0)) && isspace(line[3])) break;
-    }
-    if (csconv == NULL) csconv = get_current_cs("ISO8859-1");
-    fclose(afflst);
-    return 0;
-}
-
-/* parse in the ALIAS table */
-int  HashMgr::parse_aliasf(char * line, FILE * af)
-{
-   if (numaliasf != 0) {
-      HUNSPELL_WARNING(stderr, "error: duplicate AF (alias for flag vector) tables used\n");
-      return 1;
-   }
-   char * tp = line;
-   char * piece;
-   int i = 0;
-   int np = 0;
-   piece = mystrsep(&tp, 0);
-   while (piece) {
-       if (*piece != '\0') {
-          switch(i) {
-             case 0: { np++; break; }
-             case 1: { 
-                       numaliasf = atoi(piece);
-                       if (numaliasf < 1) {
-                          numaliasf = 0;
-                          aliasf = NULL;
-                          aliasflen = NULL;
-                          HUNSPELL_WARNING(stderr, "incorrect number of entries in AF table\n");
-                          free(piece);
-                          return 1;
-                       }
-                       aliasf = (unsigned short **) malloc(numaliasf * sizeof(unsigned short *));
-                       aliasflen = (unsigned short *) malloc(numaliasf * sizeof(short));
-                       if (!aliasf || !aliasflen) {
-                          numaliasf = 0;
-                          if (aliasf) free(aliasf);
-                          if (aliasflen) free(aliasflen);
-                          aliasf = NULL;
-                          aliasflen = NULL;
-                          return 1;
-                       }
-                       np++;
-                       break;
-                     }
-             default: break;
-          }
-          i++;
-       }
-       free(piece);
-       piece = mystrsep(&tp, 0);
-   }
-   if (np != 2) {
-      numaliasf = 0;
-      free(aliasf);
-      free(aliasflen);
-      aliasf = NULL;
-      aliasflen = NULL;
-      HUNSPELL_WARNING(stderr, "error: missing AF table information\n");
-      return 1;
-   } 
- 
-   /* now parse the numaliasf lines to read in the remainder of the table */
-   char * nl = line;
-   for (int j=0; j < numaliasf; j++) {
-        if (!fgets(nl,MAXDELEN,af)) return 1;
-        mychomp(nl);
-        tp = nl;
-        i = 0;
-        aliasf[j] = NULL;
-        aliasflen[j] = 0;
-        piece = mystrsep(&tp, 0);
-        while (piece) {
-           if (*piece != '\0') {
-               switch(i) {
-                  case 0: {
-                             if (strncmp(piece,"AF",2) != 0) {
-                                 numaliasf = 0;
-                                 free(aliasf);
-                                 free(aliasflen);
-                                 aliasf = NULL;
-                                 aliasflen = NULL;
-                                 HUNSPELL_WARNING(stderr, "error: AF table is corrupt\n");
-                                 free(piece);
-                                 return 1;
-                             }
-                             break;
-                          }
-                  case 1: {
-                            aliasflen[j] = (unsigned short) decode_flags(&(aliasf[j]), piece);
-                            flag_qsort(aliasf[j], 0, aliasflen[j]);
-                            break; 
-                          }
-                  default: break;
-               }
-               i++;
-           }
-           free(piece);
-           piece = mystrsep(&tp, 0);
-        }
-        if (!aliasf[j]) {
-             free(aliasf);
-             free(aliasflen);
-             aliasf = NULL;
-             aliasflen = NULL;
-             numaliasf = 0;
-             HUNSPELL_WARNING(stderr, "error: AF table is corrupt\n");
-             return 1;
-        }
-   }
-   return 0;
-}
-
-int HashMgr::is_aliasf() {
-    return (aliasf != NULL);
-}
-
-int HashMgr::get_aliasf(int index, unsigned short ** fvec) {
-    if ((index > 0) && (index <= numaliasf)) {
-        *fvec = aliasf[index - 1];
-        return aliasflen[index - 1];
-    }
-    HUNSPELL_WARNING(stderr, "error: bad flag alias index: %d\n", index);
-    *fvec = NULL;
-    return 0;
-}
-
-#ifdef HUNSPELL_EXPERIMENTAL
-/* parse morph alias definitions */
-int  HashMgr::parse_aliasm(char * line, FILE * af)
-{
-   if (numaliasm != 0) {
-      HUNSPELL_WARNING(stderr, "error: duplicate AM (aliases for morphological descriptions) tables used\n");
-      return 1;
-   }
-   char * tp = line;
-   char * piece;
-   int i = 0;
-   int np = 0;
-   piece = mystrsep(&tp, 0);
-   while (piece) {
-       if (*piece != '\0') {
-          switch(i) {
-             case 0: { np++; break; }
-             case 1: { 
-                       numaliasm = atoi(piece);
-                       if (numaliasm < 1) {
-                          HUNSPELL_WARNING(stderr, "incorrect number of entries in AM table\n");
-                          free(piece);
-                          return 1;
-                       }
-                       aliasm = (char **) malloc(numaliasm * sizeof(char *));
-                       if (!aliasm) {
-                          numaliasm = 0;
-                          return 1;
-                       }
-                       np++;
-                       break;
-                     }
-             default: break;
-          }
-          i++;
-       }
-       free(piece);
-       piece = mystrsep(&tp, 0);
-   }
-   if (np != 2) {
-      numaliasm = 0;
-      free(aliasm);
-      aliasm = NULL;
-      HUNSPELL_WARNING(stderr, "error: missing AM alias information\n");
-      return 1;
-   } 
-
-   /* now parse the numaliasm lines to read in the remainder of the table */
-   char * nl = line;
-   for (int j=0; j < numaliasm; j++) {
-        if (!fgets(nl,MAXDELEN,af)) return 1;
-        mychomp(nl);
-        tp = nl;
-        i = 0;
-        aliasm[j] = NULL;
-        piece = mystrsep(&tp, 0);
-        while (piece) {
-           if (*piece != '\0') {
-               switch(i) {
-                  case 0: {
-                             if (strncmp(piece,"AM",2) != 0) {
-                                 HUNSPELL_WARNING(stderr, "error: AM table is corrupt\n");
-                                 free(piece);
-                                 numaliasm = 0;
-                                 free(aliasm);
-                                 aliasm = NULL;
-                                 return 1;
-                             }
-                             break;
-                          }
-                  case 1: {
-                            if (complexprefixes) {
-                                if (utf8) reverseword_utf(piece);
-                                    else reverseword(piece);
-                            }
-                            aliasm[j] = mystrdup(piece);
-                            break; }
-                  default: break;
-               }
-               i++;
-           }
-           free(piece);
-           piece = mystrsep(&tp, 0);
-        }
-        if (!aliasm[j]) {
-             numaliasm = 0;
-             free(aliasm);
-             aliasm = NULL;
-             HUNSPELL_WARNING(stderr, "error: map table is corrupt\n");
-             return 1;
-        }
-   }
-   return 0;
-}
-
-int HashMgr::is_aliasm() {
-    return (aliasm != NULL);
-}
-
-char * HashMgr::get_aliasm(int index) {
-    if ((index > 0) && (index <= numaliasm)) return aliasm[index - 1];
-    HUNSPELL_WARNING(stderr, "error: bad morph. alias index: %d\n", index);
-    return NULL;
-}
-#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/hashmgr.hxx spellcheck/hunspell/src/hashmgr.hxx
--- spellcheck.old/hunspell/src/hashmgr.hxx	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/hashmgr.hxx	1970-01-01 01:00:00.000000000 +0100
@@ -1,129 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef _HASHMGR_HXX_
-#define _HASHMGR_HXX_
-
-#ifndef MOZILLA_CLIENT
-#include <cstdio>
-#else
-#include <stdio.h>
-#endif
-
-#include "htypes.hxx"
-
-enum flag { FLAG_CHAR, FLAG_LONG, FLAG_NUM, FLAG_UNI };
-
-class HashMgr
-{
-  int             tablesize;
-  struct hentry ** tableptr;
-  int             userword;
-  flag            flag_mode;
-  int             complexprefixes;
-  int             utf8;
-  unsigned short  forbiddenword;
-  int 		  langnum;
-  char *          enc;
-  char *          lang;
-  struct cs_info * csconv;
-  char *          ignorechars;
-  unsigned short * ignorechars_utf16;
-  int             ignorechars_utf16_len;
-  int                 numaliasf; // flag vector `compression' with aliases
-  unsigned short **   aliasf;
-  unsigned short *    aliasflen;
-  int                 numaliasm; // morphological desciption `compression' with aliases
-  char **             aliasm;
-
-
-public:
-  HashMgr(const char * tpath, const char * apath);
-  ~HashMgr();
-
-  struct hentry * lookup(const char *) const;
-  int hash(const char *) const;
-  struct hentry * walk_hashtable(int & col, struct hentry * hp) const;
-
-  int put_word(const char * word, char * ap);
-  int put_word_pattern(const char * word, const char * pattern);
-  int decode_flags(unsigned short ** result, char * flags);
-  unsigned short        decode_flag(const char * flag);
-  char *                encode_flag(unsigned short flag);
-  int is_aliasf();
-  int get_aliasf(int index, unsigned short ** fvec);
-#ifdef HUNSPELL_EXPERIMENTAL
-  int is_aliasm();
-  char * get_aliasm(int index);
-#endif
-
-  
-private:
-  int get_clen_and_captype(const char * word, int wbl, int * captype);
-  int load_tables(const char * tpath);
-  int add_word(const char * word, int wbl, int wcl, unsigned short * ap,
-    int al, const char * desc, bool onlyupcase);
-  int load_config(const char * affpath);
-  int parse_aliasf(char * line, FILE * af);
-  int add_hidden_capitalized_word(char * word, int wbl, int wcl,
-    unsigned short * flags, int al, char * dp, int captype);
-#ifdef HUNSPELL_EXPERIMENTAL
-  int parse_aliasm(char * line, FILE * af);
-#endif
-
-};
-
-#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/htypes.hxx spellcheck/hunspell/src/htypes.hxx
--- spellcheck.old/hunspell/src/htypes.hxx	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/htypes.hxx	1970-01-01 01:00:00.000000000 +0100
@@ -1,85 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef _HTYPES_HXX_
-#define _HTYPES_HXX_
-
-#define MAXDELEN    8192
-
-#define ROTATE_LEN   5
-
-#define ROTATE(v,q) \
-   (v) = ((v) << (q)) | (((v) >> (32 - q)) & ((1 << (q))-1));
-
-// approx. number  of user defined words
-#define USERWORD 1000
-
-struct hentry
-{
-  unsigned char blen; // word length in bytes
-  unsigned char clen; // word length in characters (different for UTF-8 enc.)
-  short    alen;      // length of affix flag vector
-  unsigned short * astr;  // affix flag vector
-  struct   hentry * next; // next word with same hash code
-  struct   hentry * next_homonym; // next homonym word (with same hash code)
-#ifdef HUNSPELL_EXPERIMENTAL
-  char *   description; // morphological data (optional)
-#endif
-  char     var;       // variable fields (only for special pronounciation yet)
-  char     word;      // variable-length word (8-bit or UTF-8 encoding)
-};
-
-#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/hunspell.cpp spellcheck/hunspell/src/hunspell.cpp
--- spellcheck.old/hunspell/src/hunspell.cpp	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/hunspell.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,1807 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef MOZILLA_CLIENT
-#include <cstdlib>
-#include <cstring>
-#include <cstdio>
-#else
-#include <stdlib.h> 
-#include <string.h>
-#include <stdio.h> 
-#endif
-
-#include "hunspell.hxx"
-#include "hunspell.h"
-
-#ifndef MOZILLA_CLIENT
-#ifndef W32
-using namespace std;
-#endif
-#endif
-
-Hunspell::Hunspell(const char * affpath, const char * dpath)
-{
-    encoding = NULL;
-    csconv = NULL;
-    utf8 = 0;
-    complexprefixes = 0;
-
-    /* first set up the hash manager */
-    pHMgr = new HashMgr(dpath, affpath);
-
-    /* next set up the affix manager */
-    /* it needs access to the hash manager lookup methods */
-    pAMgr = new AffixMgr(affpath,pHMgr);
-
-    /* get the preferred try string and the dictionary */
-    /* encoding from the Affix Manager for that dictionary */
-    char * try_string = pAMgr->get_try_string();
-    encoding = pAMgr->get_encoding();
-    csconv = get_current_cs(encoding);
-    langnum = pAMgr->get_langnum();
-    utf8 = pAMgr->get_utf8();
-    complexprefixes = pAMgr->get_complexprefixes();
-    wordbreak = pAMgr->get_breaktable();
-
-    /* and finally set up the suggestion manager */
-    pSMgr = new SuggestMgr(try_string, MAXSUGGESTION, pAMgr);
-    if (try_string) free(try_string);
-
-}
-
-Hunspell::~Hunspell()
-{
-    if (pSMgr) delete pSMgr;
-    if (pAMgr) delete pAMgr;
-    if (pHMgr) delete pHMgr;
-    pSMgr = NULL;
-    pAMgr = NULL;
-    pHMgr = NULL;
-#ifdef MOZILLA_CLIENT
-    free(csconv);
-#endif
-    csconv= NULL;
-    if (encoding) free(encoding);
-    encoding = NULL;
-}
-
-
-// make a copy of src at destination while removing all leading
-// blanks and removing any trailing periods after recording
-// their presence with the abbreviation flag
-// also since already going through character by character, 
-// set the capitalization type
-// return the length of the "cleaned" (and UTF-8 encoded) word
-
-int Hunspell::cleanword2(char * dest, const char * src, 
-    w_char * dest_utf, int * nc, int * pcaptype, int * pabbrev)
-{ 
-   unsigned char * p = (unsigned char *) dest;
-   const unsigned char * q = (const unsigned char * ) src;
-
-   // first skip over any leading blanks
-   while ((*q != '\0') && (*q == ' ')) q++;
-   
-   // now strip off any trailing periods (recording their presence)
-   *pabbrev = 0;
-   int nl = strlen((const char *)q);
-   while ((nl > 0) && (*(q+nl-1)=='.')) {
-       nl--;
-       (*pabbrev)++;
-   }
-   
-   // if no characters are left it can't be capitalized
-   if (nl <= 0) { 
-       *pcaptype = NOCAP;
-       *p = '\0';
-       return 0;
-   }
-   
-   strncpy(dest, (char *) q, nl);
-   *(dest + nl) = '\0';
-   nl = strlen(dest);
-   if (utf8) {
-      *nc = u8_u16(dest_utf, MAXWORDLEN, dest);
-      // don't check too long words
-      if (*nc >= MAXWORDLEN) return 0;
-      if (*nc == -1) { // big Unicode character (non BMP area)
-         *pcaptype = NOCAP;
-         return nl;
-      }
-     *pcaptype = get_captype_utf8(dest_utf, *nc, langnum);
-   } else {
-     *pcaptype = get_captype(dest, nl, csconv);
-     *nc = nl;
-   }
-   return nl;
-} 
-
-#ifdef HUNSPELL_EXPERIMENTAL
-int Hunspell::cleanword(char * dest, const char * src, 
-    int * pcaptype, int * pabbrev)
-{ 
-   unsigned char * p = (unsigned char *) dest;
-   const unsigned char * q = (const unsigned char * ) src;
-   int firstcap = 0;
-
-   // first skip over any leading blanks
-   while ((*q != '\0') && (*q == ' ')) q++;
-   
-   // now strip off any trailing periods (recording their presence)
-   *pabbrev = 0;
-   int nl = strlen((const char *)q);
-   while ((nl > 0) && (*(q+nl-1)=='.')) {
-       nl--;
-       (*pabbrev)++;
-   }
-   
-   // if no characters are left it can't be capitalized
-   if (nl <= 0) { 
-       *pcaptype = NOCAP;
-       *p = '\0';
-       return 0;
-   }
-
-   // now determine the capitalization type of the first nl letters
-   int ncap = 0;
-   int nneutral = 0;
-   int nc = 0;
-
-   if (!utf8) {
-      while (nl > 0) {
-         nc++;
-         if (csconv[(*q)].ccase) ncap++;
-         if (csconv[(*q)].cupper == csconv[(*q)].clower) nneutral++;
-         *p++ = *q++;
-         nl--;
-      }
-      // remember to terminate the destination string
-      *p = '\0';
-      firstcap = csconv[(unsigned char)(*dest)].ccase;
-   } else {
-      unsigned short idx;
-      w_char t[MAXWORDLEN];
-      nc = u8_u16(t, MAXWORDLEN, src);
-      for (int i = 0; i < nc; i++) {
-         idx = (t[i].h << 8) + t[i].l;
-         unsigned short low = unicodetolower(idx, langnum);
-         if (idx != low) ncap++;
-         if (unicodetoupper(idx, langnum) == low) nneutral++;
-      }
-      u16_u8(dest, MAXWORDUTF8LEN, t, nc);
-      if (ncap) {
-         idx = (t[0].h << 8) + t[0].l;
-         firstcap = (idx != unicodetolower(idx, langnum));
-      }
-   }
-
-   // now finally set the captype
-   if (ncap == 0) {
-        *pcaptype = NOCAP;
-   } else if ((ncap == 1) && firstcap) {
-        *pcaptype = INITCAP;
-   } else if ((ncap == nc) || ((ncap + nneutral) == nc)){
-        *pcaptype = ALLCAP;
-   } else if ((ncap > 1) && firstcap) {
-        *pcaptype = HUHINITCAP;
-   } else {
-        *pcaptype = HUHCAP;
-   }
-   return strlen(dest);
-} 
-#endif       
-
-void Hunspell::mkallcap(char * p)
-{
-  if (utf8) {
-      w_char u[MAXWORDLEN];
-      int nc = u8_u16(u, MAXWORDLEN, p);
-      unsigned short idx;
-      for (int i = 0; i < nc; i++) {
-         idx = (u[i].h << 8) + u[i].l;
-         if (idx != unicodetoupper(idx, langnum)) {
-            u[i].h = (unsigned char) (unicodetoupper(idx, langnum) >> 8);
-            u[i].l = (unsigned char) (unicodetoupper(idx, langnum) & 0x00FF);
-         }
-      }
-      u16_u8(p, MAXWORDUTF8LEN, u, nc);
-  } else {
-    while (*p != '\0') { 
-        *p = csconv[((unsigned char) *p)].cupper;
-        p++;
-    }
-  }
-}
-
-int Hunspell::mkallcap2(char * p, w_char * u, int nc)
-{
-  if (utf8) {
-      unsigned short idx;
-      for (int i = 0; i < nc; i++) {
-         idx = (u[i].h << 8) + u[i].l;
-         unsigned short up = unicodetoupper(idx, langnum);
-         if (idx != up) {
-            u[i].h = (unsigned char) (up >> 8);
-            u[i].l = (unsigned char) (up & 0x00FF);
-         }
-      }
-      u16_u8(p, MAXWORDUTF8LEN, u, nc);
-      return strlen(p);  
-  } else {
-    while (*p != '\0') { 
-        *p = csconv[((unsigned char) *p)].cupper;
-        p++;
-    }
-  }
-  return nc;
-}
-
-
-void Hunspell::mkallsmall(char * p)
-{
-    while (*p != '\0') { 
-        *p = csconv[((unsigned char) *p)].clower;
-        p++;
-    }
-}
-
-int Hunspell::mkallsmall2(char * p, w_char * u, int nc)
-{
-  if (utf8) {
-      unsigned short idx;
-      for (int i = 0; i < nc; i++) {
-         idx = (u[i].h << 8) + u[i].l;
-         unsigned short low = unicodetolower(idx, langnum);
-         if (idx != low) {
-            u[i].h = (unsigned char) (low >> 8);
-            u[i].l = (unsigned char) (low & 0x00FF);
-         }
-      }
-      u16_u8(p, MAXWORDUTF8LEN, u, nc);
-      return strlen(p);
-  } else {
-    while (*p != '\0') { 
-        *p = csconv[((unsigned char) *p)].clower;
-        p++;
-    }
-  }
-  return nc;
-}
-
-// convert UTF-8 sharp S codes to latin 1
-char * Hunspell::sharps_u8_l1(char * dest, char * source) {
-    char * p = dest;
-    *p = *source;
-    for (p++, source++; *(source - 1); p++, source++) {
-        *p = *source;
-        if (*source == '\x9F') *--p = '\xDF';
-    }
-    return dest;
-}
-
-// recursive search for right ss - sharp s permutations
-hentry * Hunspell::spellsharps(char * base, char * pos, int n,
-        int repnum, char * tmp, int * info, char **root) {
-    pos = strstr(pos, "ss");
-    if (pos && (n < MAXSHARPS)) {
-        *pos = '\xC3';
-        *(pos + 1) = '\x9F';
-        hentry * h = spellsharps(base, pos + 2, n + 1, repnum + 1, tmp, info, root);
-        if (h) return h;
-        *pos = 's';
-        *(pos + 1) = 's';
-        h = spellsharps(base, pos + 2, n + 1, repnum, tmp, info, root);
-        if (h) return h;
-    } else if (repnum > 0) {
-        if (utf8) return checkword(base, info, root);
-        return checkword(sharps_u8_l1(tmp, base), info, root);
-    }
-    return NULL;
-}
-
-int Hunspell::is_keepcase(const hentry * rv) {
-    return pAMgr && rv->astr && pAMgr->get_keepcase() &&
-        TESTAFF(rv->astr, pAMgr->get_keepcase(), rv->alen);
-}
-
-/* insert a word to beginning of the suggestion array and return ns */
-int Hunspell::insert_sug(char ***slst, char * word, int ns) {
-    if (ns == MAXSUGGESTION) {
-        ns--;
-        free((*slst)[ns]);
-    }
-    for (int k = ns; k > 0; k--) (*slst)[k] = (*slst)[k - 1];
-    (*slst)[0] = mystrdup(word);
-    return ns + 1;
-}
-
-int Hunspell::spell(const char * word, int * info, char ** root)
-{
-  struct hentry * rv=NULL;
-  // need larger vector. For example, Turkish capital letter I converted a
-  // 2-byte UTF-8 character (dotless i) by mkallsmall.
-  char cw[MAXWORDUTF8LEN];
-  char wspace[MAXWORDUTF8LEN];
-  w_char unicw[MAXWORDLEN];
-  int nc = strlen(word);
-  int wl2 = 0;
-  if (utf8) {
-    if (nc >= MAXWORDUTF8LEN) return 0;
-  } else {
-    if (nc >= MAXWORDLEN) return 0;
-  }
-  int captype = 0;
-  int abbv = 0;
-  int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
-  int info2 = 0;
-  if (wl == 0) return 1;
-  if (root) *root = NULL;
-
-  // allow numbers with dots and commas (but forbid double separators: "..", ",," etc.)
-  enum { NBEGIN, NNUM, NSEP };
-  int nstate = NBEGIN;
-  int i;
-
-  for (i = 0; (i < wl); i++) {
-    if ((cw[i] <= '9') && (cw[i] >= '0')) {
-        nstate = NNUM;
-    } else if ((cw[i] == ',') || (cw[i] == '.') || (cw[i] == '-')) {
-        if ((nstate == NSEP) || (i == 0)) break;
-        nstate = NSEP;
-    } else break;
-  }
-  if ((i == wl) && (nstate == NNUM)) return 1;
-  if (!info) info = &info2; else *info = 0;
-
-  // LANG_hu section: number(s) + (percent or degree) with suffixes
-  if (langnum == LANG_hu) {
-    if ((nstate == NNUM) && ((cw[i] == '%') || ((!utf8 && (cw[i] == '\xB0')) ||
-        (utf8 && (strncmp(cw + i, "\xC2\xB0", 2)==0))))
-               && checkword(cw + i, info, root)) return 1;
-  }
-  // END of LANG_hu section
-
-  switch(captype) {
-     case HUHCAP: 
-     case HUHINITCAP: 
-     case NOCAP: { 
-            rv = checkword(cw, info, root);
-            if ((abbv) && !(rv)) {
-                memcpy(wspace,cw,wl);
-                *(wspace+wl) = '.';
-                *(wspace+wl+1) = '\0';
-                rv = checkword(wspace, info, root);
-            }
-            break;
-         }
-     case ALLCAP: {
-            rv = checkword(cw, info, root);
-            if (rv) break;
-            if (abbv) {
-                memcpy(wspace,cw,wl);
-                *(wspace+wl) = '.';
-                *(wspace+wl+1) = '\0';
-                rv = checkword(wspace, info, root);
-                if (rv) break;
-            }
-            // Spec. prefix handling for Catalan, French, Italian:
-	    // prefixes separated by apostrophe (SANT'ELIA -> Sant'+Elia).
-            if (pAMgr && strchr(cw, '\'')) {
-                wl = mkallsmall2(cw, unicw, nc);
-        	char * apostrophe = strchr(cw, '\'');
-                if (utf8) {
-            	    w_char tmpword[MAXWORDLEN];
-            	    *apostrophe = '\0';
-            	    wl2 = u8_u16(tmpword, MAXWORDLEN, cw);
-            	    *apostrophe = '\'';
-		    if (wl2 < nc) {
-		        mkinitcap2(apostrophe + 1, unicw + wl2 + 1, nc - wl2 - 1);
-			rv = checkword(cw, info, root);
-			if (rv) break;
-		    }
-                } else {
-		    mkinitcap2(apostrophe + 1, unicw, nc);
-		    rv = checkword(cw, info, root);
-		    if (rv) break;
-		}
-		mkinitcap2(cw, unicw, nc);
-		rv = checkword(cw, info, root);
-		if (rv) break;
-            }
-            if (pAMgr && pAMgr->get_checksharps() && strstr(cw, "SS")) {
-                char tmpword[MAXWORDUTF8LEN];
-                wl = mkallsmall2(cw, unicw, nc);
-                memcpy(wspace,cw,(wl+1));
-                rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
-                if (!rv) {
-                    wl2 = mkinitcap2(cw, unicw, nc);
-                    rv = spellsharps(cw, cw, 0, 0, tmpword, info, root);
-                }
-                if ((abbv) && !(rv)) {
-                    *(wspace+wl) = '.';
-                    *(wspace+wl+1) = '\0';
-                    rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
-                    if (!rv) {
-                        memcpy(wspace, cw, wl2);
-                        *(wspace+wl2) = '.';
-                        *(wspace+wl2+1) = '\0';
-                        rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root);
-                    }
-                }
-                if (rv) break;
-            }
-        }
-     case INITCAP: { 
-             wl = mkallsmall2(cw, unicw, nc);
-             memcpy(wspace,cw,(wl+1));
-             wl2 = mkinitcap2(cw, unicw, nc);
-    	     if (captype == INITCAP) *info += SPELL_INITCAP;
-             rv = checkword(cw, info, root);
-    	     if (captype == INITCAP) *info -= SPELL_INITCAP;
-             // forbid bad capitalization
-             // (for example, ijs -> Ijs instead of IJs in Dutch)
-             // use explicit forms in dic: Ijs/F (F = FORBIDDENWORD flag)
-             if (*info & SPELL_FORBIDDEN) {
-                rv = NULL;
-                break;
-             }             
-             if (rv && is_keepcase(rv) && (captype == ALLCAP)) rv = NULL;
-             if (rv) break;
-
-             rv = checkword(wspace, info, root);
-             if (abbv && !rv) {
-
-                 *(wspace+wl) = '.';
-                 *(wspace+wl+1) = '\0';
-                 rv = checkword(wspace, info, root);
-                 if (!rv) {
-                    memcpy(wspace, cw, wl2);
-                    *(wspace+wl2) = '.';
-                    *(wspace+wl2+1) = '\0';
-    	    	    if (captype == INITCAP) *info += SPELL_INITCAP;
-                    rv = checkword(wspace, info, root);
-    	    	    if (captype == INITCAP) *info -= SPELL_INITCAP;
-                    if (rv && is_keepcase(rv) && (captype == ALLCAP)) rv = NULL;
-                    break;
-                 }
-             }
-             if (rv && is_keepcase(rv) &&
-                ((captype == ALLCAP) ||
-                   // if CHECKSHARPS: KEEPCASE words with \xDF  are allowed
-                   // in INITCAP form, too.
-                   !(pAMgr->get_checksharps() &&
-                      ((utf8 && strstr(wspace, "\xC3\x9F")) ||
-                      (!utf8 && strchr(wspace, '\xDF')))))) rv = NULL;             
-             break;
-           }               
-  }
-  
-  if (rv) return 1;
-
-  // recursive breaking at break points (not good for morphological analysis)
-  if (wordbreak) {
-    char * s;
-    char r;
-    int corr = 0;
-    // German words beginning with "-" are not accepted
-    if (langnum == LANG_de) corr = 1;
-    int numbreak = pAMgr ? pAMgr->get_numbreak() : 0;
-    for (int j = 0; j < numbreak; j++) {
-      s=(char *) strstr(cw + corr, wordbreak[j]);
-      if (s) {
-        r = *s;
-        *s = '\0';
-        // examine 2 sides of the break point
-        if (spell(cw) && spell(s + strlen(wordbreak[j]))) {
-            *s = r;
-            return 1;
-        }
-        *s = r;
-      }
-    }
-  }
-
-  // LANG_hu: compoundings with dashes and n-dashes XXX deprecated!
-  if (langnum == LANG_hu) {
-    int n;
-    // compound word with dash (HU) I18n
-    char * dash;
-    int result = 0;
-    // n-dash
-    dash = (char *) strstr(cw,"\xE2\x80\x93");
-    if (dash && !wordbreak) {
-        *dash = '\0';
-        // examine 2 sides of the dash
-        if (spell(cw) && spell(dash + 3)) {
-            *dash = '\xE2';
-            return 1;
-        }
-        *dash = '\xE2';
-    }
-    dash = (char *) strchr(cw,'-');
-    if (dash) {
-        *dash='\0';      
-        // examine 2 sides of the dash
-        if (dash[1] == '\0') { // base word ending with dash
-            if (spell(cw)) return 1;
-        } else {
-            // first word ending with dash: word-
-            char r2 = *(dash + 1);
-            dash[0]='-';
-            dash[1]='\0';
-            result = spell(cw);
-            dash[1] = r2;
-            dash[0]='\0';
-            if (result && spell(dash+1) && ((strlen(dash+1) > 1) || (dash[1] == 'e') ||
-                ((dash[1] > '0') && (dash[1] < '9')))) return 1;
-        }
-        // affixed number in correct word
-        if (result && (dash > cw) && (((*(dash-1)<='9') && (*(dash-1)>='0')) || (*(dash-1)>='.'))) {
-            *dash='-';
-            n = 1;
-            if (*(dash - n) == '.') n++;
-            // search first not a number character to left from dash
-            while (((dash - n)>=cw) && ((*(dash - n)=='0') || (n < 3)) && (n < 6)) {
-                n++;
-            }
-            if ((dash - n) < cw) n--;
-            // numbers: deprecated
-            for(; n >= 1; n--) {
-                if ((*(dash - n) >= '0') && (*(dash - n) <= '9') &&
-                    checkword(dash - n, info, root)) return 1;
-            }
-        }
-    }
-  }
-  return 0;
-}
-
-struct hentry * Hunspell::checkword(const char * w, int * info, char ** root)
-{
-  struct hentry * he = NULL;
-  int len;
-  char w2[MAXWORDUTF8LEN];
-  const char * word;
-
-  char * ignoredchars = pAMgr->get_ignore();
-  if (ignoredchars != NULL) {
-     strcpy(w2, w);
-     if (utf8) {
-        int ignoredchars_utf16_len;
-        unsigned short * ignoredchars_utf16 = pAMgr->get_ignore_utf16(&ignoredchars_utf16_len);
-        remove_ignored_chars_utf(w2, ignoredchars_utf16, ignoredchars_utf16_len);
-     } else {
-        remove_ignored_chars(w2,ignoredchars);
-     }
-     word = w2;
-  } else word = w;
-
-  // word reversing wrapper for complex prefixes
-  if (complexprefixes) {
-    if (word != w2) {
-      strcpy(w2, word);
-      word = w2;
-    }
-    if (utf8) reverseword_utf(w2); else reverseword(w2);
-  }
-
-  // look word in hash table
-  if (pHMgr) he = pHMgr->lookup(word);
-
-  // check forbidden and onlyincompound words
-  if ((he) && (he->astr) && (pAMgr) && TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
-    if (info) *info += SPELL_FORBIDDEN;
-    // LANG_hu section: set dash information for suggestions
-    if (langnum == LANG_hu) {
-        if (pAMgr->get_compoundflag() &&
-            TESTAFF(he->astr, pAMgr->get_compoundflag(), he->alen)) {
-                if (info) *info += SPELL_COMPOUND;
-        }
-    }
-    return NULL;
-  }
-
-  // he = next not pseudoroot, onlyincompound homonym or onlyupcase word
-  while (he && (he->astr) &&
-    ((pAMgr->get_pseudoroot() && TESTAFF(he->astr, pAMgr->get_pseudoroot(), he->alen)) ||
-       (pAMgr->get_onlyincompound() && TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
-       (info && (*info & SPELL_INITCAP) && TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen))
-    )) he = he->next_homonym;
-
-  // check with affixes
-  if (!he && pAMgr) {
-     // try stripping off affixes */
-     len = strlen(word);
-     he = pAMgr->affix_check(word, len, 0);
-
-     // check compound restriction and onlyupcase
-     if (he && he->astr && (
-        (pAMgr->get_onlyincompound() && 
-    	    TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) || 
-        (info && (*info & SPELL_INITCAP) &&
-    	    TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)))) {
-    	    he = NULL;
-     }
-
-     if (he) {
-        if ((he->astr) && (pAMgr) && TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
-            if (info) *info += SPELL_FORBIDDEN;
-            return NULL;
-        }
-        if (root) {
-            *root = mystrdup(&(he->word));
-            if (complexprefixes) {
-                if (utf8) reverseword_utf(*root); else reverseword(*root);
-            }
-        }
-     // try check compound word
-     } else if (pAMgr->get_compound()) {
-          he = pAMgr->compound_check(word, len, 
-                                  0,0,100,0,NULL,0,NULL,NULL,0);
-          // LANG_hu section: `moving rule' with last dash
-          if ((!he) && (langnum == LANG_hu) && (word[len-1]=='-')) {
-             char * dup = mystrdup(word);
-             dup[len-1] = '\0';
-             he = pAMgr->compound_check(dup, len-1, 
-                                  -5,0,100,0,NULL,1,NULL,NULL,0);
-             free(dup);
-          }
-          // end of LANG speficic region          
-          if (he) {
-                if (root) {
-                    *root = mystrdup(&(he->word));
-                    if (complexprefixes) {
-                        if (utf8) reverseword_utf(*root); else reverseword(*root);
-                    }
-                }
-                if (info) *info += SPELL_COMPOUND;
-          }
-     }
-
-  }
-
-  return he;
-}
-
-int Hunspell::suggest(char*** slst, const char * word)
-{
-  int onlycmpdsug = 0;
-  char cw[MAXWORDUTF8LEN];
-  char wspace[MAXWORDUTF8LEN];
-  if (! pSMgr) return 0;
-  w_char unicw[MAXWORDLEN];
-  int nc = strlen(word);
-  if (utf8) {
-    if (nc >= MAXWORDUTF8LEN) return 0;
-  } else {
-    if (nc >= MAXWORDLEN) return 0;
-  }
-  int captype = 0;
-  int abbv = 0;
-  int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
-  if (wl == 0) return 0;
-  int ns = 0;
-  *slst = NULL;
-  int capwords = 0;
-
-  switch(captype) {
-     case NOCAP:   { 
-                     ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug);
-                     break;
-                   }
-
-     case INITCAP: { 
-                     capwords = 1;
-                     ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug);
-                     if (ns == -1) break;
-                     memcpy(wspace,cw,(wl+1));
-                     mkallsmall2(wspace, unicw, nc);
-                     ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
-                     break;
-                   }
-     case HUHINITCAP:
-                    capwords = 1;
-     case HUHCAP: { 
-                     ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug);
-                     if (ns != -1) {
-                        int prevns;
-    		        // something.The -> something. The
-                        char * dot = strchr(cw, '.');
-		        if (dot && (dot > cw)) {
-		            int captype_;
-		            if (utf8) {
-		               w_char w_[MAXWORDLEN];
-			       int wl_ = u8_u16(w_, MAXWORDLEN, dot + 1);
-		               captype_ = get_captype_utf8(w_, wl_, langnum);
-		            } else captype_ = get_captype(dot+1, strlen(dot+1), csconv);
-		    	    if (captype_ == INITCAP) {
-                        	char * st = mystrdup(cw);
-                        	st = (char *) realloc(st, wl + 2);
-				if (st) {
-                        		st[(dot - cw) + 1] = ' ';
-                        		strcpy(st + (dot - cw) + 2, dot + 1);
-                    			ns = insert_sug(slst, st, ns);
-					free(st);
-				}
-		    	    }
-		        }
-                        if (captype == HUHINITCAP) {
-                            // TheOpenOffice.org -> The OpenOffice.org
-                            memcpy(wspace,cw,(wl+1));
-                            mkinitsmall2(wspace, unicw, nc);
-                            ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
-                        }
-                        memcpy(wspace,cw,(wl+1));
-                        mkallsmall2(wspace, unicw, nc);
-                        if (spell(wspace)) ns = insert_sug(slst, wspace, ns);
-                        prevns = ns;
-                        ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
-                        if (captype == HUHINITCAP) {
-                            mkinitcap2(wspace, unicw, nc);
-                            if (spell(wspace)) ns = insert_sug(slst, wspace, ns);
-                            ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
-                        }
-                        // aNew -> "a New" (instead of "a new")
-                        for (int j = prevns; j < ns; j++) {
-                           char * space = strchr((*slst)[j],' ');
-                           if (space) {
-                                int slen = strlen(space + 1);
-                                // different case after space (need capitalisation)
-                                if ((slen < wl) && strcmp(cw + wl - slen, space + 1)) {
-                                    w_char w[MAXWORDLEN];
-                                    int wc = 0;
-                                    char * r = (*slst)[j];
-                                    if (utf8) wc = u8_u16(w, MAXWORDLEN, space + 1);
-                                    mkinitcap2(space + 1, w, wc);
-                                    // set as first suggestion
-                                    for (int k = j; k > 0; k--) (*slst)[k] = (*slst)[k - 1];
-                                    (*slst)[0] = r;
-                                }
-                           }
-                        }
-                     }
-                     break;
-                   }
-
-     case ALLCAP: { 
-                     memcpy(wspace, cw, (wl+1));
-                     mkallsmall2(wspace, unicw, nc);
-                     ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
-                     if (ns == -1) break;
-                     if (pAMgr && pAMgr->get_keepcase() && spell(wspace))
-                        ns = insert_sug(slst, wspace, ns);
-                     mkinitcap2(wspace, unicw, nc);
-                     ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug);
-                     for (int j=0; j < ns; j++) {
-                        mkallcap((*slst)[j]);
-                        if (pAMgr && pAMgr->get_checksharps()) {
-                            char * pos;
-                            if (utf8) {
-                                pos = strstr((*slst)[j], "\xC3\x9F");
-                                while (pos) {
-                                    *pos = 'S';
-                                    *(pos+1) = 'S';
-                                    pos = strstr(pos+2, "\xC3\x9F");
-                                }
-                            } else {
-                                pos = strchr((*slst)[j], '\xDF');
-                                while (pos) {
-                                    (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 2);
-                                    mystrrep((*slst)[j], "\xDF", "SS");
-                                    pos = strchr((*slst)[j], '\xDF');
-                                }
-                            }
-                        }
-                     }
-                     break;
-                   }
-  }
-
-  // LANG_hu section: replace '-' with ' ' in Hungarian
-  if (langnum == LANG_hu) {
-      for (int j=0; j < ns; j++) {
-          char * pos = strchr((*slst)[j],'-');
-          if (pos) {
-              int info;
-              char w[MAXWORDUTF8LEN];
-              *pos = '\0';
-              strcpy(w, (*slst)[j]);
-              strcat(w, pos + 1);
-              spell(w, &info, NULL);
-              if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
-                  *pos = ' ';
-              } else *pos = '-';
-          }
-      }
-  }
-  // END OF LANG_hu section
-  
-  // try ngram approach since found nothing
-  if ((ns == 0 || onlycmpdsug) && pAMgr && (pAMgr->get_maxngramsugs() != 0)) {
-      switch(captype) {
-          case NOCAP: {
-              ns = pSMgr->ngsuggest(*slst, cw, ns, pHMgr);
-              break;
-          }
-          case HUHCAP: {
-              memcpy(wspace,cw,(wl+1));
-              mkallsmall2(wspace, unicw, nc);
-              ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr);
-              break;
-          }
-          case INITCAP: { 
-              capwords = 1;
-              memcpy(wspace,cw,(wl+1));
-              mkallsmall2(wspace, unicw, nc);
-              ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr);
-              break;
-          }
-          case ALLCAP: {
-              memcpy(wspace,cw,(wl+1));
-              mkallsmall2(wspace, unicw, nc);
-	      int oldns = ns;
-              ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr);
-              for (int j = oldns; j < ns; j++) 
-                  mkallcap((*slst)[j]);
-              break;
-         }
-      }
-  }
-
-  // word reversing wrapper for complex prefixes
-  if (complexprefixes) {
-    for (int j = 0; j < ns; j++) {
-      if (utf8) reverseword_utf((*slst)[j]); else reverseword((*slst)[j]);
-    }
-  }
-
-  // capitalize
-  if (capwords) for (int j=0; j < ns; j++) {
-      mkinitcap((*slst)[j]);
-  }
-
-  // expand suggestions with dot(s)
-  if (abbv && pAMgr && pAMgr->get_sugswithdots()) {
-    for (int j = 0; j < ns; j++) {
-      (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 1 + abbv);
-      strcat((*slst)[j], word + strlen(word) - abbv);
-    }
-  }
-
-  // remove bad capitalized and forbidden forms
-  if (pAMgr && (pAMgr->get_keepcase() || pAMgr->get_forbiddenword())) {
-  switch (captype) {
-    case INITCAP:
-    case ALLCAP: {
-      int l = 0;
-      for (int j=0; j < ns; j++) {
-        if (!strchr((*slst)[j],' ') && !spell((*slst)[j])) {
-          char s[MAXSWUTF8L];
-          w_char w[MAXSWL];
-          int len;
-          if (utf8) {
-            len = u8_u16(w, MAXSWL, (*slst)[j]);
-          } else {
-            strcpy(s, (*slst)[j]);
-            len = strlen(s);
-          }
-          mkallsmall2(s, w, len);
-          free((*slst)[j]);          
-          if (spell(s)) {
-            (*slst)[l] = mystrdup(s);
-            l++;
-          } else {
-            mkinitcap2(s, w, len);
-            if (spell(s)) {
-              (*slst)[l] = mystrdup(s);
-              l++;
-            }
-          }
-        } else {
-          (*slst)[l] = (*slst)[j];
-          l++;
-        }    
-      }
-      ns = l;
-    }
-  }
-  }
-
-  // remove duplications
-  int l = 0;
-  for (int j = 0; j < ns; j++) {
-    (*slst)[l] = (*slst)[j];
-    for (int k = 0; k < l; k++) {
-      if (strcmp((*slst)[k], (*slst)[j]) == 0) {
-        free((*slst)[j]);
-        l--;
-      }
-    }
-    l++;
-  }
-  return l;
-}
-
-char * Hunspell::get_dic_encoding()
-{
-  return encoding;
-}
-
-#ifdef HUNSPELL_EXPERIMENTAL
-// XXX need UTF-8 support
-int Hunspell::suggest_auto(char*** slst, const char * word)
-{
-  char cw[MAXWORDUTF8LEN];
-  char wspace[MAXWORDUTF8LEN];
-  if (! pSMgr) return 0;
-  int wl = strlen(word);
-  if (utf8) {
-    if (wl >= MAXWORDUTF8LEN) return 0;
-  } else {
-    if (wl >= MAXWORDLEN) return 0;
-  }
-  int captype = 0;
-  int abbv = 0;
-  wl = cleanword(cw, word, &captype, &abbv);
-  if (wl == 0) return 0;
-  int ns = 0;
-  *slst = NULL; // HU, nsug in pSMgr->suggest
-  
-  switch(captype) {
-     case NOCAP:   { 
-                     ns = pSMgr->suggest_auto(slst, cw, ns);
-                     if (ns>0) break;
-                     break;
-                   }
-
-     case INITCAP: { 
-                     memcpy(wspace,cw,(wl+1));
-                     mkallsmall(wspace);
-                     ns = pSMgr->suggest_auto(slst, wspace, ns);
-                     for (int j=0; j < ns; j++)
-                       mkinitcap((*slst)[j]);
-                     ns = pSMgr->suggest_auto(slst, cw, ns);
-                     break;
-                     
-                   }
-
-     case HUHCAP: { 
-                     ns = pSMgr->suggest_auto(slst, cw, ns);
-                     if (ns == 0) {
-                        memcpy(wspace,cw,(wl+1));
-                        mkallsmall(wspace);
-                        ns = pSMgr->suggest_auto(slst, wspace, ns);
-                     }
-                     break;
-                   }
-
-     case ALLCAP: { 
-                     memcpy(wspace,cw,(wl+1));
-                     mkallsmall(wspace);
-                     ns = pSMgr->suggest_auto(slst, wspace, ns);
-
-                     mkinitcap(wspace);
-                     ns = pSMgr->suggest_auto(slst, wspace, ns);
-
-                     for (int j=0; j < ns; j++)
-                       mkallcap((*slst)[j]);
-                     break;
-                   }
-  }
-
-  // word reversing wrapper for complex prefixes
-  if (complexprefixes) {
-    for (int j = 0; j < ns; j++) {
-      if (utf8) reverseword_utf((*slst)[j]); else reverseword((*slst)[j]);
-    }
-  }
-
-  // expand suggestions with dot(s)
-  if (abbv && pAMgr && pAMgr->get_sugswithdots()) {
-    for (int j = 0; j < ns; j++) {
-      (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 1 + abbv);
-      strcat((*slst)[j], word + strlen(word) - abbv);
-    }
-  }
-
-  // LANG_hu section: replace '-' with ' ' in Hungarian
-  if (langnum == LANG_hu) {
-      for (int j=0; j < ns; j++) {
-          char * pos = strchr((*slst)[j],'-');
-          if (pos) {
-              int info;
-              char w[MAXWORDUTF8LEN];
-              *pos = '\0';
-              strcpy(w, (*slst)[j]);
-              strcat(w, pos + 1);
-              spell(w, &info, NULL);
-              if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
-                  *pos = ' ';
-              } else *pos = '-';
-          }
-      }
-  }
-  // END OF LANG_hu section  
-  return ns;
-}
-
-// XXX need UTF-8 support
-int Hunspell::stem(char*** slst, const char * word)
-{
-  char cw[MAXWORDUTF8LEN];
-  char wspace[MAXWORDUTF8LEN];
-  if (! pSMgr) return 0;
-  int wl = strlen(word);
-  if (utf8) {
-    if (wl >= MAXWORDUTF8LEN) return 0;
-  } else {
-    if (wl >= MAXWORDLEN) return 0;
-  }
-  int captype = 0;
-  int abbv = 0;
-  wl = cleanword(cw, word, &captype, &abbv);
-  if (wl == 0) return 0;
-  
-  int ns = 0;
-
-  *slst = NULL; // HU, nsug in pSMgr->suggest
-  
-  switch(captype) {
-     case HUHCAP:
-     case NOCAP:   { 
-                     ns = pSMgr->suggest_stems(slst, cw, ns);
-
-                     if ((abbv) && (ns == 0)) {
-                         memcpy(wspace,cw,wl);
-                         *(wspace+wl) = '.';
-                         *(wspace+wl+1) = '\0';
-                         ns = pSMgr->suggest_stems(slst, wspace, ns);
-                     }
-
-                     break;
-                   }
-
-     case INITCAP: { 
-
-                     ns = pSMgr->suggest_stems(slst, cw, ns);
-
-                     if (ns == 0) {
-                        memcpy(wspace,cw,(wl+1));
-                        mkallsmall(wspace);
-                        ns = pSMgr->suggest_stems(slst, wspace, ns);
-
-                     }
-
-                     if ((abbv) && (ns == 0)) {
-                         memcpy(wspace,cw,wl);
-                         mkallsmall(wspace);
-                         *(wspace+wl) = '.';
-                         *(wspace+wl+1) = '\0';
-                         ns = pSMgr->suggest_stems(slst, wspace, ns);
-                     }
-                     
-                     break;
-                     
-                   }
-
-     case ALLCAP: { 
-                     ns = pSMgr->suggest_stems(slst, cw, ns);
-                     if (ns != 0) break;
-                     
-                     memcpy(wspace,cw,(wl+1));
-                     mkallsmall(wspace);
-                     ns = pSMgr->suggest_stems(slst, wspace, ns);
-
-                     if (ns == 0) {
-                         mkinitcap(wspace);
-                         ns = pSMgr->suggest_stems(slst, wspace, ns);
-                     }
-
-                     if ((abbv) && (ns == 0)) {
-                         memcpy(wspace,cw,wl);
-                         mkallsmall(wspace);
-                         *(wspace+wl) = '.';
-                         *(wspace+wl+1) = '\0';
-                         ns = pSMgr->suggest_stems(slst, wspace, ns);
-                     }
-
-
-                     break;
-                   }
-  }
-  
-  return ns;
-}
-
-int Hunspell::suggest_pos_stems(char*** slst, const char * word)
-{
-  char cw[MAXWORDUTF8LEN];
-  char wspace[MAXWORDUTF8LEN];
-  if (! pSMgr) return 0;
-  int wl = strlen(word);
-  if (utf8) {
-    if (wl >= MAXWORDUTF8LEN) return 0;
-  } else {
-    if (wl >= MAXWORDLEN) return 0;
-  }
-  int captype = 0;
-  int abbv = 0;
-  wl = cleanword(cw, word, &captype, &abbv);
-  if (wl == 0) return 0;
-  
-  int ns = 0; // ns=0 = normalized input
-
-  *slst = NULL; // HU, nsug in pSMgr->suggest
-  
-  switch(captype) {
-     case HUHCAP:
-     case NOCAP:   { 
-                     ns = pSMgr->suggest_pos_stems(slst, cw, ns);
-
-                     if ((abbv) && (ns == 0)) {
-                         memcpy(wspace,cw,wl);
-                         *(wspace+wl) = '.';
-                         *(wspace+wl+1) = '\0';
-                         ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
-                     }
-
-                     break;
-                   }
-
-     case INITCAP: { 
-
-                     ns = pSMgr->suggest_pos_stems(slst, cw, ns);
-
-                     if (ns == 0 || ((*slst)[0][0] == '#')) {
-                        memcpy(wspace,cw,(wl+1));
-                        mkallsmall(wspace);
-                        ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
-                     }
-                     
-                     break;
-                     
-                   }
-
-     case ALLCAP: { 
-                     ns = pSMgr->suggest_pos_stems(slst, cw, ns);
-                     if (ns != 0) break;
-                     
-                     memcpy(wspace,cw,(wl+1));
-                     mkallsmall(wspace);
-                     ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
-
-                     if (ns == 0) {
-                         mkinitcap(wspace);
-                         ns = pSMgr->suggest_pos_stems(slst, wspace, ns);
-                     }
-                     break;
-                   }
-  }
-
-  return ns;
-}
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
-const char * Hunspell::get_wordchars()
-{
-  return pAMgr->get_wordchars();
-}
-
-unsigned short * Hunspell::get_wordchars_utf16(int * len)
-{
-  return pAMgr->get_wordchars_utf16(len);
-}
-
-void Hunspell::mkinitcap(char * p)
-{
-  if (!utf8) {
-    if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper;
-  } else {
-      int len;
-      w_char u[MAXWORDLEN];
-      len = u8_u16(u, MAXWORDLEN, p);
-      unsigned short i = unicodetoupper((u[0].h << 8) + u[0].l, langnum);
-      u[0].h = (unsigned char) (i >> 8);
-      u[0].l = (unsigned char) (i & 0x00FF);
-      u16_u8(p, MAXWORDUTF8LEN, u, len);
-  }
-}
-
-int Hunspell::mkinitcap2(char * p, w_char * u, int nc)
-{
-  if (!utf8) {
-    if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper;
-  } else if (nc > 0) {
-      unsigned short i = unicodetoupper((u[0].h << 8) + u[0].l, langnum);
-      u[0].h = (unsigned char) (i >> 8);
-      u[0].l = (unsigned char) (i & 0x00FF);
-      u16_u8(p, MAXWORDUTF8LEN, u, nc);
-      return strlen(p);
-  }
-  return nc;
-}
-
-int Hunspell::mkinitsmall2(char * p, w_char * u, int nc)
-{
-  if (!utf8) {
-    if (*p != '\0') *p = csconv[((unsigned char)*p)].clower;
-  } else if (nc > 0) {
-      unsigned short i = unicodetolower((u[0].h << 8) + u[0].l, langnum);
-      u[0].h = (unsigned char) (i >> 8);
-      u[0].l = (unsigned char) (i & 0x00FF);
-      u16_u8(p, MAXWORDUTF8LEN, u, nc);
-      return strlen(p);
-  }
-  return nc;
-}
-
-int Hunspell::put_word(const char * word)
-{
-    if (pHMgr) return pHMgr->put_word(word, NULL);
-    return 0;
-}
-
-int Hunspell::put_word_pattern(const char * word, const char * pattern)
-{
-    if (pHMgr) return pHMgr->put_word_pattern(word, pattern);
-    return 0;
-}
-
-const char * Hunspell::get_version()
-{
-  return pAMgr->get_version();
-}
-
-struct cs_info * Hunspell::get_csconv()
-{
-  return csconv;
-}
-
-#ifdef HUNSPELL_EXPERIMENTAL
-// XXX need UTF-8 support
-char * Hunspell::morph(const char * word)
-{
-  char cw[MAXWORDUTF8LEN];
-  char wspace[MAXWORDUTF8LEN];
-  if (! pSMgr) return 0;
-  int wl = strlen(word);
-  if (utf8) {
-    if (wl >= MAXWORDUTF8LEN) return 0;
-  } else {
-    if (wl >= MAXWORDLEN) return 0;
-  }
-  int captype = 0;
-  int abbv = 0;
-  wl = cleanword(cw, word, &captype, &abbv);
-  if (wl == 0) {
-      if (abbv) {
-          for (wl = 0; wl < abbv; wl++) cw[wl] = '.';
-          cw[wl] = '\0';
-          abbv = 0;
-      } else return 0;
-  }
-
-  char result[MAXLNLEN];
-  char * st = NULL;
-  
-  *result = '\0';
-
-  int n = 0;
-  int n2 = 0;
-  int n3 = 0;
-
-  // test numbers
-  // LANG_hu section: set dash information for suggestions
-  if (langnum == LANG_hu) {
-  while ((n < wl) && 
-        (((cw[n] <= '9') && (cw[n] >= '0')) || (((cw[n] == '.') || (cw[n] == ',')) && (n > 0)))) {
-        n++;
-        if ((cw[n] == '.') || (cw[n] == ',')) {
-                if (((n2 == 0) && (n > 3)) || 
-                        ((n2 > 0) && ((cw[n-1] == '.') || (cw[n-1] == ',')))) break;
-                n2++;
-                n3 = n;
-        }
-  }
-
-  if ((n == wl) && (n3 > 0) && (n - n3 > 3)) return NULL;
-  if ((n == wl) || ((n>0) && ((cw[n]=='%') || (cw[n]=='\xB0')) && checkword(cw+n, NULL, NULL))) {
-        strcat(result, cw);
-        result[n - 1] = '\0';
-        if (n == wl) {
-                st = pSMgr->suggest_morph(cw + n - 1);
-                if (st) {
-                        strcat(result, st);
-                        free(st);
-                }
-        } else {
-                char sign = cw[n];
-                cw[n] = '\0';
-                st = pSMgr->suggest_morph(cw + n - 1);
-                if (st) {
-                        strcat(result, st);
-                        free(st);
-                }
-                strcat(result, "+"); // XXX SPEC. MORPHCODE
-                cw[n] = sign;
-                st = pSMgr->suggest_morph(cw + n);
-                if (st) {
-                        strcat(result, st);
-                        free(st);
-                }
-        }
-        return mystrdup(result);
-  }
-  }
-  // END OF LANG_hu section
-  
-  switch(captype) {
-     case NOCAP:   { 
-                     st = pSMgr->suggest_morph(cw);
-                     if (st) {
-                        strcat(result, st);
-                        free(st);
-                     }
-                                         if (abbv) {
-                                        memcpy(wspace,cw,wl);
-                         *(wspace+wl) = '.';
-                         *(wspace+wl+1) = '\0';
-                         st = pSMgr->suggest_morph(wspace);
-                         if (st) {
-                            if (*result) strcat(result, "\n");
-                            strcat(result, st);
-                            free(st);
-                                                 }
-                     }
-                                         break;
-                   }
-     case INITCAP: { 
-                     memcpy(wspace,cw,(wl+1));
-                     mkallsmall(wspace);
-                     st = pSMgr->suggest_morph(wspace);
-                     if (st) {
-                        strcat(result, st);
-                        free(st);
-                     }                                   
-                         st = pSMgr->suggest_morph(cw);
-                     if (st) {
-                        if (*result) strcat(result, "\n");
-                        strcat(result, st);
-                        free(st);
-                     }
-                                         if (abbv) {
-                                         memcpy(wspace,cw,wl);
-                         *(wspace+wl) = '.';
-                         *(wspace+wl+1) = '\0';
-                         mkallsmall(wspace);
-                         st = pSMgr->suggest_morph(wspace);
-                         if (st) {
-                            if (*result) strcat(result, "\n");
-                            strcat(result, st);
-                            free(st);
-                                                 }
-                         mkinitcap(wspace);
-                         st = pSMgr->suggest_morph(wspace);
-                         if (st) {
-                            if (*result) strcat(result, "\n");
-                            strcat(result, st);
-                            free(st);
-                                                 }
-                     }
-                     break;
-                   }
-     case HUHCAP: { 
-                     st = pSMgr->suggest_morph(cw);
-                     if (st) {
-                        strcat(result, st);
-                        free(st);
-                     }
-#if 0
-                     memcpy(wspace,cw,(wl+1));
-                     mkallsmall(wspace);
-                     st = pSMgr->suggest_morph(wspace);
-                     if (st) {
-                        if (*result) strcat(result, "\n");
-                        strcat(result, st);
-                        free(st);
-                     }
-#endif
-                     break;
-                 }
-     case ALLCAP: { 
-                     memcpy(wspace,cw,(wl+1));
-                     st = pSMgr->suggest_morph(wspace);
-                     if (st) {
-                        strcat(result, st);
-                        free(st);
-                     }               
-                     mkallsmall(wspace);
-                     st = pSMgr->suggest_morph(wspace);
-                     if (st) {
-                        if (*result) strcat(result, "\n");
-                        strcat(result, st);
-                        free(st);
-                     }
-                             mkinitcap(wspace);
-                             st = pSMgr->suggest_morph(wspace);
-                     if (st) {
-                        if (*result) strcat(result, "\n");
-                        strcat(result, st);
-                        free(st);
-                     }
-                                         if (abbv) {
-                        memcpy(wspace,cw,(wl+1));
-                        *(wspace+wl) = '.';
-                        *(wspace+wl+1) = '\0';
-                        if (*result) strcat(result, "\n");
-                        st = pSMgr->suggest_morph(wspace);
-                        if (st) {
-                                strcat(result, st);
-                                free(st);
-                        }                    
-                        mkallsmall(wspace);
-                        st = pSMgr->suggest_morph(wspace);
-                        if (st) {
-                          if (*result) strcat(result, "\n");
-                          strcat(result, st);
-                          free(st);
-                        }
-                                mkinitcap(wspace);
-                                st = pSMgr->suggest_morph(wspace);
-                        if (st) {
-                          if (*result) strcat(result, "\n");
-                          strcat(result, st);
-                          free(st);
-                        }
-                                         }
-                     break;
-                   }
-  }
-
-  if (result && (*result)) {
-    // word reversing wrapper for complex prefixes
-    if (complexprefixes) {
-      if (utf8) reverseword_utf(result); else reverseword(result);
-    }
-    return mystrdup(result);
-  }
-
-  // compound word with dash (HU) I18n
-  char * dash = NULL;
-  int nresult = 0;
-  // LANG_hu section: set dash information for suggestions
-  if (langnum == LANG_hu) dash = (char *) strchr(cw,'-');
-  if ((langnum == LANG_hu) && dash) {
-      *dash='\0';      
-      // examine 2 sides of the dash
-      if (dash[1] == '\0') { // base word ending with dash
-        if (spell(cw)) return pSMgr->suggest_morph(cw);
-      } else if ((dash[1] == 'e') && (dash[2] == '\0')) { // XXX (HU) -e hat.
-        if (spell(cw) && (spell("-e"))) {
-                        st = pSMgr->suggest_morph(cw);
-                        if (st) {
-                                strcat(result, st);
-                                free(st);
-                        }
-                        strcat(result,"+"); // XXX spec. separator in MORPHCODE
-                        st = pSMgr->suggest_morph("-e");
-                        if (st) {
-                                strcat(result, st);
-                                free(st);
-                        }
-                        return mystrdup(result);
-                }
-      } else {
-      // first word ending with dash: word- XXX ???
-        char r2 = *(dash + 1);
-        dash[0]='-';
-        dash[1]='\0';
-        nresult = spell(cw);
-        dash[1] = r2;
-        dash[0]='\0';
-        if (nresult && spell(dash+1) && ((strlen(dash+1) > 1) ||
-                ((dash[1] > '0') && (dash[1] < '9')))) {
-                            st = morph(cw);
-                            if (st) {
-                                strcat(result, st);
-                                    free(st);
-                                strcat(result,"+"); // XXX spec. separator in MORPHCODE
-                            }
-                            st = morph(dash+1);
-                            if (st) {
-                                    strcat(result, st);
-                                    free(st);
-                            }
-                            return mystrdup(result);                    
-                        }
-      }
-      // affixed number in correct word
-     if (nresult && (dash > cw) && (((*(dash-1)<='9') && 
-                        (*(dash-1)>='0')) || (*(dash-1)=='.'))) {
-         *dash='-';
-         n = 1;
-         if (*(dash - n) == '.') n++;
-         // search first not a number character to left from dash
-         while (((dash - n)>=cw) && ((*(dash - n)=='0') || (n < 3)) && (n < 6)) {
-            n++;
-         }
-         if ((dash - n) < cw) n--;
-         // numbers: valami1000000-hoz
-         // examine 100000-hoz, 10000-hoz 1000-hoz, 10-hoz,
-         // 56-hoz, 6-hoz
-         for(; n >= 1; n--) {
-            if ((*(dash - n) >= '0') && (*(dash - n) <= '9') && checkword(dash - n, NULL, NULL)) {
-                    strcat(result, cw);
-                    result[dash - cw - n] = '\0';
-                        st = pSMgr->suggest_morph(dash - n);
-                        if (st) {
-                        strcat(result, st);
-                                free(st);
-                        }
-                    return mystrdup(result);                    
-            }
-         }
-     }
-  }
-  return NULL;
-}
-
-// XXX need UTF-8 support
-char * Hunspell::morph_with_correction(const char * word)
-{
-  char cw[MAXWORDUTF8LEN];
-  char wspace[MAXWORDUTF8LEN];
-  if (! pSMgr) return 0;
-  int wl = strlen(word);
-  if (utf8) {
-    if (wl >= MAXWORDUTF8LEN) return 0;
-  } else {
-    if (wl >= MAXWORDLEN) return 0;
-  }
-  int captype = 0;
-  int abbv = 0;
-  wl = cleanword(cw, word, &captype, &abbv);
-  if (wl == 0) return 0;
-
-  char result[MAXLNLEN];
-  char * st = NULL;
-  
-  *result = '\0';
-  
-  
-  switch(captype) {
-     case NOCAP:   { 
-                     st = pSMgr->suggest_morph_for_spelling_error(cw);
-                     if (st) {
-                        strcat(result, st);
-                        free(st);
-                     }
-                                         if (abbv) {
-                                        memcpy(wspace,cw,wl);
-                         *(wspace+wl) = '.';
-                         *(wspace+wl+1) = '\0';
-                         st = pSMgr->suggest_morph_for_spelling_error(wspace);
-                         if (st) {
-                            if (*result) strcat(result, "\n");
-                            strcat(result, st);
-                            free(st);
-                                                 }
-                     }
-                                         break;
-                   }
-     case INITCAP: { 
-                     memcpy(wspace,cw,(wl+1));
-                     mkallsmall(wspace);
-                     st = pSMgr->suggest_morph_for_spelling_error(wspace);
-                     if (st) {
-                        strcat(result, st);
-                        free(st);
-                     }                                   
-                         st = pSMgr->suggest_morph_for_spelling_error(cw);
-                     if (st) {
-                        if (*result) strcat(result, "\n");
-                        strcat(result, st);
-                        free(st);
-                     }
-                                         if (abbv) {
-                                         memcpy(wspace,cw,wl);
-                         *(wspace+wl) = '.';
-                         *(wspace+wl+1) = '\0';
-                         mkallsmall(wspace);
-                         st = pSMgr->suggest_morph_for_spelling_error(wspace);
-                         if (st) {
-                            if (*result) strcat(result, "\n");
-                            strcat(result, st);
-                            free(st);
-                                                 }
-                         mkinitcap(wspace);
-                         st = pSMgr->suggest_morph_for_spelling_error(wspace);
-                         if (st) {
-                            if (*result) strcat(result, "\n");
-                            strcat(result, st);
-                            free(st);
-                                                 }
-                     }
-                     break;
-                   }
-     case HUHCAP: { 
-                     st = pSMgr->suggest_morph_for_spelling_error(cw);
-                     if (st) {
-                        strcat(result, st);
-                        free(st);
-                     }
-                     memcpy(wspace,cw,(wl+1));
-                     mkallsmall(wspace);
-                     st = pSMgr->suggest_morph_for_spelling_error(wspace);
-                     if (st) {
-                        if (*result) strcat(result, "\n");
-                        strcat(result, st);
-                        free(st);
-                     }               
-                     break;
-                 }
-     case ALLCAP: { 
-                     memcpy(wspace,cw,(wl+1));
-                     st = pSMgr->suggest_morph_for_spelling_error(wspace);
-                     if (st) {
-                        strcat(result, st);
-                        free(st);
-                     }               
-                     mkallsmall(wspace);
-                     st = pSMgr->suggest_morph_for_spelling_error(wspace);
-                     if (st) {
-                        if (*result) strcat(result, "\n");
-                        strcat(result, st);
-                        free(st);
-                     }
-                             mkinitcap(wspace);
-                             st = pSMgr->suggest_morph_for_spelling_error(wspace);
-                     if (st) {
-                        if (*result) strcat(result, "\n");
-                        strcat(result, st);
-                        free(st);
-                     }
-                                         if (abbv) {
-                        memcpy(wspace,cw,(wl+1));
-                        *(wspace+wl) = '.';
-                        *(wspace+wl+1) = '\0';
-                        if (*result) strcat(result, "\n");
-                        st = pSMgr->suggest_morph_for_spelling_error(wspace);
-                        if (st) {
-                                strcat(result, st);
-                                free(st);
-                        }                    
-                        mkallsmall(wspace);
-                        st = pSMgr->suggest_morph_for_spelling_error(wspace);
-                        if (st) {
-                          if (*result) strcat(result, "\n");
-                          strcat(result, st);
-                          free(st);
-                        }
-                                mkinitcap(wspace);
-                                st = pSMgr->suggest_morph_for_spelling_error(wspace);
-                        if (st) {
-                          if (*result) strcat(result, "\n");
-                          strcat(result, st);
-                          free(st);
-                        }
-                                         }
-                     break;
-                   }
-  }
-
-  if (result) return mystrdup(result);
-  return NULL;
-}
-
-/* analyze word
- * return line count 
- * XXX need a better data structure for morphological analysis */
-int Hunspell::analyze(char ***out, const char *word) {
-  int  n = 0;
-  if (!word) return 0;
-  char * m = morph(word);
-  if(!m) return 0;
-  if (!out)
-  {
-     n = line_tok(m, out);
-     free(m);
-     return n;
-  }
-
-  // without memory allocation
-  /* BUG missing buffer size checking */
-  int i, p;
-  for(p = 0, i = 0; m[i]; i++) {
-     if(m[i] == '\n' || !m[i+1]) {
-       n++;
-       strncpy((*out)[n++], m + p, i - p + 1);
-       if (m[i] == '\n') (*out)[n++][i - p] = '\0';
-       if(!m[i+1]) break;
-       p = i + 1;        
-     }
-  }
-  free(m);
-  return n;
-}
-
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
-Hunhandle *Hunspell_create(const char * affpath, const char * dpath)
-{
-        return (Hunhandle*)(new Hunspell(affpath, dpath));
-}
-
-void Hunspell_destroy(Hunhandle *pHunspell)
-{
-        delete (Hunspell*)(pHunspell);
-}
-
-int Hunspell_spell(Hunhandle *pHunspell, const char *word)
-{
-        return ((Hunspell*)pHunspell)->spell(word);
-}
-
-char *Hunspell_get_dic_encoding(Hunhandle *pHunspell)
-{
-        return ((Hunspell*)pHunspell)->get_dic_encoding();
-}
-
-int Hunspell_suggest(Hunhandle *pHunspell, char*** slst, const char * word)
-{
-        return ((Hunspell*)pHunspell)->suggest(slst, word);
-}
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/hunspell.h spellcheck/hunspell/src/hunspell.h
--- spellcheck.old/hunspell/src/hunspell.h	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/hunspell.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,89 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef _MYSPELLMGR_H_
-#define _MYSPELLMGR_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct Hunhandle Hunhandle;
-
-Hunhandle *Hunspell_create(const char * affpath, const char * dpath);
-void Hunspell_destroy(Hunhandle *pHunspell);
-
-/* spell(word) - spellcheck word
- * output: 0 = bad word, not 0 = good word
- */
-int Hunspell_spell(Hunhandle *pHunspell, const char *);
-
-char *Hunspell_get_dic_encoding(Hunhandle *pHunspell);
-
-/* suggest(suggestions, word) - search suggestions
- * input: pointer to an array of strings pointer and the (bad) word
- *   array of strings pointer (here *slst) may not be initialized
- * output: number of suggestions in string array, and suggestions in
- *   a newly allocated array of strings (*slts will be NULL when number
- *   of suggestion equals 0.)
- */
-int Hunspell_suggest(Hunhandle *pHunspell, char*** slst, const char * word);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/hunspell.hxx spellcheck/hunspell/src/hunspell.hxx
--- spellcheck.old/hunspell/src/hunspell.hxx	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/hunspell.hxx	1970-01-01 01:00:00.000000000 +0100
@@ -1,195 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#include "hashmgr.hxx"
-#include "affixmgr.hxx"
-#include "suggestmgr.hxx"
-#include "csutil.hxx"
-#include "langnum.hxx"
-
-#define  SPELL_COMPOUND  (1 << 0)
-#define  SPELL_FORBIDDEN (1 << 1)
-#define  SPELL_ALLCAP    (1 << 2)
-#define  SPELL_NOCAP     (1 << 3)
-#define  SPELL_INITCAP   (1 << 4)
-
-#define MAXSUGGESTION 15
-#define MAXSHARPS 5
-
-#ifndef _MYSPELLMGR_HXX_
-#define _MYSPELLMGR_HXX_
-
-#ifdef HUNSPELL_STATIC
-	#define DLLEXPORT
-#else
-	#ifdef HUNSPELL_EXPORTS
-		#define DLLEXPORT  __declspec( dllexport )
-	#else
-		#define DLLEXPORT  __declspec( dllimport )
-	#endif
-#endif
-
-#ifdef W32
-class DLLEXPORT Hunspell
-#else
-class Hunspell
-#endif
-{
-  AffixMgr*       pAMgr;
-  HashMgr*        pHMgr;
-  SuggestMgr*     pSMgr;
-  char *          encoding;
-  struct cs_info * csconv;
-  int             langnum;
-  int             utf8;
-  int             complexprefixes;
-  char**          wordbreak;
-
-public:
-
-  /* Hunspell(aff, dic) - constructor of Hunspell class
-   * input: path of affix file and dictionary file
-   */
-  
-  Hunspell(const char * affpath, const char * dpath);
-
-  ~Hunspell();
-
-  /* spell(word) - spellcheck word
-   * output: 0 = bad word, not 0 = good word
-   *   
-   * plus output:
-   *   info: information bit array, fields:
-   *     SPELL_COMPOUND  = a compound word 
-   *     SPELL_FORBIDDEN = an explicit forbidden word
-   *   root: root (stem), when input is a word with affix(es)
-   */
-   
-  int spell(const char * word, int * info = NULL, char ** root = NULL);
-
-  /* suggest(suggestions, word) - search suggestions
-   * input: pointer to an array of strings pointer and the (bad) word
-   *   array of strings pointer (here *slst) may not be initialized
-   * output: number of suggestions in string array, and suggestions in
-   *   a newly allocated array of strings (*slts will be NULL when number
-   *   of suggestion equals 0.)
-   */
-
-  int suggest(char*** slst, const char * word);
-  char * get_dic_encoding();
-
-  /* handling custom dictionary */
-  
-  int put_word(const char * word);
-
-  /* pattern is a sample dictionary word 
-   * put word into custom dictionary with affix flags of pattern word
-   */
-  
-  int put_word_pattern(const char * word, const char * pattern);
-
-  /* other */
-
-  /* get extra word characters definied in affix file for tokenization */
-  const char * get_wordchars();
-  unsigned short * get_wordchars_utf16(int * len);
-
-  struct cs_info * get_csconv();
-  const char * get_version();
-
-  /* experimental functions */
-
-#ifdef HUNSPELL_EXPERIMENTAL
-  /* suffix is an affix flag string, similarly in dictionary files */
-  
-  int put_word_suffix(const char * word, const char * suffix);
-  
-  /* morphological analysis */
-  
-  char * morph(const char * word);
-  int analyze(char*** out, const char *word);
-
-  char * morph_with_correction(const char * word);
-
-  /* stemmer function */
-  
-  int stem(char*** slst, const char * word);
-
-  /* spec. suggestions */
-  int suggest_auto(char*** slst, const char * word);
-  int suggest_pos_stems(char*** slst, const char * word);
-  char * get_possible_root();
-#endif
-
-private:
-   int    cleanword(char *, const char *, int * pcaptype, int * pabbrev);
-   int    cleanword2(char *, const char *, w_char *, int * w_len, int * pcaptype, int * pabbrev);
-   void   mkinitcap(char *);
-   int    mkinitcap2(char * p, w_char * u, int nc);
-   int    mkinitsmall2(char * p, w_char * u, int nc);
-   void   mkallcap(char *);
-   int    mkallcap2(char * p, w_char * u, int nc);
-   void   mkallsmall(char *);
-   int    mkallsmall2(char * p, w_char * u, int nc);
-   struct hentry * checkword(const char *, int * info, char **root);
-   char * sharps_u8_l1(char * dest, char * source);
-   hentry * spellsharps(char * base, char *, int, int, char * tmp, int * info, char **root);
-   int    is_keepcase(const hentry * rv);
-   int    insert_sug(char ***slst, char * word, int ns);
-
-};
-
-#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/langnum.hxx spellcheck/hunspell/src/langnum.hxx
--- spellcheck.old/hunspell/src/langnum.hxx	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/langnum.hxx	1970-01-01 01:00:00.000000000 +0100
@@ -1,94 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef _LANGNUM_HXX_
-#define _LANGNUM_HXX_
-
-/*
- language numbers for language specific codes
- see http://l10n.openoffice.org/languages.html
-*/
-
-enum {
-LANG_ar=96,
-LANG_az=100, // custom number
-LANG_bg=41,
-LANG_ca=37,
-LANG_cs=42,
-LANG_da=45,
-LANG_de=49,
-LANG_el=30,
-LANG_en=01,
-LANG_es=34,
-LANG_eu=10,
-LANG_fr=02,
-LANG_gl=38,
-LANG_hr=78,
-LANG_hu=36,
-LANG_it=39,
-LANG_la=99, // custom number
-LANG_lv=101, // custom number
-LANG_nl=31,
-LANG_pl=48,
-LANG_pt=03,
-LANG_ru=07,
-LANG_sv=50,
-LANG_tr=90,
-LANG_uk=80,
-LANG_xx=999
-};
-
-#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/Makefile.in spellcheck/hunspell/src/Makefile.in
--- spellcheck.old/hunspell/src/Makefile.in	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/Makefile.in	2008-04-23 19:10:45.000000000 +0200
@@ -56,17 +56,6 @@ REQUIRES         = xpcom \
 CPPSRCS          = mozHunspell.cpp \
                    $(NULL)
 
-ifndef MOZ_NATIVE_HUNSPELL
-CPPSRCS         += affentry.cpp \
-                   affixmgr.cpp \
-                   csutil.cpp \
-                   hashmgr.cpp \
-                   hunspell.cpp \
-                   phonet.cpp \
-                   suggestmgr.cpp \
-                   $(NULL)
-endif
-
 ifdef MOZ_XUL_APP
 CPPSRCS += mozHunspellDirProvider.cpp
 endif
@@ -83,4 +72,6 @@ include $(topsrcdir)/config/rules.mk
 
 ifdef MOZ_NATIVE_HUNSPELL
 CXXFLAGS += $(MOZ_HUNSPELL_CFLAGS)
+else
+CXXFLAGS += -I$(srcdir)/../hunspell
 endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/phonet.cpp spellcheck/hunspell/src/phonet.cpp
--- spellcheck.old/hunspell/src/phonet.cpp	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/phonet.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,310 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developer of the Original Code is Björn Jacke. Portions created
- * by the Initial Developers are Copyright (C) 2000-2007 the Initial
- * Developers. All Rights Reserved.
- * 
- * Contributor(s): Björn Jacke (bjoern.jacke@gmx.de)
- *                 László Németh (nemethl@gyorsposta.hu)
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * Changelog:
- *  2000-01-05  Björn Jacke <bjoern.jacke AT gmx.de>
- *              Initial Release insprired by the article about phonetic
- *              transformations out of c't 25/1999
- *
- *  2007-07-26  Björn Jacke <bjoern.jacke AT gmx.de>
- *              Released under MPL/GPL/LGPL tri-license for Hunspell
- *
- *  2007-08-23  László Németh <nemeth at OOo>
- *              Porting from Aspell to Hunspell using C-like structs
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef MOZILLA_CLIENT
-#include <cstdlib>
-#include <cstring>
-#include <cstdio>
-#include <cctype>
-#else
-#include <stdlib.h> 
-#include <string.h>
-#include <stdio.h> 
-#include <ctype.h>
-#endif
-
-#include "csutil.hxx"
-#include "phonet.hxx"
-
-void init_phonet_hash(phonetable & parms) 
-  {
-    int i, k;
-
-    for (i = 0; i < parms.hash_size; i++) {
-      parms.hash[i] = -1;
-    }
-
-    for (i = 0; parms.rules[i][0] != '\0'; i += 2) {
-      /**  set hash value  **/
-      k = (unsigned char) parms.rules[i][0];
-
-      if (parms.hash[k] < 0) {
-	parms.hash[k] = i;
-      }
-    }
-  }
-
-  // like strcpy but safe if the strings overlap
-  //   but only if dest < src
-  static inline void strmove(char * dest, char * src) {
-    while (*src) 
-      *dest++ = *src++;
-    *dest = '\0';
-  }
-
-/*  phonetic transcription algorithm                   */
-/*  see: http://aspell.net/man-html/Phonetic-Code.html */
-/*  convert string to uppercase before this call       */
-int phonet (const char * inword, char * target,
-              int len,
-	      phonetable & parms)
-  {
-    /**       Do phonetic transformation.       **/
-    /**  "len" = length of "inword" incl. '\0'. **/
-
-    /**  result:  >= 0:  length of "target"    **/
-    /**            otherwise:  error            **/
-
-    int  i,j,k=0,n,p,z;
-    int  k0,n0,p0=-333,z0;
-    char c, c0;
-    const char * s;
-    typedef unsigned char uchar;    
-    char word[MAXPHONETUTF8LEN + 1];
-    if (len == -1) len = strlen(inword);
-    if (len > MAXPHONETUTF8LEN) return 0;
-    strcpy(word, inword);
-  
-    /**  check word  **/
-    i = j = z = 0;
-    while ((c = word[i]) != '\0') {
-      n = parms.hash[(uchar) c];
-      z0 = 0;
-
-      if (n >= 0) {
-        /**  check all rules for the same letter  **/
-        while (parms.rules[n][0] == c) {
-
-          /**  check whole string  **/
-          k = 1;   /** number of found letters  **/
-          p = 5;   /** default priority  **/
-          s = parms.rules[n];
-          s++;     /**  important for (see below)  "*(s-1)"  **/
-          
-          while (*s != '\0'  &&  word[i+k] == *s
-                 &&  !isdigit (*s)  &&  strchr ("(-<^$", *s) == NULL) {
-            k++;
-            s++;
-          }
-          if (*s == '(') {
-            /**  check letters in "(..)"  **/
-            if (isalpha(word[i+k])  // ...could be implied?
-                && strchr(s+1, word[i+k]) != NULL) {
-              k++;
-              while (*s != ')')
-                s++;
-              s++;
-            }
-          }
-          p0 = (int) *s;
-          k0 = k;
-          while (*s == '-'  &&  k > 1) {
-            k--;
-            s++;
-          }
-          if (*s == '<')
-            s++;
-          if (isdigit (*s)) {
-            /**  determine priority  **/
-            p = *s - '0';
-            s++;
-          }
-          if (*s == '^'  &&  *(s+1) == '^')
-            s++;
-
-          if (*s == '\0'
-              || (*s == '^'  
-                  && (i == 0  ||  ! isalpha(word[i-1]))
-                  && (*(s+1) != '$'
-                      || (! isalpha(word[i+k0]) )))
-              || (*s == '$'  &&  i > 0  
-                  &&  isalpha(word[i-1])
-                  && (! isalpha(word[i+k0]) ))) 
-          {
-            /**  search for followup rules, if:     **/
-            /**  parms.followup and k > 1  and  NO '-' in searchstring **/
-            c0 = word[i+k-1];
-            n0 = parms.hash[(uchar) c0];
-
-//            if (parms.followup  &&  k > 1  &&  n0 >= 0
-            if (k > 1  &&  n0 >= 0
-                &&  p0 != (int) '-'  &&  word[i+k] != '\0') {
-              /**  test follow-up rule for "word[i+k]"  **/
-              while (parms.rules[n0][0] == c0) {
-
-                /**  check whole string  **/
-                k0 = k;
-                p0 = 5;
-                s = parms.rules[n0];
-                s++;
-                while (*s != '\0'  &&  word[i+k0] == *s
-                       && ! isdigit(*s)  &&  strchr("(-<^$",*s) == NULL) {
-                  k0++;
-                  s++;
-                }
-                if (*s == '(') {
-                  /**  check letters  **/
-                  if (isalpha(word[i+k0])
-                      &&  strchr (s+1, word[i+k0]) != NULL) {
-                    k0++;
-                    while (*s != ')'  &&  *s != '\0')
-                      s++;
-                    if (*s == ')')
-                      s++;
-                  }
-                }
-                while (*s == '-') {
-                  /**  "k0" gets NOT reduced   **/
-                  /**  because "if (k0 == k)"  **/
-                  s++;
-                }
-                if (*s == '<')
-                  s++;
-                if (isdigit (*s)) {
-                  p0 = *s - '0';
-                  s++;
-                }
-
-                if (*s == '\0'
-                    /**  *s == '^' cuts  **/
-                    || (*s == '$'  &&  ! isalpha(word[i+k0]))) 
-                {
-                  if (k0 == k) {
-                    /**  this is just a piece of the string  **/
-                    n0 += 2;
-                    continue;
-                  }
-
-                  if (p0 < p) {
-                    /**  priority too low  **/
-                    n0 += 2;
-                    continue;
-                  }
-                  /**  rule fits; stop search  **/
-                  break;
-                }
-                n0 += 2;
-              } /**  End of "while (parms.rules[n0][0] == c0)"  **/
-
-              if (p0 >= p  && parms.rules[n0][0] == c0) {
-                n += 2;
-                continue;
-              }
-            } /** end of follow-up stuff **/
-
-            /**  replace string  **/
-            s = parms.rules[n+1];
-            p0 = (parms.rules[n][0] != '\0'
-                 &&  strchr (parms.rules[n]+1,'<') != NULL) ? 1:0;
-            if (p0 == 1 &&  z == 0) {
-              /**  rule with '<' is used  **/
-              if (j > 0  &&  *s != '\0'
-                 && (target[j-1] == c  ||  target[j-1] == *s)) {
-                j--;
-              }
-              z0 = 1;
-              z = 1;
-              k0 = 0;
-              while (*s != '\0'  &&  word[i+k0] != '\0') {
-                word[i+k0] = *s;
-                k0++;
-                s++;
-              }
-              if (k > k0)
-                strmove (&word[0]+i+k0, &word[0]+i+k);
-
-              /**  new "actual letter"  **/
-              c = word[i];
-            }
-            else { /** no '<' rule used **/
-              i += k - 1;
-              z = 0;
-              while (*s != '\0'
-                     &&  *(s+1) != '\0'  &&  j < len) {
-                if (j == 0  ||  target[j-1] != *s) {
-                  target[j] = *s;
-                  j++;
-                }
-                s++;
-              }
-              /**  new "actual letter"  **/
-              c = *s;
-              if (parms.rules[n][0] != '\0'
-                 &&  strstr (parms.rules[n]+1, "^^") != NULL) {
-                if (c != '\0') {
-                  target[j] = c;
-                  j++;
-                }
-                strmove (&word[0], &word[0]+i+1);
-                i = 0;
-                z0 = 1;
-              }
-            }
-            break;
-          }  /** end of follow-up stuff **/
-          n += 2;
-        } /**  end of while (parms.rules[n][0] == c)  **/
-      } /**  end of if (n >= 0)  **/
-      if (z0 == 0) {
-//        if (k && (assert(p0!=-333),!p0) &&  j < len &&  c != '\0'
-//           && (!parms.collapse_result  ||  j == 0  ||  target[j-1] != c)){
-        if (k && !p0 && j < len &&  c != '\0'
-           && (1 || j == 0  ||  target[j-1] != c)){
-           /**  condense only double letters  **/
-          target[j] = c;
-	  ///printf("\n setting \n");
-          j++;
-        }
-
-        i++;
-        z = 0;
-	k=0;
-      }
-    }  /**  end of   while ((c = word[i]) != '\0')  **/
-
-    target[j] = '\0';
-    return (j);
-
-  }  /**  end of function "phonet"  **/
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/phonet.hxx spellcheck/hunspell/src/phonet.hxx
--- spellcheck.old/hunspell/src/phonet.hxx	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/phonet.hxx	1970-01-01 01:00:00.000000000 +0100
@@ -1,66 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developer of the Original Code is Björn Jacke. Portions created
- * by the Initial Developers are Copyright (C) 2000-2007 the Initial
- * Developers. All Rights Reserved.
- * 
- * Contributor(s): Björn Jacke (bjoern.jacke@gmx.de)
- *                 László Németh (nemethl@gyorsposta.hu)
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * Changelog:
- *  2000-01-05  Björn Jacke <bjoern.jacke AT gmx.de>
- *              Initial Release insprired by the article about phonetic
- *              transformations out of c't 25/1999
- *
- *  2007-07-20  Björn Jacke <bjoern.jacke AT gmx.de>
- *              Released under MPL/GPL/LGPL tri-license for Hunspell
- *
- *  2007-08-22  László Németh <nemeth at OOo>
- *              Porting from Aspell to Hunspell by little modifications
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef __PHONETHXX__
-#define __PHONETHXX__
-
-#define MAXPHONETLEN      256
-#define MAXPHONETUTF8LEN  (MAXPHONETLEN * 4)
-
-struct phonetable {
-  char utf8;
-  cs_info * lang;
-  int num;
-  char * * rules;
-  static const int hash_size = 256;
-  int hash[hash_size];
-};
-
-void init_phonet_hash(phonetable & parms);
-
-int phonet (const char * inword, char * target,
-              int len, phonetable & phone);
-
-#endif
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/README.hunspell spellcheck/hunspell/src/README.hunspell
--- spellcheck.old/hunspell/src/README.hunspell	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/README.hunspell	1970-01-01 01:00:00.000000000 +0100
@@ -1,59 +0,0 @@
-******* BEGIN LICENSE BLOCK *******
-* Version: MPL 1.1/GPL 2.0/LGPL 2.1
-* 
-* The contents of this file are subject to the Mozilla Public License Version
-* 1.1 (the "License"); you may not use this file except in compliance with
-* the License. You may obtain a copy of the License at
-* http://www.mozilla.org/MPL/
-* 
-* Software distributed under the License is distributed on an "AS IS" basis,
-* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-* for the specific language governing rights and limitations under the
-* License.
-* 
-* The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
-* and László Németh (Hunspell). Portions created by the Initial Developers
-* are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
-* 
-* Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
-*                 David Einstein (deinst@world.std.com)
-*                 László Németh (nemethl@gyorsposta.hu)
-*                 Ryan VanderMeulen (ryanvm@gmail.com)
-* 
-* Alternatively, the contents of this file may be used under the terms of
-* either the GNU General Public License Version 2 or later (the "GPL"), or
-* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-* in which case the provisions of the GPL or the LGPL are applicable instead
-* of those above. If you wish to allow use of your version of this file only
-* under the terms of either the GPL or the LGPL, and not to allow others to
-* use your version of this file under the terms of the MPL, indicate your
-* decision by deleting the provisions above and replace them with the notice
-* and other provisions required by the GPL or the LGPL. If you do not delete
-* the provisions above, a recipient may use your version of this file under
-* the terms of any one of the MPL, the GPL or the LGPL.
-*
-******* END LICENSE BLOCK *******
-
-Hunspell Version: 1.1.12
-
-Hunspell Author: László Németh
-MySpell Author: Kevin Hendricks & David Einstein
-
-Hunspell is a spell checker and morphological analyser library. Hunspell
-is based on OpenOffice.org's Myspell. Documentation, tests, and examples
-are available at http://hunspell.sourceforge.net.
-
-A special thanks and credit goes to Geoff Kuenning, the creator of Ispell.
-MySpell's affix algorithms were based on those of Ispell, which should be
-noted is copyright Geoff Kuenning et al and now available under a BSD-style
-license. For more information on Ispell and affix compression in general,
-please see: http://lasr.cs.ucla.edu/geoff/ispell.html (Ispell homepage)
-
-An almost complete rewrite of MySpell for use by the Mozilla project was
-developed by David Einstein. David was a significant help in improving MySpell.
-
-Special thanks also goes to László Németh, who is the author of the Hungarian
-dictionary and who developed and contributed the code to support compound words
-in MySpell and fixed numerous problems with the encoding case conversion tables
-along with rewriting MySpell as Hunspell and ensuring compatibility with the
-Mozilla codebase.
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/suggestmgr.cpp spellcheck/hunspell/src/suggestmgr.cpp
--- spellcheck.old/hunspell/src/suggestmgr.cpp	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/suggestmgr.cpp	1970-01-01 01:00:00.000000000 +0100
@@ -1,2036 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef MOZILLA_CLIENT
-#include <cstdlib>
-#include <cstring>
-#include <cstdio>
-#include <cctype>
-#else
-#include <stdlib.h> 
-#include <string.h>
-#include <stdio.h> 
-#include <ctype.h>
-#endif
-
-#include "suggestmgr.hxx"
-
-#ifndef MOZILLA_CLIENT
-#ifndef W32
-using namespace std;
-#endif
-#endif
-
-const w_char W_VLINE = { '\0', '|' };
-
-SuggestMgr::SuggestMgr(const char * tryme, int maxn, 
-                       AffixMgr * aptr)
-{
-
-  // register affix manager and check in string of chars to 
-  // try when building candidate suggestions
-  pAMgr = aptr;
-
-  ckeyl = 0;
-  ckey = NULL;
-  ckey_utf = NULL;
-
-  ctryl = 0;
-  ctry = NULL;
-  ctry_utf = NULL;
-
-  utf8 = 0;
-  langnum = 0;
-  complexprefixes = 0;  
-  
-  maxSug = maxn;
-  nosplitsugs = 0;
-  maxngramsugs = MAXNGRAMSUGS;
-
-  if (pAMgr) {
-        char * enc = pAMgr->get_encoding();
-        csconv = get_current_cs(enc);
-        free(enc);
-        langnum = pAMgr->get_langnum();
-        ckey = pAMgr->get_key_string();
-        nosplitsugs = pAMgr->get_nosplitsugs();
-        if (pAMgr->get_maxngramsugs() >= 0) maxngramsugs = pAMgr->get_maxngramsugs();
-        utf8 = pAMgr->get_utf8();
-        complexprefixes = pAMgr->get_complexprefixes();
-  }
-
-  if (ckey) {  
-    if (utf8) {
-        w_char t[MAXSWL];    
-        ckeyl = u8_u16(t, MAXSWL, ckey);
-        ckey_utf = (w_char *) malloc(ckeyl * sizeof(w_char));
-        if (ckey_utf) memcpy(ckey_utf, t, ckeyl * sizeof(w_char));
-    } else {
-        ckeyl = strlen(ckey);
-    }
-  }
-  
-  if (tryme) {  
-    if (utf8) {
-        w_char t[MAXSWL];    
-        ctryl = u8_u16(t, MAXSWL, tryme);
-        ctry_utf = (w_char *) malloc(ctryl * sizeof(w_char));
-        if (ctry_utf) memcpy(ctry_utf, t, ctryl * sizeof(w_char));
-    } else {
-        ctry = mystrdup(tryme);
-        ctryl = strlen(ctry);
-    }
-  }
-}
-
-
-SuggestMgr::~SuggestMgr()
-{
-  pAMgr = NULL;
-  if (ckey) free(ckey);
-  ckey = NULL;
-  if (ckey_utf) free(ckey_utf);
-  ckey_utf = NULL;
-  ckeyl = 0;
-  if (ctry) free(ctry);
-  ctry = NULL;
-  if (ctry_utf) free(ctry_utf);
-  ctry_utf = NULL;
-  ctryl = 0;
-  maxSug = 0;
-}
-
-int SuggestMgr::testsug(char** wlst, const char * candidate, int wl, int ns, int cpdsuggest,
-   int * timer, clock_t * timelimit) {
-      int cwrd = 1;
-      if (ns == maxSug) return maxSug;
-      for (int k=0; k < ns; k++) {
-        if (strcmp(candidate,wlst[k]) == 0) cwrd = 0;
-      }
-      if ((cwrd) && checkword(candidate, wl, cpdsuggest, timer, timelimit)) {
-        wlst[ns] = mystrdup(candidate);
-        if (wlst[ns] == NULL) {
-            for (int j=0; j<ns; j++) free(wlst[j]);
-            return -1;
-        }
-        ns++;
-      } 
-      return ns;
-}
-
-// generate suggestions for a mispelled word
-//    pass in address of array of char * pointers
-// onlycompoundsug: probably bad suggestions (need for ngram sugs, too)
-
-int SuggestMgr::suggest(char*** slst, const char * w, int nsug,
-    int * onlycompoundsug)
-{
-  int nocompoundtwowords = 0;
-  char ** wlst;    
-  w_char word_utf[MAXSWL];
-  int wl = 0;
-
-  char w2[MAXWORDUTF8LEN];
-  const char * word = w;
-
-  // word reversing wrapper for complex prefixes
-  if (complexprefixes) {
-    strcpy(w2, w);
-    if (utf8) reverseword_utf(w2); else reverseword(w2);
-    word = w2;
-  }
-    
-    if (*slst) {
-        wlst = *slst;
-    } else {
-        wlst = (char **) malloc(maxSug * sizeof(char *));
-        if (wlst == NULL) return -1;
-        for (int i = 0; i < maxSug; i++) {
-            wlst[i] = NULL;
-        }
-    }
-    
-    if (utf8) {
-        wl = u8_u16(word_utf, MAXSWL, word);
-    }
-
-    for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) {
-
-    // suggestions for an uppercase word (html -> HTML)
-    if ((nsug < maxSug) && (nsug > -1)) {
-        nsug = (utf8) ? capchars_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
-                    capchars(wlst, word, nsug, cpdsuggest);
-    }
-
-    // perhaps we made a typical fault of spelling
-    if ((nsug < maxSug) && (nsug > -1))
-    nsug = replchars(wlst, word, nsug, cpdsuggest);
-
-    // perhaps we made chose the wrong char from a related set
-    if ((nsug < maxSug) && (nsug > -1)) {
-      nsug = mapchars(wlst, word, nsug, cpdsuggest);
-    }
-
-    // did we swap the order of chars by mistake
-    if ((nsug < maxSug) && (nsug > -1)) {
-        nsug = (utf8) ? swapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
-                    swapchar(wlst, word, nsug, cpdsuggest);
-    }
-
-    // did we swap the order of non adjacent chars by mistake
-    if ((nsug < maxSug) && (nsug > -1)) {
-        nsug = (utf8) ? longswapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
-                    longswapchar(wlst, word, nsug, cpdsuggest);
-    }
-
-    // did we just hit the wrong key in place of a good char (case and keyboard)
-    if ((nsug < maxSug) && (nsug > -1)) {
-        nsug = (utf8) ? badcharkey_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
-                    badcharkey(wlst, word, nsug, cpdsuggest);
-    }
-
-    // did we add a char that should not be there
-    if ((nsug < maxSug) && (nsug > -1)) {
-        nsug = (utf8) ? extrachar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
-                    extrachar(wlst, word, nsug, cpdsuggest);
-    }
-
-    // only suggest compound words when no other suggestion
-    if ((cpdsuggest == 0) && (nsug > 0)) nocompoundtwowords=1;
-
-    // did we forgot a char
-    if ((nsug < maxSug) && (nsug > -1)) {
-        nsug = (utf8) ? forgotchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
-                    forgotchar(wlst, word, nsug, cpdsuggest);
-    }
-
-    // did we move a char
-    if ((nsug < maxSug) && (nsug > -1)) {
-        nsug = (utf8) ? movechar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
-                    movechar(wlst, word, nsug, cpdsuggest);
-    }
-
-    // did we just hit the wrong key in place of a good char
-    if ((nsug < maxSug) && (nsug > -1)) {
-        nsug = (utf8) ? badchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
-                    badchar(wlst, word, nsug, cpdsuggest);
-    }
-
-    // did we double two characters
-    if ((nsug < maxSug) && (nsug > -1)) {
-        nsug = (utf8) ? doubletwochars_utf(wlst, word_utf, wl, nsug, cpdsuggest) :
-                    doubletwochars(wlst, word, nsug, cpdsuggest);
-    }
-
-    // perhaps we forgot to hit space and two words ran together
-    if ((!nosplitsugs) && (nsug < maxSug) && (nsug > -1)) {
-                nsug = twowords(wlst, word, nsug, cpdsuggest);
-        }
-
-    } // repeating ``for'' statement compounding support
-
-    if (nsug < 0) {
-     // we ran out of memory - we should free up as much as possible
-       for (int i = 0; i < maxSug; i++)
-         if (wlst[i] != NULL) free(wlst[i]);
-       free(wlst);
-       wlst = NULL;
-    }
-    
-    if (!nocompoundtwowords && (nsug > 0) && onlycompoundsug) *onlycompoundsug = 1;
-
-    *slst = wlst;
-    return nsug;
-}
-
-// generate suggestions for a word with typical mistake
-//    pass in address of array of char * pointers
-#ifdef HUNSPELL_EXPERIMENTAL
-int SuggestMgr::suggest_auto(char*** slst, const char * w, int nsug)
-{
-    int nocompoundtwowords = 0;
-    char ** wlst;
-
-  char w2[MAXWORDUTF8LEN];
-  const char * word = w;
-
-  // word reversing wrapper for complex prefixes
-  if (complexprefixes) {
-    strcpy(w2, w);
-    if (utf8) reverseword_utf(w2); else reverseword(w2);
-    word = w2;
-  }
-
-    if (*slst) {
-        wlst = *slst;
-    } else {
-        wlst = (char **) malloc(maxSug * sizeof(char *));
-        if (wlst == NULL) return -1;
-    }
-
-    for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) {
-
-    // perhaps we made a typical fault of spelling
-    if ((nsug < maxSug) && (nsug > -1))
-    nsug = replchars(wlst, word, nsug, cpdsuggest);
-
-    // perhaps we made chose the wrong char from a related set
-    if ((nsug < maxSug) && (nsug > -1))
-      nsug = mapchars(wlst, word, nsug, cpdsuggest);
-
-    if ((cpdsuggest==0) && (nsug>0)) nocompoundtwowords=1; else *
-
-    // perhaps we forgot to hit space and two words ran together
-
-    if ((nsug < maxSug) && (nsug > -1) && check_forbidden(word, strlen(word))) {
-                nsug = twowords(wlst, word, nsug, cpdsuggest);
-        }
-    
-    } // repeating ``for'' statement compounding support
-
-    if (nsug < 0) {
-       for (int i=0;i<maxSug; i++)
-         if (wlst[i] != NULL) free(wlst[i]);
-       free(wlst);
-       return -1;
-    }
-
-    *slst = wlst;
-    return nsug;
-}
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
-// suggestions for an uppercase word (html -> HTML)
-int SuggestMgr::capchars_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
-{
-  char candidate[MAXSWUTF8L];
-  w_char candidate_utf[MAXSWL];
-  memcpy(candidate_utf, word, wl * sizeof(w_char));
-  mkallcap_utf(candidate_utf, wl, langnum);
-  u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
-  return testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
-}
-
-// suggestions for an uppercase word (html -> HTML)
-int SuggestMgr::capchars(char** wlst, const char * word, int ns, int cpdsuggest)
-{
-  char candidate[MAXSWUTF8L];
-  strcpy(candidate, word);
-  mkallcap(candidate, csconv);
-  return testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
-}
-
-// suggestions for when chose the wrong char out of a related set
-int SuggestMgr::mapchars(char** wlst, const char * word, int ns, int cpdsuggest)
-{
-  clock_t timelimit;
-  int timer;
-  
-  int wl = strlen(word);
-  if (wl < 2 || ! pAMgr) return ns;
-
-  int nummap = pAMgr->get_nummap();
-  struct mapentry* maptable = pAMgr->get_maptable();
-  if (maptable==NULL) return ns;
-
-  timelimit = clock();
-  timer = MINTIMER;
-  if (utf8) {
-    w_char w[MAXSWL];
-    int len = u8_u16(w, MAXSWL, word);
-    ns = map_related_utf(w, len, 0, cpdsuggest, wlst, ns, maptable, nummap, &timer, &timelimit);
-  } else ns = map_related(word, 0, wlst, cpdsuggest, ns, maptable, nummap, &timer, &timelimit);
-  return ns;
-}
-
-int SuggestMgr::map_related(const char * word, int i, char** wlst, 
-    int cpdsuggest,  int ns,
-    const mapentry* maptable, int nummap, int * timer, clock_t * timelimit)
-{
-  char c = *(word + i);  
-  if (c == 0) {
-      int cwrd = 1;
-      int wl = strlen(word);
-      for (int m=0; m < ns; m++)
-          if (strcmp(word,wlst[m]) == 0) cwrd = 0;
-      if ((cwrd) && checkword(word, wl, cpdsuggest, timer, timelimit)) {
-          if (ns < maxSug) {
-              wlst[ns] = mystrdup(word);
-              if (wlst[ns] == NULL) return -1;
-              ns++;
-          }
-      }
-      return ns;
-  } 
-  int in_map = 0;
-  for (int j = 0; j < nummap; j++) {
-    if (strchr(maptable[j].set,c) != 0) {
-      in_map = 1;
-      char * newword = mystrdup(word);
-      for (int k = 0; k < maptable[j].len; k++) {
-        *(newword + i) = *(maptable[j].set + k);
-        ns = map_related(newword, (i+1), wlst, cpdsuggest,
-           ns, maptable, nummap, timer, timelimit);
-        if (!(*timer)) return ns;
-      }
-      free(newword);
-    }
-  }
-  if (!in_map) {
-     i++;
-     ns = map_related(word, i, wlst, cpdsuggest,
-        ns, maptable, nummap, timer, timelimit);
-  }
-  return ns;
-}
-
-int SuggestMgr::map_related_utf(w_char * word, int len, int i, int cpdsuggest,
-    char** wlst, int ns, const mapentry* maptable, int nummap,
-    int * timer, clock_t * timelimit) 
-{
-  if (i == len) {
-      int cwrd = 1;
-      int wl;
-      char s[MAXSWUTF8L];
-      u16_u8(s, MAXSWUTF8L, word, len);
-      wl = strlen(s);
-      for (int m=0; m < ns; m++)
-          if (strcmp(s,wlst[m]) == 0) cwrd = 0;
-      if ((cwrd) && checkword(s, wl, cpdsuggest, timer, timelimit)) {
-          if (ns < maxSug) {
-              wlst[ns] = mystrdup(s);
-              if (wlst[ns] == NULL) return -1;
-              ns++;
-          }
-      }
-      return ns;
-  } 
-  int in_map = 0;
-  unsigned short c = *((unsigned short *) word + i);
-  for (int j = 0; j < nummap; j++) {
-    if (flag_bsearch((unsigned short *) maptable[j].set_utf16, c, maptable[j].len)) {
-      in_map = 1;
-      for (int k = 0; k < maptable[j].len; k++) {
-        *(word + i) = *(maptable[j].set_utf16 + k);
-        ns = map_related_utf(word, len, i + 1, cpdsuggest,
-           wlst, ns, maptable, nummap, timer, timelimit);
-        if (!(*timer)) return ns;
-      }
-      *((unsigned short *) word + i) = c;
-    }
-  }
-  if (!in_map) {
-     i++;
-     ns = map_related_utf(word, len, i, cpdsuggest,
-          wlst, ns, maptable, nummap, timer, timelimit);
-  }
-  return ns;
-}
-
-
-
-// suggestions for a typical fault of spelling, that
-// differs with more, than 1 letter from the right form.
-int SuggestMgr::replchars(char** wlst, const char * word, int ns, int cpdsuggest)
-{
-  char candidate[MAXSWUTF8L];
-  const char * r;
-  int lenr, lenp;
-  int wl = strlen(word);
-  if (wl < 2 || ! pAMgr) return ns;
-  int numrep = pAMgr->get_numrep();
-  struct replentry* reptable = pAMgr->get_reptable();
-  if (reptable==NULL) return ns;
-  for (int i=0; i < numrep; i++ ) {
-      r = word;
-      lenr = strlen(reptable[i].pattern2);
-      lenp = strlen(reptable[i].pattern);
-      // search every occurence of the pattern in the word
-      while ((r=strstr(r, reptable[i].pattern)) != NULL) {
-          strcpy(candidate, word);
-          if (r-word + lenr + strlen(r+lenp) >= MAXSWUTF8L) break;
-          strcpy(candidate+(r-word),reptable[i].pattern2);
-          strcpy(candidate+(r-word)+lenr, r+lenp);
-          ns = testsug(wlst, candidate, wl-lenp+lenr, ns, cpdsuggest, NULL, NULL);
-          if (ns == -1) return -1;
-          // check REP suggestions with space
-          char * sp = strchr(candidate, ' ');
-          if (sp) {
-            *sp = '\0';
-            if (checkword(candidate, strlen(candidate), 0, NULL, NULL)) {
-              int oldns = ns;
-              *sp = ' ';
-              ns = testsug(wlst, sp + 1, strlen(sp + 1), ns, cpdsuggest, NULL, NULL);
-              if (ns == -1) return -1;
-              if (oldns < ns) {
-                free(wlst[ns - 1]);
-                wlst[ns - 1] = mystrdup(candidate);
-              }
-            }            
-            *sp = ' ';
-          }
-          r++; // search for the next letter
-      }
-   }
-   return ns;
-}
-
-// perhaps we doubled two characters (pattern aba -> ababa, for example vacation -> vacacation)
-int SuggestMgr::doubletwochars(char** wlst, const char * word, int ns, int cpdsuggest)
-{
-  char candidate[MAXSWUTF8L];
-  int state=0;
-  int wl = strlen(word);
-  if (wl < 5 || ! pAMgr) return ns;
-  for (int i=2; i < wl; i++ ) {
-      if (word[i]==word[i-2]) {
-          state++;
-          if (state==3) {
-            strcpy(candidate,word);
-            strcpy(candidate+i-1,word+i+1);
-            ns = testsug(wlst, candidate, wl-2, ns, cpdsuggest, NULL, NULL);
-            if (ns == -1) return -1;
-            state=0;
-          }
-      } else {
-            state=0;
-      }
-  }
-  return ns;
-}
-
-// perhaps we doubled two characters (pattern aba -> ababa, for example vacation -> vacacation)
-int SuggestMgr::doubletwochars_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
-{
-  w_char        candidate_utf[MAXSWL];
-  char          candidate[MAXSWUTF8L];
-  int state=0;
-  if (wl < 5 || ! pAMgr) return ns;
-  for (int i=2; i < wl; i++) {
-      if (w_char_eq(word[i], word[i-2]))  {
-          state++;
-          if (state==3) {
-            memcpy(candidate_utf, word, (i - 1) * sizeof(w_char));
-            memcpy(candidate_utf+i-1, word+i+1, (wl-i-1) * sizeof(w_char));
-            u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl-2);
-            ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
-            if (ns == -1) return -1;
-            state=0;
-          }
-      } else {
-            state=0;
-      }
-  }
-  return ns;
-}
-
-// error is wrong char in place of correct one (case and keyboard related version)
-int SuggestMgr::badcharkey(char ** wlst, const char * word, int ns, int cpdsuggest)
-{
-  char  tmpc;
-  char  candidate[MAXSWUTF8L];
-  int wl = strlen(word);
-  strcpy(candidate, word);
-  // swap out each char one by one and try uppercase and neighbor
-  // keyboard chars in its place to see if that makes a good word
-
-  for (int i=0; i < wl; i++) {
-    tmpc = candidate[i];
-    // check with uppercase letters
-    candidate[i] = csconv[((unsigned char)tmpc)].cupper;
-    if (tmpc != candidate[i]) {
-       ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
-       if (ns == -1) return -1;
-       candidate[i] = tmpc;
-    }
-    // check neighbor characters in keyboard string
-    if (!ckey) continue;
-    char * loc = strchr(ckey, tmpc);
-    while (loc) {
-       if ((loc > ckey) && (*(loc - 1) != '|')) {
-          candidate[i] = *(loc - 1);
-          ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
-          if (ns == -1) return -1;
-       }
-       if ((*(loc + 1) != '|') && (*(loc + 1) != '\0')) {
-          candidate[i] = *(loc + 1);
-          ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
-          if (ns == -1) return -1;
-       }
-       loc = strchr(loc + 1, tmpc);
-    }
-    candidate[i] = tmpc;    
-  }
-  return ns;
-}
-
-// error is wrong char in place of correct one (case and keyboard related version)
-int SuggestMgr::badcharkey_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
-{
-  w_char        tmpc;
-  w_char        candidate_utf[MAXSWL];
-  char          candidate[MAXSWUTF8L];
-  memcpy(candidate_utf, word, wl * sizeof(w_char));
-  // swap out each char one by one and try all the tryme
-  // chars in its place to see if that makes a good word
-  for (int i=0; i < wl; i++) {
-    tmpc = candidate_utf[i];
-    // check with uppercase letters
-    mkallcap_utf(candidate_utf + i, 1, langnum);
-    if (!w_char_eq(tmpc, candidate_utf[i])) {
-       u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
-       ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
-       if (ns == -1) return -1;
-       candidate_utf[i] = tmpc;
-    }
-    // check neighbor characters in keyboard string
-    if (!ckey) continue;
-    w_char * loc = ckey_utf;
-    while ((loc < (ckey_utf + ckeyl)) && !w_char_eq(*loc, tmpc)) loc++;
-    while (loc < (ckey_utf + ckeyl)) {
-       if ((loc > ckey_utf) && !w_char_eq(*(loc - 1), W_VLINE)) {
-          candidate_utf[i] = *(loc - 1);
-          u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
-          ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
-          if (ns == -1) return -1;
-       }
-       if (((loc + 1) < (ckey_utf + ckeyl)) && !w_char_eq(*(loc + 1), W_VLINE)) {
-          candidate_utf[i] = *(loc + 1);
-          u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
-          ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
-          if (ns == -1) return -1;
-       }
-       do { loc++; } while ((loc < (ckey_utf + ckeyl)) && !w_char_eq(*loc, tmpc));
-    }
-    candidate_utf[i] = tmpc;    
-  }
-  return ns;
-}
-
-// error is wrong char in place of correct one
-int SuggestMgr::badchar(char ** wlst, const char * word, int ns, int cpdsuggest)
-{
-  char  tmpc;
-  char  candidate[MAXSWUTF8L];
-  clock_t timelimit = clock();
-  int timer = MINTIMER;
-  int wl = strlen(word);
-  strcpy(candidate, word);
-  // swap out each char one by one and try all the tryme
-  // chars in its place to see if that makes a good word
-  for (int i=0; i < wl; i++) {
-    tmpc = candidate[i];
-    for (int j=0; j < ctryl; j++) {
-       if (ctry[j] == tmpc) continue;
-       candidate[i] = ctry[j];
-       ns = testsug(wlst, candidate, wl, ns, cpdsuggest, &timer, &timelimit);
-       if (ns == -1) return -1;
-       if (!timer) return ns;
-       candidate[i] = tmpc;
-    }
-  }
-  return ns;
-}
-
-// error is wrong char in place of correct one
-int SuggestMgr::badchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
-{
-  w_char        tmpc;
-  w_char        candidate_utf[MAXSWL];
-  char          candidate[MAXSWUTF8L];
-  clock_t timelimit = clock();
-  int timer = MINTIMER;  
-  memcpy(candidate_utf, word, wl * sizeof(w_char));
-  // swap out each char one by one and try all the tryme
-  // chars in its place to see if that makes a good word
-  for (int i=0; i < wl; i++) {
-    tmpc = candidate_utf[i];
-    for (int j=0; j < ctryl; j++) {
-       if (w_char_eq(tmpc, ctry_utf[j])) continue;
-       candidate_utf[i] = ctry_utf[j];
-       u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
-       ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, &timer, &timelimit);
-       if (ns == -1) return -1;
-       if (!timer) return ns;
-       candidate_utf[i] = tmpc;
-    }
-  }
-  return ns;
-}
-
-// error is word has an extra letter it does not need 
-int SuggestMgr::extrachar_utf(char** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
-{
-   char candidate[MAXSWUTF8L];
-   w_char candidate_utf[MAXSWL];
-   const w_char * p;
-   w_char * r;
-   if (wl < 2) return ns;
-   // try omitting one char of word at a time
-   memcpy(candidate_utf, word + 1, (wl - 1) * sizeof(w_char));
-   for (p = word, r = candidate_utf;  p < word + wl;  ) {
-       u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl - 1);       
-       ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
-       if (ns == -1) return -1;
-       *r++ = *p++;
-   }
-   return ns;
-}
-
-// error is word has an extra letter it does not need 
-int SuggestMgr::extrachar(char** wlst, const char * word, int ns, int cpdsuggest)
-{
-   char    candidate[MAXSWUTF8L];
-   const char *  p;
-   char *  r;
-   int wl = strlen(word);
-   if (wl < 2) return ns;
-   // try omitting one char of word at a time
-   strcpy (candidate, word + 1);
-   for (p = word, r = candidate;  *p != 0;  ) {
-      ns = testsug(wlst, candidate, wl-1, ns, cpdsuggest, NULL, NULL);
-      if (ns == -1) return -1;
-      *r++ = *p++;
-   }
-   return ns;
-}
-
-
-// error is missing a letter it needs
-int SuggestMgr::forgotchar(char ** wlst, const char * word, int ns, int cpdsuggest)
-{
-   char candidate[MAXSWUTF8L];
-   const char * p;
-   char *       q;
-   clock_t timelimit = clock();
-   int timer = MINTIMER;
-   int wl = strlen(word);
-   // try inserting a tryme character before every letter
-   strcpy(candidate + 1, word);
-   for (p = word, q = candidate;  *p != 0;  )  {
-      for (int i = 0;  i < ctryl;  i++) {
-         *q = ctry[i];
-         ns = testsug(wlst, candidate, wl+1, ns, cpdsuggest, &timer, &timelimit);
-         if (ns == -1) return -1;
-         if (!timer) return ns;
-      }
-      *q++ = *p++;
-   }
-   // now try adding one to end */
-   for (int i = 0;  i < ctryl;  i++) {
-      *q = ctry[i];
-      ns = testsug(wlst, candidate, wl+1, ns, cpdsuggest, NULL, NULL);
-      if (ns == -1) return -1;
-   }
-   return ns;
-}
-
-// error is missing a letter it needs
-int SuggestMgr::forgotchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
-{
-   w_char  candidate_utf[MAXSWL];
-   char    candidate[MAXSWUTF8L];
-   const w_char * p;
-   w_char * q;
-   int cwrd;
-   clock_t timelimit = clock();
-   int timer = MINTIMER;
-   // try inserting a tryme character before every letter
-   memcpy (candidate_utf + 1, word, wl * sizeof(w_char));
-   for (p = word, q = candidate_utf;  p < (word + wl); )  {
-      for (int i = 0;  i < ctryl;  i++) {
-         *q = ctry_utf[i];
-         cwrd = 1;
-         u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl + 1);
-         ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, &timer, &timelimit);
-         if (ns == -1) return -1;
-         if (!timer) return ns;
-       }
-      *q++ = *p++;
-   }
-   // now try adding one to end */
-   for (int i = 0;  i < ctryl;  i++) {
-      *q = ctry_utf[i];
-      cwrd = 1;
-      u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl + 1);
-      ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
-      if (ns == -1) return -1;
-   }
-   return ns;
-}
-
-
-/* error is should have been two words */
-int SuggestMgr::twowords(char ** wlst, const char * word, int ns, int cpdsuggest)
-{
-    char candidate[MAXSWUTF8L];
-    char * p;
-    int c1, c2;
-    int forbidden = 0;
-    int cwrd;
-
-    int wl=strlen(word);
-    if (wl < 3) return ns;
-    
-    if (langnum == LANG_hu) forbidden = check_forbidden(word, wl);
-
-    strcpy(candidate + 1, word);
-    // split the string into two pieces after every char
-    // if both pieces are good words make them a suggestion
-    for (p = candidate + 1;  p[1] != '\0';  p++) {
-       p[-1] = *p;
-       // go to end of the UTF-8 character
-       while (utf8 && ((p[1] & 0xc0) == 0x80)) {
-         *p = p[1];
-         p++;
-       }
-       if (utf8 && p[1] == '\0') break; // last UTF-8 character
-       *p = '\0';
-       c1 = checkword(candidate,strlen(candidate), cpdsuggest, NULL, NULL);
-       if (c1) {
-         c2 = checkword((p+1),strlen(p+1), cpdsuggest, NULL, NULL);
-         if (c2) {
-            *p = ' ';
-
-            // spec. Hungarian code (need a better compound word support)
-            if ((langnum == LANG_hu) && !forbidden &&
-                // if 3 repeating letter, use - instead of space
-                (((p[-1] == p[1]) && (((p>candidate+1) && (p[-1] == p[-2])) || (p[-1] == p[2]))) ||
-                // or multiple compounding, with more, than 6 syllables
-                ((c1 == 3) && (c2 >= 2)))) *p = '-';
-
-            cwrd = 1;
-            for (int k=0; k < ns; k++)
-                if (strcmp(candidate,wlst[k]) == 0) cwrd = 0;
-            if (ns < maxSug) {
-                if (cwrd) {
-                    wlst[ns] = mystrdup(candidate);
-                    if (wlst[ns] == NULL) return -1;
-                    ns++;
-                }
-            } else return ns;
-         }
-       }
-    }
-    return ns;
-}
-
-
-// error is adjacent letter were swapped
-int SuggestMgr::swapchar(char ** wlst, const char * word, int ns, int cpdsuggest)
-{
-   char candidate[MAXSWUTF8L];
-   char * p;
-   char tmpc;
-   int wl=strlen(word);
-   // try swapping adjacent chars one by one
-   strcpy(candidate, word);
-   for (p = candidate;  p[1] != 0;  p++) {
-      tmpc = *p;
-      *p = p[1];
-      p[1] = tmpc;
-      ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
-      if (ns == -1) return -1;
-      p[1] = *p;
-      *p = tmpc;
-   }
-   // try double swaps for short words
-   // ahev -> have, owudl -> would
-   if (wl == 4 || wl == 5) {
-     candidate[0] = word[1];
-     candidate[1] = word[0];
-     candidate[2] = word[2];
-     candidate[wl - 2] = word[wl - 1];
-     candidate[wl - 1] = word[wl - 2];
-     ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
-     if (ns == -1) return -1;
-     if (wl == 5) {
-        candidate[0] = word[0];
-        candidate[1] = word[2];
-        candidate[2] = word[1];
-        ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
-        if (ns == -1) return -1;
-     }
-   }
-   return ns;
-}
-
-// error is adjacent letter were swapped
-int SuggestMgr::swapchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
-{
-   w_char candidate_utf[MAXSWL];
-   char   candidate[MAXSWUTF8L];
-   w_char * p;
-   w_char tmpc;
-   int len = 0;
-   // try swapping adjacent chars one by one
-   memcpy (candidate_utf, word, wl * sizeof(w_char));
-   for (p = candidate_utf;  p < (candidate_utf + wl - 1);  p++) {
-      tmpc = *p;
-      *p = p[1];
-      p[1] = tmpc;
-      u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
-      if (len == 0) len = strlen(candidate);
-      ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL);
-      if (ns == -1) return -1;
-      p[1] = *p;
-      *p = tmpc;
-   }
-   // try double swaps for short words
-   // ahev -> have, owudl -> would, suodn -> sound
-   if (wl == 4 || wl == 5) {
-     candidate_utf[0] = word[1];
-     candidate_utf[1] = word[0];
-     candidate_utf[2] = word[2];
-     candidate_utf[wl - 2] = word[wl - 1];
-     candidate_utf[wl - 1] = word[wl - 2];
-     u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
-     ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL);
-     if (ns == -1) return -1;
-     if (wl == 5) {
-        candidate_utf[0] = word[0];
-        candidate_utf[1] = word[2];
-        candidate_utf[2] = word[1];
-        u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
-	ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL);
-        if (ns == -1) return -1;
-     }
-   }
-   return ns;
-}
-
-// error is not adjacent letter were swapped
-int SuggestMgr::longswapchar(char ** wlst, const char * word, int ns, int cpdsuggest)
-{
-   char candidate[MAXSWUTF8L];
-   char * p;
-   char * q;
-   char tmpc;
-   int wl=strlen(word);
-   // try swapping not adjacent chars one by one
-   strcpy(candidate, word);
-   for (p = candidate;  *p != 0;  p++) {
-    for (q = candidate;  *q != 0;  q++) {
-     if (abs(p-q) > 1) {
-      tmpc = *p;
-      *p = *q;
-      *q = tmpc;
-      ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
-      if (ns == -1) return -1;
-      *q = *p;
-      *p = tmpc;
-     }
-    }
-   }
-   return ns;
-}
-
-
-// error is adjacent letter were swapped
-int SuggestMgr::longswapchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
-{
-   w_char candidate_utf[MAXSWL];
-   char   candidate[MAXSWUTF8L];
-   w_char * p;
-   w_char * q;
-   w_char tmpc;
-   // try swapping not adjacent chars
-   memcpy (candidate_utf, word, wl * sizeof(w_char));
-   for (p = candidate_utf;  p < (candidate_utf + wl);  p++) {
-     for (q = candidate_utf;  q < (candidate_utf + wl);  q++) {
-       if (abs(p-q) > 1) {
-         tmpc = *p;
-         *p = *q;
-         *q = tmpc;
-         u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
-         ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
-         if (ns == -1) return -1;
-         *q = *p;
-         *p = tmpc;
-       }
-     }
-   }
-   return ns;
-}
-
-// error is a letter was moved
-int SuggestMgr::movechar(char ** wlst, const char * word, int ns, int cpdsuggest)
-{
-   char candidate[MAXSWUTF8L];
-   char * p;
-   char * q;
-   char tmpc;
-
-   int wl=strlen(word);
-   // try moving a char
-   strcpy(candidate, word);
-   for (p = candidate;  *p != 0;  p++) {
-     for (q = p + 1;  (*q != 0) && ((q - p) < 10);  q++) {
-      tmpc = *(q-1);
-      *(q-1) = *q;
-      *q = tmpc;
-      if ((q-p) < 2) continue; // omit swap char
-      ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
-      if (ns == -1) return -1;
-    }
-    strcpy(candidate, word);
-   }
-   for (p = candidate + wl - 1;  p > candidate;  p--) {
-     for (q = p - 1;  (q >= candidate) && ((p - q) < 10);  q--) {
-      tmpc = *(q+1);
-      *(q+1) = *q;
-      *q = tmpc;
-      if ((p-q) < 2) continue; // omit swap char
-      ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL);
-      if (ns == -1) return -1;
-    }
-    strcpy(candidate, word);
-   }   
-   return ns;
-}
-
-// error is a letter was moved
-int SuggestMgr::movechar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest)
-{
-   w_char candidate_utf[MAXSWL];
-   char   candidate[MAXSWUTF8L];
-   w_char * p;
-   w_char * q;
-   w_char tmpc;
-   // try moving a char
-   memcpy (candidate_utf, word, wl * sizeof(w_char));
-   for (p = candidate_utf;  p < (candidate_utf + wl);  p++) {
-     for (q = p + 1;  (q < (candidate_utf + wl)) && ((q - p) < 10);  q++) {
-         tmpc = *(q-1);
-         *(q-1) = *q;
-         *q = tmpc;
-         if ((q-p) < 2) continue; // omit swap char
-         u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
-         ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
-         if (ns == -1) return -1;
-     }
-     memcpy (candidate_utf, word, wl * sizeof(w_char));
-   }
-   for (p = candidate_utf + wl - 1;  p > candidate_utf;  p--) {
-     for (q = p - 1;  (q >= candidate_utf) && ((p - q) < 10);  q--) {
-         tmpc = *(q+1);
-         *(q+1) = *q;
-         *q = tmpc;
-         if ((p-q) < 2) continue; // omit swap char
-         u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl);
-         ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL);
-         if (ns == -1) return -1;
-     }
-     memcpy (candidate_utf, word, wl * sizeof(w_char));
-   }
-   return ns;   
-}
-
-// generate a set of suggestions for very poorly spelled words
-int SuggestMgr::ngsuggest(char** wlst, char * w, int ns, HashMgr* pHMgr)
-{
-
-  int i, j;
-  int lval;
-  int sc, scphon;
-  int lp, lpphon;
-  int nonbmp = 0;
-
-  if (!pHMgr) return ns;
-
-  // exhaustively search through all root words
-  // keeping track of the MAX_ROOTS most similar root words
-  struct hentry * roots[MAX_ROOTS];
-  char * rootsphon[MAX_ROOTS];
-  int scores[MAX_ROOTS];
-  int scoresphon[MAX_ROOTS];
-  for (i = 0; i < MAX_ROOTS; i++) {
-    roots[i] = NULL;
-    scores[i] = -100 * i;
-    rootsphon[i] = NULL;
-    scoresphon[i] = -100 * i;
-  }
-  lp = MAX_ROOTS - 1;
-  lpphon = MAX_ROOTS - 1;
-  scphon = scoresphon[MAX_ROOTS-1];
-  
-  char w2[MAXWORDUTF8LEN];
-  char * word = w;
-
-  // word reversing wrapper for complex prefixes
-  if (complexprefixes) {
-    strcpy(w2, w);
-    if (utf8) reverseword_utf(w2); else reverseword(w2);
-    word = w2;
-  }
-
-  char mw[MAXSWUTF8L];
-  w_char u8[MAXSWL];
-  int nc = strlen(word);
-  int n = (utf8) ? u8_u16(u8, MAXSWL, word) : nc;
-  
-  // set character based ngram suggestion for words with non-BMP Unicode characters
-  if (n == -1) {
-    utf8 = 0;
-    n = nc;
-    nonbmp = 1;
-  }
-
-  struct hentry* hp = NULL;
-  int col = -1;
-  phonetable * ph = (pAMgr) ? pAMgr->get_phonetable() : NULL;
-  char target[MAXSWUTF8L];
-  char candidate[MAXSWUTF8L];
-  if (ph) {
-    strcpy(candidate, word);
-    mkallcap(candidate, csconv);
-    phonet(candidate, target, n, *ph);
-//    fprintf(stderr, "Tip: %s->%s\n", candidate, target);
-  }
-  
-  while ((hp = pHMgr->walk_hashtable(col, hp))) {
-    if ((hp->astr) && (pAMgr) && 
-       (TESTAFF(hp->astr, pAMgr->get_forbiddenword(), hp->alen) ||
-          TESTAFF(hp->astr, ONLYUPCASEFLAG, hp->alen) ||
-          TESTAFF(hp->astr, pAMgr->get_nosuggest(), hp->alen) ||
-          TESTAFF(hp->astr, pAMgr->get_onlyincompound(), hp->alen))) continue;
-
-    sc = ngram(3, word, &(hp->word), NGRAM_LONGER_WORSE + NGRAM_LOWERING) +
-	leftcommonsubstring(word, &(hp->word));
-
-    // check special pronounciation
-    if (hp->var) {
-	int sc2 = ngram(3, word, &(hp->word) + hp->blen + 1, NGRAM_LONGER_WORSE + NGRAM_LOWERING) +
-	leftcommonsubstring(word, &(hp->word) + hp->blen + 1);
-	if (sc2 > sc) sc = sc2;
-    }
-    
-    if (ph && (sc > 2) && (abs(n - (int) hp->clen) <= 3)) {
-	char target2[MAXSWUTF8L];
-        strcpy(candidate, &(hp->word));
-        mkallcap(candidate, csconv);
-        phonet(candidate, target2, -1, *ph);
-        scphon = 2 * ngram(3, target, target2, NGRAM_LONGER_WORSE);
-    }
-
-    if (sc > scores[lp]) {
-      scores[lp] = sc;  
-      roots[lp] = hp;
-      lval = sc;
-      for (j=0; j < MAX_ROOTS; j++)
-        if (scores[j] < lval) {
-          lp = j;
-          lval = scores[j];
-        }
-    }
-
-    if (scphon > scoresphon[lpphon]) {
-      scoresphon[lpphon] = scphon;
-      rootsphon[lpphon] = &(hp->word);
-      lval = scphon;
-      for (j=0; j < MAX_ROOTS; j++)
-        if (scoresphon[j] < lval) {
-          lpphon = j;
-          lval = scoresphon[j];
-        }
-    }
-  }
-
-  // find minimum threshhold for a passable suggestion
-  // mangle original word three differnt ways
-  // and score them to generate a minimum acceptable score
-  int thresh = 0;
-  for (int sp = 1; sp < 4; sp++) {
-     if (utf8) {
-       for (int k=sp; k < n; k+=4) *((unsigned short *) u8 + k) = '*';
-       u16_u8(mw, MAXSWUTF8L, u8, n);
-       thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + NGRAM_LOWERING);
-     } else {
-       strcpy(mw, word);
-       for (int k=sp; k < n; k+=4) *(mw + k) = '*';
-       thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + NGRAM_LOWERING);
-     }
-  }
-  thresh = thresh / 3;
-  thresh--;
-
-  // now expand affixes on each of these root words and
-  // and use length adjusted ngram scores to select
-  // possible suggestions
-  char * guess[MAX_GUESS];
-  char * guessorig[MAX_GUESS];
-  int gscore[MAX_GUESS];
-  for(i=0;i<MAX_GUESS;i++) {
-     guess[i] = NULL;
-     guessorig[i] = NULL;
-     gscore[i] = -100 * i;
-  }
-
-  lp = MAX_GUESS - 1;
-
-  struct guessword * glst;
-  glst = (struct guessword *) calloc(MAX_WORDS,sizeof(struct guessword));
-  if (! glst) {
-    if (nonbmp) utf8 = 1;
-    return ns;
-  }
-
-  for (i = 0; i < MAX_ROOTS; i++) {
-      if (roots[i]) {
-        struct hentry * rp = roots[i];
-        int nw = pAMgr->expand_rootword(glst, MAX_WORDS, &(rp->word), rp->blen,
-            	    rp->astr, rp->alen, word, nc, 
-                    ((rp->var) ? &(rp->word) + rp->blen + 1 : NULL));
-
-        for (int k = 0; k < nw ; k++) {
-           sc = ngram(n, word, glst[k].word, NGRAM_ANY_MISMATCH + NGRAM_LOWERING) +
-               leftcommonsubstring(word, glst[k].word);
-
-           if ((sc > thresh)) {
-              if (sc > gscore[lp]) {
-                 if (guess[lp]) {
-                    free (guess[lp]);
-                    if (guessorig[lp]) {
-                	free(guessorig[lp]);
-                	guessorig[lp] = NULL;
-            	    }
-                 }
-                 gscore[lp] = sc;
-                 guess[lp] = glst[k].word;
-                 guessorig[lp] = glst[k].orig;
-                 lval = sc;
-                 for (j=0; j < MAX_GUESS; j++)
-                    if (gscore[j] < lval) {
-                       lp = j;
-                       lval = gscore[j];
-                    }
-              } else { 
-                free(glst[k].word);
-                if (glst[k].orig) free(glst[k].orig);
-              }
-           } else {
-        	free(glst[k].word);
-                if (glst[k].orig) free(glst[k].orig);
-           }
-        }
-      }
-  }
-  free(glst);
-
-  // now we are done generating guesses
-  // sort in order of decreasing score
-  
-  
-  bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS);
-  if (ph) bubblesort(&rootsphon[0], NULL, &scoresphon[0], MAX_ROOTS);
-
-  // weight suggestions with a similarity index, based on
-  // the longest common subsequent algorithm and resort
-
-  int is_swap;
-  for (i=0; i < MAX_GUESS; i++) {
-      if (guess[i]) {
-        // lowering guess[i]
-        char gl[MAXSWUTF8L];
-        int len;
-        if (utf8) {
-          w_char _w[MAXSWL];
-          len = u8_u16(_w, MAXSWL, guess[i]);
-          mkallsmall_utf(_w, len, langnum);
-          u16_u8(gl, MAXSWUTF8L, _w, len);
-        } else {
-          strcpy(gl, guess[i]);
-          mkallsmall(gl, csconv);
-          len = strlen(guess[i]);
-        }
-
-        int _lcs = lcslen(word, gl);
-
-        // same characters with different casing
-        if ((n == len) && (n == _lcs)) {
-            gscore[i] += 2000;
-            break;
-        }
-        
-        // heuristic weigthing of ngram scores
-        gscore[i] +=
-          // length of longest common subsequent minus length difference
-          2 * _lcs - abs((int) (n - len)) +
-          // weight length of the left common substring
-          leftcommonsubstring(word, gl) +
-          // weight equal character positions
-          ((_lcs == commoncharacterpositions(word, gl, &is_swap)) ? 1: 0) +
-          // swap character (not neighboring)
-          ((is_swap) ? 1000 : 0);
-      }
-  }
-
-  bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS);
-
-// phonetic version
-  if (ph) for (i=0; i < MAX_ROOTS; i++) {
-      if (rootsphon[i]) {
-        // lowering rootphon[i]
-        char gl[MAXSWUTF8L];
-        int len;
-        if (utf8) {
-          w_char _w[MAXSWL];
-          len = u8_u16(_w, MAXSWL, rootsphon[i]);
-          mkallsmall_utf(_w, len, langnum);
-          u16_u8(gl, MAXSWUTF8L, _w, len);
-        } else {
-          strcpy(gl, rootsphon[i]);
-          mkallsmall(gl, csconv);
-          len = strlen(rootsphon[i]);
-        }
-
-        // heuristic weigthing of ngram scores
-        scoresphon[i] += 2 * lcslen(word, gl) - abs((int) (n - len)) +
-          // weight length of the left common substring
-          leftcommonsubstring(word, gl);
-      }
-  }
-
-  if (ph) bubblesort(&rootsphon[0], NULL, &scoresphon[0], MAX_ROOTS);
-
-  // copy over
-  int oldns = ns;
-
-  int same = 0;
-  for (i=0; i < MAX_GUESS; i++) {
-    if (guess[i]) {
-      if ((ns < oldns + maxngramsugs) && (ns < maxSug) && (!same || (gscore[i] > 1000))) {
-        int unique = 1;
-        // leave only excellent suggestions, if exists
-        if (gscore[i] > 1000) same = 1;
-        for (j = 0; j < ns; j++) {
-          // don't suggest previous suggestions or a previous suggestion with prefixes or affixes
-          if ((!guessorig[i] && strstr(guess[i], wlst[j])) ||
-	     (guessorig[i] && strstr(guessorig[i], wlst[j])) ||
-            // check forbidden words
-            !checkword(guess[i], strlen(guess[i]), 0, NULL, NULL)) unique = 0;
-        }
-        if (unique) {
-    	    wlst[ns++] = guess[i];
-    	    if (guessorig[i]) {
-    		free(guess[i]);
-    		wlst[ns-1] = guessorig[i];
-    	    }
-    	} else {
-    	    free(guess[i]);
-    	    if (guessorig[i]) free(guessorig[i]);
-    	}
-      } else {
-        free(guess[i]);
-    	if (guessorig[i]) free(guessorig[i]);
-      }
-    }
-  }
-
-  oldns = ns;
-  if (ph) for (i=0; i < MAX_ROOTS; i++) {
-    if (rootsphon[i]) {
-      if ((ns < oldns + MAXPHONSUGS) && (ns < maxSug)) {
-        int unique = 1;
-        for (j = 0; j < ns; j++) {
-          // don't suggest previous suggestions or a previous suggestion with prefixes or affixes
-          if (strstr(rootsphon[i], wlst[j]) || 
-            // check forbidden words
-            !checkword(rootsphon[i], strlen(rootsphon[i]), 0, NULL, NULL)) unique = 0;
-        }
-        if (unique) wlst[ns++] = mystrdup(rootsphon[i]);
-      }
-    }
-  }
-
-  if (nonbmp) utf8 = 1;
-  return ns;
-}
-
-
-// see if a candidate suggestion is spelled correctly
-// needs to check both root words and words with affixes
-
-// obsolote MySpell-HU modifications:
-// return value 2 and 3 marks compounding with hyphen (-)
-// `3' marks roots without suffix
-int SuggestMgr::checkword(const char * word, int len, int cpdsuggest, int * timer, clock_t * timelimit)
-{
-  struct hentry * rv=NULL;
-  int nosuffix = 0;
-
-  // check time limit
-  if (timer) {
-    (*timer)--;
-    if (!(*timer) && timelimit) {
-      if ((clock() - *timelimit) > TIMELIMIT) return 0;
-      *timer = MAXPLUSTIMER;
-    }
-  }
-  
-  if (pAMgr) { 
-    if (cpdsuggest==1) {
-      if (pAMgr->get_compound()) {
-        rv = pAMgr->compound_check(word,len,0,0,0,0,NULL,0,NULL,NULL,1);
-        if (rv) return 3; // XXX obsolote categorisation
-        }
-        return 0;
-    }
-
-    rv = pAMgr->lookup(word);
-
-    if (rv) {
-        if ((rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen)
-               || TESTAFF(rv->astr,pAMgr->get_nosuggest(),rv->alen))) return 0;
-        while (rv) {
-    	    if (rv->astr && (TESTAFF(rv->astr,pAMgr->get_pseudoroot(),rv->alen) ||
-                  TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
-            TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) {
-        	rv = rv->next_homonym;
-    	    } else break;
-    	}
-    } else rv = pAMgr->prefix_check(word, len, 0); // only prefix, and prefix + suffix XXX
-    
-    if (rv) {
-        nosuffix=1;
-    } else {
-        rv = pAMgr->suffix_check(word, len, 0, NULL, NULL, 0, NULL); // only suffix
-    }
-
-    if (!rv && pAMgr->have_contclass()) {
-        rv = pAMgr->suffix_check_twosfx(word, len, 0, NULL, FLAG_NULL);
-        if (!rv) rv = pAMgr->prefix_check_twosfx(word, len, 1, FLAG_NULL);
-    }
-
-    // check forbidden words
-    if ((rv) && (rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen) ||
-      TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
-      TESTAFF(rv->astr,pAMgr->get_nosuggest(),rv->alen) ||
-      TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) return 0;
-
-    if (rv) { // XXX obsolote    
-      if ((pAMgr->get_compoundflag()) && 
-          TESTAFF(rv->astr, pAMgr->get_compoundflag(), rv->alen)) return 2 + nosuffix; 
-      return 1;
-    }
-  }
-  return 0;
-}
-
-int SuggestMgr::check_forbidden(const char * word, int len)
-{
-  struct hentry * rv = NULL;
-
-  if (pAMgr) { 
-    rv = pAMgr->lookup(word);
-    if (rv && rv->astr && (TESTAFF(rv->astr,pAMgr->get_pseudoroot(),rv->alen) ||
-        TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) rv = NULL;
-    if (!(pAMgr->prefix_check(word,len,1)))
-        rv = pAMgr->suffix_check(word,len, 0, NULL, NULL, 0, NULL); // prefix+suffix, suffix
-    // check forbidden words
-    if ((rv) && (rv->astr) && TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen)) return 1;
-   }
-    return 0;
-}
-
-#ifdef HUNSPELL_EXPERIMENTAL
-// suggest stems, XXX experimental code
-int SuggestMgr::suggest_stems(char*** slst, const char * w, int nsug)
-{
-    char buf[MAXSWUTF8L];
-    char ** wlst;    
-    int prevnsug = nsug;
-
-  char w2[MAXWORDUTF8LEN];
-  const char * word = w;
-
-  // word reversing wrapper for complex prefixes
-  if (complexprefixes) {
-    strcpy(w2, w);
-    if (utf8) reverseword_utf(w2); else reverseword(w2);
-    word = w2;
-  }
-
-    if (*slst) {
-        wlst = *slst;
-    } else {
-        wlst = (char **) calloc(maxSug, sizeof(char *));
-        if (wlst == NULL) return -1;
-    }
-    // perhaps there are a fix stem in the dictionary
-    if ((nsug < maxSug) && (nsug > -1)) {
-    
-    nsug = fixstems(wlst, word, nsug);
-    if (nsug == prevnsug) {
-        char * s = mystrdup(word);
-        char * p = s + strlen(s);
-        while ((*p != '-') && (p != s)) p--;
-        if (*p == '-') {
-            *p = '\0';
-            nsug = fixstems(wlst, s, nsug);
-            if ((nsug == prevnsug) && (nsug < maxSug) && (nsug >= 0)) {
-                char * t;
-                buf[0] = '\0';
-                for (t = s; (t[0] != '\0') && ((t[0] >= '0') || (t[0] <= '9')); t++); // is a number?
-                if (*t != '\0') strcpy(buf, "# ");
-                strcat(buf, s);
-                wlst[nsug] = mystrdup(buf);
-                if (wlst[nsug] == NULL) return -1;
-                nsug++;
-            }
-            p++;
-            nsug = fixstems(wlst, p, nsug);
-        }
-
-        free(s);
-    }
-    }
-    
-    if (nsug < 0) {
-       for (int i=0;i<maxSug; i++)
-         if (wlst[i] != NULL) free(wlst[i]);
-         free(wlst);
-       return -1;
-    }
-
-    *slst = wlst;
-    return nsug;
-}
-
-
-// there are fix stems in dictionary
-int SuggestMgr::fixstems(char ** wlst, const char * word, int ns)
-{
-    char buf[MAXSWUTF8L];
-    char prefix[MAXSWUTF8L] = "";
-
-    int dicstem = 1; // 0 = lookup, 1= affix, 2 = compound
-    int cpdindex = 0;
-    struct hentry * rv = NULL;
-
-    int wl = strlen(word);
-    int cmpdstemnum;
-    int cmpdstem[MAXCOMPOUND];
-
-    if (pAMgr) { 
-        rv = pAMgr->lookup(word);
-        if (rv) {
-            dicstem = 0;
-        } else {
-            // try stripping off affixes 
-            rv = pAMgr->affix_check(word, wl);
-
-            // else try check compound word
-            if (!rv && pAMgr->get_compound()) {
-                rv = pAMgr->compound_check(word, wl,
-                     0, 0, 100, 0, NULL, 0, &cmpdstemnum, cmpdstem,1);
-
-                if (rv) {
-                    dicstem = 2;
-                    for (int j = 0; j < cmpdstemnum; j++) {
-                        cpdindex += cmpdstem[j];
-                    }
-                    if(! (pAMgr->lookup(word + cpdindex)))
-                        pAMgr->affix_check(word + cpdindex, wl - cpdindex); // for prefix
-                }
-            }
-
-
-            if (pAMgr->get_prefix()) {
-                strcpy(prefix, pAMgr->get_prefix());
-            }
-
-            // XXX obsolete, will be a general solution for stemming
-            if ((prefix) && (strncmp(prefix, "leg", 3)==0)) prefix[0] = '\0'; // (HU)       
-        }
-
-    }
-
-
-
-    if ((rv) && (ns < maxSug)) {
-    
-        // check fixstem flag and not_valid_stem flag
-        // first word
-        if ((ns < maxSug) && (dicstem < 2)) { 
-            strcpy(buf, prefix);
-            if ((dicstem > 0) && pAMgr->get_derived()) {
-                // XXX obsolote
-                   if (strlen(prefix) == 1) {
-                        strcat(buf, (pAMgr->get_derived()) + 1);
-                   } else {
-                        strcat(buf, pAMgr->get_derived());
-                   }
-                } else {
-                        // special stem in affix description
-                        const char * wordchars = pAMgr->get_wordchars();
-                        if (rv->description && 
-                           (strchr(wordchars, *(rv->description)))) {
-                           char * desc = (rv->description) + 1;
-                           while (strchr(wordchars, *desc)) desc++;
-                           strncat(buf, rv->description, desc - (rv->description));
-                        } else {
-                            strcat(buf, rv->word);
-                        }
-                }
-            wlst[ns] = mystrdup(buf);
-            if (wlst[ns] == NULL) return -1;
-            ns++;
-        }
-
-        if (dicstem == 2) {
-
-            // compound stem
-
-//          if (rv->astr && (strchr(rv->astr, '0') == NULL)) {
-            if (rv->astr) {
-                strcpy(buf, word);
-                buf[cpdindex] = '\0';
-                if (prefix) strcat(buf, prefix);
-                if (pAMgr->get_derived()) {
-                        strcat(buf, pAMgr->get_derived());
-                } else {
-                        // special stem in affix description
-                        const char * wordchars = pAMgr->get_wordchars();
-                        if (rv->description && 
-                           (strchr(wordchars, *(rv->description)))) {
-                           char * desc = (rv->description) + 1;
-                           while (strchr(wordchars, *desc)) desc++;
-                           strncat(buf, rv->description, desc - (rv->description));
-                        } else {
-                            strcat(buf, rv->word);
-                        }
-                }
-                if (ns < maxSug) {
-                    wlst[ns] = mystrdup(buf);
-                    if (wlst[ns] == NULL) return -1;
-                    ns++;
-                }
-            }
-        }
-    }
-    return ns;
-}
-
-// suggest possible stems
-int SuggestMgr::suggest_pos_stems(char*** slst, const char * w, int nsug)
-{
-    char ** wlst;    
-
-    struct hentry * rv = NULL;
-
-  char w2[MAXSWUTF8L];
-  const char * word = w;
-
-  // word reversing wrapper for complex prefixes
-  if (complexprefixes) {
-    strcpy(w2, w);
-    if (utf8) reverseword_utf(w2); else reverseword(w2);
-    word = w2;
-  }
-
-    int wl = strlen(word);
-
-
-    if (*slst) {
-        wlst = *slst;
-    } else {
-        wlst = (char **) calloc(maxSug, sizeof(char *));
-        if (wlst == NULL) return -1;
-    }
-
-    rv = pAMgr->suffix_check(word, wl, 0, NULL, wlst, maxSug, &nsug);
-
-    // delete dash from end of word
-    if (nsug > 0) {
-        for (int j=0; j < nsug; j++) {
-            if (wlst[j][strlen(wlst[j]) - 1] == '-') wlst[j][strlen(wlst[j]) - 1] = '\0';
-        }
-    }
-
-    *slst = wlst;
-    return nsug;
-}
-
-
-char * SuggestMgr::suggest_morph(const char * w)
-{
-    char result[MAXLNLEN];
-    char * r = (char *) result;
-    char * st;
-
-    struct hentry * rv = NULL;
-
-    *result = '\0';
-
-    if (! pAMgr) return NULL;
-
-  char w2[MAXSWUTF8L];
-  const char * word = w;
-
-  // word reversing wrapper for complex prefixes
-  if (complexprefixes) {
-    strcpy(w2, w);
-    if (utf8) reverseword_utf(w2); else reverseword(w2);
-    word = w2;
-  }
-
-    rv = pAMgr->lookup(word);
-    
-    while (rv) {
-        if ((!rv->astr) || !(TESTAFF(rv->astr, pAMgr->get_forbiddenword(), rv->alen) ||
-            TESTAFF(rv->astr, pAMgr->get_pseudoroot(), rv->alen) ||
-            TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) {
-            if (rv->description && ((!rv->astr) || 
-                !TESTAFF(rv->astr, pAMgr->get_lemma_present(), rv->alen)))
-                    strcat(result, word);
-            if (rv->description) strcat(result, rv->description);
-            strcat(result, "\n");
-        }
-        rv = rv->next_homonym;
-    }
-    
-    st = pAMgr->affix_check_morph(word,strlen(word));
-    if (st) {
-        strcat(result, st);
-        free(st);
-    }
-
-    if (pAMgr->get_compound() && (*result == '\0'))
-        pAMgr->compound_check_morph(word, strlen(word),
-                     0, 0, 100, 0,NULL, 0, &r, NULL);
-    
-    return (*result) ? mystrdup(line_uniq(delete_zeros(result))) : NULL;
-}
-
-char * SuggestMgr::suggest_morph_for_spelling_error(const char * word)
-{
-    char * p = NULL;
-    char ** wlst = (char **) calloc(maxSug, sizeof(char *));
-    if (!**wlst) return NULL;
-    // we will use only the first suggestion
-    for (int i = 0; i < maxSug - 1; i++) wlst[i] = "";
-    int ns = suggest(&wlst, word, maxSug - 1);
-    if (ns == maxSug) {
-        p = suggest_morph(wlst[maxSug - 1]);
-        free(wlst[maxSug - 1]);
-    }
-    if (wlst) free(wlst);
-    return p;
-}
-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
-
-
-// generate an n-gram score comparing s1 and s2
-int SuggestMgr::ngram(int n, char * s1, const char * s2, int opt)
-{
-  int nscore = 0;
-  int ns;
-  int l1;
-  int l2;
-
-  if (utf8) {
-    w_char su1[MAXSWL];
-    w_char su2[MAXSWL];
-    l1 = u8_u16(su1, MAXSWL, s1);
-    l2 = u8_u16(su2, MAXSWL, s2);
-    if ((l2 <= 0) || (l1 == -1)) return 0;
-    // lowering dictionary word
-    if (opt & NGRAM_LOWERING) mkallsmall_utf(su2, l2, langnum);
-    for (int j = 1; j <= n; j++) {
-      ns = 0;
-      for (int i = 0; i <= (l1-j); i++) {
-        for (int l = 0; l <= (l2-j); l++) {
-            int k;
-            for (k = 0; (k < j); k++) {
-              w_char * c1 = su1 + i + k;
-              w_char * c2 = su2 + l + k;
-              if ((c1->l != c2->l) || (c1->h != c2->h)) break;
-            }
-            if (k == j) {
-                ns++;
-                break;
-            }
-        }
-      }
-      nscore = nscore + ns;
-      if (ns < 2) break;
-    }
-  } else {  
-    char t[MAXSWUTF8L];
-    l1 = strlen(s1);
-    l2 = strlen(s2);
-    if (l2 == 0) return 0;
-    strcpy(t, s2);
-    if (opt & NGRAM_LOWERING) mkallsmall(t, csconv);
-    for (int j = 1; j <= n; j++) {
-      ns = 0;
-      for (int i = 0; i <= (l1-j); i++) {
-        char c = *(s1 + i + j);
-        *(s1 + i + j) = '\0';
-        if (strstr(t,(s1+i))) ns++;
-        *(s1 + i + j ) = c;
-      }
-      nscore = nscore + ns;
-      if (ns < 2) break;
-    }
-  }
-  
-  ns = 0;
-  if (opt & NGRAM_LONGER_WORSE) ns = (l2-l1)-2;
-  if (opt & NGRAM_ANY_MISMATCH) ns = abs(l2-l1)-2;
-  ns = (nscore - ((ns > 0) ? ns : 0));
-  return ns;
-}
-
-// length of the left common substring of s1 and (decapitalised) s2
-int SuggestMgr::leftcommonsubstring(char * s1, const char * s2) {
-  if (utf8) {
-    w_char su1[MAXSWL];
-    w_char su2[MAXSWL];
-    // decapitalize dictionary word
-    if (complexprefixes) {
-      int l1 = u8_u16(su1, MAXSWL, s1);
-      int l2 = u8_u16(su2, MAXSWL, s2);
-      if (*((short *)su1+l1-1) == *((short *)su2+l2-1)) return 1;
-    } else {
-      int i;
-      u8_u16(su1, 1, s1);
-      u8_u16(su2, 1, s2);
-      unsigned short idx = (su2->h << 8) + su2->l;
-      if (*((short *)su1) != *((short *)su2) &&
-         (*((unsigned short *)su1) != unicodetolower(idx, langnum))) return 0;
-      int l1 = u8_u16(su1, MAXSWL, s1);
-      int l2 = u8_u16(su2, MAXSWL, s2);
-      for(i = 1; (i < l1) && (i < l2) &&
-         (*((short *)(su1 + i)) == *((short *)(su2 + i))); i++);
-      return i;
-    }
-  } else {
-    if (complexprefixes) {
-      int l1 = strlen(s1);
-      int l2 = strlen(s2);
-      if (*(s2+l1-1) == *(s2+l2-1)) return 1;
-    } else {
-      char * olds = s1;
-      // decapitalise dictionary word
-      if ((*s1 != *s2) && (*s1 != csconv[((unsigned char)*s2)].clower)) return 0;
-      do {
-        s1++; s2++;
-      } while ((*s1 == *s2) && (*s1 != '\0'));
-      return s1 - olds;
-    }
-  }
-  return 0;
-}
-
-int SuggestMgr::commoncharacterpositions(char * s1, const char * s2, int * is_swap) {
-  int num = 0;
-  int diff = 0;
-  int diffpos[2];
-  *is_swap = 0;
-  if (utf8) {
-    w_char su1[MAXSWL];
-    w_char su2[MAXSWL];
-    int l1 = u8_u16(su1, MAXSWL, s1);
-    int l2 = u8_u16(su2, MAXSWL, s2);
-    // decapitalize dictionary word
-    if (complexprefixes) {
-      mkallsmall_utf(su2+l2-1, 1, langnum);
-    } else {
-      mkallsmall_utf(su2, 1, langnum);
-    }
-    for (int i = 0; (i < l1) && (i < l2); i++) {
-      if (((short *) su1)[i] == ((short *) su2)[i]) {
-        num++;
-      } else {
-        if (diff < 2) diffpos[diff] = i;
-        diff++;
-      }
-    }
-    if ((diff == 2) && (l1 == l2) &&
-        (((short *) su1)[diffpos[0]] == ((short *) su2)[diffpos[1]]) &&
-        (((short *) su1)[diffpos[1]] == ((short *) su2)[diffpos[0]])) *is_swap = 1;
-  } else {
-    int i;
-    char t[MAXSWUTF8L];
-    strcpy(t, s2);
-    // decapitalize dictionary word
-    if (complexprefixes) {
-      int l2 = strlen(t);
-      *(t+l2-1) = csconv[((unsigned char)*(t+l2-1))].clower;
-    } else {
-      mkallsmall(t, csconv);
-    }
-    for (i = 0; (*(s1+i) != 0) && (*(t+i) != 0); i++) {
-      if (*(s1+i) == *(t+i)) {
-        num++;
-      } else {
-        if (diff < 2) diffpos[diff] = i;
-        diff++;
-      }
-    }
-    if ((diff == 2) && (*(s1+i) == 0) && (*(t+i) == 0) &&
-      (*(s1+diffpos[0]) == *(t+diffpos[1])) &&
-      (*(s1+diffpos[1]) == *(t+diffpos[0]))) *is_swap = 1;
-  }
-  return num;
-}
-
-int SuggestMgr::mystrlen(const char * word) {
-  if (utf8) {
-    w_char w[MAXSWL];
-    return u8_u16(w, MAXSWL, word);
-  } else return strlen(word);
-}
-
-// sort in decreasing order of score
-void SuggestMgr::bubblesort(char** rword, char** rword2, int* rsc, int n )
-{
-      int m = 1;
-      while (m < n) {
-          int j = m;
-          while (j > 0) {
-            if (rsc[j-1] < rsc[j]) {
-                int sctmp = rsc[j-1];
-                char * wdtmp = rword[j-1];
-                rsc[j-1] = rsc[j];
-                rword[j-1] = rword[j];
-                rsc[j] = sctmp;
-                rword[j] = wdtmp;
-                if (rword2) {
-            	    wdtmp = rword2[j-1];
-            	    rword2[j-1] = rword2[j];
-            	    rword2[j] = wdtmp;
-                }
-                j--;
-            } else break;
-          }
-          m++;
-      }
-      return;
-}
-
-// longest common subsequence
-void SuggestMgr::lcs(const char * s, const char * s2, int * l1, int * l2, char ** result) {
-  int n, m;
-  w_char su[MAXSWL];
-  w_char su2[MAXSWL];
-  char * b;
-  char * c;
-  int i;
-  int j;
-  if (utf8) {
-    m = u8_u16(su, MAXSWL, s);
-    n = u8_u16(su2, MAXSWL, s2);
-  } else {
-    m = strlen(s);
-    n = strlen(s2);
-  }
-  c = (char *) malloc((m + 1) * (n + 1));
-  b = (char *) malloc((m + 1) * (n + 1));
-  if (!c || !b) {
-    if (c) free(c);
-    if (b) free(b);
-    *result = NULL;
-    return;
-  }
-  for (i = 1; i <= m; i++) c[i*(n+1)] = 0;
-  for (j = 0; j <= n; j++) c[j] = 0;
-  for (i = 1; i <= m; i++) {
-    for (j = 1; j <= n; j++) {
-      if ((utf8) && (*((short *) su+i-1) == *((short *)su2+j-1))
-          || (!utf8) && ((*(s+i-1)) == (*(s2+j-1)))) {
-        c[i*(n+1) + j] = c[(i-1)*(n+1) + j-1]+1;
-        b[i*(n+1) + j] = LCS_UPLEFT;
-      } else if (c[(i-1)*(n+1) + j] >= c[i*(n+1) + j-1]) {
-        c[i*(n+1) + j] = c[(i-1)*(n+1) + j];
-        b[i*(n+1) + j] = LCS_UP;
-      } else {
-        c[i*(n+1) + j] = c[i*(n+1) + j-1];
-        b[i*(n+1) + j] = LCS_LEFT;
-      }
-    }
-  }
-  *result = b;
-  free(c);
-  *l1 = m;
-  *l2 = n;
-}
-
-int SuggestMgr::lcslen(const char * s, const char* s2) {
-  int m;
-  int n;
-  int i;
-  int j;
-  char * result;
-  int len = 0;
-  lcs(s, s2, &m, &n, &result);
-  if (!result) return 0;
-  i = m;
-  j = n;
-  while ((i != 0) && (j != 0)) {
-    if (result[i*(n+1) + j] == LCS_UPLEFT) {
-      len++;
-      i--;
-      j--;
-    } else if (result[i*(n+1) + j] == LCS_UP) {
-      i--;
-    } else j--;
-  }
-  free(result);
-  return len;
-}
diff -uprN --exclude=CVS spellcheck.old/hunspell/src/suggestmgr.hxx spellcheck/hunspell/src/suggestmgr.hxx
--- spellcheck.old/hunspell/src/suggestmgr.hxx	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/hunspell/src/suggestmgr.hxx	1970-01-01 01:00:00.000000000 +0100
@@ -1,160 +0,0 @@
-/******* BEGIN LICENSE BLOCK *******
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- * 
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- * 
- * The Initial Developers of the Original Code are Kevin Hendricks (MySpell)
- * and László Németh (Hunspell). Portions created by the Initial Developers
- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
- * 
- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
- *                 David Einstein (deinst@world.std.com)
- *                 László Németh (nemethl@gyorsposta.hu)
- *                 Davide Prina
- *                 Giuseppe Modugno
- *                 Gianluca Turconi
- *                 Simon Brouwer
- *                 Noll Janos
- *                 Biro Arpad
- *                 Goldman Eleonora
- *                 Sarlos Tamas
- *                 Bencsath Boldizsar
- *                 Halacsy Peter
- *                 Dvornik Laszlo
- *                 Gefferth Andras
- *                 Nagy Viktor
- *                 Varga Daniel
- *                 Chris Halls
- *                 Rene Engelhard
- *                 Bram Moolenaar
- *                 Dafydd Jones
- *                 Harri Pitkanen
- *                 Andras Timar
- *                 Tor Lillqvist
- * 
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- ******* END LICENSE BLOCK *******/
-
-#ifndef _SUGGESTMGR_HXX_
-#define _SUGGESTMGR_HXX_
-
-#define MAXSWL 100
-#define MAXSWUTF8L (MAXSWL * 4)
-#define MAX_ROOTS 100
-#define MAX_WORDS 100
-#define MAX_GUESS 200
-#define MAXNGRAMSUGS 4
-#define MAXPHONSUGS 2
-
-// timelimit: max ~1/4 sec (process time on Linux) for a time consuming function
-#define TIMELIMIT (CLOCKS_PER_SEC >> 2)
-#define MINTIMER 100
-#define MAXPLUSTIMER 100
-
-#define NGRAM_LONGER_WORSE  (1 << 0)
-#define NGRAM_ANY_MISMATCH  (1 << 1)
-#define NGRAM_LOWERING      (1 << 2)
-
-#include "atypes.hxx"
-#include "affixmgr.hxx"
-#include "hashmgr.hxx"
-#include "langnum.hxx"
-#include <time.h>
-
-enum { LCS_UP, LCS_LEFT, LCS_UPLEFT };
-
-class SuggestMgr
-{
-  char *          ckey;
-  int             ckeyl;
-  w_char *        ckey_utf;
-
-  char *          ctry;
-  int             ctryl;
-  w_char *        ctry_utf;
-
-  AffixMgr*       pAMgr;
-  int             maxSug;
-  struct cs_info * csconv;
-  int             utf8;
-  int             langnum;
-  int             nosplitsugs;
-  int             maxngramsugs;
-  int             complexprefixes;
-
-
-public:
-  SuggestMgr(const char * tryme, int maxn, AffixMgr *aptr);
-  ~SuggestMgr();
-
-  int suggest(char*** slst, const char * word, int nsug, int * onlycmpdsug);
-  int ngsuggest(char ** wlst, char * word, int ns, HashMgr* pHMgr);
-  int suggest_auto(char*** slst, const char * word, int nsug);
-  int suggest_stems(char*** slst, const char * word, int nsug);
-  int suggest_pos_stems(char*** slst, const char * word, int nsug);
-
-  char * suggest_morph(const char * word);
-  char * suggest_morph_for_spelling_error(const char * word);
-
-private:
-   int testsug(char** wlst, const char * candidate, int wl, int ns, int cpdsuggest,
-     int * timer, clock_t * timelimit);
-   int checkword(const char *, int, int, int *, clock_t *);
-   int check_forbidden(const char *, int);
-
-   int capchars(char **, const char *, int, int);
-   int replchars(char**, const char *, int, int);
-   int doubletwochars(char**, const char *, int, int);
-   int forgotchar(char **, const char *, int, int);
-   int swapchar(char **, const char *, int, int);
-   int longswapchar(char **, const char *, int, int);
-   int movechar(char **, const char *, int, int);
-   int extrachar(char **, const char *, int, int);
-   int badcharkey(char **, const char *, int, int);
-   int badchar(char **, const char *, int, int);
-   int twowords(char **, const char *, int, int);
-   int fixstems(char **, const char *, int);
-
-   int capchars_utf(char **, const w_char *, int wl, int, int);
-   int doubletwochars_utf(char**, const w_char *, int wl, int, int);
-   int forgotchar_utf(char**, const w_char *, int wl, int, int);
-   int extrachar_utf(char**, const w_char *, int wl, int, int);
-   int badcharkey_utf(char **, const w_char *, int wl, int, int);
-   int badchar_utf(char **, const w_char *, int wl, int, int);
-   int swapchar_utf(char **, const w_char *, int wl, int, int);
-   int longswapchar_utf(char **, const w_char *, int, int, int);
-   int movechar_utf(char **, const w_char *, int, int, int);
-
-   int mapchars(char**, const char *, int, int);
-   int map_related(const char *, int, char ** wlst, int, int, const mapentry*, int, int *, clock_t *);
-   int map_related_utf(w_char *, int, int, int, char ** wlst, int, const mapentry*, int, int *, clock_t *);
-   int ngram(int n, char * s1, const char * s2, int opt);
-   int mystrlen(const char * word);
-   int leftcommonsubstring(char * s1, const char * s2);
-   int commoncharacterpositions(char * s1, const char * s2, int * is_swap);
-   void bubblesort( char ** rwd, char ** rwd2, int * rsc, int n);
-   void lcs(const char * s, const char * s2, int * l1, int * l2, char ** result);
-   int lcslen(const char * s, const char* s2);
-
-};
-
-#endif
diff -uprN --exclude=CVS spellcheck.old/src/Makefile.in spellcheck/src/Makefile.in
--- spellcheck.old/src/Makefile.in	2008-04-23 16:41:50.000000000 +0200
+++ spellcheck/src/Makefile.in	2008-04-23 16:42:09.000000000 +0200
@@ -82,6 +82,12 @@ LOCAL_INCLUDES += -I$(srcdir)/../osxspel
 else
 SHARED_LIBRARY_LIBS += ../hunspell/src/$(LIB_PREFIX)hunspell_s.$(LIB_SUFFIX)
 LOCAL_INCLUDES += -I$(srcdir)/../hunspell/src
+ifndef MOZ_NATIVE_HUNSPELL
+LOCAL_INCLUDES += -I$(srcdir)/../hunspell/hunspell
+SHARED_LIBRARY_LIBS += ../hunspell/hunspell/$(LIB_PREFIX)libhunspell_s.$(LIB_SUFFIX)
+else
+LOCAL_INCLUDES += $(MOZ_HUNSPELL_CFLAGS)
+endif
 endif
 
 EXTRA_DSO_LDOPTS = \
