[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[hunspell] 12/98: Imported Upstream version 1.1.1



This is an automated email from the git hooks/post-receive script.

rene pushed a commit to branch master
in repository hunspell.

commit 4e252d8bd7264123cbfafe8953e897ae7d9d0a74
Author: Rene Engelhard <rene@debian.org>
Date:   Thu Apr 21 14:45:10 2016 +0200

    Imported Upstream version 1.1.1
---
 ChangeLog                                          | 102 +++-
 NEWS                                               |  20 +
 THANKS                                             |  18 +-
 configure                                          |  20 +-
 configure.ac                                       |   4 +-
 man/hunspell.4                                     | 336 ++++++-----
 src/hunspell/affentry.cxx                          |   7 +-
 src/hunspell/affixmgr.cxx                          | 627 ++++++++++++++++-----
 src/hunspell/affixmgr.hxx                          |  26 +-
 src/hunspell/atypes.hxx                            |   9 +-
 src/hunspell/csutil.cxx                            | 388 +++++++++++--
 src/hunspell/csutil.hxx                            |   6 +-
 src/hunspell/hashmgr.cxx                           |  41 +-
 src/hunspell/hashmgr.hxx                           |   2 +-
 src/hunspell/htypes.hxx                            |   2 +-
 src/hunspell/hunspell.cxx                          | 128 +++--
 src/hunspell/hunspell.hxx                          |   1 +
 src/hunspell/suggestmgr.cxx                        |  43 +-
 src/hunspell/suggestmgr.hxx                        |   2 +-
 tests/Makefile.am                                  | 147 ++++-
 tests/Makefile.in                                  | 147 ++++-
 tests/affixes.aff                                  |   7 +
 tests/affixes.dic                                  |   4 +
 tests/affixes.good                                 |   7 +
 tests/{pseudoroot.test => affixes.test}            |   0
 tests/checkcompoundcase.aff                        |   3 +
 tests/checkcompoundcase.dic                        |   5 +
 tests/checkcompoundcase.good                       |   5 +
 tests/{pseudoroot2.test => checkcompoundcase.test} |   0
 tests/checkcompoundcase.wrong                      |   3 +
 tests/checkcompoundcase2.aff                       |   3 +
 tests/checkcompoundcase2.dic                       |   3 +
 tests/checkcompoundcase2.good                      |   2 +
 .../{pseudoroot3.test => checkcompoundcase2.test}  |   0
 tests/checkcompoundcase2.wrong                     |   1 +
 tests/checkcompoundcaseutf.aff                     |   3 +
 tests/checkcompoundcaseutf.dic                     |   3 +
 tests/checkcompoundcaseutf.good                    |   2 +
 .../{pseudoroot.test => checkcompoundcaseutf.test} |   2 +-
 tests/checkcompoundcaseutf.wrong                   |   1 +
 tests/compound.aff                                 |   6 +-
 tests/compound.dic                                 |  10 +-
 tests/compound.good                                |   5 +-
 tests/compound.wrong                               |  43 +-
 tests/compound2.aff                                |   3 +
 tests/compound2.dic                                |   5 +
 tests/compound2.good                               |  37 ++
 tests/{pseudoroot4.test => compound2.test}         |   0
 tests/compound2.wrong                              |   8 +
 tests/compound3.aff                                |   3 +
 tests/compound3.dic                                |   5 +
 tests/compound3.good                               |   7 +
 tests/{pseudoroot5.test => compound3.test}         |   0
 tests/compound3.wrong                              |  41 ++
 tests/compound4.aff                                |   6 +
 tests/compound4.dic                                |  24 +
 tests/compound4.good                               |  29 +
 tests/{pseudoroot.test => compound4.test}          |   2 +-
 tests/compound4.wrong                              |   5 +
 tests/compound5.aff                                |   6 +
 tests/compound5.dic                                |  14 +
 tests/compound5.good                               |   7 +
 tests/compound5.morph                              |  14 +
 tests/{pseudoroot.test => compound5.test}          |   2 +-
 tests/compound5.wrong                              |   1 +
 tests/{compound.aff => compoundflag.aff}           |   0
 tests/{compound.dic => compoundflag.dic}           |   0
 tests/{compound.good => compoundflag.good}         |   0
 tests/{pseudoroot.test => compoundflag.test}       |   0
 tests/{compound.wrong => compoundflag.wrong}       |   0
 tests/flagutf8.aff                                 |  14 +
 tests/flagutf8.dic                                 |   2 +
 tests/flagutf8.good                                |   8 +
 tests/{pseudoroot.test => flagutf8.test}           |   0
 tests/germancompounding.aff                        |  81 ++-
 tests/germancompounding.dic                        |   2 +-
 tests/germancompounding.good                       |   7 +
 ...mancompounding.aff => germancompoundingold.aff} |   0
 ...mancompounding.dic => germancompoundingold.dic} |   2 +-
 ...ncompounding.good => germancompoundingold.good} |   1 +
 .../{pseudoroot.test => germancompoundingold.test} |   0
 tests/germancompoundingold.wrong                   |  50 ++
 tests/i53643.aff                                   |   1 +
 tests/i53643.dic                                   |   2 +
 tests/i53643.good                                  |  19 +
 tests/{pseudoroot3.test => i53643.test}            |   3 +-
 tests/i53643.wrong                                 |   4 +
 tests/i54980.aff                                   |   2 +
 tests/i54980.dic                                   |   3 +
 tests/i54980.good                                  |   4 +
 tests/{pseudoroot.test => i54980.test}             |   2 +-
 tests/keepcase.aff                                 |   3 +
 tests/keepcase.dic                                 |   5 +
 tests/keepcase.good                                |   4 +
 tests/keepcase.sug                                 |   8 +
 tests/{pseudoroot.test => keepcase.test}           |   0
 tests/keepcase.wrong                               |   8 +
 tests/{pseudoroot.aff => needaffix.aff}            |   2 +-
 tests/{pseudoroot.dic => needaffix.dic}            |   0
 tests/{pseudoroot.good => needaffix.good}          |   0
 tests/{pseudoroot.test => needaffix.test}          |   0
 tests/needaffix.wrong                              |   1 +
 tests/{pseudoroot2.aff => needaffix2.aff}          |   2 +-
 tests/{pseudoroot2.dic => needaffix2.dic}          |   0
 tests/{pseudoroot2.good => needaffix2.good}        |   0
 tests/{pseudoroot2.morph => needaffix2.morph}      |   0
 tests/{pseudoroot.test => needaffix2.test}         |   0
 tests/{pseudoroot3.aff => needaffix3.aff}          |   4 +-
 tests/{pseudoroot3.dic => needaffix3.dic}          |   0
 tests/{pseudoroot3.good => needaffix3.good}        |   0
 tests/{pseudoroot.test => needaffix3.test}         |   0
 tests/{pseudoroot3.wrong => needaffix3.wrong}      |   0
 tests/{pseudoroot4.aff => needaffix4.aff}          |   2 +-
 tests/{pseudoroot4.dic => needaffix4.dic}          |   0
 tests/{pseudoroot4.good => needaffix4.good}        |   0
 tests/{pseudoroot.test => needaffix4.test}         |   0
 tests/{pseudoroot5.aff => needaffix5.aff}          |   4 +-
 tests/{pseudoroot5.dic => needaffix5.dic}          |   0
 tests/{pseudoroot5.good => needaffix5.good}        |   0
 tests/{pseudoroot.test => needaffix5.test}         |   0
 tests/{pseudoroot5.wrong => needaffix5.wrong}      |   0
 tests/nosuggest.aff                                |   5 +
 tests/nosuggest.dic                                |   3 +
 tests/{pseudoroot.wrong => nosuggest.good}         |   1 -
 tests/nosuggest.sug                                |   0
 tests/{pseudoroot.test => nosuggest.test}          |   0
 tests/nosuggest.wrong                              |   3 +
 tests/test.sh                                      |   5 +-
 128 files changed, 2073 insertions(+), 607 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6ddae32..88b7937 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,103 @@
+2005-11-09 Németh László <nemethl@gyorsposta.hu>:
+improvements:
+        * src/hunspell/affixmgr.*: new and improved affix file parameters:
+
+        - COMPOUND definitions: compound patterns with regexp-like matching.
+          See manual and test files: tests/compound*.*
+          Suggested by Bram Moolenaar.
+          Also useful for simple word-level lexical scanning, for example
+          analysing numbers or words with numbers (OOo Issue #53643):
+          http://qa.openoffice.org/issues/show_bug.cgi?id=53643
+          Examples: tests/compound{4,5}.*.
+
+        - NOSUGGEST flag: words signed with NOSUGGEST flag are not suggested.
+          Proposed flag for vulgar and obscene words (OOo Issue #55498).
+          Example: tests/nosuggest.*.
+          Problem reported by bobharvey at OOo:
+          http://qa.openoffice.org/issues/show_bug.cgi?id=55498
+
+        - KEEPCASE flag: Forbid capitalized and uppercased forms of words 
+          signed with KEEPCASE flags. Useful for special ortographies 
+          (measurements and currency often keep their case in uppercased
+          texts) and other writing systems (eg. keeping lower case of IPA
+          characters).
+
+        - CHECKCOMPOUNDCASE: Forbid upper case characters at word bound in compounds.
+          Examples: tests/checkcompoundcase* and tests/germancompounding.*
+
+        - FLAG UTF-8: New flag type: Unicode character encoded with UTF-8.
+          Example: tests/flagutf8.*.
+          Rationale: Unicode character type can be more readable
+          (in a Unicode text editor) than `long' or `num' flag type.
+
+bug fixes:
+        * src/hunspell/hunspell.cxx: accept numbers and numbers with separators (i53643)
+          Bug reported by skelet at OOo:
+          http://qa.openoffice.org/issues/show_bug.cgi?id=53643
+
+	* src/hunspell/csutil.cxx: fix casing data in ISO 8859-13 character table.
+
+        * src/hunspell/csutil.cxx: add ISO-8859-15 character encoding (i54980)
+          Rationale: ISO-8859-15 is the default encoding of the French OpenOffice.org
+          dictionary. ISO-8859-15 is a modified version of ISO-8859-1
+          (latin-1) character encoding with French œ ligatures and euro
+	  symbol. Problem reported by cbrunet at OOo in OOo Issue 54980:
+          http://qa.openoffice.org/issues/show_bug.cgi?id=54980
+
+        * src/hunspell/affixmgr.cxx: fix zero-byte malloc after a bad affix header.
+          Patch by Harri Pitkänen.
+
+	* src/hunspell/suggestmgr.cxx: fix bad NEEDAFFIX word suggestion
+          in ngram suggestions. Reported by Daniel Naber and Friedel Wolff.
+
+        * src/hunspell/hashmgr.cxx: fix bad white space checking in affix files.
+          src/hunspell/{csutil,affixmgr}.cxx: add other white space separators.
+          Problems with tabulators reported by Frederik Fouvry.
+
+        * src/hunspell/*: replace system-dependent <license.*> #include
+          parameters with quoted ones. Problem reported by Dafydd Jones.
+
+	* src/hunspell/hunspell.cxx: fix missing morphological analysis of dot(s)
+          Reported by Trón Viktor.
+
+changes:
+	* src/hunspell/affixmgr.cxx: rename PSEUDOROOT to NEEDAFFIX.
+	  Suggested by Bram Moolenaar.
+
+        * src/hunspell/suggestmgr.hxx: Increase default maximum of 
+          ngram suggestions (3->5). Suggested by Kevin Hendricks.
+
+        * src/hunspell/htypes.hxx: Increase MAXDELEN for long affix flags.
+
+        * src/hunspell/suggestmgr.cxx: modify (perhaps fix) Unicode map suggestion.
+          tests/maputf test fail on ARM platform reported by Rene Engelhard.
+
+        * src/hunspell/{affentry.cxx,atypes.hxx}: remove [PREFIX] and
+          MISSING_DESCRIPTION messages from morphological analysis.
+          Problems reported by Trón Viktor.
+
+	* tests/germancompounding.{aff,good}: Add "Computer-Arbeit" test word.
+          Suggested by Daniel Naber.
+
+        * doc/man/hunspell.4: Proof-reading patch by Goldman Eleonóra.
+          
+        * doc/man/hunspell.4: Fix bad affix example (replace `move' with `work').
+          Bug reported by Frederik Fouvry.
+          
+        * tests/*: new test files:
+          affixes.*: simple affix compression example from Hunspell 4 manual page
+          checkcompoundcase.*, checkcompoundcase2.*, checkcompoundcaseutf.*
+          compound.*, compound2.*, compound3.*, compound4.*, compound5.*
+          compoundflag.* (former compound.*)
+          flagutf8.*: test for FLAG UTF-8
+          germancompounding.*: simplification with CHECKCOMPOUNDCASE.
+          germancompoundingold.* (former germancompounding.*)
+          i53643.*: check numbers with separators
+          i54980.*: ISO8859-15 test
+          keepcase.*: test for KEEPCASE
+          needaffix*.* (former pseudoroot*.* tests)
+          nosuggest.*: test for NOSUGGEST
+
 2005-09-19 Németh László <nemethl@gyorsposta.hu>:
 	* src/hunspell/suggestmgr.cxx: improved ngram suggestion:
         - detect not neighboring swap characters (pernament -> permanent)
@@ -85,7 +185,7 @@ improvements:
 
 	* src/hunspell/{suggestmgr,affixmgr,hunspell}.cxx: improve ngram suggestion.
 	  Fix http://qa.openoffice.org/issues/show_bug.cgi?id=35725. See release
-          notes for examples. This problem reported by beccablain at OpenOffice.org.
+          notes for examples. This problem reported by beccablain at OOo.
         - ngram suggestions now are case insensitive (see `Permenant' bug in Issuezilla)
         - weight ngram suggestions (with the longest common subsequent algorithm,
           also considering lengths of bad word and suggestion, identical first
diff --git a/NEWS b/NEWS
index f36279c..8779d40 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,23 @@
+2005-11-09: Hunspell 1.1.1 release:
+
+  - Compound word patterns for complex compound word handling and
+    simple word-level lexical scanning. Ideal for checking
+    Arabic and Roman numbers, ordinal numbers in English, affixed
+    numbers in agglutinative languages, etc.
+    http://qa.openoffice.org/issues/show_bug.cgi?id=53643
+
+  - Support ISO-8859-15 encoding for French (French oe ligatures are
+    missing from the latin-1 encoding).
+    http://qa.openoffice.org/issues/show_bug.cgi?id=54980
+    
+  - Implemented a flag to forbid obscene word suggestion:
+    http://qa.openoffice.org/issues/show_bug.cgi?id=55498
+
+  - Checked with 50 regression tests in Valgrind debugging environment,
+    and tested with 52 OOo dictionaries.
+
+  - other improvements and bug fixes (see ChangeLog)
+
 2005-09-19: Hunspell 1.1.0 release
 
 * complete comparison with MySpell 3.2 (from OpenOffice.org 2 beta)
diff --git a/THANKS b/THANKS
index 2ddccb9..0be5780 100644
--- a/THANKS
+++ b/THANKS
@@ -2,32 +2,40 @@ Bencsáth Boldizsár
 Bíró Árpád
 Dmitri Gabinski
 Dvornik László
+Rene Engelhard
+Frederik Fouvry
 Gefferth András
 Godó Ferenc
 Goldman Eleonóra
-Izsók András
 Halácsy Péter
+Chris Halls
+Izsók András
+Dafydd Jones
 Kevin Hendricks
 Khiraly
 Koblinger Egmont
 Kornai András
+Moheb Mekhaiel
 Bram Moolenaar
 Daniel Naber
+Nagy Viktor
 Noll János
+Harri Pitkänen
 Sarlós Tamás
 Trón Viktor 
 Varga Dániel
+Friedel Wolff
 and others (see also AUTHORS.myspell)
 
+MOKK Research Centre
+Budapest University of Technology and Economics
+Sociology and Communications Department
+http://www.mokk.bme.hu
 
 Hungarian Ministry of Informatics and Telecommunications
 
 IMEDIA Kft.
 
-MOKK Research Centre
-Budapest University of Technology and Economics
-Sociology and Communications Department
-
 UHU-Linux Kft.
 
 
diff --git a/configure b/configure
index 69f673b..b510d17 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for hunspell 1.1.0.
+# Generated by GNU Autoconf 2.59 for hunspell 1.1.1.
 #
 # Report bugs to <nemethl@gyorsposta.hu>.
 #
@@ -269,8 +269,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='hunspell'
 PACKAGE_TARNAME='hunspell'
-PACKAGE_VERSION='1.1.0'
-PACKAGE_STRING='hunspell 1.1.0'
+PACKAGE_VERSION='1.1.1'
+PACKAGE_STRING='hunspell 1.1.1'
 PACKAGE_BUGREPORT='nemethl@gyorsposta.hu'
 
 ac_unique_file="config.h.in"
@@ -788,7 +788,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures hunspell 1.1.0 to adapt to many kinds of systems.
+\`configure' configures hunspell 1.1.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -854,7 +854,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of hunspell 1.1.0:";;
+     short | recursive ) echo "Configuration of hunspell 1.1.1:";;
    esac
   cat <<\_ACEOF
 
@@ -987,7 +987,7 @@ fi
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-hunspell configure 1.1.0
+hunspell configure 1.1.1
 generated by GNU Autoconf 2.59
 
 Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1001,7 +1001,7 @@ cat >&5 <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by hunspell $as_me 1.1.0, which was
+It was created by hunspell $as_me 1.1.1, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   $ $0 $@
@@ -1644,7 +1644,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE=hunspell
- VERSION=1.1.0
+ VERSION=1.1.1
 
 
 cat >>confdefs.h <<_ACEOF
@@ -9052,7 +9052,7 @@ _ASBOX
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by hunspell $as_me 1.1.0, which was
+This file was extended by hunspell $as_me 1.1.1, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9115,7 +9115,7 @@ _ACEOF
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-hunspell config.status 1.1.0
+hunspell config.status 1.1.1
 configured by $0, generated by GNU Autoconf 2.59,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 
diff --git a/configure.ac b/configure.ac
index eb28bac..14f7b57 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,8 +4,8 @@
 m4_pattern_allow
 
 AC_PREREQ(2.59)
-AC_INIT([hunspell],[1.1.0],[nemethl@gyorsposta.hu])
-AM_INIT_AUTOMAKE(hunspell, 1.1.0)
+AC_INIT([hunspell],[1.1.1],[nemethl@gyorsposta.hu])
+AM_INIT_AUTOMAKE(hunspell, 1.1.1)
 AC_CONFIG_SRCDIR([config.h.in])
 AC_CONFIG_HEADER([config.h])
 
diff --git a/man/hunspell.4 b/man/hunspell.4
index 909d92c..50792ac 100644
--- a/man/hunspell.4
+++ b/man/hunspell.4
@@ -10,18 +10,18 @@ and  the  second is an "affix" file that defines the meaning of
 special flags in the dictionary.
 
 A dictionary file (*.dic) contains a list of words, one per line.
-First line of the dictionaries (except personal dictionaries)
+The first line of the dictionaries (except personal dictionaries)
 contains the word count. Each word may optionally be followed
 by a slash ("/") and one or more flags, which represents
 affixes or special attributes. Default flag format is a
-single (usually alphabetic) character. In Hunspell dictionary
+single (usually alphabetic) character. In a Hunspell dictionary
 file, there is also an optional morphological field separated
 by tabulator. Morphological desciptions have custom format.
 
 An affix file (*.aff) may contain a lot of optional attributes.
 For example,
 .B SET
-is used for setting the character encodings of affix and dictionary files.
+is used for setting the character encodings of affixes and dictionary files.
 .B TRY
 sets the change characters for suggestions.
 .B REP
@@ -30,9 +30,9 @@ suggestion mode.
 .B PFX
 and
 .B SFX
-definies prefix and suffix classes named with affix flags.
+defines prefix and suffix classes named with affix flags.
 
-The following affix file example definies UTF-8 character encoding.
+The following affix file example defines UTF-8 character encoding.
 `TRY' suggestions differ from the bad word with an English letter or
 an apostrophe. With these REP definitions, Hunspell can suggest
 the right word form, when the misspelled
@@ -59,7 +59,7 @@ SFX B y ied y
 .PP
 
 There are two affix classes in the dictionary. Class A
-definies an `re-' prefix. Class B definies two `-ed'
+defines an `re-' prefix. Class B defines two `-ed'
 suffixes. First suffix can be added to a word if
 the last character of the word isn't `y'.
 Second suffix can be added to words terminated with an `y'.
@@ -72,46 +72,113 @@ uses these affix classes.
 3
 hello
 try/B
-move/AB
+work/AB
 .fi
 .RE
 .PP
 
 All accepted words with this example:
-hello, try, tried, move, moved, remove, removed.
-
-.SH "OPTIONS"
+hello, try, tried, work, worked, rework, reworked.
 
+.SH "GENERAL OPTIONS"
 .IP "SET encoding"
 Set character encoding of words and morphemes in affix and dictionary files.
 Possible values: UTF-8, ISO8859\-1 \- ISO8859\-10, 
-ISO8859\-14, KOI8-R, KOI8-U, microsoft-cp1251, ISCII-DEVANAGARI.
+ISO8859\-13 \- ISO8859\-15, KOI8-R, KOI8-U, microsoft-cp1251, ISCII-DEVANAGARI.
+.IP "FLAG value"
+Set flag type. Default type is the extended ASCII (8-bit) character. 
+`UTF-8' parameter sets UTF-8 encoded Unicode character flags.
+The `long' value sets the double extended ASCII character flag type,
+the `num' sets the decimal number flag type. Decimal flags numbered from 1 to
+65535, and in flag fields are separated by comma.
+.IP "COMPLEXPREFIXES"
+Set twofold prefix stripping (but single suffix stripping) for agglutinative
+languages with right-to-left writing system.
+.IP "LANG langcode"
+Set language code. In Hunspell may be language specific codes enabled
+by LANG code. At present there are az_AZ, de_DE, hu_HU, TR_tr specific
+codes in Hunspell (see the source code).
+.SH "OPTIONS FOR SUGGESTION"
 .IP "TRY characters"
 Hunspell can suggest right word forms, when those differs from the
-bad form by one TRY character. Parameter of TRY is case sensitive.
-.IP "NOSPLITSUGS"
-Disable split-word suggestions.
+bad form by one TRY character. The parameter of TRY is case sensitive.
+.IP "NOSUGGEST flag"
+Words signed with NOSUGGEST flag are not suggested. Proposed flag
+for vulgar and obscene words.
 .IP "MAXNGRAMSUGS num"
 Set number of n-gram suggestions. Value 0 switches off the n-gram suggestions.
+.IP "NOSPLITSUGS"
+Disable split-word suggestions.
 .IP "SUGSWITHDOTS"
 Add dot(s) to suggestions, if input word terminates in dot(s).
 (Not for OpenOffice.org dictionaries, because OpenOffice.org
 has an automatic dot expansion mechanism.)
-.IP "LANG langcode"
-Set language code. In Hunspell may be language specific codes enabled
-by LANG code. At present there are az_AZ, de_DE, hu_HU, TR_tr specific
-codes in Hunspell (see program source).
-.IP "FLAG value"
-Set flag type. Default value is character. The `long' value sets
-the 2-character flag type, the `num' sets the decimal number flag type.
-Decimal flags numbered from 1 to 65535, and in flag fields are
-separated by comma.
-.IP "COMPLEXPREFIXES"
-Set twofold prefix stripping (but single suffix stripping) for agglutinative
-languages with right-to-left writing system.
+.IP "REP number_of_replacement_definitions"
+.IP "REP what replacement"
+We can define language-dependent phonetic information
+in the affix file (.aff)  by a replacement table. 
+First REP is the header of this table and one or more REP data
+line are following it. With this table, Hunspell can suggest the right forms for the typical 
+faults of spelling when the incorrect form differs by more, 
+than 1 letter from the right form.
+For example a possible English replacement table definition
+to handle misspelled consonants:
+.PP
+.RS
+.nf
+REP 8
+REP f ph
+REP ph f
+REP f gh
+REP gh f
+REP j dg
+REP dg j
+REP k ch
+REP ch k
+.fi
+.RE
+.PP
+Replacement table is also usable in robust morphological analysis (accepting
+bad forms) or stricter compound word support in spell checking (forbidding
+generated compound words, if they are also simple words with typical fault).
+.IP "MAP number_of_map_definitions"
+.IP "MAP string_of_related_chars"
+We can define language-dependent information on characters that
+should be considered related (ie. nearer than other chars not in the set)
+in the affix file (.aff)  by a character map table. With this 
+table, Hunspell can suggest the right forms for words, which
+incorrectly choose the wrong letter from a related set more than once
+in a word.
+
+For example a possible mapping could be for the German
+umlauted � versus the regular u; the word
+Fr�hst�ck really should be written with umlauted u's and not regular ones 
+.PP
+.RS
+.nf
+MAP 1
+MAP u�
+.fi
+.RE
+.PP
+.SH "OPTIONS FOR COMPOUNDING"
+.IP "COMPOUND number_of_compound_definitions"
+.IP "COMPOUND compound_pattern"
+Define custom compound patterns with a regex-like syntax.
+The first COMPOUND is a header with the number of the following
+COMPOUND definitions. Compound patterns consist compound flags and
+star or question mark meta characters. A flag followed by a `*' matches
+a word sequence of 0 or more matches of words signed with this compound flag.
+A flag followed by a `?' matches a word sequence of
+0 or 1 matches of a word signed with this compound flag.
+See tests/compound*.* examples. Note: `*' and `?' metacharacters
+work only with the default 8-bit character and the UTF-8 FLAG types.
+Note II: COMPOUND flags haven't been compatible with the COMPOUNDFLAG,
+COMPOUNDBEGIN, etc. compound flags yet (use these flags on different
+words).
 .IP "COMPOUNDMIN num"
 Minimum length of words in compound words.
-Default value is 3 letter.
+Default value is 3 letters.
 .IP "COMPOUNDFLAG flag"
 Words signed with COMPOUNDFLAG may be in compound words (except when
 word shorter than COMPOUNDMIN). Affixes with COMPOUNDFLAG also permits
@@ -124,11 +191,9 @@ Words signed with COMPOUNDFLAG (or with a signed affix) may be last elements in
 .IP "COMPOUNDMIDDLE flag"
 Words signed with COMPOUNDFLAG (or with a signed affix) may be middle elements in compound words.
 .IP "ONLYINCOMPOUND flag"
-Suffixes signed with ONLYINCOMPOUND flag may be only in inside of compounds
+Suffixes signed with ONLYINCOMPOUND flag may be only inside of compounds
 (Fuge-elements in German, fogemorphemes in Swedish).
-.IP "CIRCUMFIX flag"
-Affixes signed with CIRCUMFIX flag may be on a word when this word also has a
-prefix with CIRCUMFIX flag and vice versa.
+ONLYINCOMPOUND flag works also with words (see tests/onlyincompound.*).
 .IP "COMPOUNDPERMITFLAG flag"
 Prefixes are allowed at the beginning of compounds,
 suffixes are allowed at the end of compounds by default.
@@ -143,9 +208,11 @@ Set maximum word count in a compound word. (Default is unlimited.)
 .IP "CHECKCOMPOUNDDUP"
 Forbid word duplication in compounds (eg. foofoo).
 .IP "CHECKCOMPOUNDREP"
-Forbid compounding, if (this usually bad) compound word may be
+Forbid compounding, if the (usually bad) compound word may be
 a non compound word with a REP fault. Useful for languages with
 `compound friendly' orthography.
+.IP "CHECKCOMPOUNDCASE"
+Forbid upper case characters at word bound in compounds.
 .IP "CHECKCOMPOUNDTRIPLE"
 Forbid compounding, if compound word contains triple letters
 (eg. foo|ox or xo|oof).
@@ -155,26 +222,6 @@ Bug: missing multi-byte character support in UTF-8 encoding
 .IP "CHECKCOMPOUNDPATTERN endchars beginchars"
 Forbid compounding, if first word in compound ends with endchars, and
 next word begins with beginchars.
-.IP "FORBIDDENWORD flag"
-This flag signs forbidden word form. Because affixed forms
-are also forbidden, we can substract a subset from set of
-the accepted affixed and compound words.
-.IP "PSEUDOROOT flag"
-This flag signs virtual stems in dictionary.
-Only affixed forms of these words will be accepted by Hunspell.
-Except, if dictionary word has a homonym or a zero affix.
-.IP "WORDCHARS characters"
-WORDCHARS extends tokenizer of Hunspell command line interface with
-additional word character. For example, dot, dash, n-dash, numbers, percent sign
-are word character in Hungarian. (This attribute haven't worked with
-UTF-8 encoding yet.)
-.IP "LEMMA_PRESENT flag"
-Generally, there are dictionary words as lemmas in output of
-morphological analysis. Sometimes dictionary words are not lemmas,
-but affixed (not real) stems and virtual stems. In this case
-lemmas (real stems) need to put into morphological description, and
-forbid not real lemmas in morphological analysis adding
-LEMMA_PRESENT flag to dictionary words.
 .IP "COMPOUNDSYLLABLE max_syllable vowels"
 Need for special compounding rules in Hungarian.
 First parameter is the maximum syllable number, that may be in a
@@ -182,70 +229,21 @@ compound, if words in compounds are more than COMPOUNDWORDMAX.
 Second parameter is the list of vowels (for calculating syllables).
 .IP "SYLLABLENUM flags"
 Need for special compounding rules in Hungarian.
-.IP "ACCENT accented_letters letters_without_accent"
-Deprecated. MAP is a better mechanism for suggesting accented words.
-.IP "REP number_of_replacement_definitions"
-.IP "REP what replacement"
-We can define language-dependent phonetic information
-in the affix file (.aff)  by a replacement table. 
-First REP is the header of this table and one or more REP data
-line are following it. With this table, MySpell can suggest the right forms for the typical 
-faults of spelling when the incorrect form differs by more, 
-than 1 letter from the right form.
-For example a possible English replacement table definition
-to handle misspelt consonants:
-.PP
-.RS
-.nf
-REP 8
-REP f ph
-REP ph f
-REP f gh
-REP gh f
-REP j dg
-REP dg j
-REP k ch
-REP ch k
-.fi
-.RE
-.PP
-Replacement table is also usable in robust morphological analysis (accepting
-bad forms) or stricter compound word support in spell checking (forbidding
-generated compound words, if they are also simple words with typical fault).
-.IP "MAP number_of_map_definitions"
-.IP "MAP string_of_related_chars"
-We can define language-dependent information on characters that
-should be considered related (ie. nearer than other chars not in the set)
-in the affix file (.aff)  by a character map table. With this 
-table, MySpell can suggest the right forms for words which
-incorrectly choose the wrong letter from a related set more than once
-in a word.
-
-For example a possible mapping could be for the German
-umlauted � versus the regular u. 
-For example Fr�hst�ck really should be written with umlauted u's and not regular ones 
-.PP
-.RS
-.nf
-MAP 1
-MAP u�
-.fi
-.RE
-.PP
+.SH "OPTIONS FOR AFFIX CREATION"
 .IP "PFX flag cross_product number"
 .IP "PFX flag stripping prefix condition morphological_description"
 .IP "SFX flag cross_product number"
 .IP "SFX flag stripping suffix condition morphological_description"
 An affix is either a prefix or a suffix attached to root words to make 
 other words. We can define affix classes with arbitrary number affix rules.
-Affix classes signed with affix flags. First line of an affix class definition
-is the header. Fields of an affix class header:
+Affix classes are signed with affix flags. The first line of an affix class definition
+is the header. The fields of an affix class header:
 
 (0) Option name (PFX or SFX)
 
 (1) Flag (name of the affix class)
 
-(2) Cross product (permission to combinate prefixes and suffixes).
+(2) Cross product (permission to combine prefixes and suffixes).
 Possible values: Y (yes) or N (no)
 
 (3) Line count of the following rules.
@@ -265,15 +263,49 @@ end (at suffix rules) of the word
 
 Zero stripping or affix are indicated by zero. Zero condition is indicated by dot.
 Condition is a simplified, regular expression-like pattern, which must be met
-before the affix can be applied. (Dot signs arbitrary character. Characters in braces
+before the affix can be applied. (Dot signs an arbitrary character. Characters in braces
 sign an arbitrary character from the character subset. Dash hasn't got special
-meaning, but circumflex (^) next the first brace sets complementer character set.)
+meaning, but circumflex (^) next the first brace sets the complementer character set.)
 
 (5) Custom morphological description.
 
+.SH "OTHER OPTIONS"
+.IP "CIRCUMFIX flag"
+Affixes signed with CIRCUMFIX flag may be on a word when this word also has a
+prefix with CIRCUMFIX flag and vice versa.
+.IP "FORBIDDENWORD flag"
+This flag signs forbidden word form. Because affixed forms
+are also forbidden, we can substract a subset from set of
+the accepted affixed and compound words.
+.IP "KEEPCASE flag"
+Forbid capitalized and uppercased forms of words 
+signed with KEEPCASE flags. Useful for special ortographies 
+(measurements and currency often keep their case in uppercased
+texts) and writing systems (eg. keeping lower case of IPA characters).
+.IP "LEMMA_PRESENT flag"
+Generally, there are dictionary words as lemmas in output of
+morphological analysis. Sometimes dictionary words are not lemmas,
+but affixed (not real) stems and virtual stems. In this case
+lemmas (real stems) need to put into morphological description, and
+forbid not real lemmas in morphological analysis adding
+LEMMA_PRESENT flag to dictionary words.
+.IP "NEEDAFFIX flag"
+This flag signs virtual stems in the dictionary.
+Only affixed forms of these words will be accepted by Hunspell.
+Except, if the dictionary word has a homonym or a zero affix.
+NEEDAFFIX works also with prefixes and prefix + suffix combinations
+(see tests/pseudoroot5.*).
+.IP "PSEUDOROOT flag"
+Deprecated. (Former name of the NEEDAFFIX option.)
+.IP "WORDCHARS characters"
+WORDCHARS extends tokenizer of Hunspell command line interface with
+additional word character. For example, dot, dash, n-dash, numbers, percent sign
+are word character in Hungarian. (This attribute haven't worked with
+UTF-8 encoding yet.)
+
 .SH "Morphological analysis"
 
-Hunmorph's affix rules has got an optional morphological description field.
+Hunspell's affix rules have got an optional morphological description field.
 There is a similar optional field in dictionary file, separated by tabulator:
 
 .PP
@@ -284,7 +316,7 @@ There is a similar optional field in dictionary file, separated by tabulator:
 .RE
 .PP
 
-We defines a simple resource with morphological informations.
+We define a simple resource with morphological informations.
 
 Affix file:
 
@@ -336,13 +368,13 @@ style.
 
 .SH "Twofold suffix stripping"
 
-Ispell's original algorithm strips only one suffix. Hunmorph can strip another one yet. 
+Ispell's original algorithm strips only one suffix. Hunspell can strip another one yet. 
 
 The twofold suffix stripping is a significant improvement in
-handling of immense number of suffixes, that characterized the agglutinative languages.
+handling of immense number of suffixes, that characterize agglutinative languages.
 
 Extending the previous example by adding a second suffix (affix class Y
-will be the continuation class of able suffix): 
+will be the continuation class of the suffix `able'):
 
 .PP
 .RS
@@ -393,7 +425,7 @@ Test:
 
 Theoretically with the twofold suffix stripping
 needs only the square root of the number of suffix rules,
-compared with a MySpell implementation. In our practice, we could have
+compared with a Hunspell implementation. In our practice, we could have
 elaborated the Hungarian inflectional morphology with twofold
 suffix stripping.
 (Note: In Hunlex preprocessor's grammar can be use not only
@@ -401,7 +433,7 @@ twofold, but multiple suffix slitting.)
 
 .SH "Extended affix classes"
 
-Hunmorph can handle more than 65000 affix classes.
+Hunspell can handle more than 65000 affix classes.
 There are two new syntax for giving flags in affix and dictionary files.
 
 \fIFLAG long\fR command sets 2-character flags:
@@ -450,7 +482,7 @@ Dictionary example:
 
 .SH "Homonyms"
 
-Hunmorph's dictionary can contain repeating elements that is homonyms:
+Hunspell's dictionary can contain repeating elements that is homonyms:
 
 .PP
 .RS
@@ -501,7 +533,7 @@ This feature also gives a way to forbid illegal prefix/suffix combinations in di
 
 .SH "Prefix--suffix dependencies"
 
-An interesting side-effect of multi-step stripping is that the
+An interesting side-effect of multi-step stripping is, that the
 appropriate treatment of circumfixes now comes for free.  For
 instance, in Hungarian, superlatives are formed by simultaneous
 prefixation of \fIleg-\fR and suffixation of \fI-bb\fR to the
@@ -509,7 +541,7 @@ adjective base.  A problem with the one-level architecture is that
 there is no way to render lexical licensing of particular prefixes and
 suffixes interdependent, and therefore incorrect forms are recognized
 as valid, i.e. *\fIlegv�n\fR = \fIleg\fR + \fIv�n\fR `old'. Until
-the introduction of clusters a special treatment of the superlative
+the introduction of clusters, a special treatment of the superlative
 had to be hardwired in the earlier \fBHunSpell\fR code. This may have
 been legitimate for a single case, but in fact prefix--suffix
 dependences are ubiquitous in category-changing derivational patterns
@@ -583,7 +615,7 @@ Unknown word.
 
 .SH "Circumfix"
 
-Conditional affixes implemented by continuation class are not enough for
+Conditional affixes implemented by a continuation class are not enough for
 circumfixes, because a circumfix is one affix
 in morphology. We also need CIRCUMFIX option for correct
 morphological analysis.
@@ -675,29 +707,28 @@ This, however, is still insufficient to handle the intricate patterns
 of compounding, not to mention idiosyncratic (and language specific)
 norms of hyphenation.
 
-The \fBMySpell\fR algorithm currently allows any affixed form of words
+The \fBHunspell\fR algorithm currently allows any affixed form of words,
 which are lexically marked as potential members of compounds. \fBHunspell\fR
-improved upon this, and its recursive compound checking
+improved this, and its recursive compound checking
 rules makes it possible to implement the intricate spelling
 conventions of Hungarian compounds. For example, using COMPOUNDWORDMAX,
 COMPOUNDSYLLABLE, COMPOUNDROOT, SYLLABLENUM
 options can be set the noteworthy Hungarian `6--3' rule.
 Further example in Hungarian, derivate suffixes often modify compounding
-properties, hence in Hunmorph can be also use the compounding flags on
-affixes, and there is also a special flag
-(COMPOUNDFORBIDFLAG) to prohibit compounding of the derivations.
+properties. Hunspell allows the compounding flags on the
+affixes, and there are two special flags (COMPOUNDPERMITFLAG and
+(COMPOUNDFORBIDFLAG) to permit or prohibit compounding of the derivations.
 
 Suffixes with this flag forbid compounding of the affixed word.
 
-We also need several Hunmorph features for handling German compounding:
+We also need several Hunspell features for handling German compounding:
 
 .PP
 .RS
 .nf
 # German compounding
 
-# set language for handling compound words with dash
-# and special casing of German sharp s
+# set language to handle special casing of German sharp s
 
 LANG de_DE
 
@@ -719,9 +750,8 @@ COMPOUNDPERMITFLAG P
 
 ONLYINCOMPOUND X
 
-# for decapitalizing nouns with fogemorphemes
-
-CIRCUMFIX Y
+# forbid uppercase characters at compound word bounds
+CHECKCOMPOUNDCASE
 
 # for handling Fuge-elements with dashes (Arbeits-) 
 # dash will be a special word
@@ -733,35 +763,37 @@ WORDCHARS -
 
 SFX A Y 3
 SFX A 0 s/UPX .
-SFX A 0 s/VPXDY .
-SFX A 0 0/WXDY .
-
-# compound settings for `Computer'
+SFX A 0 s/VPDX .
+SFX A 0 0/WXD .
 
 SFX B Y 2
 SFX B 0 0/UPX .
-SFX B 0 0/VWPXDY .
+SFX B 0 0/VWXDP .
 
 # a suffix for `Computer'
 
-SFX C Y 2
-SFX C 0 en .
-SFX C 0 en/WXDY .
+SFX C Y 1
+SFX C 0 n/WD .
 
-# for forbid exceptions <*Arbeitsnehmer>
+# for forbid exceptions (*Arbeitsnehmer)
 
 FORBIDDENWORD Z
 
+# dash prefix for compounds with dash (Arbeits-Computer)
+
+PFX - Y 1
+PFX - 0 -/P .
+
 # decapitalizing prefix
 # circumfix for positioning in compounds
 
 PFX D Y 29
-PFX D A a/PXY A
-PFX D � �/PXY �
+PFX D A a/PX A
+PFX D � �/PX �
  .
  .
-PFX D Y y/PXY Y
-PFX D Z z/PXY Z
+PFX D Y y/PX Y
+PFX D Z z/PX Z
 .fi
 .RE
 .PP
@@ -772,8 +804,8 @@ Example dictionary:
 .RS
 .nf
 4
-Arbeit/IJKC
-Computer/UAC
+Arbeit/A-
+Computer/BC-
 -/W
 Arbeitsnehmer/Z
 .fi
@@ -786,18 +818,18 @@ Accepted compound compound words with the previous resource:
 .RS
 .nf
 Computer
-Computeren
+Computern
 Arbeit
 Arbeits-
 Computerarbeit
 Computerarbeits-
 Arbeitscomputer
-Arbeitscomputeren
+Arbeitscomputern
 Computerarbeitscomputer
-Computerarbeitscomputeren
+Computerarbeitscomputern
 Arbeitscomputerarbeit
 Computerarbeits-Computer
-Computerarbeits-Computeren
+Computerarbeits-Computern
 .fi
 .RE
 .PP
@@ -843,7 +875,7 @@ language like Hungarian has a standard ASCII character set
 (ISO 8859-2), it fails to allow a full implementation of Hungarian
 orthographic conventions.  For instance, the '--' symbol (n-dash) is
 missing from this character set contrary to the fact that it is not
-only the official symbol to delimit paranthetic clauses in the language,
+only the official symbol to delimit parenthetic clauses in the language,
 but it can be in compound words as a special 'big' hyphen.
 
 MySpell has got some 8-bit encoding tables, but there are languages
@@ -863,16 +895,16 @@ The problems raised in relation to 8-bit ASCII encoding have long been
 recognized by proponents of Unicode. Unfortunately, switching to
 Unicode (e.g., UTF-16 encoding) would require a great deal of code
 optimization and would have an impact on the efficiency of the
-algorithm. The D�m�lki algorithm used in checking affixation
+algorithm. The D�m�lki algorithm used in checking affixing
 conditions utilizes 256-byte character arrays, which 
 would grow to 64k with Unicode encoding. Since online
-affixation for a richly agglutinative language can easily have several
+affixing for a richly agglutinative language can easily have several
 hundred such arrays (in the case of the standard Hungarian resources we use, this
 number is ca. 300 or more since redundant storage of structurally
 identical affix patterns improves efficiency), switching to Unicode would
 incur high resource costs.
 Nonetheless, it is clear that trading efficiency for encoding-independence has
-its advantages when it comes a truely multi-lingual application, therefore it
+its advantages when it comes a truly multi-lingual application, therefore it
 was among our plans for a long while to extend the architecture in this direction.
 
 A hybrid solution
diff --git a/src/hunspell/affentry.cxx b/src/hunspell/affentry.cxx
index b659ac2..2f00149 100644
--- a/src/hunspell/affentry.cxx
+++ b/src/hunspell/affentry.cxx
@@ -1,5 +1,5 @@
-#include <license.hunspell>
-#include <license.myspell>
+#include "license.hunspell"
+#include "license.myspell"
 
 #include <cctype>
 #include <cstring>
@@ -681,9 +681,6 @@ char * SfxEntry::check_twosfx_morph(const char * word, int len, int optflags,
                         if (st) {
                             if (((PfxEntry *) ppfx)->getMorph()) {
                                 strcat(result, ((PfxEntry *) ppfx)->getMorph());
-                            } else {
-                                strcat(result,((PfxEntry *) ppfx)->getKey());
-                                strcat(result,"[PREFIX]");
                             }
                             strcat(result,st);
                             free(st);
diff --git a/src/hunspell/affixmgr.cxx b/src/hunspell/affixmgr.cxx
index c971e2b..b807408 100644
--- a/src/hunspell/affixmgr.cxx
+++ b/src/hunspell/affixmgr.cxx
@@ -1,8 +1,9 @@
-#include <license.hunspell>
-#include <license.myspell>
+#include "license.hunspell"
+#include "license.myspell"
 
 #include <cstdlib>
 #include <cstring>
+#include <cctype>
 #include <cstdio>
 
 #include "affixmgr.hxx"
@@ -31,6 +32,8 @@ AffixMgr::AffixMgr(const char * affpath, HashMgr* ptr)
   numrep = 0;
   checkcpdtable = NULL;
   numcheckcpd = 0;
+  defcpdtable = NULL;
+  numdefcpd = 0;
   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
@@ -39,9 +42,11 @@ AffixMgr::AffixMgr(const char * affpath, HashMgr* ptr)
   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
+  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
@@ -67,6 +72,7 @@ AffixMgr::AffixMgr(const char * affpath, HashMgr* ptr)
   maxngramsugs = -1; // undefined
   nosplitsugs = 0;
   sugswithdots = 0;
+  keepcase = 0;
 
   derived = NULL; // XXX not threadsafe variable for experimental stemming
   sfx = NULL;
@@ -147,6 +153,14 @@ AffixMgr::~AffixMgr()
      free(reptable);  
      reptable = 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++) {
@@ -167,6 +181,7 @@ AffixMgr::~AffixMgr()
   FREE_FLAG(compoundforbidflag);
   FREE_FLAG(compoundroot);
   FREE_FLAG(forbiddenword);
+  FREE_FLAG(nosuggest);
   FREE_FLAG(pseudoroot);
   FREE_FLAG(lemma_present);
   FREE_FLAG(circumfix);
@@ -302,18 +317,24 @@ int  AffixMgr::parse_file(const char * affpath)
           }
        }
 
-       /* parse CHECKCOMPOUNDDUP */
        if (strncmp(line,"CHECKCOMPOUNDDUP",16) == 0)
 		   checkcompounddup = 1;
 
-       /* parse CHECKCOMPOUNDREP */
        if (strncmp(line,"CHECKCOMPOUNDREP",16) == 0)
 		   checkcompoundrep = 1;
 
-       /* parse CHECKCOMPOUNDTRIPLE */
        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")) {
+             return 1;
+          }
+       }
+
        /* parse in the flag used by forbidden words */
        if (strncmp(line,"FORBIDDENWORD",13) == 0) {
           if (parse_flag(line, &forbiddenword, "FORBIDDENWORD")) {
@@ -349,6 +370,13 @@ int  AffixMgr::parse_file(const char * affpath)
           }
        }
 
+       /* parse in the flag used by `pseudoroots' */
+       if (strncmp(line,"NEEDAFFIX",9) == 0) {
+          if (parse_flag(line, &pseudoroot, "NEEDAFFIX")) {
+             return 1;
+          }
+       }
+
        /* parse in the minimal length for words in compounds */
        if (strncmp(line,"COMPOUNDMIN",11) == 0) {
           if (parse_num(line, &cpdmin, "COMPOUNDMIN")) {
@@ -397,6 +425,13 @@ int  AffixMgr::parse_file(const char * affpath)
           }
        }
 
+       /* parse in the defcompound table */
+       if ((strncmp(line,"COMPOUND",8) == 0) && isspace(line[8])) {
+          if (parse_defcpdtable(line, afflst)) {
+             return 1;
+          }
+       }
+
        /* parse in the related character map table */
        if (strncmp(line,"MAP",3) == 0) {
           if (parse_maptable(line, afflst)) {
@@ -411,28 +446,31 @@ int  AffixMgr::parse_file(const char * affpath)
           }
        }
 
-       /* parse in the version string */
        if (strncmp(line,"VERSION",7) == 0) {
           if (parse_version(line)) {
              return 1;
           }
        }
 
-       /* parse MAXNGRAMSUGS */
        if (strncmp(line,"MAXNGRAMSUGS",12) == 0) {
           if (parse_num(line, &maxngramsugs, "MAXNGRAMSUGS")) {
              return 1;
           }
        }
 
-       /* parse NOSPLITSUGS */
        if (strncmp(line,"NOSPLITSUGS",11) == 0)
 		   nosplitsugs=1;
 
-       /* parse SUGSWITHDOTS */
        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")) {
+             return 1;
+          }
+       }
+
        /* parse this affix: P - prefix, S - suffix */
        ft = ' ';
        if (strncmp(line,"PFX",3) == 0) ft = complexprefixes ? 'S' : 'P';
@@ -481,7 +519,6 @@ int  AffixMgr::parse_file(const char * affpath)
 
     // expand wordchars string, based on csutil (for external tokenization)
 
-    struct cs_info * csconv;
     char * enc = get_encoding();
     csconv = get_current_cs(enc);
     free(enc);
@@ -489,16 +526,16 @@ int  AffixMgr::parse_file(const char * affpath)
 
     char expw[MAXLNLEN];
     if (wordchars) {
-	strcpy(expw, wordchars);
-	free(wordchars);
+        strcpy(expw, wordchars);
+        free(wordchars);
     } else *expw = '\0';
 
     for (int i = 0; i <= 255; i++) {
-	if ( (csconv[i].cupper != csconv[i].clower) &&
-	    (! strchr(expw, (char) i))) {
-		*(expw + strlen(expw) + 1) = '\0';
-		*(expw + strlen(expw)) = (char) i;
-	    }
+        if ( (csconv[i].cupper != csconv[i].clower) &&
+            (! strchr(expw, (char) i))) {
+                *(expw + strlen(expw) + 1) = '\0';
+                *(expw + strlen(expw)) = (char) i;
+        }
     }
 
     wordchars = mystrdup(expw);
@@ -1140,8 +1177,8 @@ char * AffixMgr::prefix_check_twosfx_morph(const char * word, int len,
 }
 
 
-// check compounds with replacement table (see checkcompoundrep)
-int AffixMgr::repl_check(const char * word, int wl)
+// 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;
@@ -1167,8 +1204,8 @@ int AffixMgr::repl_check(const char * word, int wl)
    return 0;
 }
 
-// forbid compoundings when there are special patterns at connection.
-int AffixMgr::checkcpd_check(const char * word, int pos)
+// 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++) {
@@ -1179,6 +1216,104 @@ int AffixMgr::checkcpd_check(const char * word, int pos)
   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 (utf_tbl[a].cletter && utf_tbl[a].cletter &&
+          ((utf_tbl[a].cupper == a) || (utf_tbl[b].cupper == 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)
+{
+  short btpp[MAXWORDLEN]; // metacharacter (*, ?) positions for backtracking
+  short btwp[MAXWORDLEN]; // word positions for metacharacters
+  char 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++) {
+    int pp = 0; // pattern position
+    int 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;
+            btwp[bt] = 0;
+            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]->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) break;
+    // 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;
@@ -1206,8 +1341,8 @@ int AffixMgr::get_syllable(const char * word, int wlen)
 	    if (strchr(cpdvowels, word[i])) num++;
         }
     } else if (cpdvowels_utf16) {
-        w_char w[MAXWORDLEN];
-        int i = u8_u16(w, MAXWORDLEN, word);
+        w_char w[MAXWORDUTF8LEN];
+        int i = u8_u16(w, MAXWORDUTF8LEN, word);
         for (; i; i--) {
             if (flag_bsearch((unsigned short *) cpdvowels_utf16,
                 ((unsigned short *) w)[i - 1], cpdvowels_utf16_len)) num++;
@@ -1217,22 +1352,23 @@ int AffixMgr::get_syllable(const char * word, int wlen)
 }
 
 // check if compound word is correctly spelled
-// hu_mov_rule = Hungarian ``moving rule''
+// hu_mov_rule = spec. Hungarian rule (XXX)
 struct hentry * AffixMgr::compound_check(const char * word, int len, 
-    int wordnum, int numsyllable, int maxwordnum,
-    int hu_mov_rule = 0, int * cmpdstemnum = NULL, int * cmpdstem = NULL)
+    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, 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;
-    // XXX
+
 #ifdef HUNSTEM
     if (cmpdstemnum) {
 	if (wordnum == 0) {
@@ -1242,7 +1378,6 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
 	}
     }
 #endif
-    
     if (utf8) {
         for (cmin = 0, i = 0; (i < cpdmin) && word[cmin]; i++) {
           cmin++;
@@ -1260,6 +1395,7 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
     strcpy(st, word);
 
     for (i = cmin; i < cmax; i++) {
+
         oldnumsyllable = numsyllable;
         oldwordnum = wordnum;
         checked_prefix = 0;
@@ -1269,9 +1405,11 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
             for (; (st[i] & 0xc0) == 0x80; i++);
             if (i >= cmax) return NULL;
         }
+
 	
         ch = st[i];
         st[i] = '\0';
+
         sfx = NULL;
         pfx = NULL;
         
@@ -1280,20 +1418,23 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
         rv = lookup(st); // perhaps without prefix
 
         // search homonym with compound flag
-        while ((rv) && 
+        while ((rv) && !hu_mov_rule &&
             ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
-		!((compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-	          (compoundbegin && (!wordnum) &&
+		!((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
+	          (compoundbegin && !wordnum &&
                         TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
-                  (compoundmiddle && wordnum &&
-                    TESTAFF(rv->astr, compoundmiddle, rv->alen))))) {
+                  (compoundmiddle && wordnum && !words &&
+                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
+                  (numdefcpd && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))
+                  ))) {
             rv = rv->next_homonym;
         }
 
         if (!rv) {
-            if (compoundflag && !(rv = prefix_check(st, i, IN_CPD_BEGIN, compoundflag))) {
+            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, IN_CPD_BEGIN)) &&
+                        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 &&
@@ -1304,21 +1445,23 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
             }
             if (rv ||
               (((wordnum == 0) && compoundbegin &&
-                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, IN_CPD_BEGIN)) ||
-                (rv = prefix_check(st, i, IN_CPD_BEGIN, 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, IN_CPD_BEGIN)) ||
-                (rv = prefix_check(st, i, IN_CPD_BEGIN, 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))) {
+            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) && 
+            if ((rv) && !hu_mov_rule &&
                 ((pfx && ((PfxEntry*)pfx)->getCont() &&
                     TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, 
                         ((PfxEntry*)pfx)->getContLen())) ||
@@ -1329,7 +1472,7 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
             }
 
             // check compoundend flag in suffix and prefix
-            if ((rv) && !checked_prefix && compoundend &&
+            if ((rv) && !checked_prefix && compoundend && !hu_mov_rule &&
                 ((pfx && ((PfxEntry*)pfx)->getCont() &&
                     TESTAFF(((PfxEntry*)pfx)->getCont(), compoundend, 
                         ((PfxEntry*)pfx)->getContLen())) ||
@@ -1339,8 +1482,8 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
                     rv = NULL;
             }
 	    
-            // check compoundend flag in suffix and prefix
-            if ((rv) && !checked_prefix && (wordnum==0) && compoundmiddle &&
+            // 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())) ||
@@ -1351,7 +1494,10 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
             }	    
 
 	// check forbiddenwords
-	if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) return NULL;
+	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 && 
@@ -1361,41 +1507,47 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
 
 	// first word is acceptable in compound words?
 	if (((rv) && 
-	  ( checked_prefix ||
+	  ( 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))
-//MAGYARISPELL
+	    ((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 Magyar Ispell codes
+		    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 word[i+1] == '\0'
+                      ((word[i-1]==word[i+1])) // may be word[i+1] == '\0'
 		   )
                ) ||
                ( 
                  // test CHECKCOMPOUNDPATTERN
-	         numcheckcpd && checkcpd_check(word, i)
-	       ))
+	         numcheckcpd && cpdpat_check(word, i)
+	       ) ||
+               ( 
+	         checkcompoundcase && cpdcase_check(word, i)
+               ))
          )
-//MAGYARISPELL
+// LANG_hu section: spec. Hungarian rule
          || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) &&
-              (sfx && ((SfxEntry*)sfx)->getCont() && (
+              (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);
@@ -1403,6 +1555,7 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
 	        // + 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;
@@ -1414,20 +1567,23 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
 
         // search homonym with compound flag
         while ((rv) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
-			!((compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-			  (compoundend && (TESTAFF(rv->astr, compoundend, 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;
 
-	    // fonev_morfo
-//MAGYARISPELL
+// 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))) {
@@ -1435,7 +1591,9 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
 	    }
 
 	    // check forbiddenwords
-	    if ((rv) && (rv->astr) && TESTAFF(rv->astr,forbiddenword,rv->alen)) return NULL;
+	    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,
@@ -1456,7 +1614,7 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
 		)
 		 {
 		      // forbid compound word, if it is a non compound word with typical fault
-		      if (checkcompoundrep && repl_check(word,len)) return NULL;
+		      if (checkcompoundrep && cpdrep_check(word,len)) return NULL;
 		      return rv;
 	    }
 
@@ -1472,6 +1630,11 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
                 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;
+            }
 
             // check non_compound flag in suffix and prefix
             if ((rv) && 
@@ -1485,7 +1648,8 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
             }
 
 	    // check forbiddenwords
-	    if ((rv) && (rv->astr) && TESTAFF(rv->astr,forbiddenword,rv->alen)) return NULL;
+	    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.
@@ -1539,7 +1703,7 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
 		   (!checkcompounddup || (rv != rv_first))
 		   )) {
 		    // forbid compound word, if it is a non compound word with typical fault
-		    if (checkcompoundrep && repl_check(word, len)) return NULL;
+		    if (checkcompoundrep && cpdrep_check(word, len)) return NULL;
 		    return rv;
 	    }
 
@@ -1551,13 +1715,14 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
 	    // perhaps second word is a compound word (recursive call)
 	    if (wordnum < maxwordnum) {
 		rv = compound_check((word+i),strlen(word+i), wordnum+1,
-		     numsyllable, maxwordnum, 0, cmpdstemnum, cmpdstem);
+		     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 && repl_check(word, len)) return NULL;
+		if (checkcompoundrep && cpdrep_check(word, len)) return NULL;
 		return rv;
 	    } else {
 #ifdef HUNSTEM
@@ -1569,21 +1734,23 @@ struct hentry * AffixMgr::compound_check(const char * word, int len,
 	wordnum = oldwordnum;
 	numsyllable = oldnumsyllable;
     }
+    
     return NULL;
 }    
 
 
 // check if compound word is correctly spelled
-// hu_mov_rule = mozg�szab�ly
+// hu_mov_rule = spec. Hungarian rule (XXX)
 int AffixMgr::compound_check_morph(const char * word, int len, 
-    int wordnum, int numsyllable, int maxwordnum,
-    int hu_mov_rule = 0, char ** result = NULL, char * partresult = NULL)
+    short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words,
+    char hu_mov_rule = 0, char ** result = NULL, char * partresult = NULL)
 {
     int i, oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
-	int ok = 0;
+    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;
     
@@ -1613,26 +1780,33 @@ int AffixMgr::compound_check_morph(const char * word, int len,
 	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) && (rv->next_homonym) && 
+        while ((rv) && !hu_mov_rule && 
             ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
-		!((compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-	        (compoundbegin && (!wordnum) &&
+		!((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
+	        (compoundbegin && !wordnum &&
                         TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
-                (compoundmiddle && wordnum &&
-                    TESTAFF(rv->astr, compoundmiddle, rv->alen))))) {
+                (compoundmiddle && wordnum && !words &&
+                    TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
+                  (numdefcpd && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0))
+                  ))) {
             rv = rv->next_homonym;
         }
 
@@ -1641,17 +1815,16 @@ int AffixMgr::compound_check_morph(const char * word, int len,
                 if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen))
 					strcat(presult, st);
                 strcat(presult, rv->description);
-            } else {
-            	strcat(presult, st);
-                strcat(presult, MISSING_DESCRIPTION);
             }
         }
         
         if (!rv) {
-            if (compoundflag && !(rv = prefix_check(st, i, IN_CPD_BEGIN, compoundflag))) {
-                if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundflag, 0)) &&
-                    ((SfxEntry*)sfx)->getCont() && ((compoundforbidflag &&
-                        TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, 
+            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())))) {
@@ -1659,13 +1832,13 @@ int AffixMgr::compound_check_morph(const char * word, int len,
                 }
             }
             
-            if (rv || 
+            if (rv ||
               (((wordnum == 0) && compoundbegin &&
-                ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, IN_CPD_BEGIN)) ||                
-                (rv = prefix_check(st, i, IN_CPD_BEGIN, 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, IN_CPD_BEGIN)) ||
-                (rv = prefix_check(st, i, IN_CPD_BEGIN, 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;
@@ -1677,9 +1850,7 @@ int AffixMgr::compound_check_morph(const char * word, int len,
                      p = affix_check_morph(st, i, compoundmiddle);                   
                    }
                 }
-                if (*p == '\0') {
-                    strcat(presult, MISSING_DESCRIPTION);
-                } else {
+                if (*p != '\0') {
                     line_uniq(p);
                     if (strchr(p, '\n')) {
                         strcat(presult, "(");
@@ -1703,7 +1874,7 @@ int AffixMgr::compound_check_morph(const char * word, int len,
 	}
 
             // check non_compound flag in suffix and prefix
-            if ((rv) && 
+            if ((rv) && !hu_mov_rule &&
                 ((pfx && ((PfxEntry*)pfx)->getCont() &&
                     TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, 
                         ((PfxEntry*)pfx)->getContLen())) ||
@@ -1714,7 +1885,7 @@ int AffixMgr::compound_check_morph(const char * word, int len,
             }
 
             // check compoundend flag in suffix and prefix
-            if ((rv) && 
+            if ((rv) && !checked_prefix && compoundend && !hu_mov_rule &&
                 ((pfx && ((PfxEntry*)pfx)->getCont() &&
                     TESTAFF(((PfxEntry*)pfx)->getCont(), compoundend, 
                         ((PfxEntry*)pfx)->getContLen())) ||
@@ -1724,6 +1895,17 @@ int AffixMgr::compound_check_morph(const char * word, int len,
                     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;
 
@@ -1735,11 +1917,11 @@ int AffixMgr::compound_check_morph(const char * word, int len,
 
 	// first word is acceptable in compound words?
 	if (((rv) && 
-	  ( checked_prefix ||
+	  ( checked_prefix || (words && words[wnum]) ||
 	    (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-	    ((oldwordnum == 0) && TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
-	    ((oldwordnum > 0) && TESTAFF(rv->astr, compoundmiddle, rv->alen)) 
-//MAGYARISPELL
+	    ((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) ||
@@ -1747,20 +1929,23 @@ int AffixMgr::compound_check_morph(const char * word, int len,
 		    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 word[i+1] == '\0'
+                      ((word[i-1]==word[i+1])) // may be word[i+1] == '\0'
 		   )
                ) ||
 	       (
 	           // test CHECKCOMPOUNDPATTERN
-                   numcheckcpd && checkcpd_check(word, i)
-	       ))
+                   numcheckcpd && cpdpat_check(word, i)
+	       ) ||
+               ( 
+	         checkcompoundcase && cpdcase_check(word, i)
+               ))
          )
-//MAGYARISPELL
+// 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()) ||
@@ -1768,9 +1953,10 @@ int AffixMgr::compound_check_morph(const char * word, int len,
                     )                
                )
 	     )
-//------------
+// 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);
@@ -1778,6 +1964,7 @@ int AffixMgr::compound_check_morph(const char * word, int len,
 	        // + 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;
@@ -1785,20 +1972,31 @@ int AffixMgr::compound_check_morph(const char * word, int len,
 
         // search homonym with compound flag
         while ((rv) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, rv->alen)) ||
-			!((compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
-			  (compoundend && (TESTAFF(rv->astr, compoundend, 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]) {
+                  strcat(*result, presult);
+                  if (rv->description && ((!rv->astr) || 
+		     !TESTAFF(rv->astr, lemma_present, rv->alen)))
+			strcat(*result, rv->word);
+                  if (rv->description) strcat(*result, rv->description);
+                  strcat(*result, "\n");
+                  ok = 1;
+                  return 0;
+            }
+
 	    oldnumsyllable2 = numsyllable;
 	    oldwordnum2 = wordnum;
 
-	    // fonev_morfo
-//MAGYARISPELL
+// 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))) {
@@ -1836,9 +2034,6 @@ int AffixMgr::compound_check_morph(const char * word, int len,
                         if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen))
 					       strcat(*result, rv->word);
                         strcat(*result, rv->description);
-                      } else {
-                        strcat(*result, word+i); // kell m�g t�keres�s XXX
-                        strcat(*result, MISSING_DESCRIPTION);
                       }
                       strcat(*result, "\n");
 		              ok = 1;
@@ -1859,6 +2054,28 @@ int AffixMgr::compound_check_morph(const char * word, int len,
                 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 && 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);
+                      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() &&
@@ -1917,7 +2134,6 @@ int AffixMgr::compound_check_morph(const char * word, int len,
                     (
 		      ((cpdwordmax==0) || (wordnum+1<cpdwordmax)) || 
 		      ((cpdmaxsyllable==0) || 
-//		          (numsyllable+get_syllable(rv->word,rv->wlen)<=cpdmaxsyllable)) XXX?
 		          (numsyllable <= cpdmaxsyllable))
 		    )
 		&& (
@@ -1945,10 +2161,9 @@ int AffixMgr::compound_check_morph(const char * word, int len,
 	    wordnum = oldwordnum2;
 
 	    // perhaps second word is a compound word (recursive call)
-//	    if ((wordnum < maxwordnum)) {
 	    if ((wordnum < maxwordnum) && (ok == 0)) {
-			compound_check_morph((word+i),strlen(word+i), 
-				wordnum+1, numsyllable, maxwordnum, 0, result, presult);
+			compound_check_morph((word+i),strlen(word+i), wordnum+1, 
+                             numsyllable, maxwordnum, wnum + 1, words, 0, result, presult);
 	    } else {
 		rv=NULL;
 	    }
@@ -2046,7 +2261,6 @@ struct hentry * AffixMgr::suffix_check (const char * word, int len,
                     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()) && ! derived) derived = mystrdup(word);
        	   	    if (cclass || sptr->getCont()) {
 				if (!derived) {
 					derived = mystrdup(word);
@@ -2162,7 +2376,7 @@ char * AffixMgr::suffix_check_twosfx_morph(const char * word, int len,
                 result3[0] = '\0';
 #ifdef DEBUG
                 unsigned short flag = sptr->getFlag();
-                char flagch[2] = &flag; // XXX sizeof(int)=2
+                char flagch[2] = &flag;
                 if (flag_mode == FLAG_NUM) {
                     sprintf(result3, "%d", sptr->getKey());
                 } else if (flag_mode == FLAG_LONG) {
@@ -2185,7 +2399,6 @@ char * AffixMgr::suffix_check_twosfx_morph(const char * word, int len,
     return NULL;
 }
 
-// XXX BUG NEED in_compound code
 char * AffixMgr::suffix_check_morph(const char * word, int len, 
        int sfxopts, AffEntry * ppfx, const FLAG cclass, const FLAG needflag, char in_compound)
 {
@@ -2384,7 +2597,7 @@ int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts
 
     // first add root word to list
 
-    if (nh < maxn) {
+    if ((nh < maxn) && ((al == 0) || !pseudoroot || !(TESTAFF(ap, pseudoroot, al)))) {
        wlst[nh].word = mystrdup(ts);
        wlst[nh].allow = (1 == 0);
        nh++;
@@ -2396,7 +2609,11 @@ int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts
        SfxEntry * sptr = (SfxEntry *)sFlag[c];
        while (sptr) {
          if (!sptr->getKeyLen() || ((badl > sptr->getKeyLen()) &&
-                (strcmp(sptr->getAffix(), bad + badl - sptr->getKeyLen()) == 0))) {
+                (strcmp(sptr->getAffix(), bad + badl - sptr->getKeyLen()) == 0)) &&
+                // check pseudoroot flag
+                !(pseudoroot && sptr->getCont() && 
+                      TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen()))
+                ) {
 	    char * newword = sptr->add(ts, wl);
             if (newword) {
                 if (nh < maxn) {
@@ -2447,7 +2664,11 @@ int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts
        PfxEntry * ptr = (PfxEntry *) pFlag[c];
        while (ptr) {
          if (!ptr->getKeyLen() || ((badl > ptr->getKeyLen()) &&
-                (strncmp(ptr->getKey(), bad, ptr->getKeyLen()) == 0))) {
+                (strncmp(ptr->getKey(), bad, ptr->getKeyLen()) == 0)) &&
+                // check pseudoroot flag
+                !(pseudoroot && ptr->getCont() && 
+                      TESTAFF(ptr->getCont(), pseudoroot, ptr->getContLen()))
+                ) {
 	    char * newword = ptr->add(ts, wl);
             if (newword) {
 	        if (nh < maxn) {
@@ -2515,12 +2736,17 @@ struct unicode_info2 * AffixMgr::get_utf_conv()
   return utf_tbl;
 }
 
-// return complexprefixes
+// return double prefix option
 int AffixMgr::get_complexprefixes()
 {
   return complexprefixes;
 }
 
+FLAG AffixMgr::get_keepcase()
+{
+  return keepcase;
+}
+
 // return the preferred try string for suggestions
 char * AffixMgr::get_try_string()
 {
@@ -2534,6 +2760,12 @@ const char * AffixMgr::get_wordchars()
   return wordchars;
 }
 
+// is there compounding?
+int AffixMgr::get_compound()
+{
+  return compoundflag || compoundbegin || numdefcpd;
+}
+
 // return the compound words control flag
 FLAG AffixMgr::get_compoundflag()
 {
@@ -2546,6 +2778,12 @@ 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()
 {
@@ -2655,7 +2893,7 @@ int  AffixMgr::parse_try(char * line)
    char * piece;
    int i = 0;
    int np = 0;
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
       if (*piece != '\0') {
           switch(i) {
 	      case 0: { np++; break; }
@@ -2685,7 +2923,7 @@ int  AffixMgr::parse_set(char * line)
    char * piece;
    int i = 0;
    int np = 0;
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
       if (*piece != '\0') {
           switch(i) {
 	     case 0: { np++; break; }
@@ -2697,14 +2935,14 @@ int  AffixMgr::parse_set(char * line)
                         if (utf_tbl) {
                             int j;
                             for (j = 0; j < CONTSIZE; j++) {
-                                utf_tbl[j].ccase = 0;
+                                utf_tbl[j].cletter = 0;
                                 utf_tbl[j].clower = j;
                                 utf_tbl[j].cupper = j;
                             }
                             for (j = 0; j < get_utf_cs_len(); j++) {
-                                utf_tbl[uni[j].ccase].ccase = 1;
-                                utf_tbl[uni[j].ccase].clower = uni[j].clower;
-                                utf_tbl[uni[j].ccase].cupper = uni[j].cupper;
+                                utf_tbl[uni[j].c].cletter = 1;
+                                utf_tbl[uni[j].c].clower = uni[j].clower;
+                                utf_tbl[uni[j].c].cupper = uni[j].cupper;
                             }
                             // set Azeri, Turkish spec. lowercasing
                             set_spec_utf8_encoding();
@@ -2735,7 +2973,7 @@ int AffixMgr::parse_flag(char * line, unsigned short * out, char * name)
    char * piece;
    int i = 0;
    int np = 0;
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
       if (*piece != '\0') {
           switch(i) {
 	      case 0: { np++; break; }
@@ -2764,7 +3002,7 @@ int AffixMgr::parse_num(char * line, int * out, char * name)
    char * piece;
    int i = 0;
    int np = 0;
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
       if (*piece != '\0') {
           switch(i) {
 	      case 0: { np++; break; }
@@ -2797,7 +3035,7 @@ int  AffixMgr::parse_wordchars(char * line)
    char * piece;
    int i = 0;
    int np = 0;
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
       if (*piece != '\0') {
           switch(i) {
 	      case 0: { np++; break; }
@@ -2824,7 +3062,7 @@ int  AffixMgr::parse_cpdsyllable(char * line)
    int i = 0;
    int np = 0;
    w_char w[MAXWORDLEN];
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
       if (*piece != '\0') {
           switch(i) {
 	     case 0: { np++; break; }
@@ -2865,7 +3103,7 @@ int  AffixMgr::parse_syllablenum(char * line)
    char * piece;
    int i = 0;
    int np = 0;
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
       if (*piece != '\0') {
           switch(i) {
 	     case 0: { np++; break; }
@@ -2894,7 +3132,7 @@ int  AffixMgr::parse_reptable(char * line, FILE * af)
    char * piece;
    int i = 0;
    int np = 0;
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
        if (*piece != '\0') {
           switch(i) {
 	     case 0: { np++; break; }
@@ -2929,7 +3167,7 @@ int  AffixMgr::parse_reptable(char * line, FILE * af)
         i = 0;
         reptable[j].pattern = NULL;
         reptable[j].pattern2 = NULL;
-        while ((piece=mystrsep(&tp,' '))) {
+        while ((piece=mystrsep(&tp, 0))) {
            if (*piece != '\0') {
                switch(i) {
                   case 0: {
@@ -2967,7 +3205,7 @@ int  AffixMgr::parse_checkcpdtable(char * line, FILE * af)
    char * piece;
    int i = 0;
    int np = 0;
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
        if (*piece != '\0') {
           switch(i) {
 	     case 0: { np++; break; }
@@ -3002,11 +3240,11 @@ int  AffixMgr::parse_checkcpdtable(char * line, FILE * af)
         i = 0;
         checkcpdtable[j].pattern = NULL;
         checkcpdtable[j].pattern2 = NULL;
-        while ((piece=mystrsep(&tp,' '))) {
+        while ((piece=mystrsep(&tp, 0))) {
            if (*piece != '\0') {
                switch(i) {
                   case 0: {
-		             if (strncmp(piece,"CHECKCOMPOUNDPATTERN",3) != 0) {
+		             if (strncmp(piece,"CHECKCOMPOUNDPATTERN",20) != 0) {
 		                 fprintf(stderr,"error: compound pattern table is corrupt\n");
                                  free(piece);
                                  return 1;
@@ -3022,13 +3260,89 @@ int  AffixMgr::parse_checkcpdtable(char * line, FILE * af)
            free(piece);
         }
 	if ((!(checkcpdtable[j].pattern)) || (!(checkcpdtable[j].pattern2))) {
-	     fprintf(stderr,"error: replacement table is corrupt\n");
+	     fprintf(stderr,"error: compound pattern table is corrupt\n");
              return 1;
         }
    }
    return 0;
 }
 
+/* parse in the defcompound table */
+int  AffixMgr::parse_defcpdtable(char * line, FILE * af)
+{
+   if (numdefcpd != 0) {
+      fprintf(stderr,"error: duplicate compound definition tables used\n");
+      return 1;
+   }
+   char * tp = line;
+   char * piece;
+   int i = 0;
+   int np = 0;
+   while ((piece=mystrsep(&tp, 0))) {
+       if (*piece != '\0') {
+          switch(i) {
+	     case 0: { np++; break; }
+             case 1: { 
+                       numdefcpd = atoi(piece);
+	               if (numdefcpd < 1) {
+			  fprintf(stderr,"incorrect number of entries in compound definition table\n");
+			  free(piece);
+                          return 1;
+                       }
+                       defcpdtable = (flagentry *) malloc(numdefcpd * sizeof(flagentry));
+                       np++;
+                       break;
+	             }
+	     default: break;
+          }
+          i++;
+       }
+       free(piece);
+   }
+   if (np != 2) {
+      fprintf(stderr,"error: missing compound definition 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;
+        while ((piece=mystrsep(&tp, 0))) {
+           if (*piece != '\0') {
+               switch(i) {
+                  case 0: {
+		             if (strncmp(piece, "COMPOUND", 8) != 0) {
+		                 fprintf(stderr,"error: compound definition table is corrupt\n");
+                                 free(piece);
+                                 return 1;
+                             }
+                             break;
+		          }
+                  case 1: { 
+                            defcpdtable[j].len = 
+                                pHMgr->decode_flags(&(defcpdtable[j].def), piece);
+                            break; 
+                           }
+		  default: break;
+               }
+               i++;
+           }
+           free(piece);
+        }
+	if (!defcpdtable[j].len) {
+	     fprintf(stderr,"error: compound definition table is corrupt\n");
+             return 1;
+        }
+   }
+   return 0;
+}
+
+
 /* parse in the character map table */
 int  AffixMgr::parse_maptable(char * line, FILE * af)
 {
@@ -3040,7 +3354,7 @@ int  AffixMgr::parse_maptable(char * line, FILE * af)
    char * piece;
    int i = 0;
    int np = 0;
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
        if (*piece != '\0') {
           switch(i) {
 	     case 0: { np++; break; }
@@ -3075,7 +3389,7 @@ int  AffixMgr::parse_maptable(char * line, FILE * af)
         i = 0;
         maptable[j].set = NULL;
         maptable[j].len = 0;
-        while ((piece=mystrsep(&tp,' '))) {
+        while ((piece=mystrsep(&tp, 0))) {
            if (*piece != '\0') {
                switch(i) {
                   case 0: {
@@ -3129,7 +3443,7 @@ int  AffixMgr::parse_lang(char * line)
    char * piece;
    int i = 0;
    int np = 0;
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
       if (*piece != '\0') {
           switch(i) {
 	     case 0: { np++; break; }
@@ -3160,7 +3474,7 @@ int  AffixMgr::parse_version(char * line)
       return 1;
    }
    char * tp = line;
-   char * piece = mystrsep(&tp,' ');
+   char * piece = mystrsep(&tp, 0);
    version = mystrdup(tp);
    free(piece);
    return 0;
@@ -3187,7 +3501,7 @@ int  AffixMgr::parse_affix(char * line, const char at, FILE * af)
    // split affix header line into pieces
 
    int np = 0;
-   while ((piece=mystrsep(&tp,' '))) {
+   while ((piece=mystrsep(&tp, 0))) {
       if (*piece != '\0') {
           switch(i) {
              // piece 1 - is type of affix
@@ -3206,6 +3520,13 @@ int  AffixMgr::parse_affix(char * line, const char at, FILE * af)
              case 3: { 
                        np++;
                        numents = atoi(piece); 
+                       if (numents == 0) {
+                           char * err = pHMgr->encode_flag(aflag);
+                           fprintf(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));
                        ptr->xpflg = ff;
                        ptr->aflag = aflag;
@@ -3240,7 +3561,7 @@ int  AffixMgr::parse_affix(char * line, const char at, FILE * af)
       nptr->utf8 = utf8;
 
       // split line into pieces
-      while ((piece=mystrsep(&tp,' '))) {
+      while ((piece=mystrsep(&tp, 0))) {
          if (*piece != '\0') {
              switch(i) {
                 // piece 1 - is type
@@ -3351,7 +3672,7 @@ int  AffixMgr::parse_affix(char * line, const char at, FILE * af)
                           }
                           if (nptr->stripl && (strcmp(piece, ".") != 0) &&
                             redundant_condition(at, nptr->strip, nptr->stripl, piece, nl))
-                              strcpy(piece, ".");
+                                strcpy(piece, ".");
                           encodeit(nptr,piece);
                          break;
                 }
@@ -3390,7 +3711,7 @@ int  AffixMgr::parse_affix(char * line, const char at, FILE * af)
          free(piece);
       }
       // check to make sure we parsed enough pieces
-      if (np < 5) { // HUNMORPH
+      if (np < 5) {
           char * err = pHMgr->encode_flag(aflag);
           fprintf(stderr, "error: affix %s is corrupt near line %s\n", err, nl);
           free(err);
@@ -3398,17 +3719,19 @@ int  AffixMgr::parse_affix(char * line, const char at, FILE * af)
           return 1;
       }
 
+#if DEBUG
       // detect unnecessary fields, excepting comments
       if (basefieldnum) {
         int fieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6);
-        if (fieldnum != basefieldnum) 
-          fprintf(stderr, "warning - bad field number:\n%s\n", nl);
+          if (fieldnum != basefieldnum) 
+            fprintf(stderr, "warning - bad field number:\n%s\n", nl);
       } else {
         basefieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6);
       }
+#endif
       nptr++;
    }
-         
+ 
    // now create SfxEntry or PfxEntry objects and use links to
    // build an ordered (sorted by affix string) list
    nptr = ptr;
diff --git a/src/hunspell/affixmgr.hxx b/src/hunspell/affixmgr.hxx
index d3a8a78..a2ba7bb 100644
--- a/src/hunspell/affixmgr.hxx
+++ b/src/hunspell/affixmgr.hxx
@@ -18,6 +18,7 @@ class AffixMgr
   HashMgr *           pHMgr;
   char *              trystring;
   char *              encoding;
+  struct cs_info *    csconv;
   int                 utf8;
   struct unicode_info2 * utf_tbl;
   int                 complexprefixes;
@@ -30,8 +31,10 @@ class AffixMgr
   FLAG                compoundpermitflag;
   int                 checkcompounddup;
   int                 checkcompoundrep;
+  int                 checkcompoundcase;
   int                 checkcompoundtriple;
   FLAG                forbiddenword;
+  FLAG                nosuggest;
   FLAG                pseudoroot;
   int                 cpdmin;
   int                 numrep;
@@ -40,6 +43,8 @@ class AffixMgr
   mapentry *          maptable;
   int                 numcheckcpd;
   replentry *         checkcpdtable;
+  int                 numdefcpd;
+  flagentry *         defcpdtable;
   int                 maxngramsugs;
   int                 nosplitsugs;
   int                 sugswithdots;
@@ -63,11 +68,10 @@ class AffixMgr
   FLAG                lemma_present;
   FLAG                circumfix;
   FLAG                onlyincompound;
+  FLAG                keepcase;
 
   int                 havecontclass; // boolean variable
-#ifndef NOT_SHORT_2BYTE
   short               contclasses[CONTSIZE]; // flags of possible continuing classes (twofold affix)
-#endif
   flag                flag_mode;
 
 public:
@@ -102,16 +106,18 @@ public:
                         int wl, const unsigned short * ap, unsigned short al, char * bad, int);
 
   int                 get_syllable (const char * word, int wlen);
-  int                 repl_check(const char * word, int len);
-  int                 checkcpd_check(const char * word, int len);
+  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);
   int                 candidate_check(const char * word, int len);
   struct hentry *     compound_check(const char * word, int len,
-                              int wordnum, int numsyllable, int maxwordnum, int hu_mov_rule,
-			      int * cmpdstemnum, int * cmpdstem);
+                              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,
-                              int wordnum, int numsyllable, int maxwordnum, int hu_mov_rule,
-                              char ** result, char * partresult);
+                              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();
@@ -123,9 +129,11 @@ public:
   struct unicode_info2 * get_utf_conv();
   char *              get_try_string();
   const char *        get_wordchars();
+  int                 get_compound();
   FLAG                get_compoundflag();
   FLAG                get_compoundbegin();
   FLAG                get_forbiddenword();
+  FLAG                get_nosuggest();
   FLAG                get_pseudoroot();
   FLAG                get_onlyincompound();
   FLAG                get_compoundroot();
@@ -143,6 +151,7 @@ public:
   int                 get_maxngramsugs();
   int                 get_nosplitsugs();
   int                 get_sugswithdots(void);
+  FLAG                get_keepcase(void);
 
 private:
   int  parse_file(const char * affpath);
@@ -158,6 +167,7 @@ private:
   int  parse_reptable(char * line, FILE * af);
   int  parse_maptable(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);
   int  parse_wordchars(char * line);
   int  parse_lang(char * line);
diff --git a/src/hunspell/atypes.hxx b/src/hunspell/atypes.hxx
index 3cba8a9..76d8226 100644
--- a/src/hunspell/atypes.hxx
+++ b/src/hunspell/atypes.hxx
@@ -13,7 +13,7 @@
 #define MAXWORDUTF8LEN  (MAXWORDLEN * 4)
 #define XPRODUCT        (1 << 0)
 
-enum {IN_CPD_NOT, IN_CPD_BEGIN, IN_CPD_END};
+enum {IN_CPD_NOT, IN_CPD_BEGIN, IN_CPD_END, IN_CPD_OTHER};
 
 #define MAXLNLEN        8192 * 4
 
@@ -21,8 +21,6 @@ enum {IN_CPD_NOT, IN_CPD_BEGIN, IN_CPD_END};
 
 #define MAXACC          1000
 
-#define MISSING_DESCRIPTION "[<missing_description>]"
-
 #define FLAG unsigned short
 #define FLAG_NULL 0x00
 #define FREE_FLAG(a) a = 0
@@ -65,6 +63,11 @@ struct mapentry {
   int len;
 };
 
+struct flagentry {
+  FLAG * def;
+  int len;
+};
+
 struct guessword {
   char * word;
   bool allow;
diff --git a/src/hunspell/csutil.cxx b/src/hunspell/csutil.cxx
index 963849b..5bf7214 100644
--- a/src/hunspell/csutil.cxx
+++ b/src/hunspell/csutil.cxx
@@ -1,5 +1,6 @@
 #include <cstdlib>
 #include <cstring>
+#include <cctype>
 #include <cstdio>
 #include "csutil.hxx"
 
@@ -176,6 +177,7 @@ int flag_bsearch(unsigned short flags[], unsigned short flag, short length) {
  // 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)
  {
@@ -183,7 +185,13 @@ int flag_bsearch(unsigned short flags[], unsigned short flag, short length) {
    char * mp = *stringp;
    int n = strlen(mp);
    if (n > 0) {
-      char * dp = (char *)memchr(mp,(int)((unsigned char)delim),n);
+      char * dp;
+      if (delim) {
+        dp = (char *)memchr(mp,(int)((unsigned char)delim),n);
+      } else {
+        for (dp = mp; (*dp && !isspace(*dp)); dp++);
+        if (!*dp) dp = NULL;
+      }
       if (dp) {
          *stringp = dp+1;
          int nc = (int)((unsigned long)dp - (unsigned long)mp);
@@ -201,7 +209,7 @@ int flag_bsearch(unsigned short flags[], unsigned short flag, short length) {
    }
    return NULL;
  }
- 
+
  
  // replaces strdup with ansi version
  char * mystrdup(const char * s)
@@ -4018,14 +4026,14 @@ struct cs_info iso13_tbl[] = {
 { 0x00, 0xA5, 0xA5 },
 { 0x00, 0xA6, 0xA6 },
 { 0x00, 0xA7, 0xA7 },
-{ 0x00, 0xA8, 0xA8 },
+{ 0x01, 0xB8, 0xA8 },
 { 0x00, 0xA9, 0xA9 },
-{ 0x00, 0xAA, 0xAA },
+{ 0x01, 0xBA, 0xAA },
 { 0x00, 0xAB, 0xAB },
 { 0x00, 0xAC, 0xAC },
 { 0x00, 0xAD, 0xAD },
 { 0x00, 0xAE, 0xAE },
-{ 0x00, 0xAF, 0xAF },
+{ 0x01, 0xBF, 0xAF },
 { 0x00, 0xB0, 0xB0 },
 { 0x00, 0xB1, 0xB1 },
 { 0x00, 0xB2, 0xB2 },
@@ -4034,76 +4042,76 @@ struct cs_info iso13_tbl[] = {
 { 0x00, 0xB5, 0xB5 },
 { 0x00, 0xB6, 0xB6 },
 { 0x00, 0xB7, 0xB7 },
-{ 0x00, 0xB8, 0xB8 },
+{ 0x00, 0xB8, 0xA8 },
 { 0x00, 0xB9, 0xB9 },
-{ 0x00, 0xBA, 0xBA },
+{ 0x00, 0xBA, 0xAA },
 { 0x00, 0xBB, 0xBB },
 { 0x00, 0xBC, 0xBC },
 { 0x00, 0xBD, 0xBD },
 { 0x00, 0xBE, 0xBE },
-{ 0x00, 0xBF, 0xBF },
-{ 0x00, 0xE0, 0xC0 },
-{ 0x00, 0xE1, 0xC1 },
-{ 0x00, 0xC2, 0xC2 },
-{ 0x00, 0xC3, 0xC3 },
-{ 0x00, 0xC4, 0xC4 },
-{ 0x00, 0xC5, 0xC5 },
-{ 0x00, 0xE6, 0xC6 },
-{ 0x00, 0xC7, 0xC7 },
-{ 0x00, 0xE8, 0xC8 },
-{ 0x00, 0xC9, 0xC9 },
-{ 0x00, 0xCA, 0xCA },
-{ 0x00, 0xEB, 0xCB },
-{ 0x00, 0xCC, 0xCC },
-{ 0x00, 0xCD, 0xCD },
-{ 0x00, 0xCE, 0xCE },
-{ 0x00, 0xCF, 0xCF },
-{ 0x00, 0xF0, 0xD0 },
-{ 0x00, 0xD1, 0xD1 },
-{ 0x00, 0xD2, 0xD2 },
-{ 0x00, 0xD3, 0xD3 },
-{ 0x00, 0xD4, 0xD4 },
-{ 0x00, 0xD5, 0xD5 },
-{ 0x00, 0xD6, 0xD6 },
+{ 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 },
-{ 0x00, 0xF8, 0xD8 },
-{ 0x00, 0xD9, 0xD9 },
-{ 0x00, 0xDA, 0xDA },
-{ 0x00, 0xFB, 0xDB },
-{ 0x00, 0xDC, 0xDC },
-{ 0x00, 0xDD, 0xDD },
-{ 0x00, 0xFE, 0xDE },
+{ 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, 0xE2 },
-{ 0x00, 0xE3, 0xE3 },
-{ 0x00, 0xE4, 0xE4 },
-{ 0x00, 0xE5, 0xE5 },
+{ 0x00, 0xE2, 0xC2 },
+{ 0x00, 0xE3, 0xC3 },
+{ 0x00, 0xE4, 0xC4 },
+{ 0x00, 0xE5, 0xC5 },
 { 0x00, 0xE6, 0xC6 },
-{ 0x00, 0xE7, 0xE7 },
+{ 0x00, 0xE7, 0xC7 },
 { 0x00, 0xE8, 0xC8 },
-{ 0x00, 0xE9, 0xE9 },
-{ 0x00, 0xEA, 0xEA },
+{ 0x00, 0xE9, 0xC9 },
+{ 0x00, 0xEA, 0xCA },
 { 0x00, 0xEB, 0xCB },
-{ 0x00, 0xEC, 0xEC },
-{ 0x00, 0xED, 0xED },
-{ 0x00, 0xEE, 0xEE },
-{ 0x00, 0xEF, 0xEF },
+{ 0x00, 0xEC, 0xCC },
+{ 0x00, 0xED, 0xCD },
+{ 0x00, 0xEE, 0xCE },
+{ 0x00, 0xEF, 0xCF },
 { 0x00, 0xF0, 0xD0 },
-{ 0x00, 0xF1, 0xF1 },
-{ 0x00, 0xF2, 0xF2 },
-{ 0x00, 0xF3, 0xF3 },
-{ 0x00, 0xF4, 0xF4 },
-{ 0x00, 0xF5, 0xF5 },
-{ 0x00, 0xF6, 0xF6 },
+{ 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, 0xF9 },
-{ 0x00, 0xFA, 0xFA },
+{ 0x00, 0xF9, 0xD9 },
+{ 0x00, 0xFA, 0xDA },
 { 0x00, 0xFB, 0xDB },
-{ 0x00, 0xFC, 0xFC },
-{ 0x00, 0xFD, 0xFD },
+{ 0x00, 0xFC, 0xDC },
+{ 0x00, 0xFD, 0xDD },
 { 0x00, 0xFE, 0xDE },
 { 0x00, 0xFF, 0xFF },
 };
@@ -4368,6 +4376,265 @@ struct cs_info iso14_tbl[] = {
 { 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 },
@@ -4643,6 +4910,7 @@ struct enc_entry encds[] = {
 {"microsoft-cp1251",cp1251_tbl},
 {"ISO8859-13", iso13_tbl},
 {"ISO8859-14", iso14_tbl},
+{"ISO8859-15", iso15_tbl},
 {"ISCII-DEVANAGARI", iscii_devanagari_tbl},
 };
 
@@ -4678,7 +4946,7 @@ struct lang_map lang2enc[] = {
 {"es", "ISO8859-1", LANG_es},
 {"eu", "ISO8859-1", LANG_eu},
 {"gl", "ISO8859-1", LANG_gl},
-{"fr", "ISO8859-1", LANG_fr},
+{"fr", "ISO8859-15", LANG_fr},
 {"hr", "ISO8859-2", LANG_hr},
 {"hu", "ISO8859-2", LANG_hu},
 {"it", "ISO8859-1", LANG_it},
diff --git a/src/hunspell/csutil.hxx b/src/hunspell/csutil.hxx
index 903f110..62202ca 100644
--- a/src/hunspell/csutil.hxx
+++ b/src/hunspell/csutil.hxx
@@ -31,6 +31,8 @@ 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 *);
@@ -71,13 +73,13 @@ struct cs_info {
 
 // Unicode character encoding information
 struct unicode_info {
-  unsigned short ccase;
+  unsigned short c;
   unsigned short cupper;
   unsigned short clower;
 };
 
 struct unicode_info2 {
-  char ccase;
+  char cletter;
   unsigned short cupper;
   unsigned short clower;
 };
diff --git a/src/hunspell/hashmgr.cxx b/src/hunspell/hashmgr.cxx
index 5043227..a9452b5 100644
--- a/src/hunspell/hashmgr.cxx
+++ b/src/hunspell/hashmgr.cxx
@@ -1,8 +1,9 @@
-#include <license.hunspell>
-#include <license.myspell>
+#include "license.hunspell"
+#include "license.myspell"
 
 #include <cstdlib>
 #include <cstring>
+#include <cctype>
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
@@ -294,7 +295,14 @@ int HashMgr::decode_flags(unsigned short ** result, char * flags) {
         if (*dest == 0) fprintf(stderr, "error: 0 is wrong flag id\n");
         break;
       }    
-      default: { // Ispell one-character flags (erfg -> e r f g)
+      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));
+        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));
@@ -310,11 +318,17 @@ int HashMgr::decode_flags(unsigned short ** result, char * flags) {
 
 unsigned short HashMgr::decode_flag(const char * f) {
     unsigned short s = 0;
-    if (flag_mode == FLAG_LONG) {
+    switch (flag_mode) {
+      case FLAG_LONG:
         s = ((unsigned short) f[0] << 8) + (unsigned short) f[1];
-    } else if (flag_mode == FLAG_NUM) {
+        break;
+      case FLAG_NUM:
         s = (unsigned short) atoi(f);
-    } else {
+        break;
+      case FLAG_UNI:
+        u8_u16((w_char *) &s, 1, f);
+        break;
+      default:
         s = (unsigned short) *((unsigned char *)f);
     }
     if (!s) fprintf(stderr, "error: 0 is wrong flag id\n");
@@ -330,6 +344,8 @@ char * HashMgr::encode_flag(unsigned short f) {
         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';
@@ -359,19 +375,20 @@ int  HashMgr::load_config(const char * affpath)
         mychomp(line);
 
         /* parse in the try string */
-        if (strncmp(line,"FLAG ",5) == 0) {
+        if ((strncmp(line,"FLAG",4) == 0) && isspace(line[4])) {
             if (flag_mode != FLAG_CHAR) {
                 fprintf(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, "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) {
-                fprintf(stderr,"error: FLAG need `num' or `long' parameter: %s\n", line);
+                fprintf(stderr,"error: FLAG need `num', `long' or `UTF-8' parameter: %s\n", line);
             }
         }
-        if ((strncmp(line,"SET ",4) == 0) && strstr(line, " UTF-8")) utf8 = 1;
+        if ((strncmp(line,"SET",3) == 0) && isspace(line[3]) && strstr(line, "UTF-8")) utf8 = 1;
         if (strncmp(line,"COMPLEXPREFIXES",15) == 0) complexprefixes = 1;
-        if ((strncmp(line,"SFX ",4) == 0) || (strncmp(line,"PFX ",4) == 0)) break;
+        if (((strncmp(line,"SFX",3) == 0) || (strncmp(line,"PFX",3) == 0)) && isspace(line[3])) break;
     }
     fclose(afflst);
     return 0;
diff --git a/src/hunspell/hashmgr.hxx b/src/hunspell/hashmgr.hxx
index a5b41f3..61461c8 100644
--- a/src/hunspell/hashmgr.hxx
+++ b/src/hunspell/hashmgr.hxx
@@ -3,7 +3,7 @@
 
 #include "htypes.hxx"
 
-enum flag { FLAG_CHAR, FLAG_LONG, FLAG_NUM };
+enum flag { FLAG_CHAR, FLAG_LONG, FLAG_NUM, FLAG_UNI };
 
 class HashMgr
 {
diff --git a/src/hunspell/htypes.hxx b/src/hunspell/htypes.hxx
index eac3f24..14a4783 100644
--- a/src/hunspell/htypes.hxx
+++ b/src/hunspell/htypes.hxx
@@ -1,7 +1,7 @@
 #ifndef _HTYPES_HXX_
 #define _HTYPES_HXX_
 
-#define MAXDELEN    256
+#define MAXDELEN    8192
 
 #define ROTATE_LEN   5
 
diff --git a/src/hunspell/hunspell.cxx b/src/hunspell/hunspell.cxx
index b9441c9..a837d30 100644
--- a/src/hunspell/hunspell.cxx
+++ b/src/hunspell/hunspell.cxx
@@ -1,5 +1,5 @@
-#include <license.hunspell>
-#include <license.myspell>
+#include "license.hunspell"
+#include "license.myspell"
 
 #include <cstring>
 #include <cstdlib>
@@ -84,10 +84,10 @@ int Hunspell::cleanword2(char * dest, const char * src,
        (*pabbrev)++;
    }
    
-   // if no characters are left it can't be an abbreviation and can't be capitalized
+   // if no characters are left it can't be capitalized
    if (nl <= 0) { 
        *pcaptype = NOCAP;
-       *pabbrev = 0;
+//       *pabbrev = 0;
        *p = '\0';
        return 0;
    }
@@ -135,8 +135,7 @@ int Hunspell::cleanword2(char * dest, const char * src,
         *pcaptype = ALLCAP;
   } else {
         *pcaptype = HUHCAP;
-  }
-  
+  }  
   return strlen(dest);
 } 
 
@@ -158,10 +157,10 @@ int Hunspell::cleanword(char * dest, const char * src,
        (*pabbrev)++;
    }
    
-   // if no characters are left it can't be an abbreviation and can't be capitalized
+   // if no characters are left it can't be capitalized
    if (nl <= 0) { 
        *pcaptype = NOCAP;
-       *pabbrev = 0;
+//       *pabbrev = 0;
        *p = '\0';
        return 0;
    }
@@ -316,6 +315,11 @@ hentry * Hunspell::spellsharps(char * base, char * pos, int n, int repnum, char
     return NULL;
 }
 
+int Hunspell::is_keepcase(const hentry * rv) {
+    return pAMgr && rv->astr && pAMgr->get_keepcase() &&
+        TESTAFF(rv->astr, pAMgr->get_keepcase(), rv->alen);
+}
+
 int Hunspell::spell(const char * word)
 {
   struct hentry * rv=NULL;
@@ -334,33 +338,26 @@ int Hunspell::spell(const char * word)
   int captype = 0;
   int abbv = 0;
   int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
+
   if (wl == 0) return 1;
 
-  // LANG_hu section: numbers with suffixes
-  if (langnum == LANG_hu) {
-    int n = 0;
-    int n2 = 0;
-    int n3 = 0;
-    // test numbers and 56%-kal, 45%-kal 50-50%, 11.20-kor, but
-    // numbers with two, or more dots are bad (for example 2003.07.22.)
-    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;
-        }
-    }
+  // 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) && 
+      (((cw[i] <= '9') && (cw[i] >= '0') && (nstate = NNUM)) ||
+          ((nstate == NNUM) && ((cw[i] == ',') ||
+              (cw[i] == '.') || (cw[i] == '-')) && (nstate = NSEP))); i++);     
+  if ((i == wl) && (nstate == NNUM)) return 1;
 
-    // numbers with 3, or more digits (HU)
-    if ((n == wl) && (n3 > 0) && (n - n3 > 3)) return 0;
-    if ((n == wl) || (((cw[n]=='%') || (cw[n]=='�')) && check(cw+n))) return 1;
-    //  if ((cw[n]=='.') && check(cw + n + 1)) return 1;
+  // LANG_hu section: number(s) + (percent or degree) with suffixes
+  if (langnum == LANG_hu) {
+    if ((nstate == NNUM) && ((cw[i] == '%') || (cw[i] == '�')) && check(cw + i)) return 1;
   }
   // END of LANG_hu section
-  
+
   switch(captype) {
      case HUHCAP: 
      case NOCAP: { 
@@ -415,19 +412,21 @@ int Hunspell::spell(const char * word)
                      wl = mkallsmall2(cw, unicw, nc);
                      memcpy(wspace,cw,(wl+1));                     
                      rv = check(wspace);
-                     if (!rv) {
+                     if (!rv || is_keepcase(rv)) {
                         wl2 = mkinitcap2(cw, unicw, nc);
                         rv = check(cw);
+                        if (rv && (captype == ALLCAP) && is_keepcase(rv)) rv = NULL;
                      }
-                     if ((abbv) && !(rv)) {
+                     if (abbv && !rv) {
                          *(wspace+wl) = '.';
                          *(wspace+wl+1) = '\0';
                          rv = check(wspace);
-			 if (!rv) {
+			 if (!rv || is_keepcase(rv)) {
 		            memcpy(wspace, cw, wl2);
                             *(wspace+wl2) = '.';
                             *(wspace+wl2+1) = '\0';
 			    rv = check(wspace);
+                            if (rv && ((captype == ALLCAP) && is_keepcase(rv))) rv = NULL;
 			 }
                      }
 		     break;
@@ -537,15 +536,15 @@ struct hentry * Hunspell::check(const char * w)
 	    return NULL;
         }
 	prevroot = he->word;
-     } else if (pAMgr->get_compoundflag() || pAMgr->get_compoundbegin()) {
+     } else if (pAMgr->get_compound()) {
           he = pAMgr->compound_check(word, len, 
-	                          0,0,100,0,NULL,NULL);
+	                          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,1,NULL,NULL);
+	                          -5,0,100,0,NULL,1,NULL,NULL,0);
 	     free(dup);
 	  }
           // end of LANG speficic region          
@@ -579,6 +578,7 @@ int Hunspell::suggest(char*** slst, const char * word)
   int ns = 0;
   *slst = NULL;
   int capwords = 0;
+  int ngramsugs = 0;
 
   switch(captype) {
      case NOCAP:   { 
@@ -642,9 +642,11 @@ int Hunspell::suggest(char*** slst, const char * word)
           if (pos) *pos = ' ';
       }
   }
+  // END OF LANG_de section
 
   // try ngram approach since found nothing
   if ((ns == 0) && pAMgr && (pAMgr->get_maxngramsugs() != 0)) {
+      ngramsugs = 1;
       switch(captype) {
 	  case NOCAP: {
               ns = pSMgr->ngsuggest(*slst, cw, pHMgr);
@@ -706,6 +708,43 @@ int Hunspell::suggest(char*** slst, const char * word)
     }
   }
 
+  // suggest keepcase
+  switch (captype) {
+    case INITCAP:
+    case ALLCAP: {
+      int l = 0;
+      for (int j=0; j < ns; j++) {
+        if (!spell((*slst)[j])) {
+          int len;
+          char s[MAXSWUTF8L];
+          w_char w[MAXSWL];
+          if (utf8) {
+            len = u8_u16(w, MAXSWL, (*slst)[j]);
+          } else {
+            strcpy(s, (*slst)[j]);
+            len = strlen(s);
+          }
+          int wl = mkallsmall2(s, w, len);
+          free((*slst)[j]);          
+          if (spell(s)) {
+            (*slst)[j] = mystrdup(s);
+            l++;
+          } else {
+            int wl = mkinitcap2(s, w, len);
+            if (spell(s)) {
+              (*slst)[j] = mystrdup(s);
+              l++;
+            }
+          }
+        } else {
+          (*slst)[l] = (*slst)[j];
+          l++;
+        }
+      }
+      ns = l;
+    }
+  }
+
   return ns;
 }
 
@@ -1054,7 +1093,13 @@ char * Hunspell::morph(const char * word)
   int captype = 0;
   int abbv = 0;
   wl = cleanword(cw, word, &captype, &abbv);
-  if (wl == 0) return 0;
+  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;
@@ -1065,8 +1110,9 @@ char * Hunspell::morph(const char * word)
   int n2 = 0;
   int n3 = 0;
 
-  // test numbers and 56%-kal, 45%-kal 50-50%, 11.20-kor, but
-  // numbers with two, or more dots are bad (for example 2003.07.22.)
+  // 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++;
@@ -1078,7 +1124,6 @@ char * Hunspell::morph(const char * word)
 	}
   }
 
-  // numbers with 3, or more digits (HU)
   if ((n == wl) && (n3 > 0) && (n - n3 > 3)) return NULL;
   if ((n == wl) || ((n>0) && ((cw[n]=='%') || (cw[n]=='�')) && check(cw+n))) {
   	strcat(result, cw);
@@ -1107,6 +1152,8 @@ char * Hunspell::morph(const char * word)
 	}
 	return mystrdup(result);
   }
+  }
+  // END OF LANG_de section
   
   switch(captype) {
      case NOCAP:   { 
@@ -1240,6 +1287,7 @@ char * Hunspell::morph(const char * word)
   // compound word with dash (HU) I18n
   char * dash;
   int nresult = 0;
+  // LANG_hu section: set dash information for suggestions
   if ((langnum == LANG_hu) && (dash=(char *) strchr(cw,'-'))) {
       *dash='\0';      
       // examine 2 sides of the dash
diff --git a/src/hunspell/hunspell.hxx b/src/hunspell/hunspell.hxx
index 05d5290..bc20e54 100644
--- a/src/hunspell/hunspell.hxx
+++ b/src/hunspell/hunspell.hxx
@@ -131,6 +131,7 @@ private:
    struct hentry * check(const char *);
    char * sharps_u8_l1(char * dest, char * source);
    hentry * spellsharps(char * base, char *, int, int, char * tmp);
+   int    is_keepcase(const hentry * rv);
 
 };
 
diff --git a/src/hunspell/suggestmgr.cxx b/src/hunspell/suggestmgr.cxx
index 58684ce..5fe1584 100644
--- a/src/hunspell/suggestmgr.cxx
+++ b/src/hunspell/suggestmgr.cxx
@@ -1,5 +1,5 @@
-#include <license.hunspell>
-#include <license.myspell>
+#include "license.hunspell"
+#include "license.myspell"
 
 #include <cstdlib>
 #include <cctype>
@@ -299,7 +299,8 @@ int SuggestMgr::map_related_utf(w_char * word, int len, int i, char** wlst, int
       return ns;
   } 
   int in_map = 0;
-  unsigned short c = *((unsigned short *) word + i);
+//  unsigned short c = *((unsigned short *) word + i);
+  unsigned short c = ((word + i)->h << 8) + (word + i)->l;
   for (int j = 0; j < nummap; j++) {
     if (flag_bsearch((unsigned short *) maptable[j].set_utf16, c, maptable[j].len)) {
       in_map = 1;
@@ -798,7 +799,9 @@ int SuggestMgr::ngsuggest(char** wlst, char * w, HashMgr* pHMgr)
   int col = -1;
   while ((hp = pHMgr->walk_hashtable(col, hp))) {
     // check forbidden words
-    if ((hp->astr) && (pAMgr) && TESTAFF(hp->astr, pAMgr->get_forbiddenword(), hp->alen)) continue;
+    if ((hp->astr) && (pAMgr) && 
+       (TESTAFF(hp->astr, pAMgr->get_forbiddenword(), hp->alen) ||
+          TESTAFF(hp->astr, pAMgr->get_nosuggest(), hp->alen))) continue;
     sc = ngram(3, word, hp->word, NGRAM_LONGER_WORSE);
     if (sc > scores[lp]) {
       scores[lp] = sc;  
@@ -970,8 +973,8 @@ int SuggestMgr::check(const char * word, int len, int cpdsuggest, int * timer, t
   
   if (pAMgr) { 
     if (cpdsuggest==1) {
-      if (pAMgr->get_compoundflag() || pAMgr->get_compoundbegin()) {
-	rv = pAMgr->compound_check(word,len,0,0,0,0,NULL,NULL);
+      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;
@@ -980,8 +983,11 @@ int SuggestMgr::check(const char * word, int len, int cpdsuggest, int * timer, t
     rv = pAMgr->lookup(word);
 
     if (rv) {
-	if ((rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen))) return 0;
-        if (rv->astr && TESTAFF(rv->astr,pAMgr->get_pseudoroot(),rv->alen)) rv = NULL;
+        if ((rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen)
+               || TESTAFF(rv->astr,pAMgr->get_nosuggest(),rv->alen))) return 0;
+        if (rv->astr && TESTAFF(rv->astr,pAMgr->get_pseudoroot(),rv->alen)) {
+            rv = NULL;
+        }
     } else rv = pAMgr->prefix_check(word, len, 0); // only prefix, and prefix + suffix XXX
     
     if (rv) {
@@ -996,13 +1002,12 @@ int SuggestMgr::check(const char * word, int len, int cpdsuggest, int * timer, t
     }
 
     // check forbidden words
-    if ((rv) && (rv->astr) && TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen)) return 0;
+    if ((rv) && (rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen)
+      || TESTAFF(rv->astr,pAMgr->get_nosuggest(),rv->alen))) return 0;
 
     if (rv) { // XXX obsolote
       if ((pAMgr->get_compoundflag()) && 
-          TESTAFF(rv->astr, pAMgr->get_compoundflag(), rv->alen)) {
-	    return 2 + nosuffix; 
-      }
+          TESTAFF(rv->astr, pAMgr->get_compoundflag(), rv->alen)) return 2 + nosuffix; 
       return 1;
     }
   }
@@ -1114,9 +1119,9 @@ int SuggestMgr::fixstems(char ** wlst, const char * word, int ns)
 	    rv = pAMgr->affix_check(word, wl);
 
 	    // else try check compound word
-	    if ((!rv) && (pAMgr->get_compoundflag() || pAMgr->get_compoundbegin())) {
+	    if (!rv && pAMgr->get_compound()) {
         	rv = pAMgr->compound_check(word, wl,
-		     0, 0, 100, 0, &cmpdstemnum, cmpdstem);
+		     0, 0, 100, 0, NULL, 0, &cmpdstemnum, cmpdstem,1);
 
 		if (rv) {
 		    dicstem = 2;
@@ -1268,9 +1273,9 @@ while (rv) {
 		    buf[cpdindex] = '\0';
 		    strcat(buf + cpdindex, buf2);
 
-		    if ((pAMgr->get_compoundflag() || pAMgr->get_compoundbegin()) &&
-        		(pAMgr->compound_check(buf, strlen(buf), 
-	                          0,0,100,0,NULL,NULL))) {
+		    if (pAMgr->get_compound() &&
+        		(pAMgr->compound_check(buf, strlen(buf),
+	                          0,0,100,0,NULL,0,NULL,NULL,1))) {
             		    wlst[ns] = mystrdup(buf);
             		    if (wlst[ns] == NULL) return -1;
 			    ns++;
@@ -1400,9 +1405,9 @@ char * SuggestMgr::suggest_morph(const char * w)
         free(st);
     }
 
-    if ((pAMgr->get_compoundflag() || pAMgr->get_compoundbegin()) && (*result == '\0'))
+    if (pAMgr->get_compound() && (*result == '\0'))
         pAMgr->compound_check_morph(word, strlen(word),
-		     0, 0, 100, 0, &r, NULL);
+		     0, 0, 100, 0,NULL, 0, &r, NULL);
     
     return (*result) ? mystrdup(line_uniq(delete_zeros(result))) : NULL;
 }
diff --git a/src/hunspell/suggestmgr.hxx b/src/hunspell/suggestmgr.hxx
index 6d39a41..5bc64bb 100644
--- a/src/hunspell/suggestmgr.hxx
+++ b/src/hunspell/suggestmgr.hxx
@@ -6,7 +6,7 @@
 #define MAX_ROOTS 50
 #define MAX_WORDS 200
 #define MAX_GUESS 200
-#define MAXNGRAMSUGS 3
+#define MAXNGRAMSUGS 5
 
 #define MINTIMER 500
 #define MAXPLUSTIMER 500
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 856b326..520ebdc 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,18 +1,22 @@
 ## Process this file with automake to create Makefile.in
 
 TESTS =	\
+affixes.test \
 base.test \
+keepcase.test \
 map.test \
 rep.test \
 flag.test \
 flaglong.test \
 flagnum.test \
+flagutf8.test \
 forbiddenword.test \
-pseudoroot.test \
-pseudoroot2.test \
-pseudoroot3.test \
-pseudoroot4.test \
-pseudoroot5.test \
+nosuggest.test \
+needaffix.test \
+needaffix2.test \
+needaffix3.test \
+needaffix4.test \
+needaffix5.test \
 circumfix.test \
 fogemorpheme.test \
 onlyincompound.test \
@@ -21,20 +25,30 @@ complexprefixesutf.test \
 conditionalprefix.test \
 zeroaffix.test \
 utf8.test \
+compoundflag.test \
 compound.test \
+compound2.test \
+compound3.test \
+compound4.test \
+compound5.test \
 compoundaffix.test \
 compoundaffix2.test \
 compoundaffix3.test \
 checkcompounddup.test \
 checkcompoundtriple.test \
 checkcompoundrep.test \
+checkcompoundcase2.test \
+checkcompoundcaseutf.test \
 checkcompoundpattern.test \
 utfcompound.test \
 germansharps.test \
 germansharpsutf.test \
 germancompounding.test \
+germancompoundingold.test \
 i35725.test \
+i53643.test \
 i54633.test \
+i54980.test \
 maputf.test \
 reputf.test
 
@@ -43,12 +57,22 @@ distclean-local:
         
 EXTRA_DIST = \
 test.sh \
+affixes.aff \
+affixes.dic \
+affixes.good \
+affixes.test \
 base.aff \
 base.dic \
 base.good \
 base.sug \
 base.test \
 base.wrong \
+keepcase.aff \
+keepcase.dic \
+keepcase.good \
+keepcase.sug \
+keepcase.test \
+keepcase.wrong \
 map.aff \
 map.dic \
 map.sug \
@@ -80,35 +104,46 @@ forbiddenword.dic \
 forbiddenword.good \
 forbiddenword.test \
 forbiddenword.wrong \
+nosuggest.aff \
+nosuggest.dic \
+nosuggest.good \
+nosuggest.sug \
+nosuggest.test \
+nosuggest.wrong \
 germancompounding.aff \
 germancompounding.dic \
 germancompounding.good \
 germancompounding.test \
 germancompounding.wrong \
-pseudoroot2.aff \
-pseudoroot2.dic \
-pseudoroot2.good \
-pseudoroot2.morph \
-pseudoroot2.test \
-pseudoroot3.aff \
-pseudoroot3.dic \
-pseudoroot3.good \
-pseudoroot3.test \
-pseudoroot3.wrong \
-pseudoroot4.aff \
-pseudoroot4.dic \
-pseudoroot4.good \
-pseudoroot4.test \
-pseudoroot5.aff \
-pseudoroot5.dic \
-pseudoroot5.good \
-pseudoroot5.test \
-pseudoroot5.wrong \
-pseudoroot.aff \
-pseudoroot.dic \
-pseudoroot.good \
-pseudoroot.test \
-pseudoroot.wrong \
+germancompoundingold.aff \
+germancompoundingold.dic \
+germancompoundingold.good \
+germancompoundingold.test \
+germancompoundingold.wrong \
+needaffix2.aff \
+needaffix2.dic \
+needaffix2.good \
+needaffix2.morph \
+needaffix2.test \
+needaffix3.aff \
+needaffix3.dic \
+needaffix3.good \
+needaffix3.test \
+needaffix3.wrong \
+needaffix4.aff \
+needaffix4.dic \
+needaffix4.good \
+needaffix4.test \
+needaffix5.aff \
+needaffix5.dic \
+needaffix5.good \
+needaffix5.test \
+needaffix5.wrong \
+needaffix.aff \
+needaffix.dic \
+needaffix.good \
+needaffix.test \
+needaffix.wrong \
 zeroaffix.aff \
 zeroaffix.dic \
 zeroaffix.good \
@@ -123,11 +158,37 @@ utfcompound.dic \
 utfcompound.good \
 utfcompound.test \
 utfcompound.wrong \
+compoundflag.aff \
+compoundflag.dic \
+compoundflag.good \
+compoundflag.test \
+compoundflag.wrong \
 compound.aff \
 compound.dic \
 compound.good \
 compound.test \
 compound.wrong \
+compound2.aff \
+compound2.dic \
+compound2.good \
+compound2.test \
+compound2.wrong \
+compound3.aff \
+compound3.dic \
+compound3.good \
+compound3.test \
+compound3.wrong \
+compound4.aff \
+compound4.dic \
+compound4.good \
+compound4.test \
+compound4.wrong \
+compound5.aff \
+compound5.dic \
+compound5.good \
+compound5.morph \
+compound5.test \
+compound5.wrong \
 compoundaffix.aff \
 compoundaffix.dic \
 compoundaffix.good \
@@ -147,6 +208,21 @@ checkcompounddup.dic \
 checkcompounddup.good \
 checkcompounddup.test \
 checkcompounddup.wrong \
+checkcompoundcase.aff \
+checkcompoundcase.dic \
+checkcompoundcase.good \
+checkcompoundcase.test \
+checkcompoundcase.wrong \
+checkcompoundcase2.aff \
+checkcompoundcase2.dic \
+checkcompoundcase2.good \
+checkcompoundcase2.test \
+checkcompoundcase2.wrong \
+checkcompoundcaseutf.aff \
+checkcompoundcaseutf.dic \
+checkcompoundcaseutf.good \
+checkcompoundcaseutf.test \
+checkcompoundcaseutf.wrong \
 checkcompoundrep.aff \
 checkcompoundrep.dic \
 checkcompoundrep.good \
@@ -190,6 +266,10 @@ flag.aff \
 flag.dic \
 flag.good \
 flag.test \
+flagutf8.aff \
+flagutf8.dic \
+flagutf8.good \
+flagutf8.test \
 complexprefixes.aff \
 complexprefixes.dic \
 complexprefixes.good \
@@ -206,12 +286,21 @@ i35725.good \
 i35725.sug \
 i35725.test \
 i35725.wrong \
+i53643.aff \
+i53643.dic \
+i53643.good \
+i53643.test \
+i53643.wrong \
 i54633.aff \
 i54633.dic \
 i54633.good \
 i54633.sug \
 i54633.test \
 i54633.wrong \
+i54980.aff \
+i54980.dic \
+i54980.good \
+i54980.test \
 maputf.aff \
 maputf.dic \
 maputf.sug \
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 3325abd..a759060 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -165,18 +165,22 @@ sharedstatedir = @sharedstatedir@
 sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 TESTS = \
+affixes.test \
 base.test \
+keepcase.test \
 map.test \
 rep.test \
 flag.test \
 flaglong.test \
 flagnum.test \
+flagutf8.test \
 forbiddenword.test \
-pseudoroot.test \
-pseudoroot2.test \
-pseudoroot3.test \
-pseudoroot4.test \
-pseudoroot5.test \
+nosuggest.test \
+needaffix.test \
+needaffix2.test \
+needaffix3.test \
+needaffix4.test \
+needaffix5.test \
 circumfix.test \
 fogemorpheme.test \
 onlyincompound.test \
@@ -185,31 +189,51 @@ complexprefixesutf.test \
 conditionalprefix.test \
 zeroaffix.test \
 utf8.test \
+compoundflag.test \
 compound.test \
+compound2.test \
+compound3.test \
+compound4.test \
+compound5.test \
 compoundaffix.test \
 compoundaffix2.test \
 compoundaffix3.test \
 checkcompounddup.test \
 checkcompoundtriple.test \
 checkcompoundrep.test \
+checkcompoundcase2.test \
+checkcompoundcaseutf.test \
 checkcompoundpattern.test \
 utfcompound.test \
 germansharps.test \
 germansharpsutf.test \
 germancompounding.test \
+germancompoundingold.test \
 i35725.test \
+i53643.test \
 i54633.test \
+i54980.test \
 maputf.test \
 reputf.test
 
 EXTRA_DIST = \
 test.sh \
+affixes.aff \
+affixes.dic \
+affixes.good \
+affixes.test \
 base.aff \
 base.dic \
 base.good \
 base.sug \
 base.test \
 base.wrong \
+keepcase.aff \
+keepcase.dic \
+keepcase.good \
+keepcase.sug \
+keepcase.test \
+keepcase.wrong \
 map.aff \
 map.dic \
 map.sug \
@@ -241,35 +265,46 @@ forbiddenword.dic \
 forbiddenword.good \
 forbiddenword.test \
 forbiddenword.wrong \
+nosuggest.aff \
+nosuggest.dic \
+nosuggest.good \
+nosuggest.sug \
+nosuggest.test \
+nosuggest.wrong \
 germancompounding.aff \
 germancompounding.dic \
 germancompounding.good \
 germancompounding.test \
 germancompounding.wrong \
-pseudoroot2.aff \
-pseudoroot2.dic \
-pseudoroot2.good \
-pseudoroot2.morph \
-pseudoroot2.test \
-pseudoroot3.aff \
-pseudoroot3.dic \
-pseudoroot3.good \
-pseudoroot3.test \
-pseudoroot3.wrong \
-pseudoroot4.aff \
-pseudoroot4.dic \
-pseudoroot4.good \
-pseudoroot4.test \
-pseudoroot5.aff \
-pseudoroot5.dic \
-pseudoroot5.good \
-pseudoroot5.test \
-pseudoroot5.wrong \
-pseudoroot.aff \
-pseudoroot.dic \
-pseudoroot.good \
-pseudoroot.test \
-pseudoroot.wrong \
+germancompoundingold.aff \
+germancompoundingold.dic \
+germancompoundingold.good \
+germancompoundingold.test \
+germancompoundingold.wrong \
+needaffix2.aff \
+needaffix2.dic \
+needaffix2.good \
+needaffix2.morph \
+needaffix2.test \
+needaffix3.aff \
+needaffix3.dic \
+needaffix3.good \
+needaffix3.test \
+needaffix3.wrong \
+needaffix4.aff \
+needaffix4.dic \
+needaffix4.good \
+needaffix4.test \
+needaffix5.aff \
+needaffix5.dic \
+needaffix5.good \
+needaffix5.test \
+needaffix5.wrong \
+needaffix.aff \
+needaffix.dic \
+needaffix.good \
+needaffix.test \
+needaffix.wrong \
 zeroaffix.aff \
 zeroaffix.dic \
 zeroaffix.good \
@@ -284,11 +319,37 @@ utfcompound.dic \
 utfcompound.good \
 utfcompound.test \
 utfcompound.wrong \
+compoundflag.aff \
+compoundflag.dic \
+compoundflag.good \
+compoundflag.test \
+compoundflag.wrong \
 compound.aff \
 compound.dic \
 compound.good \
 compound.test \
 compound.wrong \
+compound2.aff \
+compound2.dic \
+compound2.good \
+compound2.test \
+compound2.wrong \
+compound3.aff \
+compound3.dic \
+compound3.good \
+compound3.test \
+compound3.wrong \
+compound4.aff \
+compound4.dic \
+compound4.good \
+compound4.test \
+compound4.wrong \
+compound5.aff \
+compound5.dic \
+compound5.good \
+compound5.morph \
+compound5.test \
+compound5.wrong \
 compoundaffix.aff \
 compoundaffix.dic \
 compoundaffix.good \
@@ -308,6 +369,21 @@ checkcompounddup.dic \
 checkcompounddup.good \
 checkcompounddup.test \
 checkcompounddup.wrong \
+checkcompoundcase.aff \
+checkcompoundcase.dic \
+checkcompoundcase.good \
+checkcompoundcase.test \
+checkcompoundcase.wrong \
+checkcompoundcase2.aff \
+checkcompoundcase2.dic \
+checkcompoundcase2.good \
+checkcompoundcase2.test \
+checkcompoundcase2.wrong \
+checkcompoundcaseutf.aff \
+checkcompoundcaseutf.dic \
+checkcompoundcaseutf.good \
+checkcompoundcaseutf.test \
+checkcompoundcaseutf.wrong \
 checkcompoundrep.aff \
 checkcompoundrep.dic \
 checkcompoundrep.good \
@@ -351,6 +427,10 @@ flag.aff \
 flag.dic \
 flag.good \
 flag.test \
+flagutf8.aff \
+flagutf8.dic \
+flagutf8.good \
+flagutf8.test \
 complexprefixes.aff \
 complexprefixes.dic \
 complexprefixes.good \
@@ -367,12 +447,21 @@ i35725.good \
 i35725.sug \
 i35725.test \
 i35725.wrong \
+i53643.aff \
+i53643.dic \
+i53643.good \
+i53643.test \
+i53643.wrong \
 i54633.aff \
 i54633.dic \
 i54633.good \
 i54633.sug \
 i54633.test \
 i54633.wrong \
+i54980.aff \
+i54980.dic \
+i54980.good \
+i54980.test \
 maputf.aff \
 maputf.dic \
 maputf.sug \
diff --git a/tests/affixes.aff b/tests/affixes.aff
new file mode 100644
index 0000000..cf3c500
--- /dev/null
+++ b/tests/affixes.aff
@@ -0,0 +1,7 @@
+# simple example for affix compression (see Hunspell(4))
+PFX A Y 1
+PFX A 0 re .
+
+SFX B Y 2
+SFX B 0 ed [^y]
+SFX B y ied y
diff --git a/tests/affixes.dic b/tests/affixes.dic
new file mode 100644
index 0000000..e228043
--- /dev/null
+++ b/tests/affixes.dic
@@ -0,0 +1,4 @@
+3
+hello
+try/B
+work/AB
diff --git a/tests/affixes.good b/tests/affixes.good
new file mode 100644
index 0000000..20097e8
--- /dev/null
+++ b/tests/affixes.good
@@ -0,0 +1,7 @@
+hello
+try
+tried
+work
+worked
+rework
+reworked
diff --git a/tests/pseudoroot.test b/tests/affixes.test
similarity index 100%
copy from tests/pseudoroot.test
copy to tests/affixes.test
diff --git a/tests/checkcompoundcase.aff b/tests/checkcompoundcase.aff
new file mode 100644
index 0000000..7ac46ee
--- /dev/null
+++ b/tests/checkcompoundcase.aff
@@ -0,0 +1,3 @@
+# forbid upper case letters at word bounds in compounding
+CHECKCOMPOUNDCASE
+COMPOUNDFLAG A
diff --git a/tests/checkcompoundcase.dic b/tests/checkcompoundcase.dic
new file mode 100644
index 0000000..80f65d3
--- /dev/null
+++ b/tests/checkcompoundcase.dic
@@ -0,0 +1,5 @@
+4
+foo/A
+Bar/A
+BAZ/A
+-/A
diff --git a/tests/checkcompoundcase.good b/tests/checkcompoundcase.good
new file mode 100644
index 0000000..9cbd790
--- /dev/null
+++ b/tests/checkcompoundcase.good
@@ -0,0 +1,5 @@
+Barfoo
+foo-Bar
+foo-BAZ
+BAZ-foo
+BAZ-Bar
diff --git a/tests/pseudoroot2.test b/tests/checkcompoundcase.test
similarity index 100%
rename from tests/pseudoroot2.test
rename to tests/checkcompoundcase.test
diff --git a/tests/checkcompoundcase.wrong b/tests/checkcompoundcase.wrong
new file mode 100644
index 0000000..0714c22
--- /dev/null
+++ b/tests/checkcompoundcase.wrong
@@ -0,0 +1,3 @@
+fooBar
+BAZBar
+BAZfoo
diff --git a/tests/checkcompoundcase2.aff b/tests/checkcompoundcase2.aff
new file mode 100644
index 0000000..fea046b
--- /dev/null
+++ b/tests/checkcompoundcase2.aff
@@ -0,0 +1,3 @@
+# check extended ascii
+CHECKCOMPOUNDCASE
+COMPOUNDFLAG A
diff --git a/tests/checkcompoundcase2.dic b/tests/checkcompoundcase2.dic
new file mode 100644
index 0000000..086de0a
--- /dev/null
+++ b/tests/checkcompoundcase2.dic
@@ -0,0 +1,3 @@
+2
+�o�/A
+�o�/A
diff --git a/tests/checkcompoundcase2.good b/tests/checkcompoundcase2.good
new file mode 100644
index 0000000..b38fd0c
--- /dev/null
+++ b/tests/checkcompoundcase2.good
@@ -0,0 +1,2 @@
+�o��o�
+�o��o�
diff --git a/tests/pseudoroot3.test b/tests/checkcompoundcase2.test
similarity index 100%
copy from tests/pseudoroot3.test
copy to tests/checkcompoundcase2.test
diff --git a/tests/checkcompoundcase2.wrong b/tests/checkcompoundcase2.wrong
new file mode 100644
index 0000000..94786e9
--- /dev/null
+++ b/tests/checkcompoundcase2.wrong
@@ -0,0 +1 @@
+�o��o�
diff --git a/tests/checkcompoundcaseutf.aff b/tests/checkcompoundcaseutf.aff
new file mode 100644
index 0000000..546f478
--- /dev/null
+++ b/tests/checkcompoundcaseutf.aff
@@ -0,0 +1,3 @@
+SET UTF-8
+CHECKCOMPOUNDCASE
+COMPOUNDFLAG A
diff --git a/tests/checkcompoundcaseutf.dic b/tests/checkcompoundcaseutf.dic
new file mode 100644
index 0000000..0b7fbc9
--- /dev/null
+++ b/tests/checkcompoundcaseutf.dic
@@ -0,0 +1,3 @@
+2
+áoó/A
+Óoá/A
diff --git a/tests/checkcompoundcaseutf.good b/tests/checkcompoundcaseutf.good
new file mode 100644
index 0000000..6df144d
--- /dev/null
+++ b/tests/checkcompoundcaseutf.good
@@ -0,0 +1,2 @@
+áoóáoó	
+Óoááoó	
diff --git a/tests/pseudoroot.test b/tests/checkcompoundcaseutf.test
similarity index 71%
copy from tests/pseudoroot.test
copy to tests/checkcompoundcaseutf.test
index 7f44369..4d9d1a8 100755
--- a/tests/pseudoroot.test
+++ b/tests/checkcompoundcaseutf.test
@@ -1,4 +1,4 @@
 #!/bin/sh
 DIR="`dirname $0`"
 NAME="`basename $0 .test`"
-$DIR/test.sh $NAME
+$DIR/test.sh $NAME -1
diff --git a/tests/checkcompoundcaseutf.wrong b/tests/checkcompoundcaseutf.wrong
new file mode 100644
index 0000000..cb78fac
--- /dev/null
+++ b/tests/checkcompoundcaseutf.wrong
@@ -0,0 +1 @@
+áoóÓoá	
diff --git a/tests/compound.aff b/tests/compound.aff
index bc8369c..4f4a707 100644
--- a/tests/compound.aff
+++ b/tests/compound.aff
@@ -1,3 +1,3 @@
-COMPOUNDMIN 3
-COMPOUNDFLAG A
-
+COMPOUNDMIN 1
+COMPOUND 1
+COMPOUND ABC
diff --git a/tests/compound.dic b/tests/compound.dic
index d1ea8e9..b11e829 100644
--- a/tests/compound.dic
+++ b/tests/compound.dic
@@ -1,5 +1,5 @@
-4
-foo/A
-bar/A
-xy/A
-yz/A
+3
+a/A
+b/B
+c/BC
+
diff --git a/tests/compound.good b/tests/compound.good
index 21cc29f..c7a0763 100644
--- a/tests/compound.good
+++ b/tests/compound.good
@@ -1,3 +1,2 @@
-foobar
-barfoo
-foobarfoo
+abc
+acc
diff --git a/tests/compound.wrong b/tests/compound.wrong
index c185bf1..bc151ea 100644
--- a/tests/compound.wrong
+++ b/tests/compound.wrong
@@ -1,4 +1,39 @@
-xyyz
-fooxy
-xyfoo
-fooxybar
+ba
+aaabaaa
+bbaaa
+aaaaba
+bbbbbaa
+aa
+aaa
+aaaa
+ab
+aab
+aaab
+aaaab
+abb
+aabb
+aaabbb
+bb
+bbb
+bbbb
+aaab
+abcc
+abbc
+abbcc
+aabc
+aabcc
+aabbc
+aabbcc
+aaabbbccc
+ac
+aac
+aacc
+aaaccc
+bc
+bcc
+bbc
+bbcc
+bbbccc
+cc
+ccc
+cccccc
diff --git a/tests/compound2.aff b/tests/compound2.aff
new file mode 100644
index 0000000..605b2b0
--- /dev/null
+++ b/tests/compound2.aff
@@ -0,0 +1,3 @@
+COMPOUNDMIN 1
+COMPOUND 1
+COMPOUND A*B*C*
diff --git a/tests/compound2.dic b/tests/compound2.dic
new file mode 100644
index 0000000..7d07bbc
--- /dev/null
+++ b/tests/compound2.dic
@@ -0,0 +1,5 @@
+3
+a/A
+b/B
+c/C
+
diff --git a/tests/compound2.good b/tests/compound2.good
new file mode 100644
index 0000000..de743bb
--- /dev/null
+++ b/tests/compound2.good
@@ -0,0 +1,37 @@
+aa
+aaa
+aaaa
+ab
+aab
+aaab
+aaaab
+abb
+aabb
+aaabbb
+bb
+bbb
+bbbb
+aaab
+abc
+abcc
+abbc
+abbcc
+aabc
+aabcc
+aabbc
+aabbcc
+aaabbbccc
+ac
+acc
+aac
+aacc
+aaaccc
+bc
+bcc
+bbc
+bbcc
+bbbccc
+cc
+ccc
+cccccc
+abcc
diff --git a/tests/pseudoroot4.test b/tests/compound2.test
similarity index 100%
rename from tests/pseudoroot4.test
rename to tests/compound2.test
diff --git a/tests/compound2.wrong b/tests/compound2.wrong
new file mode 100644
index 0000000..9e5d38d
--- /dev/null
+++ b/tests/compound2.wrong
@@ -0,0 +1,8 @@
+ba
+aaabaaa
+bbaaa
+aaaaba
+bbbbbaa
+cba
+cab
+acb
diff --git a/tests/compound3.aff b/tests/compound3.aff
new file mode 100644
index 0000000..6f938de
--- /dev/null
+++ b/tests/compound3.aff
@@ -0,0 +1,3 @@
+COMPOUNDMIN 1
+COMPOUND 1
+COMPOUND A?B?C?
diff --git a/tests/compound3.dic b/tests/compound3.dic
new file mode 100644
index 0000000..7d07bbc
--- /dev/null
+++ b/tests/compound3.dic
@@ -0,0 +1,5 @@
+3
+a/A
+b/B
+c/C
+
diff --git a/tests/compound3.good b/tests/compound3.good
new file mode 100644
index 0000000..7f51889
--- /dev/null
+++ b/tests/compound3.good
@@ -0,0 +1,7 @@
+a
+b
+c
+ab
+abc
+ac
+bc
diff --git a/tests/pseudoroot5.test b/tests/compound3.test
similarity index 100%
rename from tests/pseudoroot5.test
rename to tests/compound3.test
diff --git a/tests/compound3.wrong b/tests/compound3.wrong
new file mode 100644
index 0000000..6bd1d80
--- /dev/null
+++ b/tests/compound3.wrong
@@ -0,0 +1,41 @@
+aa
+aaa
+aaaa
+aab
+aaab
+aaaab
+abb
+aabb
+aaabbb
+bb
+bbb
+bbbb
+aaab
+abcc
+abbc
+abbcc
+aabc
+aabcc
+aabbc
+aabbcc
+aaabbbccc
+acc
+aac
+aacc
+aaaccc
+bcc
+bbc
+bbcc
+bbbccc
+cc
+ccc
+cccccc
+abcc
+ba
+aaabaaa
+bbaaa
+aaaaba
+bbbbbaa
+cba
+cab
+acb
diff --git a/tests/compound4.aff b/tests/compound4.aff
new file mode 100644
index 0000000..fb64dba
--- /dev/null
+++ b/tests/compound4.aff
@@ -0,0 +1,6 @@
+# English ordinal numbers
+COMPOUNDMIN 1
+ONLYINCOMPOUND c
+COMPOUND 2
+COMPOUND n*1t
+COMPOUND n*mp
diff --git a/tests/compound4.dic b/tests/compound4.dic
new file mode 100644
index 0000000..ced0735
--- /dev/null
+++ b/tests/compound4.dic
@@ -0,0 +1,24 @@
+22
+0/nm
+1/n1
+2/nm
+3/nm
+4/nm
+5/nm
+6/nm
+7/nm
+8/nm
+9/nm
+0th/pt
+1st/p
+1th/tc
+2nd/p
+2th/tc
+3rd/p
+3th/tc
+4th/pt
+5th/pt
+6th/pt
+7th/pt
+8th/pt
+9th/pt
diff --git a/tests/compound4.good b/tests/compound4.good
new file mode 100644
index 0000000..61beacc
--- /dev/null
+++ b/tests/compound4.good
@@ -0,0 +1,29 @@
+1st	
+2nd	
+3rd	
+4th	
+5th	
+6th	
+7th	
+8th	
+9th	
+10th	
+11th	
+12th	
+13th	
+14th	
+15th	
+16th	
+17th	
+18th	
+19th	
+20th	
+21st	
+22nd	
+23rd	
+24th	
+25th	
+100th	
+1000th	
+10001st	
+10011th	
diff --git a/tests/pseudoroot.test b/tests/compound4.test
similarity index 71%
copy from tests/pseudoroot.test
copy to tests/compound4.test
index 7f44369..4d9d1a8 100755
--- a/tests/pseudoroot.test
+++ b/tests/compound4.test
@@ -1,4 +1,4 @@
 #!/bin/sh
 DIR="`dirname $0`"
 NAME="`basename $0 .test`"
-$DIR/test.sh $NAME
+$DIR/test.sh $NAME -1
diff --git a/tests/compound4.wrong b/tests/compound4.wrong
new file mode 100644
index 0000000..1fef554
--- /dev/null
+++ b/tests/compound4.wrong
@@ -0,0 +1,5 @@
+1th	
+2th	
+3th	
+10001th	
+10011st	
diff --git a/tests/compound5.aff b/tests/compound5.aff
new file mode 100644
index 0000000..6d37f17
--- /dev/null
+++ b/tests/compound5.aff
@@ -0,0 +1,6 @@
+# number + percent
+SET UTF-8
+COMPOUNDMIN 1
+COMPOUND 2
+COMPOUND N*%?
+COMPOUND NN*.NN*%?
diff --git a/tests/compound5.dic b/tests/compound5.dic
new file mode 100644
index 0000000..3d25189
--- /dev/null
+++ b/tests/compound5.dic
@@ -0,0 +1,14 @@
+13
+0/N	[NUM]
+1/N	[NUM]
+2/N	[NUM]
+3/N	[NUM]
+4/N	[NUM]
+5/N	[NUM]
+6/N	[NUM]
+7/N	[NUM]
+8/N	[NUM]
+9/N	[NUM]
+./.	[DOT]
+%/%	[PERCENT_SIGN]
+‰/%	[PER_MILLE_SIGN]
diff --git a/tests/compound5.good b/tests/compound5.good
new file mode 100644
index 0000000..eb203ea
--- /dev/null
+++ b/tests/compound5.good
@@ -0,0 +1,7 @@
+10%	
+0.2%	
+0.20%	
+123.4561‰	
+10	
+0000	
+10.25	
diff --git a/tests/compound5.morph b/tests/compound5.morph
new file mode 100644
index 0000000..1387e77
--- /dev/null
+++ b/tests/compound5.morph
@@ -0,0 +1,14 @@
+> 10%
+1[NUM]0[NUM]%[PERCENT_SIGN]
+> 0.2%
+0[NUM].[DOT]2[NUM]%[PERCENT_SIGN]
+> 0.20%
+0[NUM].[DOT]2[NUM]0[NUM]%[PERCENT_SIGN]
+> 123.4561‰
+1[NUM]2[NUM]3[NUM].[DOT]4[NUM]5[NUM]6[NUM]1[NUM]‰[PER_MILLE_SIGN]
+> 10
+1[NUM]0[NUM]
+> 0000
+0[NUM]0[NUM]0[NUM]0[NUM]
+> 10.25
+1[NUM]0[NUM].[DOT]2[NUM]5[NUM]
diff --git a/tests/pseudoroot.test b/tests/compound5.test
similarity index 71%
copy from tests/pseudoroot.test
copy to tests/compound5.test
index 7f44369..4d9d1a8 100755
--- a/tests/pseudoroot.test
+++ b/tests/compound5.test
@@ -1,4 +1,4 @@
 #!/bin/sh
 DIR="`dirname $0`"
 NAME="`basename $0 .test`"
-$DIR/test.sh $NAME
+$DIR/test.sh $NAME -1
diff --git a/tests/compound5.wrong b/tests/compound5.wrong
new file mode 100644
index 0000000..5210853
--- /dev/null
+++ b/tests/compound5.wrong
@@ -0,0 +1 @@
+.25	
diff --git a/tests/compound.aff b/tests/compoundflag.aff
similarity index 100%
copy from tests/compound.aff
copy to tests/compoundflag.aff
diff --git a/tests/compound.dic b/tests/compoundflag.dic
similarity index 100%
copy from tests/compound.dic
copy to tests/compoundflag.dic
diff --git a/tests/compound.good b/tests/compoundflag.good
similarity index 100%
copy from tests/compound.good
copy to tests/compoundflag.good
diff --git a/tests/pseudoroot.test b/tests/compoundflag.test
similarity index 100%
copy from tests/pseudoroot.test
copy to tests/compoundflag.test
diff --git a/tests/compound.wrong b/tests/compoundflag.wrong
similarity index 100%
copy from tests/compound.wrong
copy to tests/compoundflag.wrong
diff --git a/tests/flagutf8.aff b/tests/flagutf8.aff
new file mode 100644
index 0000000..a11870b
--- /dev/null
+++ b/tests/flagutf8.aff
@@ -0,0 +1,14 @@
+# UTF-8 flags
+FLAG UTF-8
+
+SFX A Y 1
+SFX A 0 s/ÖüÜ .
+
+SFX Ö Y 1
+SFX Ö 0 bar .
+
+SFX ü Y 1
+SFX ü 0 baz .
+
+PFX Ü Y 1
+PFX Ü 0 un .
diff --git a/tests/flagutf8.dic b/tests/flagutf8.dic
new file mode 100644
index 0000000..2944490
--- /dev/null
+++ b/tests/flagutf8.dic
@@ -0,0 +1,2 @@
+1
+foo/AÜ
diff --git a/tests/flagutf8.good b/tests/flagutf8.good
new file mode 100644
index 0000000..d5c27b1
--- /dev/null
+++ b/tests/flagutf8.good
@@ -0,0 +1,8 @@
+foo
+foos
+foosbar
+foosbaz
+unfoo
+unfoos
+unfoosbar
+unfoosbaz
diff --git a/tests/pseudoroot.test b/tests/flagutf8.test
similarity index 100%
copy from tests/pseudoroot.test
copy to tests/flagutf8.test
diff --git a/tests/germancompounding.aff b/tests/germancompounding.aff
index ed32a3b..a2e549c 100644
--- a/tests/germancompounding.aff
+++ b/tests/germancompounding.aff
@@ -22,9 +22,8 @@ COMPOUNDPERMITFLAG P
 
 ONLYINCOMPOUND X
 
-# for decapitalizing nouns with fogemorphemes
-
-CIRCUMFIX Y
+# forbid uppercase characters at compound word bounds
+CHECKCOMPOUNDCASE
 
 # for handling Fuge-elements with dashes (Arbeits-) 
 # dash will be a special word
@@ -36,20 +35,17 @@ WORDCHARS -
 
 SFX A Y 3
 SFX A 0 s/UPX .
-SFX A 0 s/VPXDY .
-SFX A 0 0/WXDY .
-
-# compound settings for `Computer'
+SFX A 0 s/VPDX .
+SFX A 0 0/WXD .
 
 SFX B Y 2
 SFX B 0 0/UPX .
-SFX B 0 0/VWPXDY .
+SFX B 0 0/VWXDP .
 
 # a suffix for `Computer'
 
-SFX C Y 2
-SFX C 0 n .
-SFX C 0 n/WXDY .
+SFX C Y 1
+SFX C 0 n/WD .
 
 # for forbid exceptions (*Arbeitsnehmer)
 
@@ -57,40 +53,39 @@ FORBIDDENWORD Z
 
 # dash prefix for compounds with dash (Arbeits-Computer)
 
-PFX - Y 2
-PFX - 0 -/PUVW .
-PFX - 0 -/PY .
+PFX - Y 1
+PFX - 0 -/P .
 
 # decapitalizing prefix
 # circumfix for positioning in compounds
 
 PFX D Y 29
-PFX D A a/PXY A
-PFX D � �/PXY �
-PFX D B b/PXY B
-PFX D C c/PXY C
-PFX D D d/PXY D
-PFX D E e/PXY E
-PFX D F f/PXY F
-PFX D G g/PXY G
-PFX D H h/PXY H
-PFX D I i/PXY I
-PFX D J j/PXY J
-PFX D K k/PXY K
-PFX D L l/PXY L
-PFX D M m/PXY M
-PFX D N n/PXY N
-PFX D O o/PXY O
-PFX D � �/PXY �
-PFX D P p/PXY P
-PFX D Q q/PXY Q
-PFX D R r/PXY R
-PFX D S s/PXY S
-PFX D T t/PXY T
-PFX D U u/PXY U
-PFX D � �/PXY �
-PFX D V v/PXY V
-PFX D W w/PXY W
-PFX D X x/PXY X
-PFX D Y y/PXY Y
-PFX D Z z/PXY Z
+PFX D A a/PX A
+PFX D � �/PX �
+PFX D B b/PX B
+PFX D C c/PX C
+PFX D D d/PX D
+PFX D E e/PX E
+PFX D F f/PX F
+PFX D G g/PX G
+PFX D H h/PX H
+PFX D I i/PX I
+PFX D J j/PX J
+PFX D K k/PX K
+PFX D L l/PX L
+PFX D M m/PX M
+PFX D N n/PX N
+PFX D O o/PX O
+PFX D � �/PX �
+PFX D P p/PX P
+PFX D Q q/PX Q
+PFX D R r/PX R
+PFX D S s/PX S
+PFX D T t/PX T
+PFX D U u/PX U
+PFX D � �/PX �
+PFX D V v/PX V
+PFX D W w/PX W
+PFX D X x/PX X
+PFX D Y y/PX Y
+PFX D Z z/PX Z
diff --git a/tests/germancompounding.dic b/tests/germancompounding.dic
index 2f6d0ed..5db6783 100644
--- a/tests/germancompounding.dic
+++ b/tests/germancompounding.dic
@@ -1,5 +1,5 @@
 4
-Arbeit/A
+Arbeit/A-
 Computer/BC-
 -/W
 Arbeitsnehmer/Z
diff --git a/tests/germancompounding.good b/tests/germancompounding.good
index d87fb04..e494555 100644
--- a/tests/germancompounding.good
+++ b/tests/germancompounding.good
@@ -5,9 +5,16 @@ Arbeits-
 Computerarbeit
 Computerarbeits-
 Arbeitscomputer
+Computercomputer
+Computercomputern
 Arbeitscomputern
 Computerarbeitscomputer
 Computerarbeitscomputern
+Arbeitscomputercomputer
+Computercomputerarbeit
 Arbeitscomputerarbeit
+Arbeitsarbeitsarbeit
+Computerarbeitsarbeit
 Computerarbeits-Computer
 Computerarbeits-Computern
+Computer-Arbeit
diff --git a/tests/germancompounding.aff b/tests/germancompoundingold.aff
similarity index 100%
copy from tests/germancompounding.aff
copy to tests/germancompoundingold.aff
diff --git a/tests/germancompounding.dic b/tests/germancompoundingold.dic
similarity index 77%
copy from tests/germancompounding.dic
copy to tests/germancompoundingold.dic
index 2f6d0ed..5db6783 100644
--- a/tests/germancompounding.dic
+++ b/tests/germancompoundingold.dic
@@ -1,5 +1,5 @@
 4
-Arbeit/A
+Arbeit/A-
 Computer/BC-
 -/W
 Arbeitsnehmer/Z
diff --git a/tests/germancompounding.good b/tests/germancompoundingold.good
similarity index 93%
copy from tests/germancompounding.good
copy to tests/germancompoundingold.good
index d87fb04..5357bff 100644
--- a/tests/germancompounding.good
+++ b/tests/germancompoundingold.good
@@ -11,3 +11,4 @@ Computerarbeitscomputern
 Arbeitscomputerarbeit
 Computerarbeits-Computer
 Computerarbeits-Computern
+Computer-Arbeit
diff --git a/tests/pseudoroot.test b/tests/germancompoundingold.test
similarity index 100%
copy from tests/pseudoroot.test
copy to tests/germancompoundingold.test
diff --git a/tests/germancompoundingold.wrong b/tests/germancompoundingold.wrong
new file mode 100644
index 0000000..c5f2ba1
--- /dev/null
+++ b/tests/germancompoundingold.wrong
@@ -0,0 +1,50 @@
+computer
+computern
+arbeit
+Arbeits
+arbeits
+ComputerArbeit
+ComputernArbeit
+Computernarbeit
+ComputerArbeits
+Arbeitcomputer
+Arbeitcomputern
+ArbeitsComputer
+ArbeitsComputern
+Computerarbeitcomputer
+ComputerArbeitcomputer
+ComputerArbeitscomputer
+Computerarbeitcomputern
+ComputerArbeitcomputern
+ComputerArbeitscomputern
+Arbeitscomputerarbeits
+Arbeitscomputernarbeits
+Computerarbeits-computer
+Arbeitsnehmer
+computers
+computern
+computernarbeit
+computernArbeit
+computerArbeit
+computerArbeits
+arbeitcomputer
+arbeitsComputer
+computerarbeitcomputer
+computerArbeitcomputer
+computerArbeitscomputer
+arbeitscomputerarbeits
+computerarbeits-computer
+arbeitsnehmer
+computernarbeit
+computernArbeit
+arbeits-
+computerarbeit
+computerarbeits-
+arbeitscomputer
+arbeitscomputern
+computerarbeitscomputer
+computerarbeitscomputern
+computerarbeitscomputers
+arbeitscomputerarbeit
+computerarbeits-Computer
+computerarbeits-Computern
diff --git a/tests/i53643.aff b/tests/i53643.aff
new file mode 100644
index 0000000..2f95528
--- /dev/null
+++ b/tests/i53643.aff
@@ -0,0 +1 @@
+# check numbers with separators
diff --git a/tests/i53643.dic b/tests/i53643.dic
new file mode 100644
index 0000000..aec5d50
--- /dev/null
+++ b/tests/i53643.dic
@@ -0,0 +1,2 @@
+1
+foo
diff --git a/tests/i53643.good b/tests/i53643.good
new file mode 100644
index 0000000..0e4e4d0
--- /dev/null
+++ b/tests/i53643.good
@@ -0,0 +1,19 @@
+1	
+12	
+123	
+1234	
+12345	
+123456	
+1234567	
+1.1	
+1.12	
+1.123	
+1.1234	
+1.12345	
+1.123456	
+12.1	
+123.12	
+1234.123	
+12345.1234	
+123456.12345	
+1234567.123456	
diff --git a/tests/pseudoroot3.test b/tests/i53643.test
similarity index 70%
rename from tests/pseudoroot3.test
rename to tests/i53643.test
index 7f44369..df97945 100755
--- a/tests/pseudoroot3.test
+++ b/tests/i53643.test
@@ -1,4 +1,5 @@
 #!/bin/sh
 DIR="`dirname $0`"
 NAME="`basename $0 .test`"
-$DIR/test.sh $NAME
+$DIR/test.sh $NAME -1
+
diff --git a/tests/i53643.wrong b/tests/i53643.wrong
new file mode 100644
index 0000000..2075f10
--- /dev/null
+++ b/tests/i53643.wrong
@@ -0,0 +1,4 @@
+1..2	
+1,,2	
+1.,2	
+1,.2	
diff --git a/tests/i54980.aff b/tests/i54980.aff
new file mode 100644
index 0000000..37cc5c5
--- /dev/null
+++ b/tests/i54980.aff
@@ -0,0 +1,2 @@
+# ISO-8859-15 (extended latin-1) support for French, Finnish and EURO symbol
+SET ISO8859-15
diff --git a/tests/i54980.dic b/tests/i54980.dic
new file mode 100644
index 0000000..414f9b8
--- /dev/null
+++ b/tests/i54980.dic
@@ -0,0 +1,3 @@
+2
+c�ur
+�uvre
diff --git a/tests/i54980.good b/tests/i54980.good
new file mode 100644
index 0000000..c8e97a2
--- /dev/null
+++ b/tests/i54980.good
@@ -0,0 +1,4 @@
+c�ur	
+�uvre	
+C�UR	
+�UVRE	
diff --git a/tests/pseudoroot.test b/tests/i54980.test
similarity index 71%
copy from tests/pseudoroot.test
copy to tests/i54980.test
index 7f44369..4d9d1a8 100755
--- a/tests/pseudoroot.test
+++ b/tests/i54980.test
@@ -1,4 +1,4 @@
 #!/bin/sh
 DIR="`dirname $0`"
 NAME="`basename $0 .test`"
-$DIR/test.sh $NAME
+$DIR/test.sh $NAME -1
diff --git a/tests/keepcase.aff b/tests/keepcase.aff
new file mode 100644
index 0000000..b08006b
--- /dev/null
+++ b/tests/keepcase.aff
@@ -0,0 +1,3 @@
+# keep case in signed words
+KEEPCASE A
+WORDCHARS .
diff --git a/tests/keepcase.dic b/tests/keepcase.dic
new file mode 100644
index 0000000..bf9992a
--- /dev/null
+++ b/tests/keepcase.dic
@@ -0,0 +1,5 @@
+4
+foo/A
+Bar/A
+baz./A
+Quux./A
diff --git a/tests/keepcase.good b/tests/keepcase.good
new file mode 100644
index 0000000..e6ff181
--- /dev/null
+++ b/tests/keepcase.good
@@ -0,0 +1,4 @@
+foo
+Bar
+baz.
+Quux.
diff --git a/tests/keepcase.sug b/tests/keepcase.sug
new file mode 100644
index 0000000..e9e6628
--- /dev/null
+++ b/tests/keepcase.sug
@@ -0,0 +1,8 @@
+foo
+foo
+Bar
+Bar
+baz., Bar
+baz., Bar
+Quux.
+Quux.
diff --git a/tests/pseudoroot.test b/tests/keepcase.test
similarity index 100%
copy from tests/pseudoroot.test
copy to tests/keepcase.test
diff --git a/tests/keepcase.wrong b/tests/keepcase.wrong
new file mode 100644
index 0000000..3b79142
--- /dev/null
+++ b/tests/keepcase.wrong
@@ -0,0 +1,8 @@
+Foo
+FOO
+BAR
+bar
+Baz.
+BAZ.
+quux.
+QUUX.
diff --git a/tests/pseudoroot.aff b/tests/needaffix.aff
similarity index 75%
rename from tests/pseudoroot.aff
rename to tests/needaffix.aff
index 211b92a..a5981ef 100644
--- a/tests/pseudoroot.aff
+++ b/tests/needaffix.aff
@@ -1,4 +1,4 @@
-PSEUDOROOT X
+NEEDAFFIX X
 COMPOUNDFLAG Y
 
 SFX A Y 1
diff --git a/tests/pseudoroot.dic b/tests/needaffix.dic
similarity index 100%
rename from tests/pseudoroot.dic
rename to tests/needaffix.dic
diff --git a/tests/pseudoroot.good b/tests/needaffix.good
similarity index 100%
rename from tests/pseudoroot.good
rename to tests/needaffix.good
diff --git a/tests/pseudoroot.test b/tests/needaffix.test
similarity index 100%
copy from tests/pseudoroot.test
copy to tests/needaffix.test
diff --git a/tests/needaffix.wrong b/tests/needaffix.wrong
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/tests/needaffix.wrong
@@ -0,0 +1 @@
+foo
diff --git a/tests/pseudoroot2.aff b/tests/needaffix2.aff
similarity index 53%
rename from tests/pseudoroot2.aff
rename to tests/needaffix2.aff
index 9346291..c434dac 100644
--- a/tests/pseudoroot2.aff
+++ b/tests/needaffix2.aff
@@ -1,2 +1,2 @@
-PSEUDOROOT X
+NEEDAFFIX X
 COMPOUNDFLAG Y
diff --git a/tests/pseudoroot2.dic b/tests/needaffix2.dic
similarity index 100%
rename from tests/pseudoroot2.dic
rename to tests/needaffix2.dic
diff --git a/tests/pseudoroot2.good b/tests/needaffix2.good
similarity index 100%
rename from tests/pseudoroot2.good
rename to tests/needaffix2.good
diff --git a/tests/pseudoroot2.morph b/tests/needaffix2.morph
similarity index 100%
rename from tests/pseudoroot2.morph
rename to tests/needaffix2.morph
diff --git a/tests/pseudoroot.test b/tests/needaffix2.test
similarity index 100%
copy from tests/pseudoroot.test
copy to tests/needaffix2.test
diff --git a/tests/pseudoroot3.aff b/tests/needaffix3.aff
similarity index 58%
rename from tests/pseudoroot3.aff
rename to tests/needaffix3.aff
index 625e1f9..5d55d38 100644
--- a/tests/pseudoroot3.aff
+++ b/tests/needaffix3.aff
@@ -1,5 +1,5 @@
-# pseudoaffix
-PSEUDOROOT X
+# neeadaffix on affixes
+NEEDAFFIX X
 
 SFX A Y 1
 SFX A 0 s/XB .
diff --git a/tests/pseudoroot3.dic b/tests/needaffix3.dic
similarity index 100%
rename from tests/pseudoroot3.dic
rename to tests/needaffix3.dic
diff --git a/tests/pseudoroot3.good b/tests/needaffix3.good
similarity index 100%
rename from tests/pseudoroot3.good
rename to tests/needaffix3.good
diff --git a/tests/pseudoroot.test b/tests/needaffix3.test
similarity index 100%
copy from tests/pseudoroot.test
copy to tests/needaffix3.test
diff --git a/tests/pseudoroot3.wrong b/tests/needaffix3.wrong
similarity index 100%
rename from tests/pseudoroot3.wrong
rename to tests/needaffix3.wrong
diff --git a/tests/pseudoroot4.aff b/tests/needaffix4.aff
similarity index 53%
rename from tests/pseudoroot4.aff
rename to tests/needaffix4.aff
index 9346291..c434dac 100644
--- a/tests/pseudoroot4.aff
+++ b/tests/needaffix4.aff
@@ -1,2 +1,2 @@
-PSEUDOROOT X
+NEEDAFFIX X
 COMPOUNDFLAG Y
diff --git a/tests/pseudoroot4.dic b/tests/needaffix4.dic
similarity index 100%
rename from tests/pseudoroot4.dic
rename to tests/needaffix4.dic
diff --git a/tests/pseudoroot4.good b/tests/needaffix4.good
similarity index 100%
rename from tests/pseudoroot4.good
rename to tests/needaffix4.good
diff --git a/tests/pseudoroot.test b/tests/needaffix4.test
similarity index 100%
copy from tests/pseudoroot.test
copy to tests/needaffix4.test
diff --git a/tests/pseudoroot5.aff b/tests/needaffix5.aff
similarity index 81%
rename from tests/pseudoroot5.aff
rename to tests/needaffix5.aff
index bfa1168..6399a3e 100644
--- a/tests/pseudoroot5.aff
+++ b/tests/needaffix5.aff
@@ -1,5 +1,5 @@
-# pseudoaffix
-PSEUDOROOT X
+# on affixes
+NEEDAFFIX X
 
 SFX A Y 2
 SFX A 0 suf/B .
diff --git a/tests/pseudoroot5.dic b/tests/needaffix5.dic
similarity index 100%
rename from tests/pseudoroot5.dic
rename to tests/needaffix5.dic
diff --git a/tests/pseudoroot5.good b/tests/needaffix5.good
similarity index 100%
rename from tests/pseudoroot5.good
rename to tests/needaffix5.good
diff --git a/tests/pseudoroot.test b/tests/needaffix5.test
similarity index 100%
copy from tests/pseudoroot.test
copy to tests/needaffix5.test
diff --git a/tests/pseudoroot5.wrong b/tests/needaffix5.wrong
similarity index 100%
rename from tests/pseudoroot5.wrong
rename to tests/needaffix5.wrong
diff --git a/tests/nosuggest.aff b/tests/nosuggest.aff
new file mode 100644
index 0000000..c9361da
--- /dev/null
+++ b/tests/nosuggest.aff
@@ -0,0 +1,5 @@
+# don't suggest word with NOSUGGEST flag (for example vulgar or obscene words)
+# See OpenOffice.org Issue #55498
+# (nosuggest.sug is an empty file)
+NOSUGGEST A
+COMPOUNDFLAG B
diff --git a/tests/nosuggest.dic b/tests/nosuggest.dic
new file mode 100644
index 0000000..dc80c91
--- /dev/null
+++ b/tests/nosuggest.dic
@@ -0,0 +1,3 @@
+1
+foo/AB
+bar/B
diff --git a/tests/pseudoroot.wrong b/tests/nosuggest.good
similarity index 69%
rename from tests/pseudoroot.wrong
rename to tests/nosuggest.good
index 0731eb7..ad91a5e 100644
--- a/tests/pseudoroot.wrong
+++ b/tests/nosuggest.good
@@ -1,4 +1,3 @@
 foo
 foobar
-foosbar
 barfoo
diff --git a/tests/nosuggest.sug b/tests/nosuggest.sug
new file mode 100644
index 0000000..e69de29
diff --git a/tests/pseudoroot.test b/tests/nosuggest.test
similarity index 100%
rename from tests/pseudoroot.test
rename to tests/nosuggest.test
diff --git a/tests/nosuggest.wrong b/tests/nosuggest.wrong
new file mode 100644
index 0000000..89c7a1a
--- /dev/null
+++ b/tests/nosuggest.wrong
@@ -0,0 +1,3 @@
+foox
+foobarx
+barfoox
diff --git a/tests/test.sh b/tests/test.sh
index 4b16c81..bf7c025 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -78,7 +78,8 @@ check_valgrind_log "bad words"
 
 # Tests morphological analysis
 if test -f $TESTDIR/$NAME.morph; then
-    hunmorph $TESTDIR/$NAME.aff $TESTDIR/$NAME.dic $TESTDIR/$NAME.good >$TEMPDIR/$NAME.morph
+    sed 's/	$//' $TESTDIR/$NAME.good >$TEMPDIR/$NAME.good
+    hunmorph $TESTDIR/$NAME.aff $TESTDIR/$NAME.dic $TEMPDIR/$NAME.good >$TEMPDIR/$NAME.morph
     if ! cmp $TEMPDIR/$NAME.morph $TESTDIR/$NAME.morph >/dev/null; then
         echo "============================================="
         echo "Fail in $NAME.morph. Bad analysis?"
@@ -86,7 +87,7 @@ if test -f $TESTDIR/$NAME.morph; then
         rm -f $TEMPDIR/$NAME.morph
         exit 1
     fi
-    rm -f $TEMPDIR/$NAME.morph
+    rm -f $TEMPDIR/$NAME.{morph,good}
 fi
 
 check_valgrind_log "morphological analysis"

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-openoffice/hunspell.git


Reply to: