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

[hunspell] 56/98: Imported Upstream version 1.2.4



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

rene pushed a commit to branch master
in repository hunspell.

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

    Imported Upstream version 1.2.4
---
 ChangeLog                   |  79 ++++++++++++++++
 NEWS                        |  15 +++
 THANKS                      |  13 ++-
 configure                   | 102 +++++++++++----------
 configure.ac                |  39 ++++----
 hunspell.pc.in              |   4 +-
 man/Makefile.am             |   2 +-
 man/Makefile.in             |  72 ++++++++++++---
 man/hu/hunspell.1           |   1 +
 man/hu/hunspell.4           |   2 +-
 man/hunspell.1              |  19 ++--
 man/hunspell.3              | 218 ++++++++++++++++++++++++++++++++++++++++++++
 man/hunzip.1                |  24 +++++
 man/hzip.1                  |  24 +++++
 po/hu.gmo                   | Bin 8886 -> 8886 bytes
 po/hu.po                    | 144 ++++++++++++++---------------
 po/hunspell.pot             | 144 ++++++++++++++---------------
 src/hunspell/affentry.cxx   |  45 +++++----
 src/hunspell/affixmgr.cxx   | 110 ++++++++++------------
 src/hunspell/csutil.cxx     |  40 +++++---
 src/hunspell/csutil.hxx     |   9 ++
 src/hunspell/hashmgr.cxx    |  17 ++--
 src/hunspell/hunspell.cxx   | 155 +++++++++++++++++++++++++++++--
 src/hunspell/hunspell.h     |   4 +
 src/hunspell/hunspell.hxx   |  18 +++-
 src/hunspell/suggestmgr.cxx |  40 ++++++--
 src/tools/analyze.cxx       |  14 +--
 src/tools/chmorph.cxx       |  12 +--
 src/tools/example.cxx       |   3 +-
 src/tools/hunspell.cxx      |  56 ++++++------
 src/win_api/Hunspell.rc     |   8 +-
 src/win_api/README          |   2 +-
 src/win_api/hunspelldll.c   |   4 +
 src/win_api/hunspelldll.h   |   4 +-
 tests/1975530.aff           |   6 ++
 tests/1975530.dic           |   3 +
 tests/1975530.good          |   3 +
 tests/1975530.test          |   4 +
 tests/1975530.wrong         |   1 +
 tests/Makefile.am           |  22 ++++-
 tests/Makefile.in           |  22 ++++-
 tests/base.sug              |   2 +-
 tests/base_utf.sug          |   2 +-
 tests/condition.aff         |  37 ++++++++
 tests/condition.dic         |   2 +
 tests/condition.good        |  18 ++++
 tests/condition.test        |   4 +
 tests/condition.wrong       |  15 +++
 tests/condition_utf.aff     |  38 ++++++++
 tests/condition_utf.dic     |   2 +
 tests/condition_utf.good    |  19 ++++
 tests/condition_utf.test    |   4 +
 tests/condition_utf.wrong   |  14 +++
 53 files changed, 1240 insertions(+), 421 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c031218..f8b3e3c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,82 @@
+2008-06-17 Németh László <nemeth at OOo>:
+        * src/{hunspell.cxx,hunspell.h}: add free_list() to the C and
+          C++ interface to deallocate suggestion lists. The problem
+          reported by Laurie Mercer and Christophe Paris.
+        * csutil.cxx: fix freelist() to deallocate non-NULL list, when n = 0.
+        * tools/{analyze,example,chmorph,hunspell}.cxx: use free_list().
+
+        * tools/hunspell.cxx: fix only --with-readline compiling problem.
+          Reported by Volkov Peter in SF.net Bug 1995842.
+          
+        * man/hunspell.3,hunspell.hxx: fix analyze and generate examples in
+          the manual and comments (using char*** parameter instead of char**).
+        
+        * tools/example.cxx: fix suggestion example.
+
+2008-06-17 Németh László <nemeth at OOo>:
+        * affentry.cxx: fix the new affix rule matching algorithm of
+          Hunspell 1.2. Arabic dictionary problem reported by Khaled Hosny
+          in SF.net Bug ID 1975530. Mohamed Kebdani also sent a
+          prepared test data.
+        * tests/{1975530,condition*}: tests for the fix
+
+2008-06-13 Ingo H. de Boer <idb_winshell at SF.net>:
+        * src/hunspell/{affixmgr.cxx,hunspell.cxx}: add missing type 
+          cast to strstr() calls for VC8 compatibility.
+
+2008-06-13 Németh László <nemeth at OOo>:
+        * suggestmgr.cxx: add also part1-part2 suggestion with dash
+          for bad part1part2 word forms, suggested by Ruud Baars.
+          For example, now suggestion of "parttime": "part time"
+          and "part-time".          
+          NOTE: this feature will work only when the TRY definition
+          contains "-" or the letter "a".
+
+        * hunspell.cxx: new XML API in spell() and suggest() (see hunspell(3)).
+
+        * src/hunspell/*: fixes for OpenOffice.org build environment.
+
+        * man/{hunspell.3,hzip.1,hunzip.1}: add new manual pages for
+          Hunspell programming API and dictionary compression and
+          encryption utilities.
+          
+        * src/hunspell/*: handle failed mystrdup() calls and other potential
+          insufficient memory problems. The problem reported by Elio Voci
+          in OpenOffice.org Issue 90604 and others.
+
+        * src/tools/affixmgr.cxx: restore original behaviour of get_wordchars
+          without conditional code. Problem reported by Ingo H. de Boer
+          in SF.net Bug 1763105.
+
+        * win_api/hunspelldll.h: put_word() renamed to add() in the (old)
+          Windows DLL API bug reported in SF.net Bug 1943236. Also reported
+          by Bartkó Zoltán.
+  
+        * tools/hunspell.cxx: fix chench() for environments without
+          native language support (ENABLE_NLS 0 in config.h),
+          PHP system_exec() bug reported by Michel Weimerskirch in
+          SF.net Bug 1951087.
+        
+        * hunspell.cxx, affixmgr.cxx: remove "result" from the
+          (result && *result) conditions, when "result" is a static variable.
+          The problem and a possible solution reported by Ladislav Michnovič.
+
+        * affixmgr.cxx: parse_affix(): print line instead of NULL in
+          the warning message, when affix class header is bad.
+          The problem reported by Ladislav Michnovič.
+
+2008-06-01 Christian Lohmaier <cloph at OOo>
+        * configure.ac: patch to fix --with-readline, --with-ui logic.
+          Reported in the SF.net Bug 981395.
+
+2008-05-04: Volkov Peter <volkov_peter at users sourceforge net>
+        * configure.ac: fix LibTool 2.22 incompatibility by removing
+          unused LT_* macros. Report and patch in SF.net Bug 1957383.
+          The problem reported and fixed by Ladislav Michnovič, too.
+
+2008-04-23: Ladislav Michnovič <lmichnovic at suse cz>
+        * hunspell.pc.in: fix wrongly set directories.
+
 2008-04-12 Németh László <nemeth at OOo>:
         * src/tools/hunspell.cxx: 
         - Multilingual spell checking and special dictionary support with -d.
diff --git a/NEWS b/NEWS
index 61c2453..159c8f3 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,18 @@
+2008-06-17: Hunspell 1.2.4 release:
+  - add free_list() for C, C++ interfaces to deallocate suggestion lists
+  
+  - bug fixes
+
+2008-06-17: Hunspell 1.2.3 release:
+  - extended XML interface to use morphological functions by standard
+    spell checking interface, spell() and suggest(). See hunspell.3 manual page.
+
+  - default dash suggestions for compound words: newword-> new word and new-word
+
+  - new manual pages: hunspell.3, hzip.1, hunzip.1.
+  
+  - bug fixes
+
 2008-04-12: Hunspell 1.2.2 release:
   - extended dictionary (dic file) support to use multiple base and
     special dictionaries.
diff --git a/THANKS b/THANKS
index 2474acf..764c888 100644
--- a/THANKS
+++ b/THANKS
@@ -1,6 +1,7 @@
 Many thanks to the following contributors and supporters:
 
 Lars Aronsson
+Ruud Baars
 Bartkó Zoltán
 Bencsáth Boldizsár
 Bíró Árpád
@@ -32,6 +33,7 @@ Jean-Christophe Helary
 Kevin Hendricks
 Martin Hollmichel
 Pavel Janík
+Mohamed Kebdani
 Kelemen Gábor
 Kéménczy Kálmán
 Dan Kenigsberg
@@ -40,12 +42,15 @@ Khiraly László
 Koblinger Egmont
 Kornai András
 Tor Lillqvist
+Christian Lohmaier
 Robert Longson
 Marot at SF dot net
 Mark McClain
 Caolan McNamara
 Michael Meeks
 Moheb Mekhaiel
+Laurie Mercer
+Ladislav Michnovič
 Ellis Miller
 Giuseppe Modugno
 János Mohácsi
@@ -54,8 +59,10 @@ Daniel Naber
 Nagy Viktor
 John Nisly
 Noll János
+Christophe Paris
 Malcolm Parsons
 Sylvain Paschein
+Volkov Peter
 Bryan Petty
 Harri Pitkänen
 Davide Prina
@@ -73,8 +80,10 @@ Trón Viktor
 Gianluca Turconi
 Ryan VanderMeulen
 Varga Dániel
+Elio Voci
 Miha Vrhovnik
 Martijn Wargers
+Michel Weimerskirch
 Friedel Wolff
 Gábor Zahemszky
 Taha Zerrouki 
@@ -90,13 +99,13 @@ http://www.mokk.bme.hu
 
 Hungarian Ministry of Informatics and Telecommunications
 
-IMEDIA Ltd.
+IMEDIA Kft.
 http://www.imedia.hu
 
 OpenOffice.org community
 http://www.openoffice.org
 
-UHU-Linux Ltd.
+UHU-Linux Kft.
 
 Thanks,
 
diff --git a/configure b/configure
index 48880d9..099d34d 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.2.2.
+# Generated by GNU Autoconf 2.59 for hunspell 1.2.4.
 #
 # Report bugs to <nemeth@openoffice.org>.
 #
@@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='hunspell'
 PACKAGE_TARNAME='hunspell'
-PACKAGE_VERSION='1.2.2'
-PACKAGE_STRING='hunspell 1.2.2'
+PACKAGE_VERSION='1.2.4'
+PACKAGE_STRING='hunspell 1.2.4'
 PACKAGE_BUGREPORT='nemeth@openoffice.org'
 
 ac_unique_file="config.h.in"
@@ -954,7 +954,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.2.2 to adapt to many kinds of systems.
+\`configure' configures hunspell 1.2.4 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1021,7 +1021,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of hunspell 1.2.2:";;
+     short | recursive ) echo "Configuration of hunspell 1.2.4:";;
    esac
   cat <<\_ACEOF
 
@@ -1171,7 +1171,7 @@ fi
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-hunspell configure 1.2.2
+hunspell configure 1.2.4
 generated by GNU Autoconf 2.59
 
 Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1185,7 +1185,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.2.2, which was
+It was created by hunspell $as_me 1.2.4, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   $ $0 $@
@@ -1913,7 +1913,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE=hunspell
- VERSION=1.2.2
+ VERSION=1.2.4
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2048,11 +2048,6 @@ HUNSPELL_VERSION_MINOR=`echo $VERSION | cut -d"." -f2`
 
 
 
-# library version
-LT_CURRENT=1
-LT_REVISION=0
-LT_AGE=0
-
 
           ac_config_headers="$ac_config_headers config.h"
 
@@ -4194,7 +4189,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 4197 "configure"' > conftest.$ac_ext
+  echo '#line 4192 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -5329,7 +5324,7 @@ fi
 
 
 # Provide some information about the compiler.
-echo "$as_me:5332:" \
+echo "$as_me:5327:" \
      "checking for Fortran 77 compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
 { (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
@@ -6392,11 +6387,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6395: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6390: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:6399: \$? = $ac_status" >&5
+   echo "$as_me:6394: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -6660,11 +6655,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6663: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6658: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:6667: \$? = $ac_status" >&5
+   echo "$as_me:6662: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -6764,11 +6759,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:6767: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6762: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:6771: \$? = $ac_status" >&5
+   echo "$as_me:6766: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -8233,7 +8228,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 8236 "configure"' > conftest.$ac_ext
+    echo '#line 8231 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -9130,7 +9125,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 9133 "configure"
+#line 9128 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -9230,7 +9225,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 9233 "configure"
+#line 9228 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11573,11 +11568,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:11576: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:11571: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:11580: \$? = $ac_status" >&5
+   echo "$as_me:11575: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -11677,11 +11672,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:11680: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:11675: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:11684: \$? = $ac_status" >&5
+   echo "$as_me:11679: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -12213,7 +12208,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 12216 "configure"' > conftest.$ac_ext
+    echo '#line 12211 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -13271,11 +13266,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13274: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13269: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13278: \$? = $ac_status" >&5
+   echo "$as_me:13273: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -13375,11 +13370,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13378: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13373: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13382: \$? = $ac_status" >&5
+   echo "$as_me:13377: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -14824,7 +14819,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 14827 "configure"' > conftest.$ac_ext
+    echo '#line 14822 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -15602,11 +15597,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15605: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15600: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15609: \$? = $ac_status" >&5
+   echo "$as_me:15604: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -15870,11 +15865,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15873: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15868: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15877: \$? = $ac_status" >&5
+   echo "$as_me:15872: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -15974,11 +15969,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15977: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15972: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:15981: \$? = $ac_status" >&5
+   echo "$as_me:15976: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -17443,7 +17438,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 17446 "configure"' > conftest.$ac_ext
+    echo '#line 17441 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -22894,7 +22889,12 @@ CURSESLIB=""
 if test "${with_ui+set}" = set; then
   withval="$with_ui"
 
-   echo "$as_me:$LINENO: checking for tparm in -lncursesw" >&5
+else
+  with_ui=no
+
+fi;
+if test "x$with_ui" != xno; then
+  echo "$as_me:$LINENO: checking for tparm in -lncursesw" >&5
 echo $ECHO_N "checking for tparm in -lncursesw... $ECHO_C" >&6
 if test "${ac_cv_lib_ncursesw_tparm+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -23123,16 +23123,22 @@ _ACEOF
 
    fi
 
-fi;
+fi
+
 
 
-rl=n
 
 # Check whether --with-readline or --without-readline was given.
 if test "${with_readline+set}" = set; then
   withval="$with_readline"
 
-   echo "$as_me:$LINENO: checking for tparm in -lcurses" >&5
+else
+  with_readline=no
+
+fi;
+rl=n
+if test "x$with_readline" != xno; then
+  echo "$as_me:$LINENO: checking for tparm in -lcurses" >&5
 echo $ECHO_N "checking for tparm in -lcurses... $ECHO_C" >&6
 if test "${ac_cv_lib_curses_tparm+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -23492,7 +23498,7 @@ _ACEOF
    fi
    LDFLAGS=$LDSAVE
 
-fi;
+fi
 
 
 
@@ -23881,7 +23887,7 @@ _ASBOX
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by hunspell $as_me 1.2.2, which was
+This file was extended by hunspell $as_me 1.2.4, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -23944,7 +23950,7 @@ _ACEOF
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-hunspell config.status 1.2.2
+hunspell config.status 1.2.4
 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 0e580d0..dbeffb3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,22 +4,17 @@
 m4_pattern_allow
 
 AC_PREREQ(2.59)
-AC_INIT([hunspell],[1.2.2],[nemeth@openoffice.org])
+AC_INIT([hunspell],[1.2.4],[nemeth@openoffice.org])
 
 AC_CANONICAL_SYSTEM
 AC_SUBST(XFAILED)
 
-AM_INIT_AUTOMAKE(hunspell, 1.2.2)
+AM_INIT_AUTOMAKE(hunspell, 1.2.4)
 HUNSPELL_VERSION_MAJOR=`echo $VERSION | cut -d"." -f1`
 HUNSPELL_VERSION_MINOR=`echo $VERSION | cut -d"." -f2`
 AC_SUBST(HUNSPELL_VERSION_MAJOR)
 AC_SUBST(HUNSPELL_VERSION_MINOR)
 
-# library version
-LT_CURRENT=1
-LT_REVISION=0
-LT_AGE=0
-
 AC_CONFIG_SRCDIR([config.h.in])
 AC_CONFIG_HEADER([config.h])
 
@@ -56,8 +51,15 @@ AC_ARG_WITH(experimental,[  --with-experimental     compile with some extra func
 ])
 
 CURSESLIB=""
-AC_ARG_WITH(ui,[  --with-ui               support Curses user interface], [
-   AC_CHECK_LIB(ncursesw,tparm,CURSESLIB=-lncursesw,
+AC_ARG_WITH(
+   [ui],
+   [AS_HELP_STRING([--with-ui],[support Curses user interface])],
+   [],
+   [with_ui=no]
+)
+AS_IF(
+   [test "x$with_ui" != xno],
+   [AC_CHECK_LIB(ncursesw,tparm,CURSESLIB=-lncursesw,
      AC_CHECK_LIB(curses,tparm,CURSESLIB=-lcurses,
        AC_CHECK_LIB(ncurses,tparm,CURSESLIB=-lncurses)))
    if test "$CURSESLIB" != "" ; then
@@ -69,13 +71,19 @@ AC_ARG_WITH(ui,[  --with-ui               support Curses user interface], [
        AC_DEFINE(HAVE_NCURSESW_H,1,"Define if you have the <ncursesw/curses.h> header")       
      fi
      AC_DEFINE(HUNSPELL_WARNING_ON,1,"Define if you need warning messages")
-   fi
-])
+   fi]
+)
 AC_SUBST(CURSESLIB)
 
+AC_ARG_WITH(
+   [readline],
+   [AS_HELP_STRING([--with-readline],[support fancy command input editing])],
+   [],
+   [with_readline=no]
+)
 rl=n
-AC_ARG_WITH(readline,[  --with-readline         support fancy command input editing], [
-   AC_CHECK_LIB(curses,tparm,TERMLIB=-lncurses,
+AS_IF([test "x$with_readline" != xno],
+   [AC_CHECK_LIB(curses,tparm,TERMLIB=-lncurses,
      AC_CHECK_LIB(termcap,tgetent,TERMLIB=-ltermcap))
    LDSAVE=$LDFLAGS
    LDFLAGS="$LDFLAGS $TERMLIB"
@@ -87,9 +95,8 @@ AC_ARG_WITH(readline,[  --with-readline         support fancy command input edit
      echo Using the readline library.
      AC_DEFINE(HAVE_READLINE,1,"Define if you have fancy command input editing with Readline")
    fi
-   LDFLAGS=$LDSAVE
-])
-
+   LDFLAGS=$LDSAVE]
+)
 AC_SUBST(READLINELIB)
 
 AC_CONFIG_FILES([Makefile
diff --git a/hunspell.pc.in b/hunspell.pc.in
index b9f51a2..7b8d5e0 100644
--- a/hunspell.pc.in
+++ b/hunspell.pc.in
@@ -1,7 +1,7 @@
 prefix=@prefix@
 exec_prefix=${prefix}
-libdir=${prefix}/lib
-includedir=${prefix}/include
+libdir=@libdir@
+includedir=@includedir@
 
 Name: hunspell
 Description: Hunpell spellchecking library
diff --git a/man/Makefile.am b/man/Makefile.am
index 1c4479c..94e6fb2 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -1,3 +1,3 @@
-man_MANS = hunspell.1 hunspell.4
+man_MANS = hunspell.1 hunspell.3 hunspell.4 hzip.1 hunzip.1
 EXTRA_DIST = $(man_MANS)
 SUBDIRS=hu
diff --git a/man/Makefile.in b/man/Makefile.in
index 51b189d..b1ec3f4 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -59,7 +59,9 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
 	pdf-recursive ps-recursive uninstall-info-recursive \
 	uninstall-recursive
 man1dir = $(mandir)/man1
-am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man4dir)"
+am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" \
+	"$(DESTDIR)$(man4dir)"
+man3dir = $(mandir)/man3
 man4dir = $(mandir)/man4
 NROFF = nroff
 MANS = $(man_MANS)
@@ -196,7 +198,7 @@ target_alias = @target_alias@
 target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
-man_MANS = hunspell.1 hunspell.4
+man_MANS = hunspell.1 hunspell.3 hunspell.4 hzip.1 hunzip.1
 EXTRA_DIST = $(man_MANS)
 SUBDIRS = hu
 all: all-recursive
@@ -286,6 +288,51 @@ uninstall-man1:
 	  echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \
 	  rm -f "$(DESTDIR)$(man1dir)/$$inst"; \
 	done
+install-man3: $(man3_MANS) $(man_MANS)
+	@$(NORMAL_INSTALL)
+	test -z "$(man3dir)" || $(mkdir_p) "$(DESTDIR)$(man3dir)"
+	@list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.3*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+	  else file=$$i; fi; \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    3*) ;; \
+	    *) ext='3' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \
+	  $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst"; \
+	done
+uninstall-man3:
+	@$(NORMAL_UNINSTALL)
+	@list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \
+	l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+	for i in $$l2; do \
+	  case "$$i" in \
+	    *.3*) list="$$list $$i" ;; \
+	  esac; \
+	done; \
+	for i in $$list; do \
+	  ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+	  case "$$ext" in \
+	    3*) ;; \
+	    *) ext='3' ;; \
+	  esac; \
+	  inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+	  inst=`echo $$inst | sed -e 's/^.*\///'`; \
+	  inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+	  echo " rm -f '$(DESTDIR)$(man3dir)/$$inst'"; \
+	  rm -f "$(DESTDIR)$(man3dir)/$$inst"; \
+	done
 install-man4: $(man4_MANS) $(man_MANS)
 	@$(NORMAL_INSTALL)
 	test -z "$(man4dir)" || $(mkdir_p) "$(DESTDIR)$(man4dir)"
@@ -511,7 +558,7 @@ check: check-recursive
 all-am: Makefile $(MANS)
 installdirs: installdirs-recursive
 installdirs-am:
-	for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man4dir)"; do \
+	for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man4dir)"; do \
 	  test -z "$$dir" || $(mkdir_p) "$$dir"; \
 	done
 install: install-recursive
@@ -563,7 +610,7 @@ install-exec-am:
 
 install-info: install-info-recursive
 
-install-man: install-man1 install-man4
+install-man: install-man1 install-man3 install-man4
 
 installcheck-am:
 
@@ -587,7 +634,7 @@ uninstall-am: uninstall-info-am uninstall-man
 
 uninstall-info: uninstall-info-recursive
 
-uninstall-man: uninstall-man1 uninstall-man4
+uninstall-man: uninstall-man1 uninstall-man3 uninstall-man4
 
 .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \
 	clean clean-generic clean-libtool clean-recursive ctags \
@@ -595,13 +642,14 @@ uninstall-man: uninstall-man1 uninstall-man4
 	distclean-recursive distclean-tags distdir dvi dvi-am html \
 	html-am info info-am install install-am install-data \
 	install-data-am install-exec install-exec-am install-info \
-	install-info-am install-man install-man1 install-man4 \
-	install-strip installcheck installcheck-am installdirs \
-	installdirs-am maintainer-clean maintainer-clean-generic \
-	maintainer-clean-recursive mostlyclean mostlyclean-generic \
-	mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \
-	tags tags-recursive uninstall uninstall-am uninstall-info-am \
-	uninstall-man uninstall-man1 uninstall-man4
+	install-info-am install-man install-man1 install-man3 \
+	install-man4 install-strip installcheck installcheck-am \
+	installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic maintainer-clean-recursive \
+	mostlyclean mostlyclean-generic mostlyclean-libtool \
+	mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am uninstall-info-am uninstall-man \
+	uninstall-man1 uninstall-man3 uninstall-man4
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/man/hu/hunspell.1 b/man/hu/hunspell.1
index 7c3423b..0d0b6c8 100644
--- a/man/hu/hunspell.1
+++ b/man/hu/hunspell.1
@@ -107,6 +107,7 @@ hibás szót sem tartalmaznak.
 Elemző üzemmód: a bemeneti szövegszavak morfológia elemzése, illetve a szótári
 morfológiai leírás hiányában a toldalékolt szavak kapcsolóinak
 kijelzése (szótárfejlesztőknek).
+.TP
 .B \-n
 Nroff/troff bemeneti állományformátum beállítása, elsősorban a 
 kézikönyvlapok ellenőrzésére.
diff --git a/man/hu/hunspell.4 b/man/hu/hunspell.4
index dd2bfe7..c381623 100644
--- a/man/hu/hunspell.4
+++ b/man/hu/hunspell.4
@@ -342,7 +342,7 @@ kapcsoló (germán nyelvek esetében tipikus).
 Ezzel a kapcsolóval jelölt szuffixum csak ugyanilyen kapcsolóval
 jelölt prefixummal jelenhet meg egy tövön. (Pl. leg-édes-ebb).
 .IP "COMPOUNDPERMITFLAG kapcsoló"
-Alapéetelmezés szerint a prefixumok és szuffixumok nem fordulhatnak
+Alapértelmezés szerint a prefixumok és szuffixumok nem fordulhatnak
 elő az összetett szavak belsejében. A COMPOUNDPERMITFLAG
 kapcsolóval rendelkező affixumok viszont itt is megjelenhetnek.
 .IP "COMPOUNDFORBIDFLAG kapcsoló"
diff --git a/man/hunspell.1 b/man/hunspell.1
index b788796..91b6586 100644
--- a/man/hunspell.1
+++ b/man/hunspell.1
@@ -1,4 +1,4 @@
-.TH hunspell 1 "2008-04-11"
+.TH hunspell 1 "2008-06-12"
 .LO 1
 .SH NAME
 hunspell \- spell checker, stemmer and morphological analyzer
@@ -16,9 +16,9 @@ Typing "cat" and "exsample" in two input lines, we got an asterisk
 .RS
 .nf
 $ hunspell -d en_US
-Hunspell 1.2.2
+Hunspell 1.2.3
 *
-& exsample 3 0: example, examples, ex sample
+& exsample 4 0: example, examples, ex sample, ex-sample
 .fi
 .RE
 .PP
@@ -370,16 +370,11 @@ See hunspell(4).
 .BI $HOME/.hunspell_default.
 Default path to personal dictionary.
 .SH SEE ALSO
-.B hunspell (4)
+.B hunspell (3), hunspell(4)
 .SH AUTHOR
-Hunspell based on Ispell's algorithms and OpenOffice.org's Myspell source code.
+Author of Hunspell executable is László Németh. For Hunspell library,
+see hunspell(3).
 .PP
-Author of International Ispell is Geoff Kuenning.
-.PP
-Author of MySpell is Kevin Hendricks.
-.PP
-Author of Hunspell is László Németh.
-.PP
-This manual based on Ispell's manual (See ispell(1)).
+This manual based on Ispell's manual. See ispell(1).
 .SH BUGS
 There are some layout problems with long lines.
diff --git a/man/hunspell.3 b/man/hunspell.3
new file mode 100644
index 0000000..15994b9
--- /dev/null
+++ b/man/hunspell.3
@@ -0,0 +1,218 @@
+.TH hunspell 3 "2008-06-13"
+.LO 1
+.hy 0
+.SH NAME
+\fBhunspell\fR - spell checking, stemming, morphological generation and analysis
+.SH SYNOPSIS
+\fB#include <hunspell/hunspell.hxx> /* or */\fR
+.br
+\fB#include <hunspell/hunspell.h>\fR
+.br
+.sp
+.BI "Hunspell(const char *" affpath ", const char *" dpath );
+.sp
+.BI "Hunspell(const char *" affpath ", const char *" dpath ", const char * " key );
+.sp
+.BI "~Hunspell(" );
+.sp
+.BI "int add_dic(const char *" dpath );
+.sp
+.BI "int add_dic(const char *" dpath ", const char *" key );
+.sp
+.BI "int spell(const char *" word );
+.sp
+.BI "int spell(const char *" word ", int *" info ", char **" root );
+.sp
+.BI "int suggest(char***" slst ", const char *" word);
+.sp
+.BI "int analyze(char***" slst ", const char *" word);
+.sp
+.BI "int stem(char***" slst ", const char *" word);
+.sp
+.BI "int stem(char***" slst ", char **" morph ", int " n);
+.sp
+.BI "int generate(char***" slst ", const char *" word ", const char *" word2);
+.sp
+.BI "int generate(char***" slst ", const char *" word ", char **" desc ", int " n);
+.sp
+.BI "void free_list(char ***" slst ", int " n);
+.sp
+.BI "int add(const char *" word);
+.sp
+.BI "int add_with_affix(const char *" word ", const char *" example);
+.sp
+.BI "int remove(const char *" word);
+.sp
+.BI "char * get_dic_encoding(" );
+.sp
+.BI "const char * get_wordchars(" );
+.sp
+.BI "unsigned short * get_wordchars_utf16(int *" len);
+.sp
+.BI "struct cs_info * get_csconv(" );
+.sp
+.BI "const char * get_version(" );
+.SH DESCRIPTION
+The \fBHunspell\fR library routines give the user word-level
+linguistic functions: spell checking and correction, stemming,
+morphological generation and analysis in item-and-arrangement style.
+.PP
+The optional C header contains the C interface of the C++ library with
+Hunspell_create and Hunspell_destroy constructor and destructor, and
+an extra HunHandle parameter (the allocated object) in the
+wrapper functions (see in the C header file \fBhunspell.h\fR).
+.PP
+The basic spelling functions, \fBspell()\fR and \fBsuggest()\fR can
+be used for stemming, morphological generation and analysis by
+XML input texts (see XML API).
+.
+.SS Constructor and destructor
+Hunspell's constructor needs paths of the affix and dictionary files. 
+See the \fBhunspell\fR(4) manual page for the dictionary format.
+Optional \fBkey\fR parameter is for dictionaries encrypted by
+the \fBhzip\fR tool of the Hunspell distribution.
+.
+.SS Extra dictionaries
+The add_dic() function load an extra dictionary file. 
+The extra dictionaries use the affix file of the allocated Hunspell
+object. Maximal number of the extra dictionaries is limited in the source code (20).
+.
+.SS Spelling and correction
+The spell() function returns non-zero, if the input word is recognised
+by the spell checker, and a zero value if not. Optional reference
+variables return a bit array (info) and the root word of the input word.
+Info bits checked with the SPELL_COMPOUND and SPELL_FORBIDDEN
+macros sign compound words and explicit forbidden words.
+.PP
+The suggest() function has two input parameters, a reference variable
+of the output suggestion list, and an input word. The function returns
+the number of the suggestions. The reference variable
+will contain the address of the newly allocated suggestion list or NULL,
+if the return value of suggest() is zero. Maximal number of the suggestions
+is limited in the source code.
+.PP
+The spell() and suggest() can recognize XML input, see the XML API section.
+.
+.SS Morphological functions
+The plain stem() and analyze() functions are similar to the suggest(), but
+instead of suggestions, return stems and results of the morphological
+analysis. The plain generate() waits a second word, too. This extra word
+and its affixation will be the model of the morphological generation of
+the requested forms of the first word.
+.PP
+The extended stem() and generate() use the results of a
+morphological analysis:
+.PP
+.RS
+.nf
+char ** result, result2;
+int n1 = analyze(&result, "words");
+int n2 = stem(&result2, result, n1);   
+.fi
+.RE
+.PP
+The morphological annotation of the Hunspell library has fixed
+(two letter and a colon) field identifiers, see the
+\fBhunspell\fR(4) manual page.
+.PP
+.RS
+.nf
+char ** result;
+char * affix = "is:plural"; // description depends from dictionaries, too
+int n = generate(&result, "word", &affix, 1);
+for (int i = 0; i < n; i++) printf("%s\n", result[i]);
+.fi
+.RE
+.PP
+.SS Memory deallocation
+The free_list() function frees the memory allocated by suggest(),
+analyze, generate and stem() functions.
+.SS Other functions
+The add(), add_with_affix() and remove() are helper functions of a
+personal dictionary implementation to add and remove words from the
+base dictionary in run-time. The add_with_affix() uses a second word
+as a model of the enabled affixation of the new word.
+.PP
+The get_dic_encoding() function returns "ISO8859-1" or the character
+encoding defined in the affix file with the "SET" keyword.
+.PP
+The get_csconv() function returns the 8-bit character case table of the
+encoding of the dictionary.
+.PP
+The get_wordchars() and get_wordchars_utf16() return the 
+extra word characters definied in affix file for tokenization by
+the "WORDCHARS" keyword.
+.PP
+The get_version() returns the version string of the library.
+.SS XML API
+The spell() function returns non-zero for the "<?xml?>" input
+indicating the XML API support.
+.PP
+The suggest() function stems, analyzes and generates the forms of the
+input word, if it was added by one of the following "SPELLML" syntaxes:
+.PP
+.RS
+.nf
+<?xml?>
+<query type="analyze">
+<word>dogs</word>
+</query>
+.fi
+.RE
+.PP
+
+.PP
+.RS
+.nf
+<?xml?>
+<query type="stem">
+<word>dogs</word>
+</query>
+.fi
+.RE
+.PP
+
+.PP
+.RS
+.nf
+<?xml?>
+<query type="generate">
+<word>dog</word>
+<word>cats</word>
+</query>
+.fi
+.RE
+.PP
+
+.PP
+.RS
+.nf
+<?xml?>
+<query type="generate">
+<word>dog</word>
+<code><a>is:pl</a><a>is:poss</a></code>
+</query>
+.fi
+.RE
+.PP
+
+The outputs of the type="stem" query and the stem() library function
+are the same. The output of the type="analyze" query is a string contained
+a <code><a>result1</a><a>result2</a>...</code> element. This 
+element can be used in the second syntax of the type="generate" query.
+.SH EXAMPLE
+See analyze.cxx in the Hunspell distribution.
+.SH AUTHORS
+Hunspell based on Ispell's spell checking algorithms and OpenOffice.org's Myspell source code.
+.PP
+Author of International Ispell is Geoff Kuenning.
+.PP
+Author of MySpell is Kevin Hendricks.
+.PP
+Author of Hunspell is László Németh.
+.PP
+Author of the original C API is Caolan McNamara.
+.PP
+Author of the Aspell table-driven phonetic transcription algorithm and code is Björn Jacke.
+.PP
+See also THANKS and Changelog files of Hunspell distribution.
diff --git a/man/hunzip.1 b/man/hunzip.1
new file mode 100644
index 0000000..768a3a2
--- /dev/null
+++ b/man/hunzip.1
@@ -0,0 +1,24 @@
+.TH hzip 1 "2008-06-12"
+.LO 1
+.SH NAME
+hunzip \- decompress and decrypt hzip files to the standard output
+.SH SYNOPSIS
+hunzip [\-h] file.hz [password]
+.SH DESCRIPTION
+.I Hunzip
+is the decompression and decryption program of hzip format.
+.SH OPTIONS
+.IP \fB\-h\fR
+Display short help description.
+.SH EXAMPLE
+.sp
+.BI "hunzip file.hz >file"
+.SH NOTES
+Redirection of the standard output results platform-specific
+line terminating, so a compressed hzip file with new line terminators
+would be bigger with the extra CR characters of the decompression on
+Windows platforms.
+.SH SEE ALSO
+.B hunzip (1), hunspell(1)
+.SH AUTHOR
+László Németh.
diff --git a/man/hzip.1 b/man/hzip.1
new file mode 100644
index 0000000..e10aecc
--- /dev/null
+++ b/man/hzip.1
@@ -0,0 +1,24 @@
+.TH hunzip 1 "2008-06-12"
+.LO 1
+.SH NAME
+hunzip \- compress and encrypt dictionary files
+.SH SYNOPSIS
+hzip [\-h] [\-P password] [file(s)]
+.SH DESCRIPTION
+.I hunzip
+is a small utility for text file compression and encryption, especially for
+sorted dictionaries. "hunspell filename" creates the compressed
+file "filename.hz" without removing the original file.
+
+The compression algorithm uses 16-bit Huffman encoding and
+line-oriented prefix-suffix compression. It has good
+compression ratio for huge sorted word lists.
+.SH OPTIONS
+.IP \fB\-h\fR
+Display short help description.
+.IP \fB\-P password\fR
+Encrypted compression by an arbitrary length password.
+.SH SEE ALSO
+.B hzip (1), hunspell(1)
+.SH AUTHOR
+László Németh.
diff --git a/po/hu.gmo b/po/hu.gmo
index 4a25d29..da04b98 100644
Binary files a/po/hu.gmo and b/po/hu.gmo differ
diff --git a/po/hu.po b/po/hu.po
index cbeca78..3e635c7 100644
--- a/po/hu.po
+++ b/po/hu.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: hunspell\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-04-12 01:05+0200\n"
+"POT-Creation-Date: 2008-06-17 15:11+0200\n"
 "PO-Revision-Date: 2005-09-03 11:22+0200\n"
 "Last-Translator: László Németh <nemeth dot lacko at gmail>\n"
 "Language-Team: Hungarian <openscope.org>\n"
@@ -16,32 +16,32 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: src/tools/hunspell.cxx:189 src/tools/hunspell.cxx:295
+#: src/tools/hunspell.cxx:193 src/tools/hunspell.cxx:301
 #, c-format
 msgid "error - iconv_open: %s -> %s\n"
 msgstr "hiba - iconv_open: %s -> %s\n"
 
-#: src/tools/hunspell.cxx:232 src/tools/hunspell.cxx:253
+#: src/tools/hunspell.cxx:236 src/tools/hunspell.cxx:259
 #, c-format
 msgid "error - iconv_open: UTF-8 -> %s\n"
 msgstr "hiba - iconv_open: UTF-8 -> %s\n"
 
-#: src/tools/hunspell.cxx:543 src/tools/hunspell.cxx:1022
-#: src/tools/hunspell.cxx:1153
+#: src/tools/hunspell.cxx:550 src/tools/hunspell.cxx:1023
+#: src/tools/hunspell.cxx:1154
 #, c-format
 msgid "error - missing HOME variable\n"
 msgstr "hiba - nincs definiálva a HOME környezeti változó\n"
 
-#: src/tools/hunspell.cxx:618
+#: src/tools/hunspell.cxx:625
 #, c-format
 msgid "Line %d: %s -> "
 msgstr "%d. sor: %s -> "
 
-#: src/tools/hunspell.cxx:847
+#: src/tools/hunspell.cxx:848
 msgid "FORBIDDEN!"
 msgstr "TILTOTT!"
 
-#: src/tools/hunspell.cxx:848
+#: src/tools/hunspell.cxx:849
 #, c-format
 msgid ""
 "\t%s\t\tFile: %s\n"
@@ -50,7 +50,7 @@ msgstr ""
 "\t%s\t\tFájl: %s\n"
 "\n"
 
-#: src/tools/hunspell.cxx:900
+#: src/tools/hunspell.cxx:901
 msgid ""
 "\n"
 "[SPACE] R)epl A)ccept I)nsert U)ncap S)tem Q)uit e(X)it or ? for help\n"
@@ -59,7 +59,7 @@ msgstr ""
 "Szóköz=tovább <szám> C)sere J)ó F)elvesz K)isbetűvel T)ő M)égsem V)ége ?"
 "=Súgó\n"
 
-#: src/tools/hunspell.cxx:945
+#: src/tools/hunspell.cxx:946
 msgid ""
 "Whenever a word is found that is not in the dictionary\n"
 "it is printed on the first line of the screen.  If the dictionary\n"
@@ -73,7 +73,7 @@ msgstr ""
 "egyet, de megadhatunk akár egy új szót is.\n"
 "Részletes leírás a program lehetőségeiről: man hunspell.\n"
 
-#: src/tools/hunspell.cxx:950
+#: src/tools/hunspell.cxx:951
 msgid ""
 "\n"
 "Commands are:\n"
@@ -83,28 +83,28 @@ msgstr ""
 "Billentyűparancsok: \n"
 "\n"
 
-#: src/tools/hunspell.cxx:951
+#: src/tools/hunspell.cxx:952
 msgid "R\tReplace the misspelled word completely.\n"
 msgstr "C\tA hibás szó kicserélése egy megadott szóra.\n"
 
-#: src/tools/hunspell.cxx:952
+#: src/tools/hunspell.cxx:953
 msgid "Space\tAccept the word this time only.\n"
 msgstr "Szóköz\tA szó egyszeri átugrása változtatás nélkül.\n"
 
-#: src/tools/hunspell.cxx:953
+#: src/tools/hunspell.cxx:954
 msgid "A\tAccept the word for the rest of this session.\n"
 msgstr "J\tA szó minden előfordulását jónak tekinti a program futása során.\n"
 
-#: src/tools/hunspell.cxx:954
+#: src/tools/hunspell.cxx:955
 msgid "I\tAccept the word, and put it in your private dictionary.\n"
 msgstr ""
 "F\tA szót felveszi a saját szótárba, így új indításkor is ismerni fogja.\n"
 
-#: src/tools/hunspell.cxx:955
+#: src/tools/hunspell.cxx:956
 msgid "U\tAccept and add lowercase version to private dictionary.\n"
 msgstr "K\tMint az előző, de a szót kisbetűsen veszi fel a saját szótárba.\n"
 
-#: src/tools/hunspell.cxx:957
+#: src/tools/hunspell.cxx:958
 msgid ""
 "S\tAsk a stem and a model word and store them in the private dictionary.\n"
 "\tThe stem will be accepted also with the affixes of the model word.\n"
@@ -112,28 +112,28 @@ msgstr ""
 "T\tSzótő és mintaszó bekérése és saját szótárban való tárolása.\n"
 "\tA tő felveheti a mintául megadott szó toldalékait is.\n"
 
-#: src/tools/hunspell.cxx:960
+#: src/tools/hunspell.cxx:961
 msgid "0-n\tReplace with one of the suggested words.\n"
 msgstr "0-n\tA javasolt szavak közül az adott sorszámúra cserél.\n"
 
-#: src/tools/hunspell.cxx:961
+#: src/tools/hunspell.cxx:962
 msgid ""
 "X\tWrite the rest of this file, ignoring misspellings, and start next file.\n"
 msgstr "V\tMenti az eddigi javításokat, és rátér a következő fájlra.\n"
 
-#: src/tools/hunspell.cxx:962
+#: src/tools/hunspell.cxx:963
 msgid "Q\tQuit immediately. Asks for confirmation. Leaves file unchanged.\n"
 msgstr "M\tKilép a javítások mentése nélkül, de előtte megerősítést kér.\n"
 
-#: src/tools/hunspell.cxx:963
+#: src/tools/hunspell.cxx:964
 msgid "^Z\tSuspend program. Restart with fg command.\n"
 msgstr "^Z\tA program felfüggesztése. Újraindítás fg paranccsal.\n"
 
-#: src/tools/hunspell.cxx:964
+#: src/tools/hunspell.cxx:965
 msgid "?\tShow this help screen.\n"
 msgstr "?\tEnnek a leírásnak a megjelenítése.\n"
 
-#: src/tools/hunspell.cxx:965
+#: src/tools/hunspell.cxx:966
 msgid ""
 "\n"
 "-- Type space to continue -- \n"
@@ -143,11 +143,11 @@ msgstr ""
 
 #. TRANSLATORS: translate this letter according to the shortcut letter used
 #. previously in the  translation of "R)epl" before
-#: src/tools/hunspell.cxx:975
+#: src/tools/hunspell.cxx:976
 msgid "r"
 msgstr "c"
 
-#: src/tools/hunspell.cxx:987
+#: src/tools/hunspell.cxx:988
 msgid "Replace with: "
 msgstr "Csere: "
 
@@ -155,74 +155,74 @@ msgstr "Csere: "
 #. previously in the  translation of "U)ncap" before
 #. TRANSLATORS: translate this letter according to the shortcut letter used
 #. previously in the  translation of "U)ncap" and I)nsert before
-#: src/tools/hunspell.cxx:1008 src/tools/hunspell.cxx:1013
-#: src/tools/hunspell.cxx:1044
+#: src/tools/hunspell.cxx:1009 src/tools/hunspell.cxx:1014
+#: src/tools/hunspell.cxx:1045
 msgid "u"
 msgstr "k"
 
-#: src/tools/hunspell.cxx:1013 src/tools/hunspell.cxx:1044
+#: src/tools/hunspell.cxx:1014 src/tools/hunspell.cxx:1045
 msgid "i"
 msgstr "f"
 
-#: src/tools/hunspell.cxx:1038 src/tools/hunspell.cxx:1169
+#: src/tools/hunspell.cxx:1039 src/tools/hunspell.cxx:1170
 #, c-format
 msgid "Cannot update personal dictionary."
 msgstr "Nem lehet frissíteni a saját szótárat."
 
-#: src/tools/hunspell.cxx:1044
+#: src/tools/hunspell.cxx:1045
 msgid "a"
 msgstr "j"
 
 #. TRANSLATORS: translate this letter according to the shortcut letter used
 #. previously in the  translation of "S)tem" before
-#: src/tools/hunspell.cxx:1051
+#: src/tools/hunspell.cxx:1052
 msgid "s"
 msgstr "t"
 
-#: src/tools/hunspell.cxx:1084
+#: src/tools/hunspell.cxx:1085
 msgid "New word (stem): "
 msgstr "Új szó(tő): "
 
-#: src/tools/hunspell.cxx:1111
+#: src/tools/hunspell.cxx:1112
 msgid "Model word (a similar dictionary word): "
 msgstr "Mintaszó (egy hasonló szótári szó): "
 
-#: src/tools/hunspell.cxx:1175
+#: src/tools/hunspell.cxx:1176
 msgid "Model word must be in the dictionary. Press any key!"
 msgstr "A minta csak szótári szó lehet! Továbblépés billentyűleütéssel."
 
 #. TRANSLATORS: translate this letter according to the shortcut letter used
 #. previously in the  translation of "e(X)it" before
-#: src/tools/hunspell.cxx:1184
+#: src/tools/hunspell.cxx:1185
 msgid "x"
 msgstr "v"
 
 #. TRANSLATORS: translate this letter according to the shortcut letter used
 #. previously in the  translation of "Q)uit" before
-#: src/tools/hunspell.cxx:1189
+#: src/tools/hunspell.cxx:1190
 msgid "q"
 msgstr "m"
 
-#: src/tools/hunspell.cxx:1191
+#: src/tools/hunspell.cxx:1192
 msgid "Are you sure you want to throw away your changes? "
 msgstr "Kilép a módosítások mentése nélkül (i/n)? "
 
 #. TRANSLATORS: translate this letter according to the shortcut letter y)es
-#: src/tools/hunspell.cxx:1193
+#: src/tools/hunspell.cxx:1194
 msgid "y"
 msgstr "i"
 
-#: src/tools/hunspell.cxx:1265
+#: src/tools/hunspell.cxx:1266
 #, c-format
 msgid "Can't create tempfile %s.\n"
 msgstr "Nem lehet létrehozni a(z) %s átmeneti fájlt.\n"
 
-#: src/tools/hunspell.cxx:1425
+#: src/tools/hunspell.cxx:1426
 #, c-format
 msgid "Usage: hunspell [OPTION]... [FILE]...\n"
 msgstr "Használat: hunspell [KAPCSOLÓ]... [FÁJL]...\n"
 
-#: src/tools/hunspell.cxx:1426
+#: src/tools/hunspell.cxx:1427
 #, c-format
 msgid ""
 "Check spelling of each FILE. Without FILE, check standard input.\n"
@@ -231,103 +231,103 @@ msgstr ""
 "A FÁJL(OK) (ennek hiányában a szabványos bemenet) helyesírását ellenőrzi.\n"
 "\n"
 
-#: src/tools/hunspell.cxx:1427
+#: src/tools/hunspell.cxx:1428
 #, c-format
 msgid "  -1\t\tcheck only first field in lines (delimiter = tabulator)\n"
 msgstr ""
 "  -1\t\tcsak az első mezőt ellenőrzi a sorban (mezőhatároló = tabulátor)\n"
 
-#: src/tools/hunspell.cxx:1428
+#: src/tools/hunspell.cxx:1429
 #, c-format
 msgid "  -a\t\tIspell's pipe interface\n"
 msgstr "  -a\t\tIspell-szerű csőfelület\n"
 
-#: src/tools/hunspell.cxx:1429
+#: src/tools/hunspell.cxx:1430
 #, c-format
 msgid "  --check-url\tCheck URLs, e-mail addresses and directory paths\n"
 msgstr "  --check-url\tURL-ek, e-mail címek és útvonalak ellenőrzése\n"
 
-#: src/tools/hunspell.cxx:1430
+#: src/tools/hunspell.cxx:1431
 #, c-format
 msgid "  -d d[,d2,...]\tuse d (d2 etc.) dictionaries\n"
 msgstr "  -d d[,d2,...]\ta d (d2 stb.) nevű szótárat használja\n"
 
-#: src/tools/hunspell.cxx:1431
+#: src/tools/hunspell.cxx:1432
 #, c-format
 msgid "  -D\t\tshow available dictionaries\n"
 msgstr "  -D\t\taz elérhető szótárak kilistázása\n"
 
-#: src/tools/hunspell.cxx:1432
+#: src/tools/hunspell.cxx:1433
 #, c-format
 msgid "  -G\t\tprint only correct words or lines\n"
 msgstr "  -G\t\tkiírja a bemenet helyes szavait vagy sorait\n"
 
-#: src/tools/hunspell.cxx:1433
+#: src/tools/hunspell.cxx:1434
 #, c-format
 msgid "  -h, --help\tdisplay this help and exit\n"
 msgstr "  -h, --help\tkiírja ezt a leírást\n"
 
-#: src/tools/hunspell.cxx:1434
+#: src/tools/hunspell.cxx:1435
 #, c-format
 msgid "  -H\t\tHTML input file format\n"
 msgstr "  -H\t\tHTML bemeneti formátum\n"
 
-#: src/tools/hunspell.cxx:1435
+#: src/tools/hunspell.cxx:1436
 #, c-format
 msgid "  -i enc\tinput encoding\n"
 msgstr "  -i kód\tbemeneti karakterkódolás\n"
 
-#: src/tools/hunspell.cxx:1436
+#: src/tools/hunspell.cxx:1437
 #, c-format
 msgid "  -l\t\tprint mispelled words\n"
 msgstr "  -l\t\tkiírja a hibás szavakat\n"
 
-#: src/tools/hunspell.cxx:1437
+#: src/tools/hunspell.cxx:1438
 #, c-format
 msgid "  -L\t\tprint lines with mispelled words\n"
 msgstr "  -L\t\tkiírja a hibás sorokat\n"
 
-#: src/tools/hunspell.cxx:1438
+#: src/tools/hunspell.cxx:1439
 #, c-format
 msgid "  -m \t\tanalyze the words of the input text\n"
 msgstr "  -m \t\tszövegszavak morfológiai elemzése\n"
 
-#: src/tools/hunspell.cxx:1439
+#: src/tools/hunspell.cxx:1440
 #, c-format
 msgid "  -n\t\tnroff/troff input file format\n"
 msgstr "  -n\t\tnroff/troff bemeneti formátum\n"
 
-#: src/tools/hunspell.cxx:1440
+#: src/tools/hunspell.cxx:1441
 #, c-format
 msgid "  -p dict\tset dict custom dictionary\n"
 msgstr "  -p tár\ta tár nevű saját szótárat használja\n"
 
-#: src/tools/hunspell.cxx:1441
+#: src/tools/hunspell.cxx:1442
 #, c-format
 msgid "  -P password\tset password for encrypted dictionaries\n"
 msgstr "  -P jelszó\tjelszó megadása a titkosított szótárakhoz\n"
 
-#: src/tools/hunspell.cxx:1442
+#: src/tools/hunspell.cxx:1443
 #, c-format
 msgid "  -s \t\tstem the words of the input text\n"
 msgstr "  -s \t\tszövegszavak tövezése\n"
 
-#: src/tools/hunspell.cxx:1443
+#: src/tools/hunspell.cxx:1444
 #, c-format
 msgid "  -t\t\tTeX/LaTeX input file format\n"
 msgstr "  -t\t\tTeX/LaTeX bemeneti formátum\n"
 
-#: src/tools/hunspell.cxx:1448
+#: src/tools/hunspell.cxx:1449
 #, c-format
 msgid "  -v, --version\tprint version number\n"
 msgstr "  -v, --version\tkiírja a változat számát\n"
 
-#: src/tools/hunspell.cxx:1449
+#: src/tools/hunspell.cxx:1450
 #, c-format
 msgid "  -vv\t\tprint Ispell compatible version number\n"
 msgstr "  -vv\t\tkiírja a változat számát Ispell-szerűen\n"
 
-#: src/tools/hunspell.cxx:1450
+#: src/tools/hunspell.cxx:1451
 #, c-format
 msgid ""
 "  -w\t\tprint mispelled words (= lines) from one word/line input.\n"
@@ -336,7 +336,7 @@ msgstr ""
 "  -w\t\tkiírja a hibás szavakat a soronként egy szavas bemenetből.\n"
 "\n"
 
-#: src/tools/hunspell.cxx:1451
+#: src/tools/hunspell.cxx:1452
 #, c-format
 msgid ""
 "Example: hunspell -d en_US file.txt    # interactive spelling\n"
@@ -349,12 +349,12 @@ msgstr ""
 "        hunspell -i utf-8 fájl.txt    # UTF-8-as fájl ellenőrzése\n"
 "\n"
 
-#: src/tools/hunspell.cxx:1454
+#: src/tools/hunspell.cxx:1455
 #, c-format
 msgid "Bug reports: http://hunspell.sourceforge.net\n";
 msgstr "Hibajelzés: http://hunspell.sourceforge.net\n";
 
-#: src/tools/hunspell.cxx:1460
+#: src/tools/hunspell.cxx:1461
 #, c-format
 msgid ""
 "\n"
@@ -371,7 +371,7 @@ msgstr ""
 "MySpell copyright (C) Kevin Hendricks, 2001-2002, Licenc: BSD.\n"
 "\n"
 
-#: src/tools/hunspell.cxx:1463
+#: src/tools/hunspell.cxx:1464
 #, c-format
 msgid ""
 "This is free software; see the source for copying conditions.  There is NO\n"
@@ -382,12 +382,12 @@ msgstr ""
 "NINCS garancia, még az eladhatóságra vagy valamely célra való\n"
 "alkalmazhatóságra sem.\n"
 
-#: src/tools/hunspell.cxx:1503 src/tools/hunspell.cxx:1619
+#: src/tools/hunspell.cxx:1504 src/tools/hunspell.cxx:1620
 #, c-format
 msgid "Can't open %s.\n"
 msgstr "Nem lehet megnyitni a(z) %s-t.\n"
 
-#: src/tools/hunspell.cxx:1545
+#: src/tools/hunspell.cxx:1546
 #, c-format
 msgid ""
 "SEARCH PATH:\n"
@@ -396,12 +396,12 @@ msgstr ""
 "KERESÉSI ÚTVONAL:\n"
 "%s\n"
 
-#: src/tools/hunspell.cxx:1546
+#: src/tools/hunspell.cxx:1547
 #, c-format
 msgid "AVAILABLE DICTIONARIES (path is not mandatory for -d option):\n"
 msgstr "ELÉRHETŐ SZÓTÁRAK (az útvonal nem kötelező a -d kapcsolónál):\n"
 
-#: src/tools/hunspell.cxx:1548
+#: src/tools/hunspell.cxx:1549
 #, c-format
 msgid ""
 "LOADED DICTIONARY:\n"
@@ -412,17 +412,17 @@ msgstr ""
 "%s\n"
 "%s\n"
 
-#: src/tools/hunspell.cxx:1566
+#: src/tools/hunspell.cxx:1567
 #, c-format
 msgid "error - %s exceeds dictionary limit.\n"
 msgstr "hiba - %s meghaladja a szótárlimitet.\n"
 
-#: src/tools/hunspell.cxx:1570
+#: src/tools/hunspell.cxx:1571
 #, c-format
 msgid "Can't open affix or dictionary files.\n"
 msgstr "Nem lehet megnyitni a ragozási vagy a szótárfájlt.\n"
 
-#: src/tools/hunspell.cxx:1631 src/tools/hunspell.cxx:1634
+#: src/tools/hunspell.cxx:1632 src/tools/hunspell.cxx:1635
 #, c-format
 msgid "Hunspell has been compiled without Ncurses user interface.\n"
 msgstr "A Hunspell Ncurses felhasználói felület nélkül lett fordítva.\n"
diff --git a/po/hunspell.pot b/po/hunspell.pot
index af6eda0..03c5d84 100644
--- a/po/hunspell.pot
+++ b/po/hunspell.pot
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-04-12 01:05+0200\n"
+"POT-Creation-Date: 2008-06-17 15:11+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,45 +16,45 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: src/tools/hunspell.cxx:189 src/tools/hunspell.cxx:295
+#: src/tools/hunspell.cxx:193 src/tools/hunspell.cxx:301
 #, c-format
 msgid "error - iconv_open: %s -> %s\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:232 src/tools/hunspell.cxx:253
+#: src/tools/hunspell.cxx:236 src/tools/hunspell.cxx:259
 #, c-format
 msgid "error - iconv_open: UTF-8 -> %s\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:543 src/tools/hunspell.cxx:1022
-#: src/tools/hunspell.cxx:1153
+#: src/tools/hunspell.cxx:550 src/tools/hunspell.cxx:1023
+#: src/tools/hunspell.cxx:1154
 #, c-format
 msgid "error - missing HOME variable\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:618
+#: src/tools/hunspell.cxx:625
 #, c-format
 msgid "Line %d: %s -> "
 msgstr ""
 
-#: src/tools/hunspell.cxx:847
+#: src/tools/hunspell.cxx:848
 msgid "FORBIDDEN!"
 msgstr ""
 
-#: src/tools/hunspell.cxx:848
+#: src/tools/hunspell.cxx:849
 #, c-format
 msgid ""
 "\t%s\t\tFile: %s\n"
 "\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:900
+#: src/tools/hunspell.cxx:901
 msgid ""
 "\n"
 "[SPACE] R)epl A)ccept I)nsert U)ncap S)tem Q)uit e(X)it or ? for help\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:945
+#: src/tools/hunspell.cxx:946
 msgid ""
 "Whenever a word is found that is not in the dictionary\n"
 "it is printed on the first line of the screen.  If the dictionary\n"
@@ -63,61 +63,61 @@ msgid ""
 "completely, or choosing one of the suggested words.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:950
+#: src/tools/hunspell.cxx:951
 msgid ""
 "\n"
 "Commands are:\n"
 "\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:951
+#: src/tools/hunspell.cxx:952
 msgid "R\tReplace the misspelled word completely.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:952
+#: src/tools/hunspell.cxx:953
 msgid "Space\tAccept the word this time only.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:953
+#: src/tools/hunspell.cxx:954
 msgid "A\tAccept the word for the rest of this session.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:954
+#: src/tools/hunspell.cxx:955
 msgid "I\tAccept the word, and put it in your private dictionary.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:955
+#: src/tools/hunspell.cxx:956
 msgid "U\tAccept and add lowercase version to private dictionary.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:957
+#: src/tools/hunspell.cxx:958
 msgid ""
 "S\tAsk a stem and a model word and store them in the private dictionary.\n"
 "\tThe stem will be accepted also with the affixes of the model word.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:960
+#: src/tools/hunspell.cxx:961
 msgid "0-n\tReplace with one of the suggested words.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:961
+#: src/tools/hunspell.cxx:962
 msgid ""
 "X\tWrite the rest of this file, ignoring misspellings, and start next file.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:962
+#: src/tools/hunspell.cxx:963
 msgid "Q\tQuit immediately. Asks for confirmation. Leaves file unchanged.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:963
+#: src/tools/hunspell.cxx:964
 msgid "^Z\tSuspend program. Restart with fg command.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:964
+#: src/tools/hunspell.cxx:965
 msgid "?\tShow this help screen.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:965
+#: src/tools/hunspell.cxx:966
 msgid ""
 "\n"
 "-- Type space to continue -- \n"
@@ -125,11 +125,11 @@ msgstr ""
 
 #. TRANSLATORS: translate this letter according to the shortcut letter used
 #. previously in the  translation of "R)epl" before
-#: src/tools/hunspell.cxx:975
+#: src/tools/hunspell.cxx:976
 msgid "r"
 msgstr ""
 
-#: src/tools/hunspell.cxx:987
+#: src/tools/hunspell.cxx:988
 msgid "Replace with: "
 msgstr ""
 
@@ -137,183 +137,183 @@ msgstr ""
 #. previously in the  translation of "U)ncap" before
 #. TRANSLATORS: translate this letter according to the shortcut letter used
 #. previously in the  translation of "U)ncap" and I)nsert before
-#: src/tools/hunspell.cxx:1008 src/tools/hunspell.cxx:1013
-#: src/tools/hunspell.cxx:1044
+#: src/tools/hunspell.cxx:1009 src/tools/hunspell.cxx:1014
+#: src/tools/hunspell.cxx:1045
 msgid "u"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1013 src/tools/hunspell.cxx:1044
+#: src/tools/hunspell.cxx:1014 src/tools/hunspell.cxx:1045
 msgid "i"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1038 src/tools/hunspell.cxx:1169
+#: src/tools/hunspell.cxx:1039 src/tools/hunspell.cxx:1170
 #, c-format
 msgid "Cannot update personal dictionary."
 msgstr ""
 
-#: src/tools/hunspell.cxx:1044
+#: src/tools/hunspell.cxx:1045
 msgid "a"
 msgstr ""
 
 #. TRANSLATORS: translate this letter according to the shortcut letter used
 #. previously in the  translation of "S)tem" before
-#: src/tools/hunspell.cxx:1051
+#: src/tools/hunspell.cxx:1052
 msgid "s"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1084
+#: src/tools/hunspell.cxx:1085
 msgid "New word (stem): "
 msgstr ""
 
-#: src/tools/hunspell.cxx:1111
+#: src/tools/hunspell.cxx:1112
 msgid "Model word (a similar dictionary word): "
 msgstr ""
 
-#: src/tools/hunspell.cxx:1175
+#: src/tools/hunspell.cxx:1176
 msgid "Model word must be in the dictionary. Press any key!"
 msgstr ""
 
 #. TRANSLATORS: translate this letter according to the shortcut letter used
 #. previously in the  translation of "e(X)it" before
-#: src/tools/hunspell.cxx:1184
+#: src/tools/hunspell.cxx:1185
 msgid "x"
 msgstr ""
 
 #. TRANSLATORS: translate this letter according to the shortcut letter used
 #. previously in the  translation of "Q)uit" before
-#: src/tools/hunspell.cxx:1189
+#: src/tools/hunspell.cxx:1190
 msgid "q"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1191
+#: src/tools/hunspell.cxx:1192
 msgid "Are you sure you want to throw away your changes? "
 msgstr ""
 
 #. TRANSLATORS: translate this letter according to the shortcut letter y)es
-#: src/tools/hunspell.cxx:1193
+#: src/tools/hunspell.cxx:1194
 msgid "y"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1265
+#: src/tools/hunspell.cxx:1266
 #, c-format
 msgid "Can't create tempfile %s.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1425
+#: src/tools/hunspell.cxx:1426
 #, c-format
 msgid "Usage: hunspell [OPTION]... [FILE]...\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1426
+#: src/tools/hunspell.cxx:1427
 #, c-format
 msgid ""
 "Check spelling of each FILE. Without FILE, check standard input.\n"
 "\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1427
+#: src/tools/hunspell.cxx:1428
 #, c-format
 msgid "  -1\t\tcheck only first field in lines (delimiter = tabulator)\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1428
+#: src/tools/hunspell.cxx:1429
 #, c-format
 msgid "  -a\t\tIspell's pipe interface\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1429
+#: src/tools/hunspell.cxx:1430
 #, c-format
 msgid "  --check-url\tCheck URLs, e-mail addresses and directory paths\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1430
+#: src/tools/hunspell.cxx:1431
 #, c-format
 msgid "  -d d[,d2,...]\tuse d (d2 etc.) dictionaries\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1431
+#: src/tools/hunspell.cxx:1432
 #, c-format
 msgid "  -D\t\tshow available dictionaries\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1432
+#: src/tools/hunspell.cxx:1433
 #, c-format
 msgid "  -G\t\tprint only correct words or lines\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1433
+#: src/tools/hunspell.cxx:1434
 #, c-format
 msgid "  -h, --help\tdisplay this help and exit\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1434
+#: src/tools/hunspell.cxx:1435
 #, c-format
 msgid "  -H\t\tHTML input file format\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1435
+#: src/tools/hunspell.cxx:1436
 #, c-format
 msgid "  -i enc\tinput encoding\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1436
+#: src/tools/hunspell.cxx:1437
 #, c-format
 msgid "  -l\t\tprint mispelled words\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1437
+#: src/tools/hunspell.cxx:1438
 #, c-format
 msgid "  -L\t\tprint lines with mispelled words\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1438
+#: src/tools/hunspell.cxx:1439
 #, c-format
 msgid "  -m \t\tanalyze the words of the input text\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1439
+#: src/tools/hunspell.cxx:1440
 #, c-format
 msgid "  -n\t\tnroff/troff input file format\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1440
+#: src/tools/hunspell.cxx:1441
 #, c-format
 msgid "  -p dict\tset dict custom dictionary\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1441
+#: src/tools/hunspell.cxx:1442
 #, c-format
 msgid "  -P password\tset password for encrypted dictionaries\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1442
+#: src/tools/hunspell.cxx:1443
 #, c-format
 msgid "  -s \t\tstem the words of the input text\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1443
+#: src/tools/hunspell.cxx:1444
 #, c-format
 msgid "  -t\t\tTeX/LaTeX input file format\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1448
+#: src/tools/hunspell.cxx:1449
 #, c-format
 msgid "  -v, --version\tprint version number\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1449
+#: src/tools/hunspell.cxx:1450
 #, c-format
 msgid "  -vv\t\tprint Ispell compatible version number\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1450
+#: src/tools/hunspell.cxx:1451
 #, c-format
 msgid ""
 "  -w\t\tprint mispelled words (= lines) from one word/line input.\n"
 "\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1451
+#: src/tools/hunspell.cxx:1452
 #, c-format
 msgid ""
 "Example: hunspell -d en_US file.txt    # interactive spelling\n"
@@ -322,12 +322,12 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1454
+#: src/tools/hunspell.cxx:1455
 #, c-format
 msgid "Bug reports: http://hunspell.sourceforge.net\n";
 msgstr ""
 
-#: src/tools/hunspell.cxx:1460
+#: src/tools/hunspell.cxx:1461
 #, c-format
 msgid ""
 "\n"
@@ -338,7 +338,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1463
+#: src/tools/hunspell.cxx:1464
 #, c-format
 msgid ""
 "This is free software; see the source for copying conditions.  There is NO\n"
@@ -346,24 +346,24 @@ msgid ""
 "to the extent permitted by law.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1503 src/tools/hunspell.cxx:1619
+#: src/tools/hunspell.cxx:1504 src/tools/hunspell.cxx:1620
 #, c-format
 msgid "Can't open %s.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1545
+#: src/tools/hunspell.cxx:1546
 #, c-format
 msgid ""
 "SEARCH PATH:\n"
 "%s\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1546
+#: src/tools/hunspell.cxx:1547
 #, c-format
 msgid "AVAILABLE DICTIONARIES (path is not mandatory for -d option):\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1548
+#: src/tools/hunspell.cxx:1549
 #, c-format
 msgid ""
 "LOADED DICTIONARY:\n"
@@ -371,17 +371,17 @@ msgid ""
 "%s\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1566
+#: src/tools/hunspell.cxx:1567
 #, c-format
 msgid "error - %s exceeds dictionary limit.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1570
+#: src/tools/hunspell.cxx:1571
 #, c-format
 msgid "Can't open affix or dictionary files.\n"
 msgstr ""
 
-#: src/tools/hunspell.cxx:1631 src/tools/hunspell.cxx:1634
+#: src/tools/hunspell.cxx:1632 src/tools/hunspell.cxx:1635
 #, c-format
 msgid "Hunspell has been compiled without Ncurses user interface.\n"
 msgstr ""
diff --git a/src/hunspell/affentry.cxx b/src/hunspell/affentry.cxx
index 2436fbb..edfbad9 100644
--- a/src/hunspell/affentry.cxx
+++ b/src/hunspell/affentry.cxx
@@ -106,14 +106,19 @@ inline int PfxEntry::test_condition(const char * st)
     while (1) {
       switch (*p) {
         case '\0': return 1;
-        case '[': { p = nextchar(p); pos = st; break; }
-        case '^': { p = nextchar(p); neg = true; break; }
-        case ']': { if ((neg && ingroup) || (!neg && !ingroup)) return 0;
-                pos = NULL;
+        case '[': { 
                 neg = false;
                 ingroup = false;
                 p = nextchar(p);
-                st++;
+                pos = st; break;
+            }
+        case '^': { p = nextchar(p); neg = true; break; }
+        case ']': { 
+                if ((neg && ingroup) || (!neg && !ingroup)) return 0;
+                pos = NULL;
+                p = nextchar(p);
+                // skip the next character
+                if (!ingroup) for (st++; (opts & aeUTF8) && (*st & 0xc0) == 0x80; st++);
                 if (*st == '\0' && p && *p != '\0') return 0; // word <= condition
                 break;
             }
@@ -138,8 +143,14 @@ inline int PfxEntry::test_condition(const char * st)
                             p = nextchar(p);
                             st++;
                         }
-                        if (st != pos) ingroup = true;
-                    } else if (pos) ingroup = true;
+                        if (pos && st != pos) {
+                            ingroup = true;
+                            while (p && *p != ']' && (p = nextchar(p)));
+                        }
+                    } else if (pos) {
+                        ingroup = true;
+                        while (p && *p != ']' && (p = nextchar(p)));
+                    }
                 } else if (pos) { // group
                     p = nextchar(p);
                 } else return 0;
@@ -163,7 +174,6 @@ struct hentry * PfxEntry::checkword(const char * word, int len, char in_compound
 
      tmpl = len - appndl;
 
-//     if ((tmpl > 0) && (tmpl + stripl >= numconds)) {
      if (tmpl > 0) {
 
             // generate new root word by removing prefix and adding
@@ -226,7 +236,6 @@ struct hentry * PfxEntry::check_twosfx(const char * word, int len,
      tmpl = len - appndl;
 
      if ((tmpl > 0) && (tmpl + stripl >= numconds)) {
-//     if (tmpl > 0) {
 
             // generate new root word by removing prefix and adding
             // back any characters that would have been stripped
@@ -273,7 +282,6 @@ char * PfxEntry::check_twosfx_morph(const char * word, int len,
      tmpl = len - appndl;
 
      if ((tmpl > 0) && (tmpl + stripl >= numconds)) {
-//     if (tmpl > 0) {
 
             // generate new root word by removing prefix and adding
             // back any characters that would have been stripped
@@ -324,7 +332,6 @@ char * PfxEntry::check_morph(const char * word, int len, char in_compound, const
      tmpl = len - appndl;
 
      if ((tmpl > 0) && (tmpl + stripl >= numconds)) {
-//     if (tmpl > 0) {
 
             // generate new root word by removing prefix and adding
             // back any characters that would have been stripped
@@ -357,13 +364,12 @@ char * PfxEntry::check_morph(const char * word, int len, char in_compound, const
                             if (!HENTRY_FIND(he, MORPH_STEM)) {
                                 strcat(result, " ");
                                 strcat(result, MORPH_STEM);
-                                strcat(result,HENTRY_WORD(he));
+                                strcat(result, HENTRY_WORD(he));
                             }
                             // store the pointer of the hash entry
-//                            sprintf(result + strlen(result), " %s%p", MORPH_HENTRY, he);
                             if (HENTRY_DATA(he)) {
                                 strcat(result, " ");
-                                strcat(result,HENTRY_DATA(he));
+                                strcat(result, HENTRY_DATA2(he));
                             } else {
                                 // return with debug information
                                 char * flag = pmyMgr->encode_flag(getFlag());
@@ -485,11 +491,15 @@ inline int SfxEntry::test_condition(const char * st, const char * beg)
         case '^': { p = nextchar(p); neg = true; break; }
         case ']': { if (!neg && !ingroup) return 0;
                 i++;
+                // skip the next character
+                if (!ingroup) {
+                    for (; (opts & aeUTF8) && (st >= beg) && (*st & 0xc0) == 0x80; st--);
+                    st--;
+                }                    
                 pos = NULL;
                 neg = false;
                 ingroup = false;
                 p = nextchar(p);
-                st--;
                 if (st < beg && p && *p != '\0') return 0; // word <= condition
                 break;
             }
@@ -524,12 +534,14 @@ inline int SfxEntry::test_condition(const char * st, const char * beg)
                             if (neg) return 0;
                             else if (i == numconds) return 1;
                             ingroup = true;
+                            while (p && *p != ']' && (p = nextchar(p)));
                         }
                         if (p && *p != '\0') p = nextchar(p);
                     } else if (pos) {
                         if (neg) return 0;
                         else if (i == numconds) return 1;
                         ingroup = true;
+                        st--;
                     }
                     if (!pos) {
                         i++;
@@ -572,7 +584,6 @@ struct hentry * SfxEntry::checkword(const char * word, int len, int optflags,
     // it checked in test_condition()
 
     if ((tmpl > 0) && (tmpl + stripl >= numconds)) {
-//    if (tmpl > 0) {
 
             // generate new root word by removing suffix and adding
             // back any characters that would have been stripped or
@@ -672,7 +683,6 @@ struct hentry * SfxEntry::check_twosfx(const char * word, int len, int optflags,
     tmpl = len - appndl;
 
     if ((tmpl > 0) && (tmpl + stripl >= numconds)) {
-//    if (tmpl > 0) {
 
             // generate new root word by removing suffix and adding
             // back any characters that would have been stripped or
@@ -737,7 +747,6 @@ char * SfxEntry::check_twosfx_morph(const char * word, int len, int optflags,
     tmpl = len - appndl;
 
     if ((tmpl > 0) && (tmpl + stripl >= numconds)) {
-//    if (tmpl > 0) {
 
             // generate new root word by removing suffix and adding
             // back any characters that would have been stripped or
diff --git a/src/hunspell/affixmgr.cxx b/src/hunspell/affixmgr.cxx
index 1bcec78..c12e265 100644
--- a/src/hunspell/affixmgr.cxx
+++ b/src/hunspell/affixmgr.cxx
@@ -148,11 +148,11 @@ AffixMgr::~AffixMgr()
        sStart[j] = NULL;
   }
 
-  if (keystring) free(keystring);
+  if (keystring && keystring != SPELL_KEYSTRING) free(keystring);
   keystring=NULL;
   if (trystring) free(trystring);
   trystring=NULL;
-  if (encoding) free(encoding);
+  if (encoding && encoding != SPELL_ENCODING) free(encoding);
   encoding=NULL;
   if (maptable) {  
      for (int j=0; j < nummap; j++) {
@@ -662,12 +662,12 @@ int  AffixMgr::parse_file(const char * affpath, const char * key)
     process_sfx_order();
 
     /* get encoding for CHECKCOMPOUNDCASE */
+    if (!utf8) {
     char * enc = get_encoding();
     csconv = get_current_cs(enc);
     free(enc);
     enc = NULL;
 
-#ifdef WINSHELL
     char expw[MAXLNLEN];
     if (wordchars) {
         strcpy(expw, wordchars);
@@ -683,13 +683,14 @@ int  AffixMgr::parse_file(const char * affpath, const char * key)
     }
 
     wordchars = mystrdup(expw);
-#endif
+    }
+
     // temporary BREAK definition for German dash handling (OOo issue 64400)
     if ((langnum == LANG_de) && (!breaktable)) {
         breaktable = (char **) malloc(sizeof(char *));
         if (!breaktable) return 1;
         breaktable[0] = mystrdup("-");
-        numbreak = 1;
+        if (breaktable[0]) numbreak = 1;
     }
     return 0;
 }
@@ -968,8 +969,10 @@ void AffixMgr::debugflag(char * result, unsigned short flag) {
     char * st = encode_flag(flag);
     strcat(result, " ");
     strcat(result, MORPH_FLAG);
-    strcat(result, st);
-    free(st);
+    if (st) {
+        strcat(result, st);
+        free(st);
+    }
 }
 
 // calculate the character length of the condition
@@ -997,6 +1000,7 @@ int AffixMgr::encodeit(struct affentry * ptr, char * cs)
     if (ptr->c.conds[MAXCONDLEN - 1] && cs[MAXCONDLEN]) {
       ptr->opts += aeLONGCOND;
       ptr->c.l.conds2 = mystrdup(cs + MAXCONDLEN_1);
+      if (!ptr->c.l.conds2) return 1;
     }
   } else {
     ptr->numconds = 0;
@@ -1860,7 +1864,7 @@ int AffixMgr::compound_check_morph(const char * word, int len,
             // store the pointer of the hash entry
 //            sprintf(presult + strlen(presult), "%c%s%p", MSEP_FLD, MORPH_HENTRY, rv);
             if (HENTRY_DATA(rv)) {
-                sprintf(presult + strlen(presult), "%c%s", MSEP_FLD, HENTRY_DATA(rv));
+                sprintf(presult + strlen(presult), "%c%s", MSEP_FLD, HENTRY_DATA2(rv));
             }
         }        
         if (!rv) {
@@ -2021,7 +2025,7 @@ int AffixMgr::compound_check_morph(const char * word, int len,
                   strcat(*result, " ");
                   strcat(*result, MORPH_PART);
                   strcat(*result, word+i);
-                  if (complexprefixes && HENTRY_DATA(rv)) strcat(*result, HENTRY_DATA(rv));
+                  if (complexprefixes && HENTRY_DATA(rv)) strcat(*result, HENTRY_DATA2(rv));
                   if (!HENTRY_FIND(rv, MORPH_STEM)) {
                     strcat(*result, " ");
                     strcat(*result, MORPH_STEM);
@@ -2031,7 +2035,7 @@ int AffixMgr::compound_check_morph(const char * word, int len,
 //                  sprintf(*result + strlen(*result), " %s%p", MORPH_HENTRY, rv);
                   if (!complexprefixes && HENTRY_DATA(rv)) {
                     strcat(*result, " ");
-                    strcat(*result, HENTRY_DATA(rv));
+                    strcat(*result, HENTRY_DATA2(rv));
                   }
                   strcat(*result, "\n");
                   ok = 1;
@@ -2083,7 +2087,7 @@ int AffixMgr::compound_check_morph(const char * word, int len,
                       strcat(*result, word+i);
                                           
                       if (HENTRY_DATA(rv)) {
-                        if (complexprefixes) strcat(*result, HENTRY_DATA(rv));
+                        if (complexprefixes) strcat(*result, HENTRY_DATA2(rv));
                         if (! HENTRY_FIND(rv, MORPH_STEM)) {
                            strcat(*result, " ");
                            strcat(*result, MORPH_STEM);
@@ -2093,7 +2097,7 @@ int AffixMgr::compound_check_morph(const char * word, int len,
 //                        sprintf(*result + strlen(*result), " %s%p", MORPH_HENTRY, rv);
                         if (!complexprefixes) {
                             strcat(*result, " ");
-                            strcat(*result, HENTRY_DATA(rv));
+                            strcat(*result, HENTRY_DATA2(rv));
                         }
                       }
                       strcat(*result, "\n");
@@ -2490,7 +2494,7 @@ char * AffixMgr::suffix_check_twosfx_morph(const char * word, int len,
              sptr = sptr->getNextNE();
         }
     }
-    if (result) return mystrdup(result);
+    if (*result) return mystrdup(result);
     return NULL;
 }
 
@@ -2541,7 +2545,7 @@ char * AffixMgr::suffix_check_morph(const char * word, int len,
                     strcat(result, " ");
                 } else debugflag(result, ((PfxEntry *) ppfx)->getFlag());
             }
-            if (complexprefixes && HENTRY_DATA(rv)) strcat(result, HENTRY_DATA(rv));
+            if (complexprefixes && HENTRY_DATA(rv)) strcat(result, HENTRY_DATA2(rv));
             if (! HENTRY_FIND(rv, MORPH_STEM)) {
                 strcat(result, " ");                                
                 strcat(result, MORPH_STEM);
@@ -2552,7 +2556,7 @@ char * AffixMgr::suffix_check_morph(const char * word, int len,
             
             if (!complexprefixes && HENTRY_DATA(rv)) {
                     strcat(result, " ");                                
-                    strcat(result, HENTRY_DATA(rv));
+                    strcat(result, HENTRY_DATA2(rv));
             }
             if (se->getMorph()) {
                 strcat(result, " ");                                
@@ -2599,7 +2603,7 @@ char * AffixMgr::suffix_check_morph(const char * word, int len,
                             strcat(result, " ");
                         } else debugflag(result, ((PfxEntry *) ppfx)->getFlag());
                     }    
-                    if (complexprefixes && HENTRY_DATA(rv)) strcat(result, HENTRY_DATA(rv));
+                    if (complexprefixes && HENTRY_DATA(rv)) strcat(result, HENTRY_DATA2(rv));
                     if (! HENTRY_FIND(rv, MORPH_STEM)) {
                             strcat(result, " ");                                
                             strcat(result, MORPH_STEM);
@@ -2610,7 +2614,7 @@ char * AffixMgr::suffix_check_morph(const char * word, int len,
 
                     if (!complexprefixes && HENTRY_DATA(rv)) {
                         strcat(result, " ");                                
-                        strcat(result, HENTRY_DATA(rv));
+                        strcat(result, HENTRY_DATA2(rv));
                     }
 #ifdef DEBUG
                 unsigned short flag = sptr->getFlag();
@@ -2796,14 +2800,17 @@ int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts
     if ((nh < maxn) && !(al && ((needaffix && TESTAFF(ap, needaffix, al)) ||
          (onlyincompound && TESTAFF(ap, onlyincompound, al))))) {
        wlst[nh].word = mystrdup(ts);
+       if (!wlst[nh].word) return 0;
        wlst[nh].allow = (1 == 0);
        wlst[nh].orig = NULL;
        nh++;
        // add special phonetic version
        if (phon && (nh < maxn)) {
     	    wlst[nh].word = mystrdup(phon);
+            if (!wlst[nh].word) return nh - 1;
     	    wlst[nh].allow = (1 == 0);
     	    wlst[nh].orig = mystrdup(ts);
+            if (!wlst[nh].orig) return nh - 1;
     	    nh++;
        }
     }
@@ -2837,8 +2844,10 @@ int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts
     			strcat(st, sptr->getKey());
     			reverseword(st + strlen(phon));
     			wlst[nh].word = mystrdup(st);
+    			if (!wlst[nh].word) return nh - 1;
     			wlst[nh].allow = (1 == 0);
     			wlst[nh].orig = mystrdup(newword);
+                        if (!wlst[nh].orig) return nh - 1;
     			nh++;
     		    }
                 } else {
@@ -2964,7 +2973,7 @@ char ** AffixMgr::get_breaktable()
 char * AffixMgr::get_encoding()
 {
   if (! encoding ) {
-      encoding = mystrdup("ISO8859-1");
+      encoding = SPELL_ENCODING;
   }
   return mystrdup(encoding);
 }
@@ -3014,7 +3023,7 @@ unsigned short * AffixMgr::get_ignore_utf16(int * len)
 // return the keyboard string for suggestions
 char * AffixMgr::get_key_string()
 {
-  if (! keystring ) return NULL;
+  if (! keystring ) keystring = SPELL_KEYSTRING;
   return mystrdup(keystring);
 }
 
@@ -3223,7 +3232,6 @@ int  AffixMgr::parse_cpdsyllable(char * line)
           }
           i++;
       }
-      // free(piece);
       piece = mystrsep(&tp, 0);
    }
    if (np < 2) {
@@ -3254,7 +3262,6 @@ int  AffixMgr::parse_reptable(char * line, FileMgr * af)
                        numrep = atoi(piece);
                        if (numrep < 1) {
                           HUNSPELL_WARNING(stderr, "incorrect number of entries in replacement table\n");
-                          // free(piece);
                           return 1;
                        }
                        reptable = (replentry *) malloc(numrep * sizeof(struct replentry));
@@ -3266,7 +3273,6 @@ int  AffixMgr::parse_reptable(char * line, FileMgr * af)
           }
           i++;
        }
-       // free(piece);
        piece = mystrsep(&tp, 0);
    }
    if (np != 2) {
@@ -3291,7 +3297,6 @@ int  AffixMgr::parse_reptable(char * line, FileMgr * af)
                              if (strncmp(piece,"REP",3) != 0) {
                                  HUNSPELL_WARNING(stderr, "error: replacement table is corrupt\n");
                                  numrep = 0;
-                                 // free(piece);
                                  return 1;
                              }
                              break;
@@ -3302,7 +3307,6 @@ int  AffixMgr::parse_reptable(char * line, FileMgr * af)
                }
                i++;
            }
-           // free(piece);
            piece = mystrsep(&tp, 0);
         }
         if ((!(reptable[j].pattern)) || (!(reptable[j].pattern2))) {
@@ -3338,7 +3342,6 @@ int  AffixMgr::parse_phonetable(char * line, FileMgr * af)
                        if (!phone) return 1;
                        if (phone->num < 1) {
                           HUNSPELL_WARNING(stderr, "incorrect number of entries in phonelacement table\n");
-                          // free(piece);
                           return 1;
                        }
                        phone->rules = (char * *) malloc(2 * (phone->num + 1) * sizeof(char *));
@@ -3350,7 +3353,6 @@ int  AffixMgr::parse_phonetable(char * line, FileMgr * af)
           }
           i++;
        }
-       // free(piece);
        piece = mystrsep(&tp, 0);
    }
    if (np != 2) {
@@ -3375,7 +3377,6 @@ int  AffixMgr::parse_phonetable(char * line, FileMgr * af)
                              if (strncmp(piece,"PHONE",5) != 0) {
                                  HUNSPELL_WARNING(stderr, "error: PHONE table is corrupt\n");
                                  phone->num = 0;
-                                 // free(piece);
                                  return 1;
                              }
                              break;
@@ -3386,7 +3387,6 @@ int  AffixMgr::parse_phonetable(char * line, FileMgr * af)
                }
                i++;
            }
-           // free(piece);
            piece = mystrsep(&tp, 0);
         }
         if ((!(phone->rules[j * 2])) || (!(phone->rules[j * 2 + 1]))) {
@@ -3421,7 +3421,6 @@ int  AffixMgr::parse_checkcpdtable(char * line, FileMgr * af)
                        numcheckcpd = atoi(piece);
                        if (numcheckcpd < 1) {
                           HUNSPELL_WARNING(stderr, "incorrect number of entries in compound pattern table\n");
-                          // free(piece);
                           return 1;
                        }
                        checkcpdtable = (replentry *) malloc(numcheckcpd * sizeof(struct replentry));
@@ -3433,7 +3432,6 @@ int  AffixMgr::parse_checkcpdtable(char * line, FileMgr * af)
           }
           i++;
        }
-       // free(piece);
        piece = mystrsep(&tp, 0);
    }
    if (np != 2) {
@@ -3458,7 +3456,6 @@ int  AffixMgr::parse_checkcpdtable(char * line, FileMgr * af)
                              if (strncmp(piece,"CHECKCOMPOUNDPATTERN",20) != 0) {
                                  HUNSPELL_WARNING(stderr, "error: compound pattern table is corrupt\n");
                                  numcheckcpd = 0;
-                                 // free(piece);
                                  return 1;
                              }
                              break;
@@ -3469,7 +3466,6 @@ int  AffixMgr::parse_checkcpdtable(char * line, FileMgr * af)
                }
                i++;
            }
-           // free(piece);
            piece = mystrsep(&tp, 0);
         }
         if ((!(checkcpdtable[j].pattern)) || (!(checkcpdtable[j].pattern2))) {
@@ -3501,7 +3497,6 @@ int  AffixMgr::parse_defcpdtable(char * line, FileMgr * af)
                        numdefcpd = atoi(piece);
                        if (numdefcpd < 1) {
                           HUNSPELL_WARNING(stderr, "incorrect number of entries in compound rule table\n");
-                          // free(piece);
                           return 1;
                        }
                        defcpdtable = (flagentry *) malloc(numdefcpd * sizeof(flagentry));
@@ -3513,7 +3508,6 @@ int  AffixMgr::parse_defcpdtable(char * line, FileMgr * af)
           }
           i++;
        }
-       // free(piece);
        piece = mystrsep(&tp, 0);
    }
    if (np != 2) {
@@ -3536,7 +3530,6 @@ int  AffixMgr::parse_defcpdtable(char * line, FileMgr * af)
                   case 0: {
                              if (strncmp(piece, "COMPOUNDRULE", 12) != 0) {
                                  HUNSPELL_WARNING(stderr, "error: compound rule table is corrupt\n");
-                                 // free(piece);
                                  numdefcpd = 0;
                                  return 1;
                              }
@@ -3551,7 +3544,6 @@ int  AffixMgr::parse_defcpdtable(char * line, FileMgr * af)
                }
                i++;
            }
-           // free(piece);
            piece = mystrsep(&tp, 0);
         }
         if (!defcpdtable[j].len) {
@@ -3584,7 +3576,6 @@ int  AffixMgr::parse_maptable(char * line, FileMgr * af)
                        nummap = atoi(piece);
                        if (nummap < 1) {
                           HUNSPELL_WARNING(stderr, "incorrect number of entries in map table\n");
-                          // free(piece);
                           return 1;
                        }
                        maptable = (mapentry *) malloc(nummap * sizeof(struct mapentry));
@@ -3596,7 +3587,6 @@ int  AffixMgr::parse_maptable(char * line, FileMgr * af)
           }
           i++;
        }
-       // free(piece);
        piece = mystrsep(&tp, 0);
    }
    if (np != 2) {
@@ -3621,7 +3611,6 @@ int  AffixMgr::parse_maptable(char * line, FileMgr * af)
                              if (strncmp(piece,"MAP",3) != 0) {
                                  HUNSPELL_WARNING(stderr, "error: map table is corrupt\n");
                                  nummap = 0;
-                                 // free(piece);
                                  return 1;
                              }
                              break;
@@ -3649,7 +3638,6 @@ int  AffixMgr::parse_maptable(char * line, FileMgr * af)
                }
                i++;
            }
-           // free(piece);
            piece = mystrsep(&tp, 0);
         }
         if ((!(maptable[j].set || maptable[j].set_utf16)) || (!(maptable[j].len))) {
@@ -3681,7 +3669,6 @@ int  AffixMgr::parse_breaktable(char * line, FileMgr * af)
                        numbreak = atoi(piece);
                        if (numbreak < 1) {
                           HUNSPELL_WARNING(stderr, "incorrect number of entries in BREAK table\n");
-                          // free(piece);
                           return 1;
                        }
                        breaktable = (char **) malloc(numbreak * sizeof(char *));
@@ -3693,7 +3680,6 @@ int  AffixMgr::parse_breaktable(char * line, FileMgr * af)
           }
           i++;
        }
-       // free(piece);
        piece = mystrsep(&tp, 0);
    }
    if (np != 2) {
@@ -3715,7 +3701,6 @@ int  AffixMgr::parse_breaktable(char * line, FileMgr * af)
                   case 0: {
                              if (strncmp(piece,"BREAK",5) != 0) {
                                  HUNSPELL_WARNING(stderr, "error: BREAK table is corrupt\n");
-                                 // free(piece);
                                  numbreak = 0;
                                  return 1;
                              }
@@ -3729,7 +3714,6 @@ int  AffixMgr::parse_breaktable(char * line, FileMgr * af)
                }
                i++;
            }
-           // free(piece);
            piece = mystrsep(&tp, 0);
         }
         if (!breaktable) {
@@ -3777,7 +3761,7 @@ int  AffixMgr::parse_affix(char * line, const char at, FileMgr * af, char * dupf
    struct affentry * nptr= NULL;
 
    char * tp = line;
-   char * nl = NULL;
+   char * nl = line;
    char * piece;
    int i = 0;
 
@@ -3789,6 +3773,7 @@ int  AffixMgr::parse_affix(char * line, const char at, FileMgr * af, char * dupf
    // split affix header line into pieces
 
    int np = 0;
+
    piece = mystrsep(&tp, 0);
    while (piece) {
       if (*piece != '\0') {
@@ -3817,9 +3802,11 @@ int  AffixMgr::parse_affix(char * line, const char at, FileMgr * af, char * dupf
                        numents = atoi(piece); 
                        if (numents == 0) {
                            char * err = pHMgr->encode_flag(aflag);
-                           HUNSPELL_WARNING(stderr, "error: affix %s header has incorrect entry count in line %s\n",
+                           if (err) {
+                                HUNSPELL_WARNING(stderr, "error: affix %s header has incorrect entry count in line %s\n",
                                    err, nl);
-                           free(err);
+                                free(err);
+                           }
                            return 1;
                        }
                        ptr = (struct affentry *) malloc(numents * sizeof(struct affentry));
@@ -3835,14 +3822,15 @@ int  AffixMgr::parse_affix(char * line, const char at, FileMgr * af, char * dupf
           }
           i++;
       }
-      // free(piece);
       piece = mystrsep(&tp, 0);
    }
    // check to make sure we parsed enough pieces
    if (np != 4) {
-       char * err = pHMgr->encode_flag(aflag); 
-       HUNSPELL_WARNING(stderr, "error: affix %s header has insufficient data in line %s\n", err, nl);
-       free(err);
+       char * err = pHMgr->encode_flag(aflag);
+       if (err) {
+            HUNSPELL_WARNING(stderr, "error: affix %s header has insufficient data in line %s\n", err, nl);
+            free(err);
+       }
        free(ptr);
        return 1;
    }
@@ -3876,10 +3864,11 @@ int  AffixMgr::parse_affix(char * line, const char at, FileMgr * af, char * dupf
                           np++;
                           if (pHMgr->decode_flag(piece) != aflag) {
                               char * err = pHMgr->encode_flag(aflag);
-                              HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl);
-                              HUNSPELL_WARNING(stderr, "error: possible incorrect count\n");
-                              free(err);
-                              // free(piece);
+                              if (err) {
+                                HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl);
+                                HUNSPELL_WARNING(stderr, "error: possible incorrect count\n");
+                                free(err);
+                              }
                               return 1;
                           }
 
@@ -3997,8 +3986,8 @@ int  AffixMgr::parse_affix(char * line, const char at, FileMgr * af, char * dupf
                                 *(tp - 1) = ' ';
                                 tp = tp + strlen(tp);
                             }
-                            nptr->morphcode = (char *) malloc(strlen(piece)+1);
-                            strcpy(nptr->morphcode, piece);
+                            nptr->morphcode = mystrdup(piece);
+                            if (!nptr->morphcode) return 1;
                           }
                           break; 
                 }
@@ -4006,14 +3995,15 @@ int  AffixMgr::parse_affix(char * line, const char at, FileMgr * af, char * dupf
              }
              i++;
          }
-         // free(piece);
          piece = mystrsep(&tp, 0);
       }
       // check to make sure we parsed enough pieces
       if (np < 4) {
           char * err = pHMgr->encode_flag(aflag);
-          HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl);
-          free(err);
+          if (err) {
+            HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl);
+            free(err);
+          }
           free(ptr);
           return 1;
       }
diff --git a/src/hunspell/csutil.cxx b/src/hunspell/csutil.cxx
index e282754..50e2b22 100644
--- a/src/hunspell/csutil.cxx
+++ b/src/hunspell/csutil.cxx
@@ -253,7 +253,11 @@ int flag_bsearch(unsigned short flags[], unsigned short flag, int length) {
    if (s) {
       int sl = strlen(s);
       d = (char *) malloc(((sl+1) * sizeof(char)));
-      if (d) memcpy(d,s,((sl+1)*sizeof(char)));
+      if (d) {
+         memcpy(d,s,((sl+1)*sizeof(char)));
+         return d;
+      }
+      HUNSPELL_WARNING(stderr, "Can't allocate memory.\n");
    }
    return d;
  }
@@ -298,7 +302,9 @@ int line_tok(const char * text, char *** lines, char breakchar) {
         p = strchr(p, breakchar);
     }
     linenum++;
+//    fprintf(stderr, "LINEN:%d %p %p\n", linenum, lines, *lines);
     *lines = (char **) malloc(linenum * sizeof(char *));
+//    fprintf(stderr, "hello\n");
     if (!(*lines)) {
         free(dup);
         return 0;
@@ -309,6 +315,11 @@ int line_tok(const char * text, char *** lines, char breakchar) {
     for (int i = 0; i < linenum; i++) {
         if (*p != '\0') {
             (*lines)[l] = mystrdup(p);
+            if (!(*lines)[l]) {
+                for (i = 0; i < l; i++) free((*lines)[i]);
+                free(dup);
+                return 0;
+            }
             l++;
         }
         p += strlen(p) + 1;
@@ -390,16 +401,18 @@ char * line_uniq_app(char ** text, char breakchar) {
     char * dup = mystrdup(dest);
     char * source = dup;
     int len = strlen(s);
-    while (*source) {
-        if (*source == '\n') {
-            strncpy(dest, s, len);
-            dest += len;
+    if (dup) {
+        while (*source) {
+            if (*source == '\n') {
+                strncpy(dest, s, len);
+                dest += len;
+            }
+            *dest = *source;
+            source++; dest++;
         }
-        *dest = *source;
-        source++; dest++;
+        strcpy(dest, s);
+        free(dup);
     }
-    strcpy(dest, s);
-    free(dup);
  }
 
 // change \n to char c
@@ -600,10 +613,10 @@ char * mystrrep(char * word, const char * pat, const char * rep) {
  }
  
  void freelist(char *** list, int n) {
-   if (list && (n > 0)) {
-      for (int i = 0; i < n; i++) if ((*list)[i]) free((*list)[i]);
-      free(*list);
-      *list = NULL;
+   if (list && *list && n > 0) {
+     for (int i = 0; i < n; i++) if ((*list)[i]) free((*list)[i]);
+     free(*list);
+     *list = NULL;
    }
  }
  
@@ -5481,6 +5494,7 @@ int parse_string(char * line, char ** out, const char * warnvar)
               case 0: { np++; break; }
               case 1: { 
                 *out = mystrdup(piece);
+                if (!*out) return 1;
                 np++;
                 break;
               }
diff --git a/src/hunspell/csutil.hxx b/src/hunspell/csutil.hxx
index 2a16538..d86959a 100644
--- a/src/hunspell/csutil.hxx
+++ b/src/hunspell/csutil.hxx
@@ -5,12 +5,18 @@
 
 #include "w_char.hxx"
 
+// casing
 #define NOCAP   0
 #define INITCAP 1
 #define ALLCAP  2
 #define HUHCAP  3
 #define HUHINITCAP  4
 
+// default encoding and keystring
+#define SPELL_ENCODING  "ISO8859-1"
+#define SPELL_KEYSTRING "qwertyuiop|asdfghjkl|zxcvbnm" 
+
+// default morphological fields
 #define MORPH_STEM        "st:"
 #define MORPH_ALLOMORPH   "al:"
 #define MORPH_POS         "po:"
@@ -41,6 +47,9 @@
 // hash entry macros
 #define HENTRY_DATA(h) (h->var ? ((h->var & H_OPT_ALIASM) ? \
     get_stored_pointer(&(h->word) + h->blen + 1) : &(h->word) + h->blen + 1) : NULL)
+// NULL-free version for warning-free OOo build
+#define HENTRY_DATA2(h) (h->var ? ((h->var & H_OPT_ALIASM) ? \
+    get_stored_pointer(&(h->word) + h->blen + 1) : &(h->word) + h->blen + 1) : "")
 #define HENTRY_FIND(h,p) (HENTRY_DATA(h) ? strstr(HENTRY_DATA(h), p) : NULL)
 
 #define w_char_eq(a,b) (((a).l == (b).l) && ((a).h == (b).h))
diff --git a/src/hunspell/hashmgr.cxx b/src/hunspell/hashmgr.cxx
index a1ca329..b60223a 100644
--- a/src/hunspell/hashmgr.cxx
+++ b/src/hunspell/hashmgr.cxx
@@ -284,6 +284,7 @@ int HashMgr::remove(const char * word)
         }
         dp = dp->next_homonym;
     }
+    return 0;
 }
 
 /* remove forbidden flag to add a personal word to the hash */
@@ -682,7 +683,7 @@ int  HashMgr::load_config(const char * affpath, const char * key)
        if (strncmp(line,"COMPLEXPREFIXES",15) == 0) complexprefixes = 1;
        if (((strncmp(line,"SFX",3) == 0) || (strncmp(line,"PFX",3) == 0)) && isspace(line[3])) break;
     }
-    if (csconv == NULL) csconv = get_current_cs("ISO8859-1");
+    if (csconv == NULL) csconv = get_current_cs(SPELL_ENCODING);
     delete afflst;
     return 0;
 }
@@ -710,7 +711,6 @@ int  HashMgr::parse_aliasf(char * line, FileMgr * af)
                           aliasf = NULL;
                           aliasflen = NULL;
                           HUNSPELL_WARNING(stderr, "incorrect number of entries in AF table\n");
-                          // free(piece);
                           return 1;
                        }
                        aliasf = (unsigned short **) malloc(numaliasf * sizeof(unsigned short *));
@@ -730,7 +730,6 @@ int  HashMgr::parse_aliasf(char * line, FileMgr * af)
           }
           i++;
        }
-       // free(piece);
        piece = mystrsep(&tp, 0);
    }
    if (np != 2) {
@@ -764,7 +763,6 @@ int  HashMgr::parse_aliasf(char * line, FileMgr * af)
                                  aliasf = NULL;
                                  aliasflen = NULL;
                                  HUNSPELL_WARNING(stderr, "error: AF table is corrupt\n");
-                                 // free(piece);
                                  return 1;
                              }
                              break;
@@ -778,7 +776,6 @@ int  HashMgr::parse_aliasf(char * line, FileMgr * af)
                }
                i++;
            }
-           // free(piece);
            piece = mystrsep(&tp, 0);
         }
         if (!aliasf[j]) {
@@ -828,7 +825,6 @@ int  HashMgr::parse_aliasm(char * line, FileMgr * af)
                        numaliasm = atoi(piece);
                        if (numaliasm < 1) {
                           HUNSPELL_WARNING(stderr, "incorrect number of entries in AM table\n");
-                          // free(piece);
                           return 1;
                        }
                        aliasm = (char **) malloc(numaliasm * sizeof(char *));
@@ -843,7 +839,6 @@ int  HashMgr::parse_aliasm(char * line, FileMgr * af)
           }
           i++;
        }
-       // free(piece);
        piece = mystrsep(&tp, 0);
    }
    if (np != 2) {
@@ -869,7 +864,6 @@ int  HashMgr::parse_aliasm(char * line, FileMgr * af)
                   case 0: {
                              if (strncmp(piece,"AM",2) != 0) {
                                  HUNSPELL_WARNING(stderr, "error: AM table is corrupt\n");
-                                 // free(piece);
                                  numaliasm = 0;
                                  free(aliasm);
                                  aliasm = NULL;
@@ -888,12 +882,17 @@ int  HashMgr::parse_aliasm(char * line, FileMgr * af)
                                     else reverseword(piece);
                             }
                             aliasm[j] = mystrdup(piece);
+                            if (!aliasm[j]) {
+                                 numaliasm = 0;
+                                 free(aliasm);
+                                 aliasm = NULL;
+                                 return 1;                            
+                            }
                             break; }
                   default: break;
                }
                i++;
            }
-           // free(piece);
            piece = mystrsep(&tp, ' ');
         }
         if (!aliasm[j]) {
diff --git a/src/hunspell/hunspell.cxx b/src/hunspell/hunspell.cxx
index e74b34a..8777b4e 100644
--- a/src/hunspell/hunspell.cxx
+++ b/src/hunspell/hunspell.cxx
@@ -74,7 +74,7 @@ Hunspell::~Hunspell()
 
 // load extra dictionaries
 int Hunspell::add_dic(const char * dpath, const char * key) {
-    if (maxdic == MAXDIC) return 1;
+    if (maxdic == MAXDIC || !affixpath) return 1;
     pHMgr[maxdic] = new HashMgr(dpath, affixpath, key);
     if (pHMgr[maxdic]) maxdic++; else return 1;
     return 0;
@@ -318,12 +318,14 @@ int Hunspell::is_keepcase(const hentry * rv) {
 
 /* insert a word to beginning of the suggestion array and return ns */
 int Hunspell::insert_sug(char ***slst, char * word, int ns) {
+    char * dup = mystrdup(word);
+    if (!dup) return ns;
     if (ns == MAXSUGGESTION) {
         ns--;
         free((*slst)[ns]);
     }
     for (int k = ns; k > 0; k--) (*slst)[k] = (*slst)[k - 1];
-    (*slst)[0] = mystrdup(word);
+    (*slst)[0] = dup;
     return ns + 1;
 }
 
@@ -335,6 +337,8 @@ int Hunspell::spell(const char * word, int * info, char ** root)
   char cw[MAXWORDUTF8LEN];
   char wspace[MAXWORDUTF8LEN];
   w_char unicw[MAXWORDLEN];
+  // Hunspell supports XML input of the simplified API (see manual)
+  if (strcmp(word, SPELL_XML) == 0) return 1;
   int nc = strlen(word);
   int wl2 = 0;
   if (utf8) {
@@ -645,7 +649,7 @@ struct hentry * Hunspell::checkword(const char * w, int * info, char ** root)
         }
         if (root) {
             *root = mystrdup(&(he->word));
-            if (complexprefixes) {
+            if (*root && complexprefixes) {
                 if (utf8) reverseword_utf(*root); else reverseword(*root);
             }
         }
@@ -656,6 +660,7 @@ struct hentry * Hunspell::checkword(const char * w, int * info, char ** root)
           // LANG_hu section: `moving rule' with last dash
           if ((!he) && (langnum == LANG_hu) && (word[len-1]=='-')) {
              char * dup = mystrdup(word);
+             if (!dup) return NULL;
              dup[len-1] = '\0';
              he = pAMgr->compound_check(dup, len-1, 
                                   -5,0,100,0,NULL,1,NULL,NULL,0);
@@ -665,7 +670,7 @@ struct hentry * Hunspell::checkword(const char * w, int * info, char ** root)
           if (he) {
                 if (root) {
                     *root = mystrdup(&(he->word));
-                    if (complexprefixes) {
+                    if (*root && complexprefixes) {
                         if (utf8) reverseword_utf(*root); else reverseword(*root);
                     }
                 }
@@ -685,6 +690,11 @@ int Hunspell::suggest(char*** slst, const char * word)
   char wspace[MAXWORDUTF8LEN];
   if (!pSMgr || maxdic == 0) return 0;
   w_char unicw[MAXWORDLEN];
+  *slst = NULL;
+  // process XML input of the simplified API (see manual)
+  if (strncmp(word, SPELL_XML, sizeof(SPELL_XML) - 3) == 0) {
+     return spellml(slst, word);
+  }
   int nc = strlen(word);
   if (utf8) {
     if (nc >= MAXWORDUTF8LEN) return 0;
@@ -696,7 +706,6 @@ int Hunspell::suggest(char*** slst, const char * word)
   int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv);
   if (wl == 0) return 0;
   int ns = 0;
-  *slst = NULL;
   int capwords = 0;
 
   switch(captype) {
@@ -731,7 +740,7 @@ int Hunspell::suggest(char*** slst, const char * word)
 		            } else captype_ = get_captype(dot+1, strlen(dot+1), csconv);
 		    	    if (captype_ == INITCAP) {
                         	char * st = mystrdup(cw);
-                        	st = (char *) realloc(st, wl + 2);
+                        	if (st) st = (char *) realloc(st, wl + 2);
 				if (st) {
                         		st[(dot - cw) + 1] = ' ';
                         		strcpy(st + (dot - cw) + 2, dot + 1);
@@ -904,12 +913,12 @@ int Hunspell::suggest(char*** slst, const char * word)
           free((*slst)[j]);          
           if (spell(s)) {
             (*slst)[l] = mystrdup(s);
-            l++;
+            if ((*slst)[l]) l++;
           } else {
             mkinitcap2(s, w, len);
             if (spell(s)) {
               (*slst)[l] = mystrdup(s);
-              l++;
+              if ((*slst)[l]) l++;
             }
           }
         } else {
@@ -934,9 +943,19 @@ int Hunspell::suggest(char*** slst, const char * word)
     }
     l++;
   }
+
+  // if suggestions removed by nosuggest, onlyincompound parameters
+  if (l == 0 && *slst) {
+    free(*slst);
+    *slst = NULL;
+  }
   return l;
 }
 
+void Hunspell::free_list(char *** slst, int n) {
+        freelist(slst, n);
+}
+
 char * Hunspell::get_dic_encoding()
 {
   return encoding;
@@ -1045,6 +1064,7 @@ int Hunspell::stem(char*** slst, char ** desc, int n)
 {
   char result[MAXLNLEN];
   char result2[MAXLNLEN];
+  *slst = NULL;
   if (n == 0) return 0;
   *result2 = '\0';
   for (int i = 0; i < n; i++) {
@@ -1276,6 +1296,7 @@ int Hunspell::analyze(char*** slst, const char * word)
 {
   char cw[MAXWORDUTF8LEN];
   char wspace[MAXWORDUTF8LEN];
+  *slst = NULL;
   if (! pSMgr || maxdic == 0) return 0;
   int wl = strlen(word);
   if (utf8) {
@@ -1392,7 +1413,7 @@ int Hunspell::analyze(char*** slst, const char * word)
                    }
   }
 
-  if (result && (*result)) {
+  if (*result) {
     // word reversing wrapper for complex prefixes
     if (complexprefixes) {
       if (utf8) reverseword_utf(result); else reverseword(result);
@@ -1483,6 +1504,7 @@ int Hunspell::analyze(char*** slst, const char * word)
 
 int Hunspell::generate(char*** slst, const char * word, char ** pl, int pln)
 {
+  *slst = NULL;
   if (!pSMgr || !pln) return 0;
   char **pl2;
   int pl2n = analyze(&pl2, word);
@@ -1539,6 +1561,115 @@ int Hunspell::generate(char*** slst, const char * word, const char * pattern)
   return uniqlist(*slst, n);
 }
 
+// minimal XML parser functions
+int Hunspell::get_xml_par(char * dest, const char * par, int max)
+{
+   char * d = dest;
+   if (!par) return 0;
+   char end = *par;
+   char * dmax = dest + max;
+   if (end == '>') end = '<';
+   else if (end != '\'' && end != '"') return 0; // bad XML
+   for (par++; d < dmax && *par != '\0' && *par != end; par++, d++) *d = *par;
+   *d = '\0';
+   mystrrep(dest, "&lt;", "<");
+   mystrrep(dest, "&amp;", "&");
+   return d - dest;
+}
+
+// return the beginning of the element (attr == NULL) or the attribute
+const char * Hunspell::get_xml_pos(const char * s, const char * attr)
+{
+  const char * end = strchr(s, '>');
+  const char * p = s;
+  if (attr == NULL) return end;
+  do {
+    p = strstr(p, attr);
+    if (!p || p >= end) return 0;
+  } while (*(p-1) != ' ' &&  *(p-1) != '\n');
+  return p + strlen(attr);
+}
+
+int Hunspell::check_xml_par(char * q, char * attr, char * value) {
+  char cw[MAXWORDUTF8LEN];
+  if (get_xml_par(cw, get_xml_pos(q, attr), MAXWORDUTF8LEN - 1) && 
+    strcmp(cw, value) == 0) return 1;
+  return 0;
+}
+
+int Hunspell::get_xml_list(char ***slst, char * list, char * tag) {
+    int n = 0;
+    char * p;
+    if (!list) return 0;
+    for (p = list; (p = strstr(p, tag)); p++) n++;
+    if (n == 0) return 0;
+    *slst = (char **) malloc(sizeof(char *) * n);
+    if (!*slst) return 0;
+    for (p = list, n = 0; (p = strstr(p, tag)); p++, n++) {
+        int l = strlen(p);
+        (*slst)[n] = (char *) malloc(l);
+        if (!(*slst)[n]) return (n > 0 ? n - 1 : 0);
+        get_xml_par((*slst)[n], p + strlen(tag) - 1, l);
+    }
+    return n;
+}
+
+int Hunspell::spellml(char*** slst, const char * word)
+{
+  char *q, *q2;
+  char cw[MAXWORDUTF8LEN], cw2[MAXWORDUTF8LEN];
+  q = (char *) strstr(word, "<query");
+  if (!q) return 0; // bad XML input
+  q2 = strchr(q, '>');
+  if (!q2) return 0; // bad XML input
+  q2 = strstr(q2, "<word");
+  if (!q2) return 0; // bad XML input
+  if (check_xml_par(q, "type=", "analyze")) {
+      int n = 0, s = 0;
+      if (get_xml_par(cw, strchr(q2, '>'), MAXWORDUTF8LEN)) n = analyze(slst, cw);
+      if (n == 0) return 0;
+      // convert the result to <code><a>ana1</a><a>ana2</a></code> format
+      for (int i = 0; i < n; i++) s+= strlen((*slst)[i]);
+      char * r = (char *) malloc(6 + 5 * s + 7 * n + 7 + 1); // XXX 5*s->&->&amp;
+      if (!r) return 0;
+      strcpy(r, "<code>");
+      for (int i = 0; i < n; i++) {
+        int l = strlen(r);
+        strcpy(r + l, "<a>");
+        strcpy(r + l + 3, (*slst)[i]);
+        mystrrep(r + l + 3, "\t", " ");
+        mystrrep(r + l + 3, "<", "&lt;");
+        mystrrep(r + l + 3, "&", "&amp;");
+        strcat(r, "</a>");
+        free((*slst)[i]);
+      }
+      strcat(r, "</code>");
+      (*slst)[0] = r;
+      return 1;
+  } else if (check_xml_par(q, "type=", "stem")) {
+      if (get_xml_par(cw, strchr(q2, '>'), MAXWORDUTF8LEN)) return stem(slst, cw);
+  } else if (check_xml_par(q, "type=", "generate")) {
+      int n = get_xml_par(cw, strchr(q2, '>'), MAXWORDUTF8LEN);
+      if (n == 0) return 0;
+      char * q3 = strstr(q2 + 1, "<word");
+      if (q3) {
+        if (get_xml_par(cw2, strchr(q3, '>'), MAXWORDUTF8LEN)) {
+            return generate(slst, cw, cw2);
+        }
+      } else {
+        char ** slst2;
+        if ((q2 = strstr(q2 + 1, "<code")) &&
+          (n = get_xml_list(&slst2, strchr(q2, '>'), "<a>"))) {
+             int n2 = generate(slst, cw, slst2, n);
+             freelist(&slst2, n);
+             return uniqlist(*slst, n2);
+        }
+      }
+  }
+  return 0;
+}
+
+
 #ifdef HUNSPELL_EXPERIMENTAL
 // XXX need UTF-8 support
 char * Hunspell::morph_with_correction(const char * word)
@@ -1684,7 +1815,7 @@ char * Hunspell::morph_with_correction(const char * word)
                    }
   }
 
-  if (result) return mystrdup(result);
+  if (*result) return mystrdup(result);
   return NULL;
 }
 
@@ -1771,3 +1902,7 @@ int Hunspell_add_with_affix(Hunhandle *pHunspell, const char * word,
 int Hunspell_remove(Hunhandle *pHunspell, const char * word) {
         return ((Hunspell*)pHunspell)->remove(word);
 }
+
+void Hunspell_free_list(Hunhandle *pHunspell, char *** slst, int n) {
+        freelist(slst, n);
+}
diff --git a/src/hunspell/hunspell.h b/src/hunspell/hunspell.h
index a18cec4..f926052 100644
--- a/src/hunspell/hunspell.h
+++ b/src/hunspell/hunspell.h
@@ -88,6 +88,10 @@ DLL int Hunspell_add_with_affix(Hunhandle *pHunspell, const char * word, const c
 
 DLL int Hunspell_remove(Hunhandle *pHunspell, const char * word);
 
+  /* free suggestion lists */
+
+DLL void Hunspell_free_list(Hunhandle *pHunspell, char *** slst, int n);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/hunspell/hunspell.hxx b/src/hunspell/hunspell.hxx
index 854f354..2e38541 100644
--- a/src/hunspell/hunspell.hxx
+++ b/src/hunspell/hunspell.hxx
@@ -9,6 +9,8 @@
 #define  SPELL_NOCAP     (1 << 3)
 #define  SPELL_INITCAP   (1 << 4)
 
+#define  SPELL_XML "<?xml?>"
+
 #define MAXDIC 20
 #define MAXSUGGESTION 15
 #define MAXSHARPS 5
@@ -43,7 +45,6 @@ class Hunspell
   int             utf8;
   int             complexprefixes;
   char**          wordbreak;
-  char *          key;
 
 public:
 
@@ -79,6 +80,10 @@ public:
 
   int suggest(char*** slst, const char * word);
 
+  /* deallocate suggestion lists */
+
+  void free_list(char *** slst, int n);
+
   char * get_dic_encoding();
 
  /* morphological functions */
@@ -94,8 +99,8 @@ public:
  /* stem(result, analysis, n) - get stems from a morph. analysis
   * example:
   * char ** result, result2;
-  * int n1 = analyze(result, "words");
-  * int n2 = stem(result2, result, n1);   
+  * int n1 = analyze(&result, "words");
+  * int n2 = stem(&result2, result, n1);   
   */
  
   int stem(char*** slst, char ** morph, int n);
@@ -108,7 +113,7 @@ public:
   * example:
   * char ** result;
   * char * affix = "is:plural"; // description depends from dictionaries, too
-  * int n = generate(result, "word", &affix, 1);
+  * int n = generate(&result, "word", &affix, 1);
   * for (int i = 0; i < n; i++) printf("%s\n", result[i]);
   */
 
@@ -170,6 +175,11 @@ private:
    int    insert_sug(char ***slst, char * word, int ns);
    void   cat_result(char * result, char * st);
    char * stem_description(const char * desc);
+   int    spellml(char*** slst, const char * word);
+   int    get_xml_par(char * dest, const char * par, int maxl);
+   const char * get_xml_pos(const char * s, const char * attr);
+   int    get_xml_list(char ***slst, char * list, char * tag);
+   int    check_xml_par(char * q, char * attr, char * value);
 
 };
 
diff --git a/src/hunspell/suggestmgr.cxx b/src/hunspell/suggestmgr.cxx
index c19ba08..db9ea55 100644
--- a/src/hunspell/suggestmgr.cxx
+++ b/src/hunspell/suggestmgr.cxx
@@ -73,14 +73,14 @@ SuggestMgr::SuggestMgr(const char * tryme, int maxn,
   }
   
   if (tryme) {  
-    if (utf8) {
+    ctry = mystrdup(tryme);
+    if (ctry) ctryl = strlen(ctry);
+    if (ctry && utf8) {
         w_char t[MAXSWL];    
         ctryl = u8_u16(t, MAXSWL, tryme);
         ctry_utf = (w_char *) malloc(ctryl * sizeof(w_char));
         if (ctry_utf) memcpy(ctry_utf, t, ctryl * sizeof(w_char));
-    } else {
-        ctry = mystrdup(tryme);
-        ctryl = strlen(ctry);
+        else ctryl = 0;
     }
   }
 }
@@ -369,6 +369,7 @@ int SuggestMgr::map_related(const char * word, int i, char** wlst,
     if (strchr(maptable[j].set,c) != 0) {
       in_map = 1;
       char * newword = mystrdup(word);
+      if (!newword) return -1;
       for (int k = 0; k < maptable[j].len; k++) {
         *(newword + i) = *(maptable[j].set + k);
         ns = map_related(newword, (i+1), wlst, cpdsuggest,
@@ -467,6 +468,7 @@ int SuggestMgr::replchars(char** wlst, const char * word, int ns, int cpdsuggest
               if (oldns < ns) {
                 free(wlst[ns - 1]);
                 wlst[ns - 1] = mystrdup(candidate);
+                if (!wlst[ns - 1]) return -1;
               }
             }            
             *sp = ' ';
@@ -811,6 +813,23 @@ int SuggestMgr::twowords(char ** wlst, const char * word, int ns, int cpdsuggest
                     ns++;
                 }
             } else return ns;
+            // add two word suggestion with dash, if TRY string contains
+            // "a" or "-"
+            // NOTE: cwrd doesn't modified for REP twoword sugg.
+            if (ctry && (strchr(ctry, 'a') || strchr(ctry, '-')) &&
+                mystrlen(p + 1) > 1 &&
+                mystrlen(candidate) - mystrlen(p) > 1) {
+                *p = '-'; 
+                for (int k=0; k < ns; k++)
+                    if (strcmp(candidate,wlst[k]) == 0) cwrd = 0;
+                if (ns < maxSug) {
+                    if (cwrd) {
+                        wlst[ns] = mystrdup(candidate);
+                        if (wlst[ns] == NULL) return -1;
+                        ns++;
+                    }
+                } else return ns;
+            }
          }
        }
     }
@@ -1089,7 +1108,7 @@ int SuggestMgr::ngsuggest(char** wlst, char * w, int ns, HashMgr** pHMgr, int md
   }
 
   for (i = 0; i < md; i++) {  
-  while ((hp = (pHMgr[i])->walk_hashtable(col, hp))) {
+  while (0 != (hp = (pHMgr[i])->walk_hashtable(col, hp))) {
     if ((hp->astr) && (pAMgr) && 
        (TESTAFF(hp->astr, pAMgr->get_forbiddenword(), hp->alen) ||
           TESTAFF(hp->astr, ONLYUPCASEFLAG, hp->alen) ||
@@ -1339,7 +1358,10 @@ int SuggestMgr::ngsuggest(char** wlst, char * w, int ns, HashMgr** pHMgr, int md
             // check forbidden words
             !checkword(rootsphon[i], strlen(rootsphon[i]), 0, NULL, NULL)) unique = 0;
         }
-        if (unique) wlst[ns++] = mystrdup(rootsphon[i]);
+        if (unique) {
+            wlst[ns++] = mystrdup(rootsphon[i]);
+            if (!wlst[ns - 1]) return ns - 1;
+        }
       }
     }
   }
@@ -1512,7 +1534,7 @@ char * SuggestMgr::suggest_morph(const char * w)
                 }
                 if (HENTRY_DATA(rv)) {
                     strcat(result, " ");                                
-                    strcat(result, HENTRY_DATA(rv));
+                    strcat(result, HENTRY_DATA2(rv));
                 }
                 strcat(result, "\n");
         }
@@ -1572,7 +1594,7 @@ char * SuggestMgr::suggest_hentry_gen(hentry * rv, char * pattern)
     // check all allomorphs
     char allomorph[MAXLNLEN];
     char * p = NULL;
-    if (HENTRY_DATA(rv)) p = strstr(HENTRY_DATA(rv), MORPH_ALLOMORPH);
+    if (HENTRY_DATA(rv)) p = (char *) strstr(HENTRY_DATA2(rv), MORPH_ALLOMORPH);
     while (p) {
         struct hentry * rv2 = NULL;
         p += MORPH_TAG_LEN;
@@ -1583,7 +1605,7 @@ char * SuggestMgr::suggest_hentry_gen(hentry * rv, char * pattern)
         while (rv2) {
 //            if (HENTRY_DATA(rv2) && get_sfxcount(HENTRY_DATA(rv2)) <= sfxcount) {
             if (HENTRY_DATA(rv2)) {
-                char * st = strstr(HENTRY_DATA(rv2), MORPH_STEM);
+                char * st = (char *) strstr(HENTRY_DATA2(rv2), MORPH_STEM);
                 if (st && (strncmp(st + MORPH_TAG_LEN, 
                    HENTRY_WORD(rv), fieldlen(st + MORPH_TAG_LEN)) == 0)) {
                     char * aff = pAMgr->morphgen(HENTRY_WORD(rv2), rv2->blen, rv2->astr, rv2->alen,
diff --git a/src/tools/analyze.cxx b/src/tools/analyze.cxx
index e6ac5c2..03434fa 100644
--- a/src/tools/analyze.cxx
+++ b/src/tools/analyze.cxx
@@ -50,10 +50,9 @@ int main(int argc, char **argv)
             int n = pMS->generate(&result, buf, s+1);
             for (int i = 0; i < n; i++) {
                 fprintf(stdout, "generate(%s, %s) = %s\n", buf, s+1, result[i]);
-                free(result[i]);
             }
-            if (n) free(result);
-            else fprintf(stdout, "generate(%s, %s) = NO DATA\n", buf, s+1);
+            pMS->free_list(&result, n);
+            if (n == 0) fprintf(stdout, "generate(%s, %s) = NO DATA\n", buf, s+1);
         } else {
             dp = pMS->spell(buf);
             fprintf(stdout, "> %s\n", buf);
@@ -62,19 +61,16 @@ int main(int argc, char **argv)
                 int n = pMS->analyze(&result, buf);
                 for (int i = 0; i < n; i++) {
                     fprintf(stdout, "analyze(%s) = %s\n", buf, result[i]);
-                    free(result[i]);
                 }
-                if (n) free(result);
-                result = NULL;          
+                pMS->free_list(&result, n);
                 n = pMS->stem(&result, buf);
                 for (int i = 0; i < n; i++) {
                     fprintf(stdout, "stem(%s) = %s\n", buf, result[i]);
-                    free(result[i]);
                 }
-                if (n) free(result);
+                pMS->free_list(&result, n);
             } else {
                 fprintf(stdout, "Unknown word.\n");
-            }    			
+            }
         }
     }
     delete pMS;
diff --git a/src/tools/chmorph.cxx b/src/tools/chmorph.cxx
index c2b1e28..3d437e7 100644
--- a/src/tools/chmorph.cxx
+++ b/src/tools/chmorph.cxx
@@ -9,14 +9,6 @@
 using namespace std;
 #endif
 
-void freelst(char *** list, int n) {
-   if (list && (n > 0)) {
-      for (int i = 0; i < n; i++) if ((*list)[i]) free((*list)[i]);
-      free(*list);
-      *list = NULL;
-   }
-}
-
 int 
 main(int argc, char** argv)
 {
@@ -75,13 +67,13 @@ main(int argc, char** argv)
 		    int pl2n = pMS->generate(&pl2, next, pl, pln);
 		    if (pl2n) {
 		        p->change_token(pl2[0]);
-		        freelst(&pl2, pl2n);
+		        pMS->free_list(&pl2, pl2n);
 		        // jump over the (possibly un)modified word
 		        free(next);
 		        next=p->next_token();
 		    }
 		}
-		freelst(&pl, pln);
+		pMS->free_list(&pl, pln);
 	  }
 	  free(next);
       }
diff --git a/src/tools/example.cxx b/src/tools/example.cxx
index 89a30ee..093a038 100644
--- a/src/tools/example.cxx
+++ b/src/tools/example.cxx
@@ -52,10 +52,9 @@ main(int argc, char** argv)
           int ns = pMS->suggest(&wlst,buf);
           for (int i=0; i < ns; i++) {
             fprintf(stdout,"    ...\"%s\"\n",wlst[i]);
-            free(wlst[i]);
           }
+          pMS->free_list(&wlst, ns);
           fprintf(stdout,"\n");
-          free(wlst);
        }
     }
 
diff --git a/src/tools/hunspell.cxx b/src/tools/hunspell.cxx
index 9e909c3..10a1d45 100644
--- a/src/tools/hunspell.cxx
+++ b/src/tools/hunspell.cxx
@@ -69,6 +69,8 @@
     ".openoffice.org2/user/wordbook:" \
     ".openoffice.org2.0/user/wordbook"
 #define OOODIR \
+    "/opt/openoffice.org/basis3.0/share/dict/ooo:" \
+    "/usr/lib/openoffice.org/basis3.0/share/dict/ooo:" \
     "/opt/openoffice.org2.4/share/dict/ooo:" \
     "/usr/lib/openoffice.org2.4/share/dict/ooo:" \
     "/opt/openoffice.org2.3/share/dict/ooo:" \
@@ -116,12 +118,13 @@ char text_conv[MAXLNLEN];
 #else
 #include <curses.h>
 #endif
+#endif
+
 #ifdef HAVE_READLINE
 #include <readline/readline.h>
 #else
 #define readline scanline
 #endif
-#endif
 
 #define TEMPNAME "hunSPELL.bak"
 
@@ -144,6 +147,7 @@ char * wordchars = NULL;
 char * dicpath = NULL;
 int wordchars_len;
 unsigned short * wordchars_utf16 = NULL;
+int wordchars_utf16_free = 0;
 int wordchars_utf16_len;
 char * dicname = NULL;
 char * privdicname = NULL;
@@ -179,7 +183,7 @@ int dmax = 0;                // dictionary count
 char * chenc(char * st, const char * enc1, const char * enc2) {
     char * out = st;
 #ifdef HAVE_ICONV
-    if (strcmp(enc1, enc2) != 0) {
+    if (enc1 && enc2 && strcmp(enc1, enc2) != 0) {
 	size_t c1 = strlen(st) + 1;
 	size_t c2 = MAXLNLEN;
 	char * source = st;
@@ -239,6 +243,7 @@ TextParser * get_parser(int format, char * extension, Hunspell * pMS) {
 	        int n = u8_u16((w_char *) wordchars_utf16, wlen, text_conv);
 	        if (n > 0) flag_qsort(wordchars_utf16, 0, n);
 	        wordchars_utf16_len = n;
+	        wordchars_utf16_free = 1;
 	    }
 	}
     } else {
@@ -248,6 +253,7 @@ TextParser * get_parser(int format, char * extension, Hunspell * pMS) {
 	char * pletters = letters;
 	char ch[2];
 	char u8[10];
+	*pletters = '\0';
 	iconv_t conv = iconv_open("UTF-8", io_enc);
         if (conv == (iconv_t) -1) {
 	    fprintf(stderr, gettext("error - iconv_open: UTF-8 -> %s\n"), io_enc);
@@ -295,7 +301,8 @@ TextParser * get_parser(int format, char * extension, Hunspell * pMS) {
 	        fprintf(stderr, gettext("error - iconv_open: %s -> %s\n"), io_enc, denc);
 	    } else {
 	        iconv(conv, (ICONV_CONST char **) &wchars, &c1, &dest, &c2);
-	        iconv_close(conv);		
+	        iconv_close(conv);
+	        *dest = '\0';
 	    }
 	}
 	if (*letters) wordchars = mystrdup(letters);
@@ -307,7 +314,7 @@ TextParser * get_parser(int format, char * extension, Hunspell * pMS) {
     } else {
 	char * casechars = get_casechars(denc);
 	wordchars = (char *) pMS->get_wordchars();
-	if (wordchars) {
+	if (casechars && wordchars) {
 	    casechars = (char *) realloc(casechars, strlen(casechars) + strlen(wordchars) + 1);
 	    strcat(casechars, wordchars);
 	}
@@ -625,11 +632,7 @@ if (pos >= 0) {
 					    token, chenc(wlst[0], dic_enc[d], io_enc), buf);
                                 }
 			}
-			for (int j = 1; j < ns; j++) {
-		    		free(wlst[j]);
-			}
-			if (wlst) free(wlst);
-		
+			pMS[d]->free_list(&wlst, ns);
 		}
 			free(token);
 			continue;			
@@ -640,17 +643,17 @@ if (pos >= 0) {
                 int n = pMS[d]->stem(&result, token);
                 for (int i = 0; i < n; i++) {
                 	fprintf(stdout, "%s %s\n", token, result[i]);
-                	free(result[i]);
                 }
+                pMS[d]->free_list(&result, n);
                 if (n == 0 && token[strlen(token) - 1] == '.') {
                 	token[strlen(token) - 1] = '\0';
                         n = pMS[d]->stem(&result, token);
                         for (int i = 0; i < n; i++) {
                 	        fprintf(stdout, "%s %s\n", token, result[i]);
-                	        free(result[i]);
                 	}
+                        pMS[d]->free_list(&result, n);
                 }
-                if (n == 0) fprintf(stdout, "%s\n", token); else free(result);
+                if (n == 0) fprintf(stdout, "%s\n", token);
 		free(token);
 		continue;
 		}
@@ -660,17 +663,17 @@ if (pos >= 0) {
                 int n = pMS[d]->analyze(&result, token);
                 for (int i = 0; i < n; i++) {
                 	fprintf(stdout, "%s %s\n", token, result[i]);
-                	free(result[i]);
                 }
+                pMS[d]->free_list(&result, n);
                 if (n == 0 && token[strlen(token) - 1] == '.') {
                 	token[strlen(token) - 1] = '\0';
                         n = pMS[d]->analyze(&result, token);
                         for (int i = 0; i < n; i++) {
                 	        fprintf(stdout, "%s %s\n", token, result[i]);
-                	        free(result[i]);
                 	}
+                	pMS[d]->free_list(&result, n);
                 }
-                if (n == 0) fprintf(stdout, "%s\n", token); else free(result);
+                if (n == 0) fprintf(stdout, "%s\n", token);
 		free(token);
 		continue;
 		}
@@ -691,16 +694,13 @@ if (pos >= 0) {
 				fprintf(stdout,"& %s %d %d: ", token, ns,
 				    parser->get_tokenpos() + pos);
 				fprintf(stdout,"%s", chenc(wlst[0], dic_enc[d], io_enc));
-                                free(wlst[0]);
 			}
 			for (int j = 1; j < ns; j++) {
 				fprintf(stdout, ", %s", chenc(wlst[j], dic_enc[d], io_enc));
-		    		free(wlst[j]);
 			}
-
+			pMS[d]->free_list(&wlst, ns);
 			fprintf(stdout, "\n");
 			fflush(stdout);
-			if (wlst) free(wlst);
 		}
 		free(token);
 		continue;
@@ -727,16 +727,13 @@ if (pos >= 0) {
 				fprintf(stdout,"& %s %d %d: ", chenc(token, io_enc, ui_enc), ns,
 				    parser->get_tokenpos() + pos);
 				fprintf(stdout,"%s", chenc(wlst[0], dic_enc[d], ui_enc));
-                                free(wlst[0]);
 			}
 			for (int j = 1; j < ns; j++) {
 				fprintf(stdout, ", %s", chenc(wlst[j], dic_enc[d], ui_enc));
-		    		free(wlst[j]);
 			}
-
+			pMS[d]->free_list(&wlst, ns);
 			fprintf(stdout, "\n");
 			fflush(stdout);
-			if (wlst) free(wlst);
 		}
 		free(token);
 		}
@@ -768,11 +765,14 @@ if (pos >= 0) {
 
 if (parser) delete(parser);
 
+//			fprintf(stdout,gettext(HUNSPELL_PIPE_HEADING));
+//	fprintf(stdout, "szia vilag5.\n");
+//	exit(0);
+
 } // pipe_interface
 
 #ifndef WIN32
 
-#ifdef HAVE_CURSES_H
 #ifdef HAVE_READLINE
 static char * rltext;
 
@@ -797,6 +797,7 @@ static int rl_escape (int count, int key)
 }
 #endif
 
+#ifdef HAVE_CURSES_H
 int expand_tab(char * dest, char * src, int limit) {
 	int i = 0;
         int u8 = strcmp(ui_enc, "UTF-8") == 0 ? 1 : 0;
@@ -1401,8 +1402,8 @@ int main(int argc, char** argv)
 	for(int i=1; i<argc; i++) {
 #ifdef LOG
 		log(argv[i]);
-#endif
-
+#endif    
+	
 		if (argstate == 1) {
 			if (dicname) free(dicname);
 			dicname = mystrdup(argv[i]);
@@ -1508,7 +1509,7 @@ int main(int argc, char** argv)
 			}
 		}
 	}
-    
+
         if (printgood && (filter_mode == NORMAL)) filter_mode = BADWORD;
 	
 	if (! dicname) {
@@ -1641,6 +1642,7 @@ int main(int argc, char** argv)
         if (aff) free(aff);
         if (dic) free(dic);
 	if (wordchars) free(wordchars);
+	if (wordchars_utf16_free) free(wordchars_utf16);
 #ifdef HAVE_ICONV
 	free_utf_tbl();
 #endif
diff --git a/src/win_api/Hunspell.rc b/src/win_api/Hunspell.rc
index d855de8..90c10ef 100644
--- a/src/win_api/Hunspell.rc
+++ b/src/win_api/Hunspell.rc
@@ -2,8 +2,8 @@
 #include <windows.h>
 
 VS_VERSION_INFO VERSIONINFO
-FILEVERSION 1,2,2,0
-PRODUCTVERSION 1,2,2,0
+FILEVERSION 1,2,3,0
+PRODUCTVERSION 1,2,3,0
 FILEFLAGSMASK 0x17L
 FILEFLAGS 0
 FILEOS VOS_NT_WINDOWS32
@@ -21,12 +21,12 @@ BEGIN
             VALUE "Comments", "Hunspell (http://hunspell.sourceforge.net/) by L�szl� N�meth"
             VALUE "CompanyName", "http://hunspell.sourceforge.net/";
             VALUE "FileDescription", "libhunspell"
-            VALUE "FileVersion", "1.2.2"
+            VALUE "FileVersion", "1.2.3"
             VALUE "InternalName", "libhunspell"
             VALUE "LegalCopyright", "Copyright (c) 2007-2008"
             VALUE "OriginalFilename", "libhunspell.dll"
             VALUE "ProductName", "Hunspell Dynamic Link Library"
-            VALUE "ProductVersion", "1.2.2"
+            VALUE "ProductVersion", "1.2.3"
 		END
 	END
 END
diff --git a/src/win_api/README b/src/win_api/README
index 0770496..d7c8591 100644
--- a/src/win_api/README
+++ b/src/win_api/README
@@ -9,7 +9,7 @@ mingw development package (for cygwin.dll free native Windows compilation)
  
 2. open a Cygwin shell, cd into this directory and run make
 
-HUNSPELL DLL:
+HUNSPELL DLL (not updated):
 
 hunspelldll.*: Hunspell API for Windows and Delphi
 Copyright (C) 2006 - Miha Vrhovnik (http://simail.sf.net, http://xcollect.sf.net)
diff --git a/src/win_api/hunspelldll.c b/src/win_api/hunspelldll.c
index 797359b..3e3a714 100644
--- a/src/win_api/hunspelldll.c
+++ b/src/win_api/hunspelldll.c
@@ -93,6 +93,10 @@ DLLEXPORT int hunspell_add(Hunspell *pMS, char *word)
     return pMS->add(word);
 }
 
+DLLEXPORT int hunspell_add_with_affix(Hunspell *pMS, char *word, char *modelword)
+{
+    return pMS->add_with_affix(word, modelword);
+}
 
 BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                        DWORD reason        /* Reason this function is being called. */ ,
diff --git a/src/win_api/hunspelldll.h b/src/win_api/hunspelldll.h
index f67ea4f..3cde6af 100644
--- a/src/win_api/hunspelldll.h
+++ b/src/win_api/hunspelldll.h
@@ -65,7 +65,9 @@ DLLEXPORT void hunspell_suggest_free(Hunspell *pMS, char **slst, int len);
 //make local copy of returned string!!
 DLLEXPORT char * hunspell_get_dic_encoding(Hunspell *pMS);
 //add word to dict (word is valid until spell object is not destroyed)
-DLLEXPORT int hunspell_put_word(Hunspell *pMS, char *word);
+DLLEXPORT int hunspell_add(Hunspell *pMS, char *word);
+//add word to dict with affixes of the modelword (word is valid until spell object is not destroyed)
+DLLEXPORT int hunspell_add_with_affix(Hunspell *pMS, char *word, char *modelword);
 
 #ifdef __cplusplus
 }
diff --git a/tests/1975530.aff b/tests/1975530.aff
new file mode 100644
index 0000000..0912050
--- /dev/null
+++ b/tests/1975530.aff
@@ -0,0 +1,6 @@
+SET	UTF-8
+IGNORE ٌٍَُِّْـ
+
+PFX x N 1
+PFX x	أ	ت	أ[^ي]
+
diff --git a/tests/1975530.dic b/tests/1975530.dic
new file mode 100644
index 0000000..b1b455d
--- /dev/null
+++ b/tests/1975530.dic
@@ -0,0 +1,3 @@
+2
+أرى/x
+أيار/x
diff --git a/tests/1975530.good b/tests/1975530.good
new file mode 100644
index 0000000..89212a5
--- /dev/null
+++ b/tests/1975530.good
@@ -0,0 +1,3 @@
+أرى
+أيار
+ترى
diff --git a/tests/1975530.test b/tests/1975530.test
new file mode 100755
index 0000000..4d59c42
--- /dev/null
+++ b/tests/1975530.test
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR="`dirname $0`"
+NAME="`basename $0 .test`"
+$DIR/test.sh $NAME -i UTF-8
diff --git a/tests/1975530.wrong b/tests/1975530.wrong
new file mode 100644
index 0000000..24cb576
--- /dev/null
+++ b/tests/1975530.wrong
@@ -0,0 +1 @@
+تيار
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5fa971e..8d2c0e0 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -6,6 +6,8 @@ XFAIL_TESTS = @XFAILED@
 
 TESTS =	\
 affixes.test \
+condition.test \
+condition_utf.test \
 base.test \
 base_utf.test \
 allcaps.test \
@@ -87,7 +89,8 @@ i68568utf.test \
 digits_in_words.test \
 colons_in_words.test \
 ngram_utf_fix.test \
-morph.test
+morph.test \
+1975530.test
 # infixes.test
 
 distclean-local:
@@ -99,6 +102,16 @@ affixes.aff \
 affixes.dic \
 affixes.good \
 affixes.test \
+condition.aff \
+condition.dic \
+condition.good \
+condition.test \
+condition.wrong \
+condition_utf.aff \
+condition_utf.dic \
+condition_utf.good \
+condition_utf.test \
+condition_utf.wrong \
 base.aff \
 base.dic \
 base.good \
@@ -509,7 +522,12 @@ morph.aff \
 morph.dic \
 morph.good \
 morph.morph \
-morph.test
+morph.test \
+1975530.aff \
+1975530.dic \
+1975530.good \
+1975530.test \
+1975530.wrong
 # infixes.aff
 # infixes.dic
 # infixes.good
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 76180ff..6dffb23 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -195,6 +195,8 @@ SUBDIRS = suggestiontest
 XFAIL_TESTS = @XFAILED@
 TESTS = \
 affixes.test \
+condition.test \
+condition_utf.test \
 base.test \
 base_utf.test \
 allcaps.test \
@@ -276,7 +278,8 @@ i68568utf.test \
 digits_in_words.test \
 colons_in_words.test \
 ngram_utf_fix.test \
-morph.test
+morph.test \
+1975530.test
 
 EXTRA_DIST = \
 test.sh \
@@ -284,6 +287,16 @@ affixes.aff \
 affixes.dic \
 affixes.good \
 affixes.test \
+condition.aff \
+condition.dic \
+condition.good \
+condition.test \
+condition.wrong \
+condition_utf.aff \
+condition_utf.dic \
+condition_utf.good \
+condition_utf.test \
+condition_utf.wrong \
 base.aff \
 base.dic \
 base.good \
@@ -694,7 +707,12 @@ morph.aff \
 morph.dic \
 morph.good \
 morph.morph \
-morph.test
+morph.test \
+1975530.aff \
+1975530.dic \
+1975530.good \
+1975530.test \
+1975530.wrong
 
 all: all-recursive
 
diff --git a/tests/base.sug b/tests/base.sug
index 348c668..f3df3bf 100644
--- a/tests/base.sug
+++ b/tests/base.sug
@@ -2,7 +2,7 @@ looked
 text
 hello
 said, seven
-rotten day, rotten
+rotten day, rotten-day, rotten
 tomorrow
 seven
 NASA
diff --git a/tests/base_utf.sug b/tests/base_utf.sug
index b2cf92f..b218ec6 100644
--- a/tests/base_utf.sug
+++ b/tests/base_utf.sug
@@ -2,7 +2,7 @@ looked
 text
 hello
 said, seven
-rotten day, rotten
+rotten day, rotten-day, rotten
 tomorrow, rotten
 seven
 NASA
diff --git a/tests/condition.aff b/tests/condition.aff
new file mode 100644
index 0000000..57e5e0f
--- /dev/null
+++ b/tests/condition.aff
@@ -0,0 +1,37 @@
+WORDCHARS 0123456789
+
+SFX S N 16
+SFX S   0 suf1 .
+SFX S   0 suf2  o
+SFX S   0 suf3  [aeou]
+SFX S   0 suf4  [^o]
+SFX S   0 suf5  [^aeou]
+SFX S   0 suf6  fo
+SFX S   0 suf7  f[aeou]
+SFX S   0 suf8  f[^o]
+SFX S   0 suf9  f[^aeou]
+SFX S   0 suf10 [aefu]o
+SFX S   0 suf11 [^f]o
+SFX S   0 suf12 [^aefu]o
+SFX S   0 suf13 [aefu][^aefu]
+SFX S   0 suf14 [^aeou][aeou]
+SFX S   0 suf15 [aeou][^aefu]
+SFX S   0 suf16 [^aeou][^aefu]
+
+PFX P N 16
+PFX P   0 pre1 .
+PFX P   0 pre2  o
+PFX P   0 pre3  [aeou]
+PFX P   0 pre4  [^o]
+PFX P   0 pre5  [^aeou]
+PFX P   0 pre6  of
+PFX P   0 pre7  o[aefou]
+PFX P   0 pre8  o[^f]
+PFX P   0 pre9  o[^aefu]
+PFX P   0 pre10 [aefu]o
+PFX P   0 pre11 [^f]o
+PFX P   0 pre12 [^aefou]o
+PFX P   0 pre13 [aeou][aefu]
+PFX P   0 pre14 [aeou][^aeou]
+PFX P   0 pre15 [aeou][^aefu]
+PFX P   0 pre16 [^aefu][^aeou]
diff --git a/tests/condition.dic b/tests/condition.dic
new file mode 100644
index 0000000..6b09bf8
--- /dev/null
+++ b/tests/condition.dic
@@ -0,0 +1,2 @@
+1
+ofo/SP
diff --git a/tests/condition.good b/tests/condition.good
new file mode 100644
index 0000000..c82e392
--- /dev/null
+++ b/tests/condition.good
@@ -0,0 +1,18 @@
+ofo
+ofosuf1
+pre1ofo
+ofosuf2
+pre2ofo
+ofosuf3
+pre3ofo
+ofosuf6
+pre6ofo
+ofosuf7
+pre7ofo
+ofosuf10
+ofosuf13
+pre13ofo
+ofosuf14
+pre14ofo
+ofosuf16
+pre16ofo
diff --git a/tests/condition.test b/tests/condition.test
new file mode 100755
index 0000000..7f44369
--- /dev/null
+++ b/tests/condition.test
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR="`dirname $0`"
+NAME="`basename $0 .test`"
+$DIR/test.sh $NAME
diff --git a/tests/condition.wrong b/tests/condition.wrong
new file mode 100644
index 0000000..2f76202
--- /dev/null
+++ b/tests/condition.wrong
@@ -0,0 +1,15 @@
+ofosuf4
+pre4ofo
+ofosuf5
+pre5ofo
+ofosuf8
+pre8ofo
+ofosuf9
+pre9ofo
+ofosuf11
+pre10ofo
+pre11ofo
+ofosuf12
+pre12ofo
+ofosuf15
+pre15ofo
diff --git a/tests/condition_utf.aff b/tests/condition_utf.aff
new file mode 100644
index 0000000..f716dd9
--- /dev/null
+++ b/tests/condition_utf.aff
@@ -0,0 +1,38 @@
+SET UTF-8
+WORDCHARS 0123456789
+
+SFX S N 16
+SFX S   0 suf1 .
+SFX S   0 suf2  ó
+SFX S   0 suf3  [áéóú]
+SFX S   0 suf4  [^ó]
+SFX S   0 suf5  [^áéóú]
+SFX S   0 suf6  őó
+SFX S   0 suf7  ő[áéóú]
+SFX S   0 suf8  ő[^ó]
+SFX S   0 suf9  ő[^áéóú]
+SFX S   0 suf10 [áéóőú]ó
+SFX S   0 suf11 [^ő]ó
+SFX S   0 suf12 [^áéóőú]ó
+SFX S   0 suf13 [áéőú][^ú]
+SFX S   0 suf14 [^ú][áéóú]
+SFX S   0 suf15 [áéóú][^áéőú]
+SFX S   0 suf16 [^áéóú][^áéőú]
+
+PFX P N 16
+PFX P   0 pre1 .
+PFX P   0 pre2  ó
+PFX P   0 pre3  [áéóú]
+PFX P   0 pre4  [^ó]
+PFX P   0 pre5  [^áéóú]
+PFX P   0 pre6  óő
+PFX P   0 pre7  ó[áéőú]
+PFX P   0 pre8  ó[^ő]
+PFX P   0 pre9  ó[^áéóőú]
+PFX P   0 pre10 [áéóőú]ő
+PFX P   0 pre11 [^ó]ő
+PFX P   0 pre12 [^áéóőú]ő
+PFX P   0 pre13 [áéóú][áéőú]
+PFX P   0 pre14 [áéóú][^áéóú]
+PFX P   0 pre15 [áéóú][^áéőú]
+PFX P   0 pre16 [^áéőú][^áéóú]
diff --git a/tests/condition_utf.dic b/tests/condition_utf.dic
new file mode 100644
index 0000000..f03ce4e
--- /dev/null
+++ b/tests/condition_utf.dic
@@ -0,0 +1,2 @@
+1
+óőó/SP
diff --git a/tests/condition_utf.good b/tests/condition_utf.good
new file mode 100644
index 0000000..6c62037
--- /dev/null
+++ b/tests/condition_utf.good
@@ -0,0 +1,19 @@
+óőó
+óőósuf1
+pre1óőó
+óőósuf2
+pre2óőó
+óőósuf3
+pre3óőó
+óőósuf6
+pre6óőó
+óőósuf7
+pre7óőó
+óőósuf10
+pre10óőó
+óőósuf13
+pre13óőó
+óőósuf14
+pre14óőó
+óőósuf16
+pre16óőó
diff --git a/tests/condition_utf.test b/tests/condition_utf.test
new file mode 100755
index 0000000..cde7c54
--- /dev/null
+++ b/tests/condition_utf.test
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR="`dirname $0`"
+NAME="`basename $0 .test`"
+$DIR/test.sh $NAME -i utf-8
diff --git a/tests/condition_utf.wrong b/tests/condition_utf.wrong
new file mode 100644
index 0000000..4040213
--- /dev/null
+++ b/tests/condition_utf.wrong
@@ -0,0 +1,14 @@
+óőósuf4
+pre4óőó
+óőósuf5
+pre5óőó
+óőósuf8
+pre8óőó
+óőósuf9
+pre9óőó
+óőósuf11
+pre11óőó
+óőósuf12
+pre12óőó
+óőósuf15
+pre15óőó

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


Reply to: