eliot-dev
[Top][All Lists]
Advanced

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

[Eliot-dev] eliot INSTALL TODO configure.in dic/.cvsignore ...


From: eliot-dev
Subject: [Eliot-dev] eliot INSTALL TODO configure.in dic/.cvsignore ...
Date: Tue, 08 Jan 2008 13:52:45 +0000

CVSROOT:        /cvsroot/eliot
Module name:    eliot
Changes by:     Olivier Teulière <ipkiss>      08/01/08 13:52:43

Modified files:
        .              : INSTALL TODO configure.in 
        dic            : .cvsignore Makefile.am automaton.h dic.h 
                         dic_internals.h hashtable.h regexp.h 
        doc            : dic.txt 
        game           : Makefile.am ai_percent.cpp ai_percent.h 
                         ai_player.h bag.cpp bag.h board.cpp board.h 
                         board_cross.cpp board_search.cpp coord.cpp 
                         coord.h cross.cpp cross.h debug.h duplicate.cpp 
                         duplicate.h freegame.cpp freegame.h game.cpp 
                         game.h game_factory.cpp game_factory.h 
                         game_io.cpp history.cpp history.h player.cpp 
                         player.h pldrack.cpp pldrack.h rack.cpp rack.h 
                         results.cpp results.h round.cpp round.h 
                         training.cpp training.h turn.cpp turn.h 
        m4             : .cvsignore 
        po             : .cvsignore LINGUAS POTFILES.in eliot.pot fr.po 
        test           : .cvsignore driver duplicate_2_ai.input 
                         duplicate_2_ai.ref freegame_3_ai.input 
                         freegame_3_ai.ref freegame_change.input 
                         freegame_change.ref freegame_passing.input 
                         freegame_passing.ref load_saved_game.ref 
                         regexp.ref regression.pl training_back.input 
                         training_back.ref training_cross.ref 
                         training_cross2.ref training_cross3.ref 
                         training_joker2.ref training_rosace.ref 
                         training_search.ref 
        utils          : Makefile.am eliottxt.cpp game_io.cpp 
                         ncurses.cpp ncurses.h 
        wxwin          : Makefile.am auxframes.cc auxframes.h 
                         confdimdlg.cc configdb.cc confsearch.cc 
                         gfxresult.cc main.cc mainframe.cc mainframe.h 
                         printout.cc searchpanel.cc searchpanel.h 
Added files:
        dic            : automaton.cpp compdic.cpp dic.cpp 
                         dic_exception.cpp dic_exception.h 
                         dic_search.cpp encoding.cpp encoding.h erl.lpp 
                         ery.ypp hashtable.cpp hashtable.i header.cpp 
                         header.h listdic.cpp regexp.cpp regexpmain.cpp 
                         tile.cpp tile.h 
        game           : move.cpp move.h settings.cpp settings.h 
        m4             : ax_boost_base.m4 
        test           : duplicate_humans_ai.input 
                         duplicate_humans_ai.ref training_7pl1.input 
                         training_7pl1.ref training_benj.input 
                         training_benj.ref training_racc.input 
                         training_racc.ref 
Removed files:
        dic            : alist.c alist.h automaton.c compdic.c dic.c 
                         dic_search.c dic_search.h erl.l ery.y 
                         hashtable.c listdic.c regexp.c regexpmain.c 
        game           : encoding.cpp encoding.h tile.cpp tile.h 

Log message:
        Merged the "cppdic" branch back into HEAD.
        There are too many change to list properly, here is an overview of the 
main changes:
         - the dictionary is now in C++
         - the dictionary has a new format, where it is possible to specify the 
letters,
           their points, their frequency, ... It is backwards compatible.
         - Eliot now supports non-ASCII characters everywhere
         - i18n of the compdic, listdic, regexpmain binaries
         - i18n of the wxWidgets interface (now in english by default)

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/eliot/INSTALL?cvsroot=eliot&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/eliot/TODO?cvsroot=eliot&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/eliot/configure.in?cvsroot=eliot&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/.cvsignore?cvsroot=eliot&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/Makefile.am?cvsroot=eliot&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/automaton.h?cvsroot=eliot&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic.h?cvsroot=eliot&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic_internals.h?cvsroot=eliot&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/hashtable.h?cvsroot=eliot&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/regexp.h?cvsroot=eliot&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/automaton.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/compdic.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic_exception.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic_exception.h?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic_search.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/encoding.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/encoding.h?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/erl.lpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/ery.ypp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/hashtable.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/hashtable.i?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/header.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/header.h?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/listdic.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/regexp.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/regexpmain.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/tile.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/tile.h?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/alist.c?cvsroot=eliot&r1=1.5&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/alist.h?cvsroot=eliot&r1=1.4&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/automaton.c?cvsroot=eliot&r1=1.13&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/compdic.c?cvsroot=eliot&r1=1.10&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic.c?cvsroot=eliot&r1=1.12&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic_search.c?cvsroot=eliot&r1=1.21&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic_search.h?cvsroot=eliot&r1=1.12&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/erl.l?cvsroot=eliot&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/ery.y?cvsroot=eliot&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/hashtable.c?cvsroot=eliot&r1=1.5&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/listdic.c?cvsroot=eliot&r1=1.10&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/regexp.c?cvsroot=eliot&r1=1.12&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/regexpmain.c?cvsroot=eliot&r1=1.13&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/doc/dic.txt?cvsroot=eliot&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/eliot/game/Makefile.am?cvsroot=eliot&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/eliot/game/ai_percent.cpp?cvsroot=eliot&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/eliot/game/ai_percent.h?cvsroot=eliot&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/eliot/game/ai_player.h?cvsroot=eliot&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/eliot/game/bag.cpp?cvsroot=eliot&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/eliot/game/bag.h?cvsroot=eliot&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/eliot/game/board.cpp?cvsroot=eliot&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/eliot/game/board.h?cvsroot=eliot&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/eliot/game/board_cross.cpp?cvsroot=eliot&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/eliot/game/board_search.cpp?cvsroot=eliot&r1=1.14&r2=1.15
http://cvs.savannah.gnu.org/viewcvs/eliot/game/coord.cpp?cvsroot=eliot&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/eliot/game/coord.h?cvsroot=eliot&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/eliot/game/cross.cpp?cvsroot=eliot&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/eliot/game/cross.h?cvsroot=eliot&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/eliot/game/debug.h?cvsroot=eliot&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/eliot/game/duplicate.cpp?cvsroot=eliot&r1=1.16&r2=1.17
http://cvs.savannah.gnu.org/viewcvs/eliot/game/duplicate.h?cvsroot=eliot&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/eliot/game/freegame.cpp?cvsroot=eliot&r1=1.18&r2=1.19
http://cvs.savannah.gnu.org/viewcvs/eliot/game/freegame.h?cvsroot=eliot&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game.cpp?cvsroot=eliot&r1=1.33&r2=1.34
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game.h?cvsroot=eliot&r1=1.31&r2=1.32
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game_factory.cpp?cvsroot=eliot&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game_factory.h?cvsroot=eliot&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game_io.cpp?cvsroot=eliot&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/eliot/game/history.cpp?cvsroot=eliot&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/eliot/game/history.h?cvsroot=eliot&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/eliot/game/player.cpp?cvsroot=eliot&r1=1.14&r2=1.15
http://cvs.savannah.gnu.org/viewcvs/eliot/game/player.h?cvsroot=eliot&r1=1.18&r2=1.19
http://cvs.savannah.gnu.org/viewcvs/eliot/game/pldrack.cpp?cvsroot=eliot&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/eliot/game/pldrack.h?cvsroot=eliot&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/eliot/game/rack.cpp?cvsroot=eliot&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/eliot/game/rack.h?cvsroot=eliot&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/eliot/game/results.cpp?cvsroot=eliot&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/eliot/game/results.h?cvsroot=eliot&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/eliot/game/round.cpp?cvsroot=eliot&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/eliot/game/round.h?cvsroot=eliot&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/eliot/game/training.cpp?cvsroot=eliot&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/eliot/game/training.h?cvsroot=eliot&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/eliot/game/turn.cpp?cvsroot=eliot&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/eliot/game/turn.h?cvsroot=eliot&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/eliot/game/move.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/move.h?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/settings.cpp?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/settings.h?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/game/encoding.cpp?cvsroot=eliot&r1=1.3&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/game/encoding.h?cvsroot=eliot&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/game/tile.cpp?cvsroot=eliot&r1=1.7&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/game/tile.h?cvsroot=eliot&r1=1.8&r2=0
http://cvs.savannah.gnu.org/viewcvs/eliot/m4/.cvsignore?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/m4/ax_boost_base.m4?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/po/.cvsignore?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/po/LINGUAS?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/po/POTFILES.in?cvsroot=eliot&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/eliot/po/eliot.pot?cvsroot=eliot&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/eliot/po/fr.po?cvsroot=eliot&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/eliot/test/.cvsignore?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/driver?cvsroot=eliot&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/eliot/test/duplicate_2_ai.input?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/duplicate_2_ai.ref?cvsroot=eliot&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/eliot/test/freegame_3_ai.input?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/freegame_3_ai.ref?cvsroot=eliot&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/eliot/test/freegame_change.input?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/freegame_change.ref?cvsroot=eliot&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/eliot/test/freegame_passing.input?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/freegame_passing.ref?cvsroot=eliot&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/eliot/test/load_saved_game.ref?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/regexp.ref?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/regression.pl?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_back.input?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_back.ref?cvsroot=eliot&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_cross.ref?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_cross2.ref?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_cross3.ref?cvsroot=eliot&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_joker2.ref?cvsroot=eliot&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_rosace.ref?cvsroot=eliot&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_search.ref?cvsroot=eliot&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/eliot/test/duplicate_humans_ai.input?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/duplicate_humans_ai.ref?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_7pl1.input?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_7pl1.ref?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_benj.input?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_benj.ref?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_racc.input?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/test/training_racc.ref?cvsroot=eliot&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/Makefile.am?cvsroot=eliot&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/eliottxt.cpp?cvsroot=eliot&r1=1.18&r2=1.19
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/game_io.cpp?cvsroot=eliot&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/ncurses.cpp?cvsroot=eliot&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/ncurses.h?cvsroot=eliot&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/Makefile.am?cvsroot=eliot&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/auxframes.cc?cvsroot=eliot&r1=1.23&r2=1.24
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/auxframes.h?cvsroot=eliot&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/confdimdlg.cc?cvsroot=eliot&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/configdb.cc?cvsroot=eliot&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/confsearch.cc?cvsroot=eliot&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/gfxresult.cc?cvsroot=eliot&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/main.cc?cvsroot=eliot&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/mainframe.cc?cvsroot=eliot&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/mainframe.h?cvsroot=eliot&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/printout.cc?cvsroot=eliot&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/searchpanel.cc?cvsroot=eliot&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/searchpanel.h?cvsroot=eliot&r1=1.4&r2=1.5

Patches:
Index: INSTALL
===================================================================
RCS file: /cvsroot/eliot/eliot/INSTALL,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- INSTALL     4 Aug 2007 20:01:28 -0000       1.9
+++ INSTALL     8 Jan 2008 13:52:32 -0000       1.10
@@ -1,6 +1,7 @@
+
 Installation sous Linux (Un*x) (bien/facile)
 ------------------------------
-* Pour installer à partir de l'archive CVS :
+* Pour installer à partir de l'archive CVS :
 
   ./bootstrap
 
@@ -8,16 +9,16 @@
   make
   make install
 
-* Pour installer à partir de l'archive tar.gz
+* Pour installer à partir de l'archive tar.gz
 
   ./configure
   make
   make install
 
 
-il existe en fait 3 versions d'eliot, une en mode texte, une avec une
-interface curses et une avec wxwidgets. Les modes peuvent être
-sélectionnés à l'aide de la commande configure lors de la compilation
+Il existe en fait 3 versions d'eliot, une en mode texte, une avec une
+interface curses et une avec wxwidgets. Les modes peuvent être
+sélectionnés à l'aide de la commande configure lors de la compilation
 du programme.
 
 ./configure --enable-text --enable-ncurses --enable-wxwidgets
@@ -27,39 +28,56 @@
 Installation pour Windows (moins bien/facile)
 -------------------------
 
-Il y a 2 principales façons de procéder :
+Il y a 2 principales façons de procéder :
 * directement depuis Windows, en utilisant Cygwin (http://www.cygwin.com/).
 * depuis GNU/Linux, en utilisant le cross-compilateur Mingw32.
 
 
-Dans les 2 cas, les étapes sont les mêmes :
-* installation de l'environnement de compilation (cette étape n'est pas
-  décrite ici, car elle ne rentre pas dans le cadre de ce document)
+Dans les 2 cas, les étapes sont les mêmes :
+* installation de l'environnement de compilation (cette étape n'est pas
+  décrite ici, car elle ne rentre pas dans le cadre de ce document)
+
+* compilation et installation des dépendances (même remarque):
+
+    - wxWidgets (http://www.wxwidgets.org/), version 2.4.2 ou ultérieure, avec
+      support de l'unicode
 
-* compilation et installation de wxWindows (http://www.wxwidgets.org/),
-  version 2.4.2 ou ultérieure (même remarque)
+    - libiconv (http://www.gnu.org/software/libiconv/), de préférence 
compilée
+      en mode statique (--disable-shared --enable-static)
+
+    - boost (http://www.boost.org/). Eliot n'utilise pas de librairie de Boost
+      (uniquement des headers), donc il n'y a pas vraiment besoin de compiler
 
 * compilation d'Eliot :
 
-    - si vous utilisez l'archive CVS, il faut générer le script 'configure'
+    - si vous utilisez l'archive CVS, il faut générer le script 'configure'
       (aussi bien sous Cygwin que sous GNU/Linux) :
             ./bootstrap
 
+    - à cause d'un bug de gettext, il faut appliquer un patch aux fichiers 
installés
+      dans intl/ :
+            - télécharger le patch ici (lien en haut à gauche) :
+              
http://www.koders.com/noncode/fid46DF595700FEB564B6EF45BFF55067F95DCF0420.aspx
+            - exécuter la commande suivante :
+              patch -p2 < gettext-win32.patch
+
     - avec Cygwin, configurer avec la ligne de commande suivante :
+            CPPFLAGS=-I/path/to/installs/include 
LDFLAGS=-L/path/to/installs/lib \
             CC="gcc -mno-cygwin" CXX="g++ -mno-cygwin" \
-            ./configure --with-wx-config=/path/to/wx-config
-      en prenant soin d'indiquer le chemin correct vers le fichier
-      'wx-config' de l'installation de wxWindows.
+            ./configure --enable-wxwidgets --with-wx-config=/path/to/wx-config 
\
+            --with-boost=/path/to/boost/installs
+      en prenant soin de remplacer les différents chemins par les bonnes 
valeurs.
       Ensuite, un simple 'make' suffit pour terminer la compilation,
-      éventuellement suivi de 'make install'.
+      éventuellement suivi de 'make install'.
 
     - pour la cross-compilation depuis GNU/Linux, configurer avec la ligne
       de commande suivante :
+            CPPFLAGS=-I/path/to/installs/include 
LDFLAGS=-L/path/to/installs/lib \
             CC=i586-mingw32msvc-gcc CXX=i586-mingw32msvc-g++ \
             ./configure --host=i586-mingw32msvc --build=i386-linux \
-            --with-wx-config=/path/to/wx-config
-      en prenant soin d'indiquer le chemin correct vers le fichier
-      'wx-config' de l'installation de wxWindows.
+            --enable-wxwidgets --with-wx-config=/path/to/wx-config \
+            --with-boost=/path/to/installs
+      en prenant soin de remplacer les différents chemins par les bonnes 
valeurs.
       Ensuite, un simple 'make' suffit pour terminer la compilation,
-      éventuellement suivi de 'make install'.
+      éventuellement suivi de 'make install'.
 

Index: TODO
===================================================================
RCS file: /cvsroot/eliot/eliot/TODO,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- TODO        22 Jan 2006 12:23:52 -0000      1.6
+++ TODO        8 Jan 2008 13:52:32 -0000       1.7
@@ -1,33 +1,19 @@
 
-* ====================
-* TODO Current version
-* ====================
-
- - Correct game save/load functions : Advanced format
-   file saving for freegames and duplicate need a serious
-   rewrite. We need to specifie a file format that can handle
-   all the information contained in a multiplayer game.
-
- - Add "joker" type games in wxwin version of Eliot, Freegame
-   and Duplicate will follow
-
- - full French i18n interface and error messages for wxwin.
-
-
 * ==================
 * Next Eliot version
 * ==================
 
- - new dictionnary format that includes tiles
-   - number
-   - points
-   - printable equivalent
- - other languages support using the new dictionary
- - new wxWidgets interface
+ - Improve error handling (use exceptions more)
+ - Correct game save/load functions: Advanced format
+   file saving for freegames and duplicate need a serious
+   rewrite. We need to specify a file format that can handle
+   all the information contained in a multiplayer game.
+ - rack shuffling
+ - new wxWidgets or QT interface
    - support of the different modes
    - ability to choose the number and type of the players
    - ability to display the history and score of all the players
-     -- partly done : history is now a separate class
+     -- partly done: history is now a separate class
  - detection of blocked positions?
  - getopt support for all the interfaces (only ncurses is done)
 

Index: configure.in
===================================================================
RCS file: /cvsroot/eliot/eliot/configure.in,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- configure.in        4 Aug 2007 20:01:28 -0000       1.20
+++ configure.in        8 Jan 2008 13:52:33 -0000       1.21
@@ -7,6 +7,8 @@
 AC_CONFIG_SRCDIR(wxwin/main.cc)
 AM_INIT_AUTOMAKE
 AM_CONFIG_HEADER(config.h)
+AC_CANONICAL_HOST
+AC_CANONICAL_BUILD
 AM_OPTIONS_WXCONFIG
 
 dnl --------------------------------------------------------------
@@ -14,6 +16,8 @@
 dnl --------------------------------------------------------------
 AC_PROG_INSTALL
 AC_PROG_CC
+dnl Needed for gettext
+AC_GNU_SOURCE
 AC_PROG_CXX
 AC_PROG_MAKE_SET
 AC_PROG_RANLIB
@@ -23,6 +27,7 @@
     AC_MSG_ERROR([Could not find the 'bison' program on your system])
 fi
 
+dnl Better than AC_PROG_LEX
 AM_PROG_LEX
 if test "$LEX" != "flex" ; then
     AC_MSG_ERROR([Could not find the 'flex' program on your system])
@@ -56,15 +61,17 @@
 dnl Debug mode
 AC_ARG_ENABLE([debug],AC_HELP_STRING([--enable-debug],[debug mode (default 
disabled)]))
 if test "${enable_debug}" = "yes"; then
-    CFLAGS+=" -g -DDEBUG"
-    CXXFLAGS+=" -g -DDEBUG"
+    CPPFLAGS+=" -DDEBUG"
+    CFLAGS+=" -g"
+    CXXFLAGS+=" -g"
 fi
 
 dnl Profile mode
 AC_ARG_ENABLE([profile],AC_HELP_STRING([--enable-profile],[profile mode 
(default disabled)]))
 if test "${enable_profile}" = "yes"; then
-    CFLAGS+=" -pg -DPROFILE"
-    CXXFLAGS+=" -pg -DPROFILE"
+    CPPFLAGS+=" -DPROFILE"
+    CFLAGS+=" -pg"
+    CXXFLAGS+=" -pg"
     LDFLAGS+=" -pg"
 fi
 
@@ -77,6 +84,9 @@
 dnl --------------------------------------------------------------
 AC_HEADER_STDC
 AC_CHECK_HEADERS(fcntl.h unistd.h sys/wait.h)
+AC_CHECK_HEADERS(arpa/inet.h netinet/in.h)
+AC_CHECK_HEADERS([readline/readline.h], [has_readline=1], [has_readline=0])
+AM_CONDITIONAL(HAS_READLINE, test "$has_readline" = "1")
 
 dnl --------------------------------------------------------------
 dnl Checks for typedefs, structures, and compiler characteristics.
@@ -85,22 +95,26 @@
 AC_TYPE_SIZE_T
 AC_C_BIGENDIAN
 AC_C_INLINE
-AC_CHECK_SIZEOF(char, 1)
-AC_CHECK_SIZEOF(short, 2)
-AC_CHECK_SIZEOF(int *, 4)
-AC_CHECK_SIZEOF(int, 4)
-AC_CHECK_SIZEOF(long, 4)
-AC_CHECK_SIZEOF(long long, 0)
+dnl AC_CHECK_SIZEOF(char, 1)
+dnl AC_CHECK_SIZEOF(short, 2)
+dnl AC_CHECK_SIZEOF(int *, 4)
+dnl AC_CHECK_SIZEOF(int, 4)
+dnl AC_CHECK_SIZEOF(long, 4)
+dnl AC_CHECK_SIZEOF(long long, 0)
 
 dnl --------------------------------------------------------------
 dnl Checks for library functions.
 dnl --------------------------------------------------------------
 AC_FUNC_MEMCMP
+AC_CHECK_FUNCS([wcwidth])
 
 dnl --------------------------------------------------------------
 dnl Checks for libraries.
 dnl --------------------------------------------------------------
 
+dnl Check for the Boost libraries (in fact we only need the headers)
+AX_BOOST_BASE([1.33.1])
+
 dnl Check for wxWidgets
 AC_ARG_ENABLE([wxwidgets],AC_HELP_STRING([--enable-wxwidgets],[wxWidgets 
interface support (default disabled)]))
 if test "${enable_wxwidgets}" = "yes"
@@ -125,27 +139,53 @@
 AM_CONDITIONAL([BUILD_WXWIDGETS], [test "${wxWin}" = "1"])
 
 dnl Check for ncurses
-AC_ARG_ENABLE([ncurses],AC_HELP_STRING([--enable-ncurses],[ncurses interface 
support (default disabled)]))
-if test "${enable_ncurses}" = "yes"
-then
-  AC_CHECK_HEADERS(ncurses.h, want_ncurses=1,
-    [AC_MSG_ERROR([Could not find the ncurses library on your system])])
+dnl We enable it if asked by the user, or if ncursesw is found
+AC_ARG_ENABLE([ncurses],AC_HELP_STRING([--enable-ncurses],
+              [ncurses interface support (default enabled if ncursesw found on 
your system)]))
+AC_CHECK_HEADERS(ncursesw/curses.h, [has_ncursesw=1], [has_ncursesw=0])
+if test "${enable_ncurses}" != "no" -a "${has_ncursesw}" = "1"; then
+    want_ncurses=1
+else
+    want_ncurses=0
+    if test "${enable_ncurses}" = "yes"; then
+        AC_MSG_ERROR([Could not find the ncursesw library on your system])
+    fi
 fi
 AM_CONDITIONAL([BUILD_NCURSES], [test "${want_ncurses}" = "1"])
 
 dnl Enable/disable text version
 AC_ARG_ENABLE([text],AC_HELP_STRING([--enable-text],[text interface support 
(default enabled)]))
-if test "${enable_text}" != "no"
-then
-  AC_CHECK_HEADERS(readline/readline.h, want_text=1,
-    [AC_MSG_ERROR([Could not find the readline library on your system])])
-fi
 AM_CONDITIONAL([BUILD_TEXT], [test "${enable_text}" != "no"])
 
 dnl Internationalization macros
-AM_GNU_GETTEXT_VERSION(0.11.5)
+AM_GNU_GETTEXT_VERSION(0.16.1)
 AM_GNU_GETTEXT
 
+dnl Iconv
+dnl This test depends on AM_GNU_GETTEXT executed before
+AS_IF([test "$am_cv_func_iconv" != "yes"],
+      [AC_MSG_ERROR([libiconv is needed for Eliot to work properly])])
+
+
+dnl Information about who built eliot (useful for the dictionary)
+AC_DEFINE_UNQUOTED(ELIOT_COMPILE_BY, "`whoami`", [user who ran configure])
+AC_DEFINE_UNQUOTED(ELIOT_COMPILE_HOST, "`hostname`", [host which ran 
configure])
+
+dnl Check the operating system
+case "${host_os}" in
+    *mingw32* | *cygwin*)
+        SYS=mingw32
+        ;;
+    *)
+        dnl nothing to do
+        ;;
+esac
+
+if test "$SYS" = "mingw32"; then
+    # For ntohl, in particular
+    LIBS="${LIBS} -lws2_32"
+fi
+
 dnl --------------------------------------------------------------
 dnl Output
 dnl --------------------------------------------------------------

Index: dic/.cvsignore
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/.cvsignore,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- dic/.cvsignore      22 Jan 2006 12:23:53 -0000      1.2
+++ dic/.cvsignore      8 Jan 2008 13:52:33 -0000       1.3
@@ -1,10 +1,10 @@
 .deps
 Makefile
 Makefile.in
-scanner.h
-er.c
-libdic_a-er.c
-libdic_a-er.h
+libdic_a-erl.cpp
+libdic_a-erl.h
+libdic_a-ery.cpp
+libdic_a-ery.h
 compdic
 listdic
 regexp

Index: dic/Makefile.am
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Makefile.am,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- dic/Makefile.am     4 Aug 2007 19:57:46 -0000       1.15
+++ dic/Makefile.am     8 Jan 2008 13:52:33 -0000       1.16
@@ -1,6 +1,7 @@
 # Eliot
-# Copyright (C) 1999  Antoine Fraboulet
-# address@hidden
+# Copyright (C) 1999-2007  Antoine Fraboulet & Olivier Teulière
+# Authors: Antoine Fraboulet <address@hidden>
+#          Olivier Teulière <ipkiss @@ gmail.com>
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -18,47 +19,52 @@
 
 noinst_LIBRARIES = libdic.a
 
-INCLUDES = -I$(top_srcdir)
+localedir = $(datadir)/locale
+AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\"
 
-libdic_a_CFLAGS=$(DEBUGFLAGS)
-libdic_a_YFLAGS=
+INCLUDES = -I$(top_srcdir) -I../intl -I$(top_srcdir)/intl $(INCICONV)
+
+libdic_a_CFLAGS=
+libdic_a_YFLAGS=-d
 libdic_a_LFLAGS=
-libdic_a_SOURCES=                \
-       ery.y                     \
-       erl.l                     \
+libdic_a_SOURCES = \
+       erl.lpp \
+       ery.ypp \
+       dic_exception.cpp dic_exception.h \
+       header.cpp header.h \
        dic_internals.h           \
-       dic_search.c dic_search.h \
-       dic.c dic.h               \
-       automaton.c automaton.h   \
-       hashtable.h hashtable.c   \
-       regexp.c regexp.h         \
-       alist.h alist.c
+       tile.cpp tile.h \
+       dic.cpp dic.h \
+       dic_search.cpp \
+       encoding.cpp encoding.h \
+       automaton.cpp automaton.h \
+       regexp.cpp regexp.h
 
 BUILT_SOURCES=                 \
-       libdic_a-erl.c          \
+       libdic_a-erl.cpp \
        libdic_a-erl.h          \
-       libdic_a-ery.c          \
+       libdic_a-ery.cpp \
        libdic_a-ery.h
 
-nodist_libdic_a_SOURCES=       \
-       libdic_a-erl.c          \
-       libdic_a-erl.h          \
-       libdic_a-ery.c          \
-       libdic_a-ery.h
+# This hook triggers on 'make dist' (and 'make distcheck')
+# XXX: In fact, the recommended behaviour is:
+#  - list only libdic_a-ery.h in BUILT_SOURCES,
+#  - do not die with an error in configure.in if flex or bison is not found
+#  - do not have any dist-hook trigger
+# The result is that the generated files are kept in the tarball generated 
with make dist,
+# with still an error message for developers when the ypp or lpp file has been 
modified
+# and bison or flex is not found.
+# The problem is that, even though Automake is aware of the header generated 
by bison,
+# it seems to have problems with the one generated by flex...
+dist-hook:
+       -for file in $(BUILT_SOURCES) ; do rm -f $(distdir)/$$file ; done
 
 CLEANFILES=                    \
-       libdic_a-erl.c          \
+       libdic_a-erl.cpp \
        libdic_a-erl.h          \
-       libdic_a-ery.c          \
+       libdic_a-ery.cpp \
        libdic_a-ery.h
 
-
-## automake workaround to generate .h file 
-libdic_a-erl.h: erl.l
-       ${LEX} ${srcdir}/erl.l 
-
-#####################################
-
 #####################################
 if BUILD_DICTOOLS
 
@@ -67,18 +73,17 @@
        listdic                 \
        regexp
 
-compdic_SOURCES=               \
-       dic_internals.h         \
-       hashtable.c hashtble.h  \
-       compdic.c
+compdic_SOURCES=compdic.cpp \
+       hashtable.h hashtable.cpp hashtable.i
+compdic_CPPFLAGS=$(AM_CPPFLAGS) @BOOST_CPPFLAGS@
+compdic_LDADD=libdic.a @LIBINTL@
 
-listdic_SOURCES=               \
-       dic_internals.h         \
-       dic.c dic.h             \
-       listdic.c
+listdic_SOURCES=listdic.cpp
+listdic_LDADD=libdic.a @LIBINTL@
 
 #regexp_CFLAGS=-DDEBUG_RE
-regexp_SOURCES=regexpmain.c
-regexp_LDADD=libdic.a
+regexp_SOURCES=regexpmain.cpp
+regexp_LDADD=libdic.a @LIBINTL@
 
 endif
+

Index: dic/automaton.h
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/automaton.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- dic/automaton.h     1 Jan 2006 19:51:00 -0000       1.11
+++ dic/automaton.h     8 Jan 2008 13:52:33 -0000       1.12
@@ -1,21 +1,22 @@
-/* Eliot                                                                     */
-/* Copyright (C) 2005  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
 
 /**
  *  \file   automaton.h
@@ -26,51 +27,68 @@
 
 #ifndef _DIC_AUTOMATON_H_
 #define _DIC_AUTOMATON_H_
-#if defined(__cplusplus)
-extern "C"
-  {
-#endif
 
-typedef struct automaton_t       *automaton;
+class AutomatonHelper;
 
+class Automaton
+{
+public:
+    /// Constructor
     /**
-     * build a static deterministic finite automaton from
+     * Build a static deterministic finite automaton from
      * "init_state", "ptl" and "PS" given by the parser
      */
-automaton automaton_build(int init_state, int *ptl, int *PS, struct 
search_RegE_list_t *list);
+    Automaton(int init_state, int *ptl, int *PS, struct search_RegE_list_t 
*iList);
 
-    /**
-     * automaton delete function
-     */
-void      automaton_delete         (automaton a);
+    /// Destructor
+    ~Automaton();
 
     /**
-     * get the number of states in the automaton
+     * Get the number of states in the automaton.
      * @returns number of states
      */
-int       automaton_get_nstate     (automaton a);
+    int getNbStates() const { return m_nbStates; }
 
     /**
-     * query the id of the init state
+     * Query the id of the init state.
      * @returns init state id
      */
-int       automaton_get_init       (automaton a);
+    int getInitId() const { return m_init; }
 
     /**
-     * ask for the acceptor flag for the state
-     * @returns boolean flag 0 or 1
+     * Query the acceptor flag for the given state
+     * @return true/false
      */
-int       automaton_get_accept     (automaton a, int state);
+    bool accept(int state) const { return m_acceptors[state]; }
 
     /**
-     * returns the next state when the transition is taken
+     * Return the next state when the transition is taken
      * @returns next state id (1 <= id <= nstate, 0 = invalid id)
      */
-int       automaton_get_next_state (automaton a, int start, char l);
+    int getNextState(int start, char l) const
+    {
+        return m_transitions[start][(int)l];
+    }
 
-void      automaton_dump           (automaton a, char* filename);
+    /**
+     * Dump the automaton into a file (for debugging purposes)
+     */
+    void dump(const string &iFileName) const;
+
+private:
+    /// Number of states
+    int m_nbStates;
+
+    /// ID of the init state
+    int m_init;
+
+    /// Array of booleans, one for each state
+    bool *m_acceptors;
+
+    /// Matrix of transitions
+    int **m_transitions;
+
+    void finalize(const AutomatonHelper &a);
+};
 
-#if defined(__cplusplus)
-  }
-#endif
 #endif /* _DIC_AUTOMATON_H_ */

Index: dic/dic.h
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/dic.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- dic/dic.h   16 Apr 2006 11:27:19 -0000      1.13
+++ dic/dic.h   8 Jan 2008 13:52:34 -0000       1.14
@@ -1,119 +1,153 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2002-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
 
 /**
  *  \file   dic.h
  *  \brief  Dawg dictionary
- *  \author Antoine Fraboulet
+ *  \author Antoine Fraboulet & Olivier Teuliere
  *  \date   2002
  */
 
 #ifndef _DIC_H_
 #define _DIC_H_
-#if defined(__cplusplus)
-extern "C"
-  {
-#endif
 
-/**
- * different letters in the dictionary
- */
-#define DIC_LETTERS  27
+#include <string>
+#include <vector>
+#include <map>
+
+#include "tile.h"
+
+using namespace std;
+
 
 /**
  * max length of words (including last \0)
  */
 #define DIC_WORD_MAX 16
 
-typedef struct _Dict_header  Dict_header;
-typedef struct _Dictionary  *Dictionary;
+class Header;
 typedef unsigned int dic_elt_t;
 typedef unsigned char dic_code_t;
-
-
+struct params_cross_t;
+struct params_7plus1_t;
+struct params_regexp_t;
+struct search_RegE_list_t;
+
+class Dictionary
+{
+public:
     /**
-     * Dictionary header loading from a file
-     * @param dic : pointer to a header
-     * @param path : compressed dictionary path
-     * @return 0 ok, otherwise error
+     * Dictionary creation and loading from a file
+     * @param path: compressed dictionary path
      */
-int    Dic_check_header(Dict_header *header, const char* path);
+    Dictionary(const string &path);
+
+    /// Destructor
+    ~Dictionary();
 
     /**
-     * Dictionary creation and loading from a file
-     * @param dic : pointer to a dictionary
-     * @param path : compressed dictionary path
-     * @return 0 ok, 1 error
+     * Return the current instance of the dictionary object
+     * XXX: This is ugly, but I don't see any clean way apart from carrying
+     * a reference to a Dictionary object in many places...
+     * Other more or less ugly options:
+     *  - Make the dictionary a singleton (2 dictionaries cannot coexist...)
+     *  - Make many classes inherit from a common base class with a dictionary
+     *    member (possibly bad for performances)
+     * A new created dictionary replaces the previous instance, even if the
+     * previous instance is not destroyed yet
+     * If no dictionary object is instanciated when this method is called,
+     * it will probably crash...
      */
-int    Dic_load   (Dictionary* dic,const char* path);
+    static const Dictionary& GetDic() { return *m_dic; }
+
+    /** Give access to the dictionary header */
+    const Header& getHeader() const { return *m_header; }
 
     /**
-     * Destroy a dictionary
+     * Check whether all the given letters are present in the dictionary,
+     * or are one of the other accepted letters.
+     * Return true if this is the case, false otherwise
      */
-int    Dic_destroy(Dictionary dic);
+    bool validateLetters(const wstring &iLetters,
+                         const wstring &iAccepted = L"") const;
+
+    /** Return a vector containing one of each possible tile */
+    const vector<Tile>& getAllTiles() const { return m_tilesVect; }
+
+    /** Return the number of different tiles (including the joker) */
+    unsigned int getTileNumber() const { return m_tilesVect.size(); }
+
+    /** Return a tile from its code */
+    const Tile &getTileFromCode(unsigned int iCode) const { return 
m_tilesVect[iCode - 1]; }
 
     /**
-     * Dic_chr returns the character code associated with an element,
+     * Returns the character code associated with an element,
      * codes may range from 0 to 31. 0 is the null character.
      * @returns code for the encoded character
      */
-dic_code_t Dic_chr (Dictionary dic, dic_elt_t elt);
+    const dic_code_t getCode(const dic_elt_t &elt) const;
+
+    /**
+     * Returns the wide character associated with an element.
+     * @returns wide character for the element
+     */
+    wchar_t getChar(const dic_elt_t &elt) const;
 
     /**
      * Returns a boolean to show if there is another available
      * character in the current depth (a neighbor in the tree)
      * @returns 0 or 1 (true)
      */
-int    Dic_last(Dictionary dic, dic_elt_t elt);
+    bool isLast(const dic_elt_t &elt) const;
 
     /**
      * Returns a boolean to show if we are at the end of a word
-     * (see Dic_next)
+     * (see getNext)
      * @returns 0 or 1 (true)
      */
-int    Dic_word(Dictionary dic, dic_elt_t elt);
+    bool isEndOfWord(const dic_elt_t &elt) const;
 
     /**
      * Returns the root of the dictionary
      * @returns root element
      */
-dic_elt_t Dic_root(Dictionary dic);
+    const dic_elt_t getRoot() const;
 
     /**
-     * Returns the next available neighbor (see Dic_last)
+     * Returns the next available neighbor (see getLast)
      * @returns next dictionary element at the same depth
      */
-dic_elt_t Dic_next(Dictionary dic, dic_elt_t elt);
+    const dic_elt_t getNext(const dic_elt_t &elt) const;
 
     /**
      * Returns the first element available at the next depth
      * in the dictionary
-     * @params dic : dictionary
      * @params elt : current dictionary element
      * @returns next element (successor)
      */
-dic_elt_t Dic_succ(Dictionary dic, dic_elt_t elt);
+    const dic_elt_t getSucc(const dic_elt_t &elt) const;
 
     /**
      * Find the dictionary element matching the pattern starting
      * from the given root node by walking the dictionary tree
-     * @params dic : valid dictionary
      * @params root : starting dictionary node for the search
      * @params pattern : string encoded according to the dictionary codes,
      * the pattern must be null ('\0') terminated
@@ -121,19 +155,11 @@
      * element that results from walking the dictionary according to the
      * pattern
      */
-unsigned int Dic_lookup(Dictionary dic, dic_elt_t root, dic_code_t* pattern);
-
-    /**
-     * Dic_char returns the character associated with an element
-     * (in the range ['A'-'Z']), or the null character ('\0').
-     * @returns ASCII code for the character
-     */
-char   Dic_char (Dictionary dic, dic_elt_t elt);
+    unsigned int lookup(const dic_elt_t &root, const dic_code_t *pattern) 
const;
 
     /**
      * Find the dictionary element matching the pattern starting
      * from the given root node by walking the dictionary tree
-     * @params dic : valid dictionary
      * @params root : starting dictionary node for the search
      * @params pattern : string made of uppercase characters in the range
      * ['A'-'Z']. The pattern must be null ('\0') terminated
@@ -141,11 +167,136 @@
      * element that results from walking the dictionary according to the
      * pattern
      */
-unsigned int Dic_char_lookup(Dictionary dic, dic_elt_t root, char* pattern);
+    unsigned int charLookup(const dic_elt_t &iRoot, const wchar_t *iPattern) 
const;
+
+    /// Getter for the edge at the given position
+    const uint32_t *getEdgeAt(const dic_elt_t &iElt) const { return m_dawg + 
iElt; }
+
+    /**
+     * Search for a word in the dictionary
+     * @param iWord: lookup word
+     * @return true if the word is valid, false otherwise
+     */
+    bool searchWord(const wstring &iWord) const;
+
+    /**
+     * Search for benjamins
+     * @param iWord: letters
+     * @param oWordList: results
+     */
+    void searchBenj(const wstring &iWord, list<wstring> &oWordList) const;
+
+    /**
+     * Search for all words feasible by adding a letter in front or at the end
+     * @param iWord: word
+     * @param oWordList: results
+     */
+    void searchRacc(const wstring &iWord, list<wstring> &oWordList) const;
+
+    /**
+     * Search for crosswords
+     * @param iMask: letters
+     * @param oWordList: results
+     */
+    void searchCross(const wstring &iMask, list<wstring> &oWordList) const;
+
+    /**
+     * Search for all feasible word with "rack" plus one letter
+     * @param iRack: letters
+     * @param oWordlist: results
+     * @param joker: true if the search must be performed when a joker is in 
the rack
+     */
+    void search7pl1(const wstring &iRack,
+                    map<wchar_t, list<wstring> > &oWordList,
+                    bool joker) const;
+
+    /**
+     * Search for words matching a regular expression
+     * @param iRegexp: regular expression
+     * @param oWordList: results
+     * @param iList: parameters for the search (?)
+     */
+    void searchRegExp(const wstring &iRegexp,
+                      list<wstring> &oWordList,
+                      struct search_RegE_list_t *iList) const;
+
+
+
+private:
+    // Prevent from copying the dictionary!
+    Dictionary &operator=(const Dictionary&);
+    Dictionary(const Dictionary&);
+
+    Header *m_header;
+    uint32_t *m_dawg;
+
+    /** Letters of the dictionary, both in uppercase and lowercase */
+    wstring m_allLetters;
+
+    /// Vector of available tiles
+    vector<Tile> m_tilesVect;
 
-#if defined(__cplusplus)
+    static const Dictionary *m_dic;
+
+    void convertDataToArch();
+    void initializeTiles();
+
+    /// Template getter for the edge at the given position
+    template <typename DAWG_EDGE>
+    const DAWG_EDGE * getEdgeAt(const dic_elt_t &iElt) const
+    {
+        return reinterpret_cast<const DAWG_EDGE*>(m_dawg + iElt);
   }
-#endif
+
+    /**
+     * Walk the dictionary until the end of the word
+     * @param s: current pointer to letters
+     * @param eptr: current edge in the dawg
+     */
+    template <typename DAWG_EDGE>
+    const DAWG_EDGE * seekEdgePtr(const wchar_t *s, const DAWG_EDGE *eptr) 
const;
+
+    /// Helper for searchBenj()
+    template <typename DAWG_EDGE>
+    void searchBenjTempl(const wstring &iWord, list<wstring> &oWordList) const;
+
+    /// Helper for searchRacc()
+    template <typename DAWG_EDGE>
+    void searchRaccTempl(const wstring &iWord, list<wstring> &oWordList) const;
+
+    /// Helper for searchCross()
+    template <typename DAWG_EDGE>
+    void searchCrossRecTempl(struct params_cross_t *params,
+                             list<wstring> &oWordList,
+                             const DAWG_EDGE *edgeptr) const;
+
+    /// Helper for search7pl1()
+    template <typename DAWG_EDGE>
+    void search7pl1Templ(const wstring &iRack,
+                         map<wchar_t, list<wstring> > &oWordList,
+                         bool joker) const;
+
+    /// Second helper for search7pl1()
+    template <typename DAWG_EDGE>
+    void searchWordByLen(struct params_7plus1_t *params,
+                         int i, const DAWG_EDGE *edgeptr) const;
+
+    /**
+     * Internal version of searchRegExp, needed until
+     * wide chars are supported by our regexp engine.
+     */
+    void searchRegExpInner(const string &iRegexp,
+                           list<string> &oWordList,
+                           struct search_RegE_list_t *iList) const;
+
+    /// Helper for searchRegExp()
+    template <typename DAWG_EDGE>
+    void searchRegexpRecTempl(struct params_regexp_t *params,
+                              int state,
+                              const DAWG_EDGE *edgeptr,
+                              list<string> &oWordList) const;
+};
+
 #endif /* _DIC_H_ */
 
 /// Local Variables:

Index: dic/dic_internals.h
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/dic_internals.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- dic/dic_internals.h 4 Aug 2007 20:01:28 -0000       1.8
+++ dic/dic_internals.h 8 Jan 2008 13:52:34 -0000       1.9
@@ -1,21 +1,22 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2002-2007 Antoine Fraboulet
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
 
 /**
  *  \file   dic_internals.h
@@ -26,27 +27,11 @@
 
 #ifndef _DIC_INTERNALS_H_
 #define _DIC_INTERNALS_H_
-#if defined(__cplusplus)
-extern "C"
-  {
-#endif
 
 #include <stdint.h>
 #include "config.h"
 
 /**
- * bit masking for ascii characters \n
- * ('a' & CHAR) == ('A' & CHAR) == 1
- */
-#define DIC_CHAR_MASK    0x1F
-
-/**
- * keyword included in dictionary headers
- * implies little endian storage on words
- */
-#define _COMPIL_KEYWORD_ "_COMPILED_DICTIONARY_"
-
-/**
  *  structure of a compressed dictionary \n
  *  \n
  *  ----------------    \n
@@ -60,53 +45,36 @@
  *  ----------------
  */
 
-#if defined(WORDS_BIGENDIAN)
-struct __attribute__ ((packed)) _Dawg_edge {
-  uint32_t
-    chr  :  5,
-    fill :  1,
-    last :  1,
-    term :  1,
-    ptr  : 24;
-};
-#else
-struct __attribute__ ((packed)) _Dawg_edge {
+struct __attribute__ ((packed)) DicEdgeOld
+{
+    public:
   uint32_t
     ptr  : 24,
-    term :  1,
-    last :  1,
-    fill :  1,
+        term:  1,
+        last:  1,
+        fill:  1,
     chr  :  5;
-};
-#endif
-
-typedef struct _Dawg_edge Dawg_edge;
-
-
-struct _Dict_header {
-  char ident[sizeof(_COMPIL_KEYWORD_)];
-  char unused_1;
-  char unused_2;
-  int32_t root;
-  int32_t nwords;
-  uint32_t edgesused;
-  uint32_t nodesused;
-  uint32_t nodessaved;
-  uint32_t edgessaved;
+      bool operator==(const DicEdgeOld &iOther) const
+      {
+          return memcmp(this, &iOther, sizeof(*this)) == 0;
+      }
 };
 
 
-struct _Dictionary
+struct __attribute__ ((packed)) DicEdge
 {
-  Dawg_edge *dawg;
-  unsigned int root;
-  int nwords;
-  int nnodes;
-  int nedges;
+    public:
+      uint32_t
+        ptr : 24,
+        term:  1,
+        last:  1,
+        chr :  6;
+      bool operator==(const DicEdge &iOther) const
+      {
+          return memcmp(this, &iOther, sizeof(*this)) == 0;
+      }
 };
 
-#if defined(__cplusplus)
-  }
-#endif
+
 #endif /* _DIC_INTERNALS_H */
 

Index: dic/hashtable.h
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/hashtable.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- dic/hashtable.h     1 Jan 2006 19:51:00 -0000       1.6
+++ dic/hashtable.h     8 Jan 2008 13:52:35 -0000       1.7
@@ -1,21 +1,23 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
 
 /**
  *  \file   hashtable.h
@@ -26,21 +28,55 @@
 
 #ifndef _HASHTABLE_H
 #define _HASHTABLE_H
-#if defined(__cplusplus)
-extern "C"
+
+
+/// Compute a hash for the data pointed to by iPtr
+/**
+ * This function is useful to define the HASH_FCN template parameter
+ * of HashTable.
+ */
+unsigned int HashPtr(const void *iPtr, unsigned int iSize);
+
+
+template<typename KEY, typename VALUE, typename HASH_FCN>
+class HashTable
+{
+    public:
+        /// Constructor taking the number of records in the table
+        HashTable(unsigned int iSize);
+
+        /// Destructor
+        ~HashTable();
+
+        /// Return the number of records in the table
+        unsigned int size() const { return m_size; }
+
+        /// Return the value corresponding to the given key, or NULL if not 
found
+        const VALUE *find(const KEY &iKey) const;
+
+        /// Add a new key/value pair (both the key and the value are copied)
+        void add(const KEY& iKey, const VALUE &iValue);
+
+    private:
+        /// Maximum number of records
+        unsigned int m_size;
+
+        /// Definition of a record
+        class Node
   {
-#endif
+            public:
+                Node(const KEY &iKey, const VALUE &iValue, const Node *iNext);
+                ~Node();
+                KEY m_key;
+                VALUE m_value;
+                const Node *m_next;
+        };
+
+        /// All the nodes
+        const Node **m_nodes;
+};
 
-typedef struct _Hash_table* Hash_table;
+// Include the implementation of the template
+#include "hashtable.i"
 
-Hash_table hash_init(unsigned int);
-int        hash_destroy(Hash_table);
-int        hash_size(Hash_table);
-void*      hash_find(Hash_table,void* key,unsigned keysize);
-int        hash_add (Hash_table,void* key,unsigned keysize,
-                    void* value,unsigned valuesize);
-
-#if defined(__cplusplus)
-  }
-#endif
 #endif /* _HASHTABLE_H_ */

Index: dic/regexp.h
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/regexp.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- dic/regexp.h        1 Jan 2006 19:51:00 -0000       1.12
+++ dic/regexp.h        8 Jan 2008 13:52:36 -0000       1.13
@@ -1,21 +1,22 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 1999-2006 Antoine Fraboulet
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
 
 /**
  *  \file   regexp.h
@@ -24,12 +25,8 @@
  *  \date   2005
  */
 
-#ifndef _TREE_H_
-#define _TREE_H_
-#if defined(__cplusplus)
-extern "C"
-  {
-#endif
+#ifndef _REGEXP_H_
+#define _REGEXP_H_
 
 #define NODE_TOP    0
 #define NODE_VAR    1
@@ -38,12 +35,14 @@
 #define NODE_STAR   4
 #define NODE_PLUS   5
 
-typedef struct node {
+
+typedef struct node
+{
   int              type;
   char             var;
   struct node      *fg;
   struct node      *fd;
-  int numero;
+    int number;
   int position;
   int annulable;
   int PP;
@@ -51,6 +50,11 @@
 } NODE;
 
     /**
+     * different letters in the dictionary
+     */
+#define DIC_LETTERS  27
+
+    /**
      * maximum number of accepted terminals in regular expressions
      */
 #define REGEXP_MAX 32
@@ -139,7 +143,7 @@
   char msg[MAX_REGEXP_ERROR_LENGTH];
 };
 
-#include <stdio.h>
+#include <cstdio>
 
 void  regexp_print_letter(FILE* f, char l);
 void  regexp_print_letter2(FILE* f, char l);
@@ -147,10 +151,7 @@
 void  regexp_print_ptl(int ptl[]);
 void  regexp_print_tree(NODE* n, char* name, int detail);
 
-#if defined(__cplusplus)
-  }
-#endif
-#endif /* _TREE_H_ */
+#endif /* _REGEXP_H_ */
 
 /// Local Variables:
 /// mode: c++

Index: doc/dic.txt
===================================================================
RCS file: /cvsroot/eliot/eliot/doc/dic.txt,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- doc/dic.txt 19 Apr 2005 16:25:06 -0000      1.2
+++ doc/dic.txt 8 Jan 2008 13:52:36 -0000       1.3
@@ -29,36 +29,51 @@
     ptr  : index in the array of the first child
     term : is it the last letter of a word (*)
     last : is it the last child of its local root (!)
-    fill : currently unused.
     chr  : guess what !
 
  There is no pointer from a cell to its brother, it is simply the
  next cell in the array (you know you are on the last brother when
  the flag "last" is set).
 
- The way it is stored in a file is  different thing! The tree is
+ The way it is stored in a file is a different thing! The tree is
  stored bottom-up. The sink (offset 0) is the first cell of
  the array.
 
- Using compdict (which you can found in the eliot/dic directory),
+ Using compdic (which you can find in the eliot/dic directory),
  the compiled dictionary will look like this:
 
-compdict's console output:
-============================
-keyword length 21 bytes
-keyword size   22 bytes
-header size    48 bytes
-
-3 words
-
-root :       9 (edge)
-root :      36 (byte)
-
-nodes : 7+1
-edges : 9+1
-============================
+compdic console output (cut in the middle):
+===================================================================
+dictionary name: ODS 4.0
+compressed on: mer 12 déc 2007 07:29:50 GMT
+compressed using a binary compiled by: address@hidden
+dictionary type: DAWG
+letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ?
+number of letters: 27
+number of words: 369085
+header size: 360 bytes
+root: 100950 (edge)
+nodes: 40377 used + 418387 saved
+edges: 100950 used + 601922 saved
+===============================================
+letter | points | frequency | vowel | consonant
+-------+--------+-----------+-------+----------
+   A   |    1   |     9     |   1   |    0
+   B   |    3   |     2     |   0   |    1
+   C   |    3   |     2     |   0   |    1
+   D   |    2   |     3     |   0   |    1
+[... output cut here ...]
+   X   |   10   |     1     |   0   |    1
+   Y   |   10   |     1     |   1   |    1
+   Z   |   10   |     1     |   0   |    1
+   ?   |    0   |     2     |   1   |    1
+===============================================
+ Load time: 0,060 s
+ Compression time: 0,170 s
+ Maximum recursion level reached: 16
+===================================================================
 
-binary view of the dictionary:
+binary view of the dictionary (FIXME: not up to date):
 ===================================================================
           0001 0203 0405 0607 0809 0a0b 0c0d 0e0f
 00000000: 5f43 4f4d 5049 4c45 445f 4449 4354 494f  _COMPILED_DICTIO
@@ -69,27 +84,85 @@
 00000050: 0600 002a 0700 0000                      ...*....
 ===================================================================
 
-The header structure is the following:
-
+The header is made of 2 structures (for backwards compatibility
+with older headers) like this:
+===================================================================
 #define _COMPIL_KEYWORD_ "_COMPILED_DICTIONARY_"
 
-typedef struct _Dict_header {              // offset
+struct Dict_header_old                     // offset
+{
   char ident[sizeof(_COMPIL_KEYWORD_)];    // 0x00
-  char unused_1;                           // 0x16
-  char unused_2;                           // 0x17
-  int root;                                // 0x18
-  int nwords;                              // 0x1c
-  unsigned int edgesused;                  // 0x20
-  unsigned int nodesused;                  // 0x24
-  unsigned int nodessaved;                 // 0x2c
-  unsigned int edgessaved;                 // 0x30
-} Dict_header;
+  uint8_t version;                         // 0x16
+  char unused;                             // 0x17
+  uint32_t root;                           // 0x18
+  uint32_t nwords;                         // 0x1c
+  uint32_t edgesused;                      // 0x20
+  uint32_t nodesused;                      // 0x24
+  uint32_t nodessaved;                     // 0x28
+  uint32_t edgessaved;                     // 0x2c
+};
+
+#define _MAX_USER_HOST_ 32
+#define _MAX_DIC_NAME_SIZE_ 30
+#define _MAX_LETTERS_NB_ 63
+#define _MAX_LETTERS_SIZE_ 80
+
+struct Dict_header
+{
+    uint64_t compressDate;
+    // Build information
+    char userHost[_MAX_USER_HOST_];
+    // Size taken by the build information
+    uint32_t userHostSize;
+
+    // Compression algorithm (1 = DAWG, 2 = GADDAG)
+    uint8_t algorithm;
+    // Variant used in the rules (XXX: currently unused)
+    uint8_t variant;
+
+    // Dictionary official name and version (e.g.: ODS 5.0)
+    char dicName[_MAX_DIC_NAME_SIZE_];
+    // Size taken by the dictionary name
+    uint32_t dicNameSize;
+
+    // Letters used in the dictionary
+    // We should have: nbLetters <= lettersSize <= _MAX_LETTERS_SIZE_
+    // and:            nbLetters <= _MAX_LETTERS_NB_
+    // The letters themselves, in UTF-8
+    char letters[_MAX_LETTERS_SIZE_];
+    // Size taken by the letters
+    uint32_t lettersSize;
+    // Number of letters (XXX: in theory useless, but allows a sanity check)
+    uint32_t nbLetters;
+
+    // Points of the letters (indexed by their code)
+    // The "+ 1" is there for struct alignment
+    uint8_t points[_MAX_LETTERS_NB_ + 1];
+    // Frequency of the letters (indexedy their code)
+    // The "+ 1" is there for struct alignment
+    uint8_t frequency[_MAX_LETTERS_NB_ + 1];
+    // Bitfield indicating whether letters are vowels
+    uint64_t vowels;
+    // Bitfield indicating whether letters are consonants
+    uint64_t consonants;
+}
+===================================================================
 
-binary output of the header:
+In the old version of the dictionary, only the first structure was used
+(with version = 0). The current format (version = 1) has the 2 structs
+next to each other.
+The dictionary name, the letters, and the user/host information are
+stored in UTF-8. All the numbers are big endian (i.e. the output of
+the htonl() function).
+To avoid alignment issues, the extended header has been designed to
+have multiples of 64 bits regularly.
+
+
+binary output of the header (FIXME: not up to date):
 ===================================================================
 0x00 ident       : _COMPILED_DICTIONARY_
-0x16 unused 1    :      0 00000000
-0x17 unused 2    :      0 00000000
+0x16 version     :      0 00000001
+0x17 unused      :      0 00000000
 0x18 root        :      9 00000009
 0x1c words       :      3 00000003
 0x20 edges used  :      9 00000009
@@ -98,40 +171,37 @@
 0x2c edges saved :      1 00000001
 ===================================================================
 
-The real array of data begins at offset 0x34. Integer are stored in a
-machine dependent way. This dictionary was compiled on a i386 and is
-not readable on a machine with a different endianess (unless swapping
-all necessary information).  The array is stored 'as is' right after 
-the header. Each array cell is a bit-structure on 4 bytes :
+The real array of data begins at offset 0x168. The array is stored
+'as is' right after the header. Each array cell is a bit-structure
+on 4 bytes:
 
-typedef struct _Dawg_edge { 
+struct DicEdge
+{
    unsigned int ptr  : 24; 
    unsigned int term : 1;  
    unsigned int last : 1;  
-   unsigned int fill : 1;  // reserved (currently unused)
-   unsigned int chr  : 5;  
-} Dawg_edge;    
-
-Characters are not stored in ASCII. The order is preserved but
-we changed the values: A=1, B=2, ... This is very easy to do 
-with the ASCII table as ('A' & 0x1f) == ('a' & 0x1f) == 1.
-This may not work on machines that are not using ASCII. The dictionary
-can thus handle up to 32 different letters but not more.
+   unsigned int chr  : 6;
+};
+
+Characters are not stored in ASCII. The order of the letters given
+to the compdic binary is preserved, but we changed the values: the
+first letter is 1, the second one is 2, etc...
+The dictionary can thus handle up to 64 different letters but not more.
+The letter 0 is special (used for the sink node in particular), so
+in practice there are only 63 distinct letters.
 
 offs binary       structure         
 ---- -------- |   ------------------
-0x00 02000000 | 0 ptr= 0 t=0 l=1 f=0 chr=0 (`)
-0x04 1b000000 | 1 ptr= 0 t=1 l=1 f=0 chr=3 (c)
-0x08 0b000000 | 2 ptr= 0 t=1 l=1 f=0 chr=1 (a)
-0x0c 10000001 | 3 ptr= 1 t=0 l=0 f=0 chr=2 (b)
-0x10 22000002 | 4 ptr= 2 t=0 l=1 f=0 chr=4 (d)
-0x14 0a000002 | 5 ptr= 2 t=0 l=1 f=0 chr=1 (a)
-0x18 22000005 | 6 ptr= 5 t=0 l=1 f=0 chr=4 (d)
-0x1c 08000003 | 7 ptr= 3 t=0 l=0 f=0 chr=1 (a)
-0x20 2a000006 | 8 ptr= 6 t=0 l=1 f=0 chr=5 (e)
-0x24 00000007 | 9 ptr= 7 t=0 l=0 f=0 chr=0 (`)
+0x00 02000000 | 0 ptr= 0 t=0 l=1 chr=0 (`)
+0x04 1b000000 | 1 ptr= 0 t=1 l=1 chr=3 (c)
+0x08 0b000000 | 2 ptr= 0 t=1 l=1 chr=1 (a)
+0x0c 10000001 | 3 ptr= 1 t=0 l=0 chr=2 (b)
+0x10 22000002 | 4 ptr= 2 t=0 l=1 chr=4 (d)
+0x14 0a000002 | 5 ptr= 2 t=0 l=1 chr=1 (a)
+0x18 22000005 | 6 ptr= 5 t=0 l=1 chr=4 (d)
+0x1c 08000003 | 7 ptr= 3 t=0 l=0 chr=1 (a)
+0x20 2a000006 | 8 ptr= 6 t=0 l=1 chr=5 (e)
+0x24 00000007 | 9 ptr= 7 t=0 l=0 chr=0 (`)
 
 Strictly speaking, there is no node in the graph, only labelled edges. 
 
-
-

Index: game/Makefile.am
===================================================================
RCS file: /cvsroot/eliot/eliot/game/Makefile.am,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- game/Makefile.am    22 Jan 2006 12:23:53 -0000      1.13
+++ game/Makefile.am    8 Jan 2008 13:52:36 -0000       1.14
@@ -1,6 +1,7 @@
 # Eliot
-# Copyright (C) 1999  Antoine Fraboulet
-# address@hidden
+# Copyright (C) 1999-2007  Antoine Fraboulet & Olivier Teulière
+# Authors: Antoine Fraboulet <address@hidden>
+#          Olivier Teulière <ipkiss @@ gmail.com>
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -23,7 +24,6 @@
 libgame_a_SOURCES=           \
        ai_percent.cpp ai_percent.h     \
        ai_player.h                     \
-       tile.cpp tile.h                 \
        bag.cpp bag.h                   \
        coord.cpp coord.h               \
        cross.cpp cross.h               \
@@ -31,17 +31,19 @@
        board_cross.cpp                 \
        board_search.cpp                \
        duplicate.cpp duplicate.h       \
-       encoding.cpp encoding.h         \
        freegame.cpp freegame.h         \
        game.cpp game.h                 \
        game_factory.cpp game_factory.h \
        game_io.cpp                     \
+       move.cpp move.h                 \
        player.cpp player.h             \
        pldrack.cpp pldrack.h           \
        rack.cpp rack.h                 \
        results.cpp results.h           \
        round.cpp round.h               \
+       settings.cpp settings.h         \
        training.cpp training.h         \
        turn.cpp turn.h                 \
-       history.cpp history.h
+       history.cpp history.h           \
+       debug.h
 

Index: game/ai_percent.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/ai_percent.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- game/ai_percent.cpp 1 Jan 2006 19:49:35 -0000       1.5
+++ game/ai_percent.cpp 8 Jan 2008 13:52:37 -0000       1.6
@@ -1,6 +1,7 @@
 /*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,6 +22,7 @@
 #include "rack.h"
 #include "pldrack.h"
 #include "round.h"
+#include "move.h"
 #include "results.h"
 #include "board.h"
 #include "ai_percent.h"
@@ -37,32 +39,46 @@
 }
 
 
-void AIPercent::compute(const Dictionary &iDic, Board &iBoard, int turn)
+void AIPercent::compute(const Dictionary &iDic, Board &iBoard, bool iFirstWord)
 {
     m_results.clear();
 
     Rack rack;
     getCurrentRack().getRack(rack);
-    m_results.search(iDic, iBoard, rack, turn);
+    m_results.search(iDic, iBoard, rack, iFirstWord);
 }
 
 
-bool AIPercent::changesLetters() const
+Move AIPercent::getMove() const
 {
-    return (m_results.size() == 0);
-}
-
-
-const Round & AIPercent::getChosenRound() const
-{
-    int index = (int)(m_percent * (m_results.size() - 1));
-    return m_results.get(index);
-}
-
-
-vector<Tile> AIPercent::getChangedLetters() const
-{
-    return vector<Tile>();
+    if (m_results.size() == 0)
+    {
+        // If there is no result, simply pass the turn
+        // XXX: it is forbidden in duplicate mode, but well, what else to do?
+        return Move(L"");
+    }
+    else
+    {
+        // If there are results, apply the algorithm
+        double wantedScore = m_percent * m_results.get(0).getPoints();
+        // Look for the first round giving at least 'wantedScore' points
+        // Browse the results 10 by 10 (a dichotomy would be better, but this
+        // is not performance critical)
+        unsigned int index = 0;
+        while (index < m_results.size() &&
+               m_results.get(index).getPoints() > wantedScore)
+        {
+            index += 10;
+        }
+        // Now the wanted round is in the last 10 indices
+        if (index >= m_results.size())
+            index = m_results.size() - 1;
+        while (m_results.get(index).getPoints() < wantedScore)
+        {
+            --index;
+        }
+        return Move(m_results.get(index));
+    }
 }
 
 /// Local Variables:

Index: game/ai_percent.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/ai_percent.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- game/ai_percent.h   1 Jan 2006 19:49:35 -0000       1.6
+++ game/ai_percent.h   8 Jan 2008 13:52:37 -0000       1.7
@@ -1,6 +1,7 @@
 /*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,10 +28,10 @@
  * This kind of AI is parameterized by a percentage p.
  * The computation consists in finding all the N possible rounds for the
  * current rack/board, and sorting the list.
- * The chosen round is the n'th element of the sorted list, such that n/N
- * is closest to the percentage p.
- * A percentage of 0 should always return the best round (i.e. the one with
- * the highest score), while a percentage of 1 should return the worst one.
+ * The chosen round is the one with the smallest score at least equal to
+ * p * best_score.
+ * A percentage of 1 should always return the best round (i.e. the one with
+ * the highest score), while a percentage of 0 should return the worst one.
  * This kind of AI will never change letters (unless it cannot play anything,
  * in which case it just passes without changing letters).
  */
@@ -45,17 +46,15 @@
      * This method does the actual computation. It will be called before any
      * of the following methods, so it must prepare everything for them.
      */
-    virtual void compute(const Dictionary &iDic, Board &iBoard, int turn);
-    /// Return true when the AI wants to change letters instead of playing a 
word
-    virtual bool changesLetters() const;
-    /// Return the round played by the AI (if changesLetters() returns false)
-    virtual const Round & getChosenRound() const;
-    /// Get the letters to change (if changesLetters() returns true)
-    virtual vector<Tile> getChangedLetters() const;
+    virtual void compute(const Dictionary &iDic, Board &iBoard, bool 
iFirstWord);
+
+    /// Return the move played by the AI
+    virtual Move getMove() const;
 
 private:
     /// Percentage used for this player
     float m_percent;
+
     /// Container for all the found solutions
     Results m_results;
 };

Index: game/ai_player.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/ai_player.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- game/ai_player.h    1 Jan 2006 19:49:35 -0000       1.7
+++ game/ai_player.h    8 Jan 2008 13:52:37 -0000       1.8
@@ -1,6 +1,7 @@
 /*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,10 +23,10 @@
 
 #include "player.h"
 
+class Dictionary;
 class Round;
 class Board;
 class Tile;
-typedef struct _Dictionary * Dictionary;
 
 /**
  * This class is a pure interface, that must be implemented by all the AI
@@ -69,22 +70,14 @@
      * This method does the actual computation. It will be called before any
      * of the following methods, so it must prepare everything for them.
      */
-    virtual void compute(const Dictionary &iDic, Board &iBoard, int turn) = 0;
-    /**
-     * Return true when the AI wants to change letters instead of playing a
-     * word.
-     * Should return false in duplicate mode, as it is not allowed to change
-     * letters.
-     */
-    virtual bool changesLetters() const = 0;
-    /// Return the round played by the AI (if changesLetters() returns false)
-    virtual const Round & getChosenRound() const = 0;
-    /// Get the letters to change (if changesLetters() returns true)
-    virtual vector<Tile> getChangedLetters() const = 0;
+    virtual void compute(const Dictionary &iDic, Board &iBoard, bool 
iFirstWord) = 0;
+
+    /// Return the move played by the AI
+    virtual Move getMove() const = 0;
 
 protected:
     /// This class is a pure interface, forbid any direct instanciation
-    AIPlayer(int iId): Player(iId) {}
+    AIPlayer(unsigned int iId): Player(iId) {}
 };
 
 #endif

Index: game/bag.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/bag.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- game/bag.cpp        23 Dec 2006 13:50:43 -0000      1.8
+++ game/bag.cpp        8 Jan 2008 13:52:37 -0000       1.9
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,22 +21,18 @@
 
 #include <string>
 
-#include "tile.h"
+#include <dic.h>
 #include "bag.h"
 #include "debug.h"
+#include "encoding.h"
 
 
-Bag::Bag()
-{
-    init();
-}
-
-
-void Bag::init()
+Bag::Bag(const Dictionary &iDic)
+    : m_dic(iDic)
 {
     m_ntiles = 0;
-    const list<Tile>& allTiles = Tile::getAllTiles();
-    list<Tile>::const_iterator it;
+    const vector<Tile>& allTiles = m_dic.getAllTiles();
+    vector<Tile>::const_iterator it;
     for (it = allTiles.begin(); it != allTiles.end(); it++)
     {
         m_tilesMap[*it] = it->maxNumber();
@@ -53,7 +50,7 @@
 }
 
 
-unsigned int Bag::nVowels() const
+unsigned int Bag::getNbVowels() const
 {
     map<Tile, int>::const_iterator it;
     int v = 0;
@@ -67,7 +64,7 @@
 }
 
 
-unsigned int Bag::nConsonants() const
+unsigned int Bag::getNbConsonants() const
 {
     map<Tile, int>::const_iterator it;
     int c = 0;
@@ -84,7 +81,7 @@
 void Bag::takeTile(const Tile &iTile)
 {
     ASSERT(in(iTile),
-           (wstring(L"The bag does not contain the letter ") + 
iTile.toChar()).c_str());
+           "The bag does not contain the letter " + 
convertToMb(iTile.toChar()));
 
     m_tilesMap[iTile]--;
     m_ntiles--;
@@ -94,28 +91,71 @@
 void Bag::replaceTile(const Tile &iTile)
 {
     ASSERT(in(iTile) < iTile.maxNumber(),
-           (wstring(L"Cannot replace tile: ") + iTile.toChar()).c_str());
+           "Cannot replace tile: " + convertToMb(iTile.toChar()));
 
     m_tilesMap[iTile]++;
     m_ntiles++;
 }
 
 
-Tile Bag::selectRandom()
+Tile Bag::selectRandom() const
 {
-    map<Tile, int>::const_iterator it;
-    int n;
     double max = m_ntiles;
+    ASSERT(max > 0, "The bag is empty");
+
+    int n = (int)(max * rand() / (RAND_MAX + 1.0));
+
+    map<Tile, int>::const_iterator it;
+    for (it = m_tilesMap.begin(); it != m_tilesMap.end(); it++)
+    {
+        if (n < it->second)
+            return it->first;
+        n -= it->second;
+    }
+    ASSERT(false, "We should not come here");
+    return Tile();
+}
 
-    n = (int)(max * rand() / (RAND_MAX + 1.0));
+
+Tile Bag::selectRandomVowel() const
+{
+    double max = getNbVowels();
+    ASSERT(max > 0, "Not enough vowels in the bag");
+
+    int n = (int)(max * rand() / (RAND_MAX + 1.0));
+
+    map<Tile, int>::const_iterator it;
+    for (it = m_tilesMap.begin(); it != m_tilesMap.end(); it++)
+    {
+        if (!it->first.isVowel())
+            continue;
+        if (n < it->second)
+            return it->first;
+        n -= it->second;
+    }
+    ASSERT(false, "We should not come here");
+    return Tile();
+}
+
+
+Tile Bag::selectRandomConsonant() const
+{
+    double max = getNbConsonants();
+    ASSERT(max > 0, "Not enough consonants in the bag");
+
+    int n = (int)(max * rand() / (RAND_MAX + 1.0));
+
+    map<Tile, int>::const_iterator it;
     for (it = m_tilesMap.begin(); it != m_tilesMap.end(); it++)
     {
+        if (!it->first.isConsonant())
+            continue;
         if (n < it->second)
             return it->first;
         n -= it->second;
     }
     ASSERT(false, "We should not come here");
-    return Tile::dummy();
+    return Tile();
 }
 
 

Index: game/bag.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/bag.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- game/bag.h  23 Dec 2006 16:48:15 -0000      1.9
+++ game/bag.h  8 Jan 2008 13:52:37 -0000       1.10
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,11 +22,13 @@
 #ifndef _BAG_H_
 #define _BAG_H_
 
-#include "tile.h"
 #include <map>
+#include "tile.h"
 
 using std::map;
 
+class Dictionary;
+
 
 /**
  * A bag stores the set of free tiles for the game.
@@ -33,9 +36,7 @@
 class Bag
 {
 public:
-    Bag();
-    virtual ~Bag() {}
-    void init();
+    explicit Bag(const Dictionary &iDic);
 
     /// Take a tile in the bag
     void takeTile(const Tile &iTile);
@@ -47,18 +48,30 @@
 
     /**
      * Return how many tiles/vowels/consonants are available
-     * Warning: b.nVowels() + b.nConsonants() != b.nTiles(),
+     * Warning: b.getNbVowels() + b.getNbConsonants() != b.getNbTiles(),
      * because of the jokers and the 'Y'.
      */
-    unsigned int nTiles() const  { return m_ntiles; }
-    unsigned int nVowels() const;
-    unsigned int nConsonants() const;
+    unsigned int getNbTiles() const  { return m_ntiles; }
+    unsigned int getNbVowels() const;
+    unsigned int getNbConsonants() const;
 
     /**
      * Return a random available tile
      * The tile is not taken out of the bag.
      */
-    Tile selectRandom();
+    Tile selectRandom() const;
+
+    /**
+     * Return a random available vowel.
+     * The tile is not taken out of the bag.
+     */
+    Tile selectRandomVowel() const;
+
+    /**
+     * Return a random available consonant.
+     * The tile is not taken out of the bag.
+     */
+    Tile selectRandomConsonant() const;
 
     void operator=(const Bag &iOther);
 
@@ -66,8 +79,12 @@
     void dumpAll() const;
 
 private:
+    /// Dictionary
+    const Dictionary &m_dic;
+
     /// Associate to each tile its number of occurrences in the bag
     map<Tile, int> m_tilesMap;
+
     /// Total number of tiles in the bag
     int m_ntiles;
 };

Index: game/board.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/board.cpp,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- game/board.cpp      4 Aug 2007 20:01:28 -0000       1.17
+++ game/board.cpp      8 Jan 2008 13:52:37 -0000       1.18
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -82,8 +83,8 @@
 
 
 Board::Board():
-    m_tilesRow(BOARD_REALDIM, Tile::dummy()),
-    m_tilesCol(BOARD_REALDIM, Tile::dummy()),
+    m_tilesRow(BOARD_REALDIM, Tile()),
+    m_tilesCol(BOARD_REALDIM, Tile()),
     m_jokerRow(BOARD_REALDIM, false),
     m_jokerCol(BOARD_REALDIM, false),
     m_crossRow(BOARD_REALDIM, Cross()),
@@ -154,13 +155,12 @@
 void Board::addRound(const Dictionary &iDic, const Round &iRound)
 {
     Tile t;
-    int row, col;
 
-    row = iRound.getCoord().getRow();
-    col = iRound.getCoord().getCol();
+    int row = iRound.getCoord().getRow();
+    int col = iRound.getCoord().getCol();
     if (iRound.getCoord().getDir() == Coord::HORIZONTAL)
     {
-        for (int i = 0; i < iRound.getWordLen(); i++)
+        for (unsigned int i = 0; i < iRound.getWordLen(); i++)
         {
             if (m_tilesRow[row][col + i].isEmpty())
             {
@@ -174,7 +174,7 @@
     }
     else
     {
-        for (int i = 0; i < iRound.getWordLen(); i++)
+        for (unsigned int i = 0; i < iRound.getWordLen(); i++)
         {
             if (m_tilesRow[row + i][col].isEmpty())
             {
@@ -195,20 +195,18 @@
 
 void Board::removeRound(const Dictionary &iDic, const Round &iRound)
 {
-    int row, col;
-
-    row = iRound.getCoord().getRow();
-    col = iRound.getCoord().getCol();
+    int row = iRound.getCoord().getRow();
+    int col = iRound.getCoord().getCol();
     if (iRound.getCoord().getDir() == Coord::HORIZONTAL)
     {
-        for (int i = 0; i < iRound.getWordLen(); i++)
+        for (unsigned int i = 0; i < iRound.getWordLen(); i++)
         {
             if (iRound.isPlayedFromRack(i))
             {
-                m_tilesRow[row][col + i] = Tile::dummy();
+                m_tilesRow[row][col + i] = Tile();
                 m_jokerRow[row][col + i] = false;
                 m_crossRow[row][col + i].setAny();
-                m_tilesCol[col + i][row] = Tile::dummy();
+                m_tilesCol[col + i][row] = Tile();
                 m_jokerCol[col + i][row] = false;
                 m_crossCol[col + i][row].setAny();
             }
@@ -216,14 +214,14 @@
     }
     else
     {
-        for (int i = 0; i < iRound.getWordLen(); i++)
+        for (unsigned int i = 0; i < iRound.getWordLen(); i++)
         {
             if (iRound.isPlayedFromRack(i))
             {
-                m_tilesRow[row + i][col] = Tile::dummy();
+                m_tilesRow[row + i][col] = Tile();
                 m_jokerRow[row + i][col] = false;
                 m_crossRow[row + i][col].setAny();
-                m_tilesCol[col][row + i] = Tile::dummy();
+                m_tilesCol[col][row + i] = Tile();
                 m_jokerCol[col][row + i] = false;
                 m_crossCol[col][row + i].setAny();
             }
@@ -246,17 +244,15 @@
                          bool firstturn)
 {
     Tile t;
-    int row, col, i;
-    int l, p, fromrack;
-    int pts, ptscross, wordmul;
+    int l, p;
     bool isolated = true;
 
-    fromrack = 0;
-    pts = 0;
-    ptscross = 0;
-    wordmul = 1;
-    row = iRound.getCoord().getRow();
-    col = iRound.getCoord().getCol();
+    unsigned int fromrack = 0;
+    int pts = 0;
+    int ptscross = 0;
+    int wordmul = 1;
+    int row = iRound.getCoord().getRow();
+    int col = iRound.getCoord().getCol();
 
     /* Is the word an extension of another word? */
     if (!iTilesMx[row][col - 1].isEmpty() ||
@@ -265,7 +261,7 @@
         return 1;
     }
 
-    for (i = 0; i < iRound.getWordLen(); i++)
+    for (unsigned int i = 0; i < iRound.getWordLen(); i++)
     {
         t = iRound.getTile(i);
         if (!iTilesMx[row][col + i].isEmpty())
@@ -383,13 +379,12 @@
 void Board::testRound(const Round &iRound)
 {
     Tile t;
-    int row, col;
 
-    row = iRound.getCoord().getRow();
-    col = iRound.getCoord().getCol();
+    int row = iRound.getCoord().getRow();
+    int col = iRound.getCoord().getCol();
     if (iRound.getCoord().getDir() == Coord::HORIZONTAL)
     {
-        for (int i = 0; i < iRound.getWordLen(); i++)
+        for (unsigned int i = 0; i < iRound.getWordLen(); i++)
         {
             if (m_tilesRow[row][col + i].isEmpty())
             {
@@ -405,7 +400,7 @@
     }
     else
     {
-        for (int i = 0; i < iRound.getWordLen(); i++)
+        for (unsigned int i = 0; i < iRound.getWordLen(); i++)
         {
             if (m_tilesRow[row + i][col].isEmpty())
             {
@@ -430,11 +425,11 @@
         {
             if (m_testsRow[row][col])
             {
-                m_tilesRow[row][col] = Tile::dummy();
+                m_tilesRow[row][col] = Tile();
                 m_testsRow[row][col] = 0;
                 m_jokerRow[row][col] = false;
 
-                m_tilesCol[col][row] = Tile::dummy();
+                m_tilesCol[col][row] = Tile();
                 m_jokerCol[col][row] = false;
             }
         }

Index: game/board.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/board.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- game/board.h        5 Nov 2006 13:30:06 -0000       1.13
+++ game/board.h        8 Jan 2008 13:52:37 -0000       1.14
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,12 +22,13 @@
 #ifndef _BOARD_H_
 #define _BOARD_H_
 
-#include "tile.h"
-#include "cross.h"
 #include <string>
 #include <vector>
 
-typedef struct _Dictionary*Dictionary;
+#include "tile.h"
+#include "cross.h"
+
+class Dictionary;
 class Rack;
 class Round;
 class Results;
@@ -61,7 +63,6 @@
 {
 public:
     Board();
-    virtual ~Board() {}
 
     /*************************
      * Coordinates have to be BOARD_MIN <= int <= BOARD_MAX

Index: game/board_cross.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/board_cross.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- game/board_cross.cpp        23 Dec 2006 13:50:43 -0000      1.8
+++ game/board_cross.cpp        8 Jan 2008 13:52:37 -0000       1.9
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,11 +26,14 @@
  *  \date   2005
  */
 
+#include <wctype.h>
+
 #include <dic.h>
 #include "tile.h"
 #include "board.h"
 #include "debug.h"
 
+
 static void Board_checkout_tile(const Dictionary &iDic,
                                 vector<Tile>& iTiles,
                                 vector<bool> & iJoker,
@@ -37,7 +41,7 @@
                                 int& oPoints,
                                 int index)
 {
-    int i,left;
+    int i, left;
     unsigned int node, succ;
 
     oPoints = 0;
@@ -52,36 +56,36 @@
     }
 
     // FIXME: create temporary strings until the dictionary uses Tile objects
-    char leftTiles [BOARD_DIM + 1];
-    char rightTiles[BOARD_DIM + 1];
+    wchar_t leftTiles [BOARD_DIM + 1];
+    wchar_t rightTiles[BOARD_DIM + 1];
 
     for (i = left; i < index; i++)
-        leftTiles[i - left] = toupper(iTiles[i].toChar());
+        leftTiles[i - left] = towupper(iTiles[i].toChar());
     leftTiles[index - left] = 0;
 
     for (i = index + 1; !iTiles[i].isEmpty(); i++)
-        rightTiles[i - index - 1] = toupper(iTiles[i].toChar());
+        rightTiles[i - index - 1] = towupper(iTiles[i].toChar());
     rightTiles[i - index - 1] = 0;
 
     /* Tiles that can be played */
-    node = Dic_char_lookup(iDic, Dic_root(iDic), leftTiles);
+    node = iDic.charLookup(iDic.getRoot(), leftTiles);
     if (node == 0)
     {
         oCross.setNone();
         return;
     }
 
-    for (succ = Dic_succ(iDic, node); succ; succ = Dic_next(iDic, succ))
+    for (succ = iDic.getSucc(node); succ; succ = iDic.getNext(succ))
     {
-        if (Dic_word(iDic, Dic_char_lookup(iDic, succ, rightTiles)))
-            oCross.insert(Tile(Dic_char(iDic, succ)));
-        if (Dic_last(iDic, succ))
+        if (iDic.isEndOfWord(iDic.charLookup(succ, rightTiles)))
+            oCross.insert(Tile(iDic.getChar(succ)));
+        if (iDic.isLast(succ))
             break;
     }
 
     /* Points on the right part */
-    /* yes, it is REALLY [index+1] */
-    while (!iTiles[index+1].isEmpty())
+    /* yes, it is REALLY [index + 1] */
+    while (!iTiles[index + 1].isEmpty())
     {
         index++;
         if (!iJoker[index])

Index: game/board_search.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/board_search.cpp,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- game/board_search.cpp       4 Aug 2007 20:01:28 -0000       1.14
+++ game/board_search.cpp       8 Jan 2008 13:52:37 -0000       1.15
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -38,21 +39,17 @@
                                 Matrix<bool> &iJokerMx,
                                 Results &iResults, Round &iWord)
 {
-    int i, pts, ptscross;
-    int l, t, fromrack;
-    int len, row, col, wordmul;
+    unsigned int fromrack = 0;
+    int pts      = 0;
+    int ptscross = 0;
+    int wordmul  = 1;
 
-    fromrack = 0;
-    pts      = 0;
-    ptscross = 0;
-    wordmul  = 1;
+    unsigned int len = iWord.getWordLen();
 
-    len = iWord.getWordLen();
+    int row = iWord.getCoord().getRow();
+    int col = iWord.getCoord().getCol();
 
-    row = iWord.getCoord().getRow();
-    col = iWord.getCoord().getCol();
-
-    for (i = 0; i < len; i++)
+    for (unsigned int i = 0; i < len; i++)
     {
         if (!iTilesMx[row][col+i].isEmpty())
         {
@@ -61,6 +58,7 @@
         }
         else
         {
+            int l;
             if (!iWord.isJoker(i))
                 l = iWord.getTile(i).getPoints() *
                     iBoard.getLetterMultiplier(row, col + i);
@@ -69,7 +67,7 @@
             pts += l;
             wordmul *= iBoard.getWordMultiplier(row, col + i);
 
-            t = iPointsMx[row][col+i];
+            int t = iPointsMx[row][col+i];
             if (t >= 0)
                 ptscross += (t + l) * iBoard.getWordMultiplier(row, col + i);
             fromrack++;
@@ -109,33 +107,40 @@
 
     if (iTilesMx[iRow][iCol].isEmpty())
     {
-        if (Dic_word(iDic, iNode) && iCol > iAnchor)
+        if (iDic.isEndOfWord(iNode) && iCol > iAnchor)
+        {
             BoardSearchEvalMove(iBoard, iTilesMx, iPointsMx, iJokerMx,
                                 iResults, ioPartialWord);
+        }
 
-        for (succ = Dic_succ(iDic, iNode); succ; succ = Dic_next(iDic, succ))
+        // Optimization: avoid entering the for loop if no tile can match
+        if (iCrossMx[iRow][iCol].isNone())
+            return;
+
+        bool hasJokerInRack = iRack.in(Tile::Joker());
+        for (succ = iDic.getSucc(iNode); succ; succ = iDic.getNext(succ))
         {
-            l = Tile(Dic_char(iDic, succ));
+            l = Tile(iDic.getChar(succ));
             if (iCrossMx[iRow][iCol].check(l))
             {
                 if (iRack.in(l))
                 {
                     iRack.remove(l);
-                    ioPartialWord.addRightFromRack(l, 0);
+                    ioPartialWord.addRightFromRack(l, false);
                     ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
                                 iJokerMx, iRack, ioPartialWord, iResults,
                                 succ, iRow, iCol + 1, iAnchor);
-                    ioPartialWord.removeRightToRack(l, 0);
+                    ioPartialWord.removeRightToRack(l, false);
                     iRack.add(l);
                 }
-                if (iRack.in(Tile::Joker()))
+                if (hasJokerInRack)
                 {
                     iRack.remove(Tile::Joker());
-                    ioPartialWord.addRightFromRack(l, 1);
+                    ioPartialWord.addRightFromRack(l, true);
                     ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
                                 iJokerMx, iRack, ioPartialWord, iResults,
                                 succ, iRow, iCol + 1, iAnchor);
-                    ioPartialWord.removeRightToRack(l, 1);
+                    ioPartialWord.removeRightToRack(l, true);
                     iRack.add(Tile::Joker());
                 }
             }
@@ -144,15 +149,19 @@
     else
     {
         l = iTilesMx[iRow][iCol];
-        for (succ = Dic_succ(iDic, iNode); succ ; succ = Dic_next(iDic, succ))
+        wint_t upperChar = towupper(l.toChar());
+        for (succ = iDic.getSucc(iNode); succ ; succ = iDic.getNext(succ))
         {
-            if (Dic_char(iDic, succ) == toupper(l.toChar()))
+            if ((wint_t)iDic.getChar(succ) == upperChar)
             {
                 ioPartialWord.addRightFromBoard(l);
                 ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
                             iJokerMx, iRack, ioPartialWord,
                             iResults, succ, iRow, iCol + 1, iAnchor);
                 ioPartialWord.removeRightToBoard(l);
+                // The letter will be present only once in the dictionary,
+                // so we can stop looping
+                break;
             }
         }
     }
@@ -177,31 +186,32 @@
 
     if (iLimit > 0)
     {
-        for (succ = Dic_succ(iDic, n); succ; succ = Dic_next(iDic, succ))
+        bool hasJokerInRack = iRack.in(Tile::Joker());
+        for (succ = iDic.getSucc(n); succ; succ = iDic.getNext(succ))
         {
-            l = Tile(Dic_char(iDic, succ));
+            l = Tile(iDic.getChar(succ));
             if (iRack.in(l))
             {
                 iRack.remove(l);
-                ioPartialWord.addRightFromRack(l, 0);
+                ioPartialWord.addRightFromRack(l, false);
                 
ioPartialWord.accessCoord().setCol(ioPartialWord.getCoord().getCol() - 1);
                 LeftPart(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
                          iJokerMx, iRack, ioPartialWord, iResults,
                          succ, iRow, iAnchor, iLimit - 1);
                 
ioPartialWord.accessCoord().setCol(ioPartialWord.getCoord().getCol() + 1);
-                ioPartialWord.removeRightToRack(l, 0);
+                ioPartialWord.removeRightToRack(l, false);
                 iRack.add(l);
             }
-            if (iRack.in(Tile::Joker()))
+            if (hasJokerInRack)
             {
                 iRack.remove(Tile::Joker());
-                ioPartialWord.addRightFromRack(l, 1);
+                ioPartialWord.addRightFromRack(l, true);
                 
ioPartialWord.accessCoord().setCol(ioPartialWord.getCoord().getCol() - 1);
                 LeftPart(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
                          iJokerMx, iRack, ioPartialWord, iResults,
                          succ, iRow, iAnchor, iLimit - 1);
                 
ioPartialWord.accessCoord().setCol(ioPartialWord.getCoord().getCol() + 1);
-                ioPartialWord.removeRightToRack(l, 1);
+                ioPartialWord.removeRightToRack(l, true);
                 iRack.add(Tile::Joker());
             }
         }
@@ -221,10 +231,10 @@
     int row, col, lastanchor;
     Round partialword;
 
-    list<Tile> rackTiles;
+    vector<Tile> rackTiles;
     iRack.getTiles(rackTiles);
-    list<Tile>::const_iterator it;
-    bool match;
+    vector<Tile>::const_iterator it;
+    vector<Tile>::const_iterator itEnd;
 
     for (row = 1; row <= BOARD_DIM; row++)
     {
@@ -261,13 +271,13 @@
                 // Optimization compared to the original Appel & Jacobson
                 // algorithm: skip Leftpart if none of the tiles of the rack
                 // matches the cross mask for the current anchor
-                match = false;
-                for (it = rackTiles.begin();
-                     !match && it != rackTiles.end(); it++)
+                bool match = false;
+                for (it = rackTiles.begin(); it != rackTiles.end(); it++)
                 {
                     if (iCrossMx[row][col].check(*it))
                     {
                         match = true;
+                        break;
                     }
                 }
                 if (match)
@@ -277,14 +287,14 @@
                         partialword.accessCoord().setCol(lastanchor + 1);
                         ExtendRight(iBoard, iDic, iTilesMx, iCrossMx, 
iPointsMx,
                                     iJokerMx, iRack, partialword, iResults,
-                                    Dic_root(iDic), row, lastanchor + 1, col);
+                                    iDic.getRoot(), row, lastanchor + 1, col);
                     }
                     else
                     {
                         partialword.accessCoord().setCol(col);
                         LeftPart(iBoard, iDic, iTilesMx, iCrossMx, iPointsMx,
                                  iJokerMx, iRack, partialword, iResults,
-                                 Dic_root(iDic), row, col, col -
+                                 iDic.getRoot(), row, col, col -
                                  lastanchor - 1);
                     }
                 }
@@ -328,8 +338,8 @@
     partialword.accessCoord().setDir(Coord::HORIZONTAL);
     LeftPart(*this, iDic, m_tilesRow, m_crossRow,
              m_pointRow, m_jokerRow,
-             copyRack, partialword, oResults, Dic_root(iDic), row, col,
-             copyRack.nTiles() - 1);
+             copyRack, partialword, oResults, iDic.getRoot(), row, col,
+             copyRack.getNbTiles() - 1);
 }
 
 /// Local Variables:

Index: game/coord.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/coord.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- game/coord.cpp      22 Jan 2006 12:23:53 -0000      1.9
+++ game/coord.cpp      8 Jan 2008 13:52:37 -0000       1.10
@@ -1,21 +1,23 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
 
 /**
  *  \file   coord.cpp

Index: game/coord.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/coord.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- game/coord.h        22 Jan 2006 12:23:53 -0000      1.7
+++ game/coord.h        8 Jan 2008 13:52:37 -0000       1.8
@@ -1,21 +1,23 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
 
 /**
  *  \file   coord.h
@@ -27,19 +29,24 @@
 #ifndef _COORD_H
 #define _COORD_H
 
-using std::string;
+#include <string>
+
 using std::wstring;
 
+
+/**
+ * This class handles coordinates of a square on the board.
+ * The row and column start at 1.
+ */
 class Coord
 {
 public:
 
     enum Direction {VERTICAL, HORIZONTAL};
 
-    // Construction, destruction
+    // Construction
     Coord(int iRow = -1, int iCol = -1, Direction iDir = HORIZONTAL);
     Coord(const wstring &iStr);
-    virtual ~Coord() {}
 
     // Accessors
     void setRow(int iRow)       { m_row = iRow; }

Index: game/cross.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/cross.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- game/cross.cpp      5 Nov 2006 13:30:06 -0000       1.7
+++ game/cross.cpp      8 Jan 2008 13:52:37 -0000       1.8
@@ -1,6 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière & Antoine Fraboulet
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *          Antoine Fraboulet <antoine.fraboulet @@ free.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,26 +24,25 @@
 
 #define CROSS_MASK 0xFFFFFFFF
 
+
 Cross::Cross()
 {
     // The default behaviour is to match everything
     setAny();
 }
 
+
 void Cross::setAny()                   
 { 
     m_mask = CROSS_MASK;
 }
 
+
 bool Cross::isAny() const
 { 
     return m_mask == CROSS_MASK; 
 }
 
-void Cross::setNone()
-{
-    m_mask = 0;
-}
 
 string Cross::getHexContent() const
 {
@@ -51,22 +52,21 @@
     return s;
 }
 
+
 bool Cross::check(const Tile& iTile) const
 {
     return (iTile.isJoker() && m_mask != 0) || (m_mask & (1 << 
iTile.toCode()));
 }
 
+
 void Cross::insert(const Tile& iTile)
 { 
     m_mask |= (1 << iTile.toCode());
 }
 
+
 bool Cross::operator==(const Cross &iOther) const
 {
-    /* 
-     *  if (isAny() || iOther.isAny())
-     *    return isAny() && iOther.isAny();
-     */
     return m_mask == iOther.m_mask;
 }
 

Index: game/cross.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/cross.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- game/cross.h        5 Nov 2006 13:30:06 -0000       1.8
+++ game/cross.h        8 Jan 2008 13:52:37 -0000       1.9
@@ -1,6 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière & Antoine Fraboulet
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *          Antoine Fraboulet <antoine.fraboulet @@ free.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,13 +36,12 @@
 {
 public:
     Cross();
-    virtual ~Cross() {}
 
     void setAny();     
-    void setNone();
+    void setNone() { m_mask = 0; }
 
     bool isAny() const;
-    bool isNone() const;
+    bool isNone() const { return m_mask == 0; }
 
     bool check(const Tile& iTile) const;
 

Index: game/debug.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/debug.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- game/debug.h        1 Jan 2006 19:49:35 -0000       1.11
+++ game/debug.h        8 Jan 2008 13:52:37 -0000       1.12
@@ -1,6 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
+ * Eliot
+ * Copyright (C) 2004-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,8 +19,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *****************************************************************************/
 
-#ifndef _CONST_H_
-#define _CONST_H_
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
 
 /**********
  * General

Index: game/duplicate.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/duplicate.cpp,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- game/duplicate.cpp  22 Jan 2006 12:23:53 -0000      1.16
+++ game/duplicate.cpp  8 Jan 2008 13:52:37 -0000       1.17
@@ -1,6 +1,7 @@
 /*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,78 +18,74 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *****************************************************************************/
 
+#include "duplicate.h"
 #include "dic.h"
 #include "tile.h"
 #include "rack.h"
 #include "round.h"
+#include "move.h"
 #include "pldrack.h"
 #include "results.h"
 #include "player.h"
 #include "ai_player.h"
-#include "duplicate.h"
+#include "settings.h"
 #include "debug.h"
 
 
-Duplicate::Duplicate(const Dictionary &iDic): Game(iDic)
-{
-}
-
-
-Duplicate::~Duplicate()
+Duplicate::Duplicate(const Dictionary &iDic)
+    : Game(iDic)
 {
 }
 
 
-int Duplicate::setRackRandom(int p, bool iCheck, set_rack_mode mode)
-{
-    int res;
-    do
-    {
-        res = helperSetRackRandom(p, iCheck, mode);
-    } while (res == 2);
-    return res;
-}
-
-
 int Duplicate::play(const wstring &iCoord, const wstring &iWord)
 {
-    /* Perform all the validity checks, and fill a round */
+    // Perform all the validity checks, and try to fill a round
     Round round;
     int res = checkPlayedWord(iCoord, iWord, round);
-    if (res != 0)
+    if (res != 0 && Settings::Instance().getBool("duplicate-reject-invalid"))
     {
         return res;
     }
 
-    /* Everything is OK, we can play the word */
-    playRound(round, m_currPlayer);
+    // If we reach this point, either the move is valid and we can use the
+    // "round" variable, or it is invalid but played nevertheless
+    if (res == 0)
+    {
+        // Everything is OK, we can play the word
+        playMove(Move(round), m_currPlayer);
+    }
+    else
+    {
+        // Record the invalid move of the player
+        playMove(Move(iWord, iCoord), m_currPlayer);
+    }
 
-    /* Next turn */
-    // XXX: Should it be done by the interface instead?
-    endTurn();
+    // Little hack to handle duplicate games with only AI players.
+    // This will have no effect when there is at least one human player
+    tryEndTurn();
 
     return 0;
 }
 
 
-void Duplicate::duplicateAI(int n)
+void Duplicate::playAI(unsigned int p)
 {
-    ASSERT(0 <= n && n < getNPlayers(), "Wrong player number");
-    ASSERT(!m_players[n]->isHuman(), "AI requested for a human player");
+    ASSERT(p < getNPlayers(), "Wrong player number");
 
-    AIPlayer *player = static_cast<AIPlayer*>(m_players[n]);
-    player->compute(*m_dic, m_board, m_history.getSize());
+    AIPlayer *player = dynamic_cast<AIPlayer*>(m_players[p]);
+    ASSERT(player != NULL, "AI requested for a human player");
 
-    if (player->changesLetters())
-    {
-        // The AI player has nothing to play. This should not happen in
-        // duplicate mode, otherwise the implementation of the AI is buggy...
-        ASSERT(false, "AI player has nothing to play!");
-    }
-    else
+    player->compute(m_dic, m_board, m_history.beforeFirstRound());
+    const Move move = player->getMove();
+    if (move.getType() == Move::CHANGE_LETTERS ||
+        move.getType() == Move::PASS)
     {
-        playRound(player->getChosenRound(), n);
+        // The AI player must be buggy...
+        ASSERT(false, "AI tried to cheat!");
     }
+
+    playMove(move, p);
 }
 
 
@@ -96,165 +93,155 @@
 {
     ASSERT(getNPlayers(), "Cannot start a game without any player");
 
+    // Arbitrary player, since they should all have the same rack
     m_currPlayer = 0;
 
-    /* XXX: code similar with endTurnForReal() */
-    /* Complete the rack for the player that just played */
-    int res = setRackRandom(m_currPlayer, true, RACK_NEW);
-    /* End of the game? */
+    // Complete the rack for the player that just played
+    int res = helperSetRackRandom(m_currPlayer, true, RACK_NEW);
+    // End of the game?
     if (res == 1)
     {
-        end();
+        endGame();
         return 1;
     }
 
     const PlayedRack& pld = m_players[m_currPlayer]->getCurrentRack();
-    /* All the players have the same rack */
-    for (int i = 0; i < getNPlayers(); i++)
+    // All the players have the same rack
+    for (unsigned int i = 0; i < getNPlayers(); i++)
     {
         if (i != m_currPlayer)
         {
             m_players[i]->setCurrentRack(pld);
         }
-        /* Nobody has played yet in this round */
+        // Nobody has played yet in this round
         m_hasPlayed[i] = false;
     }
 
-    /* Next turn */
-    // XXX: Should it be done by the interface instead?
-    endTurn();
+    // Little hack to handle duplicate games with only AI players.
+    // This will have no effect when there is at least one human player
+    tryEndTurn();
 
     return 0;
 }
 
 
-/*
- * This function does not terminate the turn itself, but performs some
- * checks to know whether or not it should be terminated (with a call to
- * endTurnForReal()).
- *
- * For the turn to be terminated, all the players must have played.
- * Since the AI players play after the human players, we check whether
- * one of the human players has not played yet:
- *   - if so, we have nothing to do (we are waiting for him)
- *   - if not (all human players have played), the AI players can play,
- *     and we finish the turn.
- */
-int Duplicate::endTurn()
+void Duplicate::tryEndTurn()
 {
-    int i;
-    for (i = 0; i < getNPlayers(); i++)
+    for (unsigned int i = 0; i < getNPlayers(); i++)
     {
         if (m_players[i]->isHuman() && !m_hasPlayed[i])
         {
-            /* A human player has not played... */
+            // A human player has not played...
             m_currPlayer = i;
-            // XXX: check return code meaning
-            return 1;
+            // So we don't finish the turn
+            return;
         }
     }
 
-    /* If all the human players have played */
-    if (i == getNPlayers())
-    {
-        /* Make AI players play their turn */
-        for (i = 0; i < getNPlayers(); i++)
+    // Now that all the human players have played,
+    // make AI players play their turn
+    for (unsigned int i = 0; i < getNPlayers(); i++)
         {
             if (!m_players[i]->isHuman())
             {
-                duplicateAI(i);
-            }
+            playAI(i);
         }
-
-        /* Next turn */
-        endTurnForReal();
     }
 
-    // XXX: check return code meaning
-    return 0;
+    // Next turn
+    endTurn();
 }
 
 
-void Duplicate::playRound(const Round &iRound, int n)
+void Duplicate::playMove(const Move &iMove, unsigned int p)
 {
-    ASSERT(0 <= n && n < getNPlayers(), "Wrong player number");
-    Player *player = m_players[n];
+    ASSERT(p < getNPlayers(), "Wrong player number");
 
-    /* Update the rack and the score of the current player */
-    player->addPoints(iRound.getPoints());
-    player->endTurn(iRound, m_history.getSize());
+    // Update the rack and the score of the playing player
+    m_players[p]->endTurn(iMove, m_history.getSize());
 
-    m_hasPlayed[n] = true;
+    m_hasPlayed[p] = true;
 }
 
 
-/*
- * This function really changes the turn, i.e. the best word is played and
- * a new rack is given to the players.
- * We suppose that all the players have finished to play for this turn (this
- * should have been checked by endturn())
- */
-int Duplicate::endTurnForReal()
+void Duplicate::endTurn()
 {
-    int res, i, imax;
-
-    /* Play the best word on the board */
-    imax = 0;
-    for (i = 1; i < getNPlayers(); i++)
+    // Find the player with the best score
+    unsigned int imax = 0;
+    for (unsigned int i = 1; i < getNPlayers(); i++)
     {
-        if (m_players[i]->getLastRound().getPoints() >
-            m_players[imax]->getLastRound().getPoints())
+        if (m_players[i]->getLastMove().getScore() >
+            m_players[imax]->getLastMove().getScore())
         {
             imax = i;
         }
     }
-    m_currPlayer = imax;
-    helperPlayRound(m_players[imax]->getLastRound());
 
-    /* Complete the rack for the player that just played */
-    res = setRackRandom(imax, true, RACK_NEW);
-    /* End of the game? */
-    if (res == 1)
+    // TODO: do something if nobody played a valid round!
+
+    // Handle solo bonus
+    // First check whether there are enough players in the game for the
+    // bonus to apply
+    int minNbPlayers = Settings::Instance().getInt("duplicate-solo-players");
+    if (getNPlayers() >= (unsigned int)minNbPlayers &&
+        m_players[imax]->getLastMove().getType() == Move::VALID_ROUND)
     {
-        end();
-        return 1;
+        int maxScore = m_players[imax]->getLastMove().getScore();
+        // Find whether other players than imax have the same score
+        bool otherWithSameScore = false;
+        for (unsigned int i = imax + 1; i < getNPlayers(); i++)
+        {
+            if (m_players[i]->getLastMove().getScore() >= maxScore)
+            {
+                otherWithSameScore = true;
+                break;
+            }
+        }
+        if (!otherWithSameScore)
+        {
+            // Give the bonus to player imax
+            int bonus = Settings::Instance().getInt("duplicate-solo-value");
+            m_players[imax]->addPoints(bonus);
+            // TODO: keep a trace of the solo, so the interface
+            // can be aware of it...
+        }
     }
 
+    // Play the best word on the board
+    helperPlayMove(imax, m_players[imax]->getLastMove());
+
+    // Leave the same reliquate to all players
+    // This is required by the start() method which will be called to
+    // start the next turn
     const PlayedRack& pld = m_players[imax]->getCurrentRack();
-    /* All the players have the same rack */
-    for (i = 0; i < getNPlayers(); i++)
+    for (unsigned int i = 0; i < getNPlayers(); i++)
     {
         if (i != imax)
         {
             m_players[i]->setCurrentRack(pld);
         }
-        /* Nobody has played yet in this round */
-        m_hasPlayed[i] = false;
     }
 
-    /* XXX: Little hack to handle the games with only AI players.
-     * This will have no effect when there is at least one human player */
-    endTurn();
-
-    return 0;
+    // Start next turn...
+    start();
 }
 
 
-void Duplicate::end()
+void Duplicate::endGame()
 {
     m_finished = true;
 }
 
 
-int Duplicate::setPlayer(int n)
+int Duplicate::setPlayer(unsigned int p)
 {
-    ASSERT(0 <= n && n < getNPlayers(), "Wrong player number");
+    ASSERT(p < getNPlayers(), "Wrong player number");
 
-    /* Forbid switching to an AI player */
-    if (!m_players[n]->isHuman())
+    // Forbid switching to an AI player
+    if (!m_players[p]->isHuman())
         return 1;
 
-    m_currPlayer = n;
+    m_currPlayer = p;
     return 0;
 }
 

Index: game/duplicate.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/duplicate.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- game/duplicate.h    22 Jan 2006 12:23:53 -0000      1.12
+++ game/duplicate.h    8 Jan 2008 13:52:37 -0000       1.13
@@ -1,6 +1,7 @@
 /*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,7 +35,7 @@
  *     and rack are updated. He cannot change his word afterwards.
  *   - if there is still a human player who has not played for the current
  *     turn, we wait for him
- *   - if all the human players have played, it's the turn to the AI players
+ *   - if all the human players have played, it's the turn of the AI players
  *     (currently handled in a loop, but we could imagine that they are running
  *     in their own thread).
  *   - once all the players have played, we can really end the turn:
@@ -57,26 +58,73 @@
     /*************************
      * Game handling
      *************************/
+    /**
+     * In Duplicate mode, the start() method starts a new turn, and is
+     * automatically called when the previous turn is finished.
+     *
+     * Pre-requisite: all the players must have the same rack when this
+     * method is called
+     */
     virtual int start();
-    virtual int setRackRandom(int, bool, set_rack_mode);
+
+    /**
+     * See description of Game::play() for the possible return values.
+     * Note that if the "duplicate-reject-invalid" setting is set to false
+     * the method always returns 0 (the player will have 0 for this turn)
+     */
     virtual int play(const wstring &iCoord, const wstring &iWord);
-    virtual int endTurn();
 
-    int setPlayer(int);
-    // Switch to the previous human player who has not played yet
+    /**
+     * Set the current player, given its ID.
+     * The given player ID must correspond to a human player, which did not
+     * play yet for this turn.
+     * Possible return values:
+     *  0: everything went fine
+     *  1: the player is not human
+     */
+    int setPlayer(unsigned int p);
+
+    /// Switch to the previous human player who has not played yet
     void prevHumanPlayer();
-    // Switch to the next human player who has not played yet
+
+    /// Switch to the next human player who has not played yet
     void nextHumanPlayer();
 
 private:
-    // Private constructor and destructor to force using the GameFactory class
+    // Private constructor to force using the GameFactory class
     Duplicate(const Dictionary &iDic);
-    virtual ~Duplicate();
 
-    void playRound(const Round &iRound, int n);
-    int  endTurnForReal();
-    void end();
-    void duplicateAI(int n);
+    void playMove(const Move &iMove, unsigned int p);
+
+    /// Make the AI player whose ID is p play its turn
+    void playAI(unsigned int p);
+
+    /**
+     * This function does not terminate the turn itself, but performs some
+     * checks to know whether or not it should be terminated (with a call to
+     * endTurn()).
+     *
+     * For the turn to be terminated, all the players must have played.
+     * Since the AI players play after the human players, we check whether
+     * one of the human players has not played yet:
+     *   - if so, we have nothing to do (we are waiting for him/her)
+     *   - if not (all human players have played), the AI players can play,
+     *     and we finish the turn.
+     */
+    void tryEndTurn();
+
+    /**
+     * This function really changes the turn, i.e. the best word is played,
+     * the game history is updated, a "solo" bonus is given if needed, and
+     * all racks are made equal to the one of the player who played the
+     * best move.
+     * We suppose here that all the players have finished to play for this
+     * turn (this should have been checked by tryEndturn())
+     */
+    void endTurn();
+
+    /// Finish the game
+    void endGame();
 
     // m_hasPlayed[p] is true iff player p has played for this turn
     map<int, bool> m_hasPlayed;

Index: game/freegame.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/freegame.cpp,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -b -r1.18 -r1.19
--- game/freegame.cpp   22 Jan 2006 12:23:53 -0000      1.18
+++ game/freegame.cpp   8 Jan 2008 13:52:38 -0000       1.19
@@ -1,6 +1,7 @@
 /*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,89 +20,88 @@
 
 #include <iomanip>
 #include <wctype.h>
+
+#include "freegame.h"
 #include "dic.h"
 #include "tile.h"
 #include "rack.h"
 #include "round.h"
+#include "move.h"
 #include "pldrack.h"
 #include "results.h"
 #include "player.h"
 #include "ai_player.h"
-#include "freegame.h"
+#include "settings.h"
 
 #include "debug.h"
 
 
-FreeGame::FreeGame(const Dictionary &iDic): Game(iDic)
-{
-}
-
-
-FreeGame::~FreeGame()
-{
-}
-
-
-int FreeGame::setRackRandom(int p, bool iCheck, set_rack_mode mode)
+FreeGame::FreeGame(const Dictionary &iDic)
+    : Game(iDic)
 {
-    int res;
-    do
-    {
-        res = helperSetRackRandom(p, iCheck, mode);
-    } while (res == 2);
-    return res;
 }
 
 
 int FreeGame::play(const wstring &iCoord, const wstring &iWord)
 {
-    /* Perform all the validity checks, and fill a round */
+    // Perform all the validity checks, and try to fill a round
     Round round;
-
     int res = checkPlayedWord(iCoord, iWord, round);
-    if (res != 0)
+    if (res != 0 && Settings::Instance().getBool("freegame-reject-invalid"))
     {
         return res;
     }
 
-    /* Update the rack and the score of the current player */
-    m_players[m_currPlayer]->addPoints(round.getPoints());
-    m_players[m_currPlayer]->endTurn(round, m_history.getSize());
+    // If we reach this point, either the move is valid and we can use the
+    // "round" variable, or it is invalid but played nevertheless
+    if (res == 0)
+    {
+        Move move(round);
+
+        // Update the rack and the score of the current player
+        m_players[m_currPlayer]->endTurn(move, m_history.getSize());
+
+        // Everything is OK, we can play the word
+        helperPlayMove(m_currPlayer, move);
+    }
+    else
+    {
+        Move move(iWord, iCoord);
+
+        // Record the invalid move of the player
+        m_players[m_currPlayer]->endTurn(move, m_history.getSize());
 
-    /* Everything is OK, we can play the word */
-    helperPlayRound(round);
+        // Update the game
+        helperPlayMove(m_currPlayer, move);
+    }
 
-    /* Next turn */
-    // XXX: Should it be done by the interface instead?
+    // Next turn
     endTurn();
 
     return 0;
 }
 
 
-void FreeGame::freegameAI(int n)
+void FreeGame::playAI(unsigned int p)
 {
-    ASSERT(0 <= n && n < getNPlayers(), "Wrong player number");
-    ASSERT(!m_players[n]->isHuman(), "AI requested for a human player");
+    ASSERT(p < getNPlayers(), "Wrong player number");
+    ASSERT(!m_players[p]->isHuman(), "AI requested for a human player");
 
-    AIPlayer *player = static_cast<AIPlayer*>(m_players[n]);
+    AIPlayer *player = static_cast<AIPlayer*>(m_players[p]);
 
-    player->compute(*m_dic, m_board, m_history.getSize());
-    if (player->changesLetters())
+    player->compute(m_dic, m_board, m_history.beforeFirstRound());
+    const Move move = player->getMove();
+    if (move.getType() == Move::CHANGE_LETTERS ||
+        move.getType() == Move::PASS)
     {
-        helperPass(player->getChangedLetters(), n);
-        endTurn();
+        ASSERT(checkPass(move.getChangedLetters(), p) == 0, "AI tried to 
cheat!");
     }
-    else
-    {
-        const Round &round = player->getChosenRound();
-        /* Update the rack and the score of the current player */
-        player->addPoints(round.getPoints());
-        player->endTurn(round, m_history.getSize());
 
-        helperPlayRound(round);
+    // Update the rack and the score of the current player
+    player->endTurn(move, m_history.getSize());
+
+    helperPlayMove(p, move);
         endTurn();
-    }
 }
 
 
@@ -109,19 +109,18 @@
 {
     ASSERT(getNPlayers(), "Cannot start a game without any player");
 
-    /* Set the initial racks of the players */
-    for (int i = 0; i < getNPlayers(); i++)
+    // Set the initial racks of the players
+    for (unsigned int i = 0; i < getNPlayers(); i++)
     {
-        setRackRandom(i, false, RACK_NEW);
+        helperSetRackRandom(i, false, RACK_NEW);
     }
 
-    // XXX
     m_currPlayer = 0;
 
-    /* If the first player is an AI, make it play now */
-    if (!m_players[0]->isHuman())
+    // If the first player is an AI, make it play now
+    if (!m_players[m_currPlayer]->isHuman())
     {
-        freegameAI(0);
+        playAI(m_currPlayer);
     }
 
     return 0;
@@ -130,21 +129,21 @@
 
 int FreeGame::endTurn()
 {
-    /* Complete the rack for the player that just played */
-    if (setRackRandom(m_currPlayer, false, RACK_NEW) == 1)
+    // Complete the rack for the player that just played
+    if (helperSetRackRandom(m_currPlayer, false, RACK_NEW) == 1)
     {
-        /* End of the game */
-        end();
+        // End of the game
+        endGame();
         return 1;
     }
 
-    /* Next player */
+    // Next player
     nextPlayer();
 
-    /* If this player is an AI, make it play now */
+    // If this player is an AI, make it play now
     if (!m_players[m_currPlayer]->isHuman())
     {
-        freegameAI(m_currPlayer);
+        playAI(m_currPlayer);
     }
 
     return 0;
@@ -152,7 +151,7 @@
 
 
 // Adjust the scores of the players with the points of the remaining tiles
-void FreeGame::end()
+void FreeGame::endGame()
 {
     vector<Tile> tiles;
 
@@ -165,12 +164,12 @@
     // We currently handle case 1, and cannot handle case 3 until timers are
     // implemented.
     // For case 2, we need both to detect a blocked situation (not easy...) and
-    // to handle it in the end() method (very easy).
+    // to handle it in the endGame() method (very easy).
 
     /* Add the points of the remaining tiles to the score of the current
      * player (i.e. the first player with an empty rack), and remove them
      * from the score of the players who still have tiles */
-    for (int i = 0; i < getNPlayers(); i++)
+    for (unsigned int i = 0; i < getNPlayers(); i++)
     {
         if (i != m_currPlayer)
         {
@@ -184,73 +183,73 @@
         }
     }
 
-    /* Lock game */
+    // Lock game
     m_finished = true;
 }
 
 
-int FreeGame::pass(const wstring &iToChange, int n)
+int FreeGame::checkPass(const wstring &iToChange, unsigned int p) const
 {
+    ASSERT(p < getNPlayers(), "Wrong player number");
+
+    // Check that the game is not finished
     if (m_finished)
         return 3;
 
-    // According to the rules in the ODS, it is allowed to pass its turn (no
-    // need to change letters for that).
-    // TODO: However, if all the players pass their turn, the first one has to
-    // play, or change at least one letter. To implement this behaviour, we
-    // must also take care of blocked positions, where no one _can_ play (see
-    // also comment in the end() method).
-
-    // Convert the string into tiles
-    vector<Tile> tilesVect;
-    for (unsigned int i = 0; i < iToChange.size(); i++)
-    {
-        Tile tile(towupper(iToChange[i]));
-        tilesVect.push_back(tile);
-    }
-
-    int res = helperPass(tilesVect, n);
-    if (res == 0)
-        endTurn();
-    return res;
-}
-
-
-int FreeGame::helperPass(const vector<Tile> &iToChange, int n)
-{
-    ASSERT(0 <= n && n < getNPlayers(), "Wrong player number");
+    // Check that the letters are valid for the current dictionary
+    if (!m_dic.validateLetters(iToChange))
+        return 4;
 
     // It is forbidden to change letters when the bag does not contain at
-    // least 7 letters (this is explicitely stated in the ODS).
-    Bag bag;
+    // least 7 letters (this is explicitly stated in the ODS). But it is
+    // still allowed to pass
+    Bag bag(m_dic);
     realBag(bag);
-    if (bag.nTiles() < 7)
+    if (bag.getNbTiles() < 7 && !iToChange.empty())
     {
         return 1;
     }
 
-    Player *player = m_players[n];
+    // Check that the letters are all present in the player's rack
+    Player *player = m_players[p];
     PlayedRack pld = player->getCurrentRack();
     Rack rack;
     pld.getRack(rack);
-
     for (unsigned int i = 0; i < iToChange.size(); i++)
     {
-        /* Remove the letter from the rack */
-        if (!rack.in(iToChange[i]))
+        // Remove the letter from the rack
+        if (!rack.in(Tile(iToChange[i])))
         {
             return 2;
         }
-        rack.remove(iToChange[i]);
+        rack.remove(Tile(iToChange[i]));
     }
 
-    pld.reset();
-    pld.setOld(rack);
+    // According to the rules in the ODS, it is allowed to pass its turn (no
+    // need to change letters for that).
+    // TODO: However, if all the players pass their turn, the first one has to
+    // play, or change at least one letter. To implement this behaviour, we
+    // must also take care of blocked positions, where no one _can_ play (see
+    // also comment in the endGame() method).
 
-    player->setCurrentRack(pld);
+    return 0;
+}
 
-    // FIXME: the letters to change should not be in the bag while generating
-    // the new rack!
+
+int FreeGame::pass(const wstring &iToChange)
+{
+    int res = checkPass(iToChange, m_currPlayer);
+    if (res != 0)
+        return res;
+
+    Move move(iToChange);
+    // End the player's turn
+    m_players[m_currPlayer]->endTurn(move, m_history.getSize());
+    // Update the game
+    helperPlayMove(m_currPlayer, move);
+
+    // Next game turn
+    endTurn();
 
     return 0;
 }

Index: game/freegame.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/freegame.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- game/freegame.h     22 Jan 2006 12:23:53 -0000      1.11
+++ game/freegame.h     8 Jan 2008 13:52:38 -0000       1.12
@@ -1,6 +1,7 @@
 /*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -48,20 +49,54 @@
     /*************************
      * Game handling
      *************************/
+    /**
+     * Start the game.
+     * Possible return values:
+     *  0: everything went fine
+     */
     virtual int start();
-    virtual int setRackRandom(int, bool, set_rack_mode);
+
+    /**
+     * See description of Game::play() for the possible return values.
+     * Note that if the "freegame-reject-invalid" setting is set to false
+     * the method always returns 0 (the player will have 0 for this turn)
+     */
     virtual int play(const wstring &iCoord, const wstring &iWord);
-    virtual int endTurn();
-    int pass(const wstring &iToChange, int n);
+
+    /**
+     * Pass the turn, changing the letters listed in iToChange.
+     * If you simply want to pass the turn without changing any letter,
+     * provide an empty string.
+     *
+     * Possible return values:
+     *  0: everything went fine
+     *  1: changing letters is not allowed if there are less than 7 tiles
+     *     left in the bag
+     *  2: the rack of the current player does not contain all the
+     *     listed letters
+     *  3: the game is already finished
+     *  4: some letters are invalid for the current dictionary
+     */
+    int pass(const wstring &iToChange);
 
 private:
-    // Private constructor and destructor to force using the GameFactory class
+    // Private constructor to force using the GameFactory class
     FreeGame(const Dictionary &iDic);
-    virtual ~FreeGame();
 
-    void freegameAI(int n);
-    void end();
-    int helperPass(const vector<Tile> &iToChange, int n);
+    /// Make the AI player whose ID is p play its turn
+    void playAI(unsigned int p);
+
+    /// Finish the current turn
+    int endTurn();
+
+    /// Finish the game
+    void endGame();
+
+    /**
+     * Check whether it is legal to change the letters of iToChange.
+     * The return codes are the same as the ones on the pass() method
+     */
+    int checkPass(const wstring &iToChange, unsigned int p) const;
 };
 
 #endif /* _FREEGAME_H_ */

Index: game/game.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game.cpp,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -b -r1.33 -r1.34
--- game/game.cpp       4 Aug 2007 20:01:28 -0000       1.33
+++ game/game.cpp       8 Jan 2008 13:52:38 -0000       1.34
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,7 +20,6 @@
  *****************************************************************************/
 
 #include "dic.h"
-#include "dic_search.h"
 #include "tile.h"
 #include "rack.h"
 #include "round.h"
@@ -35,65 +35,70 @@
 #include "debug.h"
 
 
-const int Game::RACK_SIZE    =  7;
+const unsigned int Game::RACK_SIZE =  7;
 const int Game::BONUS_POINTS = 50;
 
 Game::Game(const Dictionary &iDic):
-    m_dic(&iDic)
+    m_dic(iDic), m_bag(iDic)
 {
     m_variant = kNONE;
     m_points = 0;
-    m_currPlayer = -1;
+    m_currPlayer = 0;
     m_finished = false;
 }
 
 
 Game::~Game()
 {
-    for (int i = 0; i < getNPlayers(); i++)
+    for (unsigned int i = 0; i < getNPlayers(); i++)
     {
         delete m_players[i];
     }
 }
 
 
-const Player& Game::getPlayer(int iNum) const
+const Player& Game::getPlayer(unsigned int iNum) const
 {
-    ASSERT(0 <= iNum && iNum < (int)m_players.size(), "Wrong player number");
+    ASSERT(iNum < m_players.size(), "Wrong player number");
     return *(m_players[iNum]);
 }
 
 
-/* This function plays a round on the board */
-int Game::helperPlayRound(const Round &iRound)
+void Game::helperPlayMove(unsigned int iPlayerId, const Move &iMove)
 {
-    /*
-     * We remove tiles from the bag only when they are played
-     * on the board. When going back in the game, we must only
-     * replace played tiles.
-     * We test a rack when it is set but tiles are left in the bag.
-     */
-
     // History of the game
-    m_history.setCurrentRack(getCurrentPlayer().getLastRack());
-    m_history.playRound(m_currPlayer, m_history.getSize(),  iRound);
+    m_history.setCurrentRack(getPlayer(iPlayerId).getLastRack());
+    m_history.playMove(iPlayerId, m_history.getSize(), iMove);
+
+    // Points
+    debug("    helper: %d points\n", iMove.getScore());
+    m_points += iMove.getScore();
 
-    debug("    helper: %d points\n",iRound.getPoints());
-    m_points += iRound.getPoints();
+    // For moves corresponding to a valid round, we have much more
+    // work to do...
+    if (iMove.getType() == Move::VALID_ROUND)
+    {
+        helperPlayRound(iPlayerId, iMove.getRound());
+    }
+}
 
+
+
+void Game::helperPlayRound(unsigned int iPlayerId, const Round &iRound)
+{
     // Before updating the bag and the board, if we are playing a "joker game",
     // we replace in the round the joker by the letter it represents
     // This is currently done by a succession of ugly hacks :-/
     if (m_variant == kJOKER)
     {
-        for (int i = 0; i < iRound.getWordLen(); i++)
+        for (unsigned int i = 0; i < iRound.getWordLen(); i++)
         {
             if (iRound.isPlayedFromRack(i) && iRound.isJoker(i))
             {
                 // Is the represented letter still available in the bag?
-                // FIXME: this way to get the represented letter sucks...
+                // XXX: this way to get the represented letter sucks...
                 Tile t(towupper(iRound.getTile(i).toChar()));
-                Bag bag;
+                Bag bag(m_dic);
                 realBag(bag);
                 // FIXME: realBag() does not give us a real bag in this
                 // particular case! This is because Player::endTurn() is called
@@ -108,12 +113,12 @@
                 // There is a big design problem here, but i am unsure what is
                 // the best way to fix it.
                 vector<Tile> tiles;
-                getPlayer(m_currPlayer).getCurrentRack().getAllTiles(tiles);
+                getPlayer(iPlayerId).getCurrentRack().getAllTiles(tiles);
                 for (unsigned int j = 0; j < tiles.size(); j++)
                 {
                     bag.replaceTile(tiles[j]);
                 }
-                getPlayer(m_currPlayer).getLastRack().getAllTiles(tiles);
+                getPlayer(iPlayerId).getLastRack().getAllTiles(tiles);
                 for (unsigned int j = 0; j < tiles.size(); j++)
                 {
                     bag.takeTile(tiles[j]);
@@ -128,12 +133,19 @@
                     // rounds
                     const_cast<Round&>(iRound).setJoker(i, false);
                 }
+
+                // In a joker game we should have only 1 joker in the rack
+                break;
             }
         }
     }
 
-    // Update the bag and the board
-    for (int i = 0; i < iRound.getWordLen(); i++)
+    // Update the bag
+    // We remove tiles from the bag only when they are played
+    // on the board. When going back in the game, we must only
+    // replace played tiles.
+    // We test a rack when it is set but tiles are left in the bag.
+    for (unsigned int i = 0; i < iRound.getWordLen(); i++)
     {
         if (iRound.isPlayedFromRack(i))
         {
@@ -147,36 +159,34 @@
             }
         }
     }
-    m_board.addRound(*m_dic, iRound);
 
-    return 0;
+    // Update the board
+    m_board.addRound(m_dic, iRound);
 }
 
 
-int Game::back(int n)
+int Game::back(unsigned int n)
 {
-    int i, j;
-    Player *player;
-
-    if (n < 0)
-    {
-        debug("Game::back negative argument\n");
-        n = -n;
-    }
     debug("Game::back %d\n",n);
-    for (i = 0; i < n; i++)
-    {
-        if (m_history.getSize() > 0)
+    // TODO: throw an exception
+    if (m_history.getSize() < n)
+        return 1;
+
+    for (unsigned int i = 0; i < n; i++)
         {
             prevPlayer();
-            player = m_players[m_currPlayer];
-            const Round &lastround = m_history.getPreviousTurn().getRound();
+        const Move &lastMove = m_history.getPreviousTurn().getMove();
+        // Nothing to cancel if the move was not a valid round
+        if (lastMove.getType() != Move::VALID_ROUND)
+            continue;
+
+        const Round &lastround = lastMove.getRound();
             debug("Game::back last round %s\n",
                   convertToMb(lastround.toString()).c_str());
             /* Remove the word from the board, and put its letters back
              * into the bag */
-            m_board.removeRound(*m_dic, lastround);
-            for (j = 0; j < lastround.getWordLen(); j++)
+        m_board.removeRound(m_dic, lastround);
+        for (unsigned int j = 0; j < lastround.getWordLen(); j++)
             {
                 if (lastround.isPlayedFromRack(j))
                 {
@@ -187,25 +197,15 @@
                 }
             }
             /* Remove the points of this round */
-            player->addPoints(- lastround.getPoints());
             m_points -= lastround.getPoints();
             /* Remove the turns */
-            player->removeLastTurn();
+        m_players[m_currPlayer]->removeLastTurn();
             m_history.removeLastTurn();
         }
-        else
-        {
-            return 1;
-        }
-    }
     return 0;
 }
 
-/**
- * The realBag is the current bag minus all the racks
- * present in the game. It represents the actual 
- * letters that are left in the bag.
- */
+
 void Game::realBag(Bag &ioBag) const
 {
     vector<Tile> tiles;
@@ -217,7 +217,7 @@
     if (getMode() == kFREEGAME)
     {
         /* In freegame mode, take the letters from all the racks */
-        for (int i = 0; i < getNPlayers(); i++)
+        for (unsigned int i = 0; i < getNPlayers(); i++)
         {
             getPlayer(i).getCurrentRack().getAllTiles(tiles);
             for (unsigned int j = 0; j < tiles.size(); j++)
@@ -239,22 +239,36 @@
 }
 
 
-int Game::helperSetRackRandom(int p, bool iCheck, set_rack_mode mode)
+int Game::helperSetRackRandom(unsigned int p, bool iCheck, set_rack_mode mode)
 {
-    ASSERT(0 <= p && p < getNPlayers(), "Wrong player number");
+    ASSERT(p < getNPlayers(), "Wrong player number");
+    // FIXME: RACK_MANUAL shouldn't be in the enum
+    ASSERT(mode != RACK_MANUAL, "Invalid rack mode");
 
-    int nold, min;
+    // When iCheck is true, we must make sure that there are at least 2 vowels
+    // and 2 consonants in the rack up to the 15th turn, and at least one of
+    // each starting from the 16th turn.
+    // So before trying to fill the rack, we'd better make sure there is a way
+    // to complete the rack with these constraints...
+    unsigned int min = 0;
+    if (iCheck)
+    {
+        // 2 vowels and 2 consonants are needed up to the 15th turn
+        if (m_history.getSize() < 15)
+            min = 2;
+        else
+            min = 1;
+    }
 
     // Make a copy of the current player's rack
     PlayedRack pld = getPlayer(p).getCurrentRack();
-    nold = pld.nOld();
+    int nold = pld.getNbOld();
 
     // Create a copy of the bag in which we can do everything we want,
     // and take from it the tiles of the players rack so that "bag"
     // contains the right number of tiles.
-    Bag bag;
+    Bag bag(m_dic);
     realBag(bag);
-
     if (mode == RACK_NEW && nold != 0)
     {
         // We may have removed too many letters from the bag (i.e. the 'new'
@@ -286,8 +300,212 @@
         debug("Game::helperSetRackRandom not a random mode\n");
     }
 
+    // Get the tiles remaining on the rack
+    vector<Tile> tiles;
+    pld.getOldTiles(tiles);
+    ASSERT(tiles.size() < RACK_SIZE,
+           "Cannot complete the rack, it is already complete");
+
+    bool jokerAdded = false;
+    // Are we dealing with a normal game or a joker game?
+    if (m_variant == kJOKER)
+    {
+        // 1) Is there already a joker in the remaining letters of the rack?
+        bool jokerFound = false;
+        for (unsigned int i = 0; i < tiles.size(); i++)
+        {
+            if (tiles[i].isJoker())
+            {
+                jokerFound = true;
+                break;
+            }
+        }
+
+        // 2) If there was no joker, we add one if possible
+        if (!jokerFound && bag.in(Tile::Joker()))
+        {
+            jokerAdded = true;
+            pld.addNew(Tile::Joker());
+            tiles.push_back(Tile::Joker());
+        }
+
+        // 3) Remove all the jokers from the bag, to avoid taking another one
+        for (unsigned int i = 0; i < bag.in(Tile::Joker()); ++i)
+        {
+            bag.takeTile(Tile::Joker());
+        }
+    }
+
+    // Nothing in the rack, nothing in the bag --> end of the (free)game
+    if (bag.getNbTiles() == 0 && pld.getNbTiles() == 0)
+    {
+        return 1;
+    }
+    // End of game condition
+    if (iCheck)
+    {
+        if (bag.getNbVowels() == 0 || bag.getNbConsonants() == 0 ||
+            bag.getNbTiles() == 1)
+        {
+            return 1;
+        }
+    }
+
+    // Handle reject:
+    // Now that the joker has been dealt with, we try to complete the rack
+    // with truly random tiles. If it meets the requirements (i.e. if there
+    // are at least "min" vowels and "min" consonants in the rack), fine.
+    // Otherwise, we reject the rack completely, and we try again
+    // to complete it, but this time we ensure by construction that the
+    // requirements will be met.
+    while (bag.getNbTiles() != 0 && pld.getNbTiles() < RACK_SIZE)
+    {
+        Tile l = bag.selectRandom();
+        bag.takeTile(l);
+        pld.addNew(l);
+    }
+
+    if (!pld.checkRack(min, min))
+    {
+        // Bad luck... we have to reject the rack
+        vector<Tile> rejectedTiles;
+        pld.getAllTiles(rejectedTiles);
+        for (unsigned int i = 0; i < rejectedTiles.size(); i++)
+        {
+            bag.replaceTile(rejectedTiles[i]);
+        }
+        pld.reset();
+        // Do not mark the rack as rejected if it was empty
+        if (nold > 0)
+            pld.setReject();
+
+        // Restore the joker if we are in a joker game
+        if (jokerAdded)
+            pld.addNew(Tile::Joker());
+
+        // Count the needed consonants and vowels in the rack
+        // (i.e. minimum required, minus what we already have in the rack)
+        unsigned int neededVowels = min;
+        unsigned int neededConsonants = min;
+        for (unsigned int i = 0; i < tiles.size(); ++i)
+        {
+            if (neededVowels > 0 && tiles[i].isVowel())
+                neededVowels--;
+            if (neededConsonants > 0 && tiles[i].isConsonant())
+                neededConsonants--;
+        }
+
+        // Check whether it is possible to complete the rack properly
+        if (bag.getNbVowels() < neededVowels ||
+            bag.getNbConsonants() < neededConsonants)
+        {
+            return 1;
+        }
+
+        // RACK_SIZE - tiles.size() is the number of letters to add to the rack
+        if (neededVowels > RACK_SIZE - tiles.size() ||
+            neededConsonants > RACK_SIZE - tiles.size())
+        {
+            // We cannot fill the rack with enough vowels or consonants!
+            // Actually this should never happen, but it doesn't hurt to 
check...
+            // FIXME: this test is not completely right, because it supposes no
+            // letter can be at the same time a vowel and a consonant
+            return 3;
+        }
+
+        // Get the required vowels and consonants first
+        for (unsigned int i = 0; i < neededVowels; ++i)
+        {
+            Tile l = bag.selectRandomVowel();
+            bag.takeTile(l);
+            pld.addNew(l);
+            // Handle the case where the vowel can also be considered
+            // as a consonant
+            if (l.isConsonant() && neededConsonants > 0)
+                neededConsonants--;
+        }
+        for (unsigned int i = 0; i < neededConsonants; ++i)
+        {
+            Tile l = bag.selectRandomConsonant();
+            bag.takeTile(l);
+            pld.addNew(l);
+        }
+
+        // The difficult part is done:
+        //  - we have handled joker games
+        //  - we have handled the checks
+        // Now complete the rack with truly random letters
+        while (bag.getNbTiles() != 0 && pld.getNbTiles() < RACK_SIZE)
+        {
+            Tile l = bag.selectRandom();
+            bag.takeTile(l);
+            pld.addNew(l);
+        }
+    }
+
+    // Shuffle the new tiles, to hide the order we imposed (joker first in a
+    // joker game, then needed vowels, then needed consonants, and rest of the
+    // rack)
+    pld.shuffleNew();
+
+    // Post-condition check. This should never fail, of course :)
+    ASSERT(pld.checkRack(min, min), "helperSetRackRandom() is buggy!")
+
+    // Until now we didn't modify anything except local variables.
+    // Let's "commit" the changes
+    m_players[p]->setCurrentRack(pld);
+
+    return 0;
+}
+
+
+int Game::helperSetRackRandomOld(unsigned int p, bool iCheck, set_rack_mode 
mode)
+{
+    ASSERT(p < getNPlayers(), "Wrong player number");
+
+    // Make a copy of the current player's rack
+    PlayedRack pld = getPlayer(p).getCurrentRack();
+    int nold = pld.getNbOld();
+
+    // Create a copy of the bag in which we can do everything we want,
+    // and take from it the tiles of the players rack so that "bag"
+    // contains the right number of tiles.
+    Bag bag(m_dic);
+    realBag(bag);
+
+    if (mode == RACK_NEW && nold != 0)
+    {
+        // We may have removed too many letters from the bag (i.e. the 'new'
+        // letters of the player)
+        vector<Tile> tiles;
+        pld.getNewTiles(tiles);
+        for (unsigned int i = 0; i < tiles.size(); i++)
+        {
+            bag.replaceTile(tiles[i]);
+        }
+        pld.resetNew();
+    }
+    else if (mode == RACK_NEW && nold == 0 || mode == RACK_ALL)
+    {
+        // Replace all the tiles in the bag before choosing random ones
+        vector<Tile> tiles;
+        pld.getAllTiles(tiles);
+        for (unsigned int i = 0; i < tiles.size(); i++)
+        {
+            bag.replaceTile(tiles[i]);
+        }
+        // RACK_NEW with an empty rack is equivalent to RACK_ALL
+        pld.reset();
+        // Do not forget to update nold, for the RACK_ALL case
+        nold = 0;
+    }
+    else
+    {
+        debug("Game::helperSetRackRandomOld not a random mode\n");
+    }
+
     // Nothing in the rack, nothing in the bag --> end of the game
-    if (bag.nTiles() == 0 && pld.nTiles() == 0)
+    if (bag.getNbTiles() == 0 && pld.getNbTiles() == 0)
     {
         return 1;
     }
@@ -297,17 +515,17 @@
     // them from the 16th turn.
     // So before trying to fill the rack, we'd better make sure there is a way
     // to complete the rack with these constraints...
-    min = 0;
+    unsigned int min = 0;
     if (iCheck)
     {
-        int oldc, oldv;
+        unsigned int oldc, oldv;
 
-        if (bag.nVowels() == 0 || bag.nConsonants() == 0)
+        if (bag.getNbVowels() == 0 || bag.getNbConsonants() == 0)
         {
             return 1;
         }
         // 2 vowels and 2 consonants are needed up to the 15th turn
-        if (bag.nVowels() > 1 && bag.nConsonants() > 1
+        if (bag.getNbVowels() > 1 && bag.getNbConsonants() > 1
             && m_history.getSize() < 15)
             min = 2;
         else
@@ -360,7 +578,9 @@
 
         // 3) Complete the rack normally... but without any joker!
         Tile l;
-        while (bag.nTiles() != 0 && pld.nTiles() != RACK_SIZE)
+        // FIXME: this can be an infinite loop if the only tile left in the
+        // bag is a joker!
+        while (bag.getNbTiles() != 0 && pld.getNbTiles() != RACK_SIZE)
         {
             l = bag.selectRandom();
             if (!l.isJoker())
@@ -374,7 +594,7 @@
     {
         // Get new tiles from the bag
         Tile l;
-        while (bag.nTiles() != 0 && pld.nTiles() != RACK_SIZE)
+        while (bag.getNbTiles() != 0 && pld.getNbTiles() != RACK_SIZE)
         {
             l = bag.selectRandom();
             bag.takeTile(l);
@@ -382,7 +602,7 @@
         }
     }
 
-    if (iCheck && !pld.checkRack(min,min))
+    if (iCheck && !pld.checkRack(min, min))
         return 2;
 
     m_players[p]->setCurrentRack(pld);
@@ -391,20 +611,10 @@
 }
 
 
-/**
- * Check if the players rack can be obtained from the bag.
- * Since letters are removed from the bag only when the
- * round is played we need to check that ALL the racks 
- * are in the bag simultaneously.
- *
- * FIXME: since we do not check for all racks it works
- * for training and duplicate but it won't work for
- * freegames.
- */
 bool Game::rackInBag(const Rack &iRack, const Bag &iBag) const
 {
-    const list<Tile>& allTiles = Tile::getAllTiles();
-    list<Tile>::const_iterator it;
+    const vector<Tile>& allTiles = m_dic.getAllTiles();
+    vector<Tile>::const_iterator it;
     for (it = allTiles.begin(); it != allTiles.end(); it++)
     {
         if (iRack.in(*it) > iBag.in(*it))
@@ -413,20 +623,16 @@
     return true;
 }
 
-/**
- * Set the rack of the player p manually.
- */
-int Game::helperSetRackManual(int p, bool iCheck, const wstring &iLetters)
+
+int Game::helperSetRackManual(unsigned int p, bool iCheck, const wstring 
&iLetters)
 {
-    int min, ret;
+    ASSERT(p < getNPlayers(), "Wrong player number");
 
-    PlayedRack pld = getPlayer(p).getCurrentRack();
-    pld.reset();
+    if (!m_dic.validateLetters(iLetters, L"+"))
+        return 3;
 
-    if ((ret = pld.setManual(iLetters)) > 0)
-    {
-        return 1; /* add new tests */
-    }
+    PlayedRack pld;
+    pld.setManual(iLetters);
 
     Rack rack;
     pld.getRack(rack);
@@ -438,12 +644,13 @@
 
     if (iCheck)
     {
-        if (m_bag.nVowels() > 1 && m_bag.nConsonants() > 1
+        int min;
+        if (m_bag.getNbVowels() > 1 && m_bag.getNbConsonants() > 1
             && m_history.getSize() < 15)
             min = 2;
         else
             min = 1;
-        if (!pld.checkRack(min,min))
+        if (!pld.checkRack(min, min))
             return 2;
     }
 
@@ -456,10 +663,10 @@
  *********************************************************/
 
 
-int Game::getNHumanPlayers() const
+unsigned int Game::getNHumanPlayers() const
 {
-    int count = 0;
-    for (int i = 0; i < getNPlayers(); i++)
+    unsigned int count = 0;
+    for (unsigned int i = 0; i < getNPlayers(); i++)
         count += (getPlayer(i).isHuman() ? 1 : 0);
     return count;
 }
@@ -474,7 +681,8 @@
 
 void Game::addAIPlayer()
 {
-    m_players.push_back(new AIPercent(getNPlayers(), 0));
+    // TODO: allow other percentages, and even other types of AI
+    m_players.push_back(new AIPercent(getNPlayers(), 1));
 }
 
 
@@ -500,34 +708,15 @@
 }
 
 
-/*
- * This function checks whether it is legal to play the given word at the
- * given coordinates. If so, the function fills a Round object, also given as
- * a parameter.
- * Possible return values:
- *  0: correct word, the Round can be used by the caller
- *  1: no dictionary set
- *  2: invalid coordinates (unreadable or out of the board)
- *  3: word not present in the dictionary
- *  4: not enough letters in the rack to play the word
- *  5: word is part of a longer one
- *  6: word overwriting an existing letter
- *  7: invalid crosscheck, or word going out of the board
- *  8: word already present on the board (no new letter from the rack)
- *  9: isolated word (not connected to the rest)
- * 10: first word not horizontal
- * 11: first word not covering the H8 square
- */
 int Game::checkPlayedWord(const wstring &iCoord,
                           const wstring &iWord, Round &oRound)
 {
     ASSERT(getNPlayers() != 0, "Expected at least one player");
 
-    int res;
-    vector<Tile> tiles;
-    Tile t;
+    if (!m_dic.validateLetters(iWord))
+        return 1;
 
-    /* Init the round with the given coordinates */
+    // Init the round with the given coordinates
     oRound.init();
     oRound.accessCoord().setFromString(iCoord);
     if (!oRound.getCoord().isValid())
@@ -536,16 +725,17 @@
         return 2;
     }
     
-    /* Check the existence of the word */
-    if (Dic_search_word(*m_dic, iWord.c_str()) == 0)
+    // Check the existence of the word
+    if (!m_dic.searchWord(iWord))
     {
         return 3;
     }
 
-    /* Set the word */
+    // Set the word
     // TODO: make this a Round_ function (Round_setwordfromchar for example)
     // or a Tiles_ function (to transform a char* into a vector<Tile>)
     // Adding a getter on the word could help too...
+    vector<Tile> tiles;
     for (unsigned int i = 0; i < iWord.size(); i++)
     {
         tiles.push_back(Tile(iWord[i]));
@@ -557,20 +747,21 @@
             oRound.setJoker(i);
     }
 
-    /* Check the word position, compute its points,
-     * and specify the origin of each letter (board or rack) */
-    res = m_board.checkRound(oRound, m_history.getSize() == 0);
+    // Check the word position, compute its points,
+    // and specify the origin of each letter (board or rack)
+    int res = m_board.checkRound(oRound, m_history.getSize() == 0);
     if (res != 0)
         return res + 4;
 
-    /* Check that the word can be formed with the tiles in the rack:
-     * we first create a copy of the rack, then we remove the tiles
-     * one by one */
+    // Check that the word can be formed with the tiles in the rack:
+    // we first create a copy of the rack, then we remove the tiles
+    // one by one
     Rack rack;
     Player *player = m_players[m_currPlayer];
     player->getCurrentRack().getRack(rack);
 
-    for (int i = 0; i < oRound.getWordLen(); i++)
+    Tile t;
+    for (unsigned int i = 0; i < oRound.getWordLen(); i++)
     {
         if (oRound.isPlayedFromRack(i))
         {

Index: game/game.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game.h,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -b -r1.31 -r1.32
--- game/game.h 4 Aug 2007 20:01:28 -0000       1.31
+++ game/game.h 8 Jan 2008 13:52:38 -0000       1.32
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,12 +29,12 @@
 #include "board.h"
 #include "history.h"
 
+class Dictionary;
 class Player;
 class PlayedRack;
 class Round;
 class Rack;
 class Turn;
-typedef struct _Dictionary * Dictionary;
 
 using namespace std;
 
@@ -47,13 +48,17 @@
 {
 public:
     /// Game specs.
-    static const int RACK_SIZE;
+    static const unsigned int RACK_SIZE;
     static const int BONUS_POINTS;
 
 
     Game(const Dictionary &iDic);
     virtual ~Game();
 
+    /***************
+     * Game type
+     ***************/
+
     /// Game mode: each one of these modes is implemented in an inherited class
     enum GameMode
     {
@@ -79,100 +84,118 @@
     void setVariant(GameVariant iVariant)   { m_variant = iVariant; }
     GameVariant getVariant() const          { return m_variant; }
 
+    /***************
+     * Various getters
+     ***************/
+
     /**
-     * Dictionary associated with the game.
-     * The dictionary can be changed during a game without problem
+     * Get the dictionary associated with the game.
+     * You should never create a new dictionary object while a Game
+     * object still exists
      */
-    const Dictionary & getDic() const   { return *m_dic; }
-    void setDic(const Dictionary &iDic) { m_dic = &iDic; }
+    const Dictionary & getDic() const   { return m_dic; }
 
+    /// Get the board
     const Board&  getBoard() const { return m_board; }
+    /// Get the bag
     const Bag&    getBag()   const { return m_bag; }
-    const Player& getPlayer(int iNum) const;
-    const Turn&   getTurn(int iNum) const;
+    /// Get the history of the game */
+    const History& getHistory() const { return m_history; }
+
+    /***************
+     * Methods to access players.
+     ***************/
+
+    const Player& getPlayer(unsigned int iNum) const;
     const Player& getCurrentPlayer() const { return getPlayer(currPlayer()); };
+    unsigned int getNPlayers() const { return m_players.size(); }
+    unsigned int getNHumanPlayers() const;
+    virtual void addHumanPlayer();
+    // TODO: Ability to specify which kind of AI player is wanted
+    virtual void addAIPlayer();
+    unsigned int currPlayer() const { return m_currPlayer; }
+
+    /***************
+     * Game handling
+     ***************/
+
+    /**
+     * Start the game.
+     * AI players are handled automatically, so if the game only has AI
+     * players, it will play until the end.
+     */
+    virtual int start() = 0;
 
     /**
-     * Eliot file formats
+     * Method used by human players to play the word iWord at coordinates
+     * iCoord, and end the turn (if possible)
+     * Possible return values:
+     *  0: correct word, the Round can be used by the caller
+     *  1: one letter of the word is invalid in the current dictionary
+     *  2: invalid coordinates (unreadable or out of the board)
+     *  3: word not present in the dictionary
+     *  4: not enough letters in the rack to play the word
+     *  5: word is part of a longer one
+     *  6: word overwriting an existing letter
+     *  7: invalid crosscheck, or word going out of the board
+     *  8: word already present on the board (no new letter from the rack)
+     *  9: isolated word (not connected to the rest)
+     * 10: first word not horizontal
+     * 11: first word not covering the H8 square
      */
-    typedef enum {
+    virtual int play(const wstring &iCoord, const wstring &iWord) = 0;
+
+    /**
+     * Go back to turn iTurn.
+     * We must have: iTurn < getHistory().getSize()
+     * Possible return values:
+     *  0: everything went fine
+     *  1: iTurn is invalid
+     */
+    int back(unsigned int iTurn);
+
+    /***************
+     * Saved games handling
+     ***************/
+
+    /**
+     * Possible formats for the saved games
+     */
+    enum game_file_format
+    {
       FILE_FORMAT_STANDARD,
       FILE_FORMAT_ADVANCED
-    } game_file_format;
+    };
 
     /**
-     * Saved games handling.
-     *
      * load() returns the loaded game, or NULL if there was a problem
-     * load() might need some more work to be robust enough to
+     * load() does need some more work to be robust enough to
      * handle "hand written" files
      */
     static Game * load(FILE *fin, const Dictionary &iDic);
 
     /**
-     * Save a game to a File
+     * Save a game to a file
      * Standard format is used for training games so that it is compatible
      * with previous versions of Eliot.
      *
      * Saving can be forced to advanced format for training games by 
      * setting the last parameter to FILE_FORMAT_ADVANCED
      */
-    void save(ostream &out, game_file_format format=FILE_FORMAT_STANDARD) 
const;
-
-    /*************************
-     * Playing the game
-     * the int parameter should be 0 <= int < getNTurns
-     *************************/
-    int back(int);
-
-    /*************************
-     * Set the rack for searching
-     *
-     * The int parameter is a boolean, if this parameter
-     * set the rack will check that there are at least
-     * 2 vowels and 2 consonants before the round 15.
-     *
-     * The setrackmanual parameter string has to contain
-     * 'a' <= char <= 'z' or 'A' <= char <= 'Z' or '?'
-     *
-     * return value
-     *    0 : the rack has been set
-     *    1 : the bag does not contain enough tiles
-     *    2 : the rack check was set on and failed
-     *    3 : the rack cannot be completed (Game_*_setrackrandom only)
-     *************************/
-    enum set_rack_mode {RACK_ALL, RACK_NEW, RACK_MANUAL};
-    int setRack(int player, set_rack_mode mode, bool check, const wstring& 
str);
+    void save(ostream &out, game_file_format format = FILE_FORMAT_STANDARD) 
const;
 
-    /**
-     * Methods to access already played words.
-     * The int parameter should be 0 <= int < getNTurns()
-     */
-    const History& getHistory() const { return m_history; }
+    /***************
+     * Setting the rack
+     ***************/
 
-    /**
-     * Methods to access players.
-     * The int parameter should be 0 <= int < getNPlayers()
-     */
-    int  getNPlayers() const    { return m_players.size(); }
-    int  getNHumanPlayers() const;
-    virtual void addHumanPlayer();
-    // TODO: Ability to specify which kind of AI player is wanted
-    virtual void addAIPlayer();
-    int  currPlayer() const     { return m_currPlayer; }
+    enum set_rack_mode {RACK_ALL, RACK_NEW, RACK_MANUAL};
 
-    /**
-     * Game handling
-     */
-    virtual int start() = 0;
-    virtual int play(const wstring &iCoord, const wstring &iWord) = 0;
-    virtual int endTurn() = 0;
 
 protected:
     /// All the players, indexed by their ID
     vector<Player*> m_players;
     /// ID of the "current" player
-    int m_currPlayer;
+    unsigned int m_currPlayer;
 
 // TODO: check what should be private and what should be protected
 // private:
@@ -181,7 +204,7 @@
     GameVariant m_variant;
 
     /// Dictionary currently associated to the game
-    const Dictionary * m_dic;
+    const Dictionary & m_dic;
 
     /// Bag
     Bag m_bag;
@@ -203,14 +226,91 @@
      * Helper functions
      *********************************************************/
 
-    int helperPlayRound(const Round &iRound);
-    int helperSetRackRandom(int p, bool iCheck, set_rack_mode mode);
-    int helperSetRackManual(int p, bool iCheck, const wstring &iLetters);
+    /** Play a Move for the given player, updating game history */
+    void helperPlayMove(unsigned int iPlayerId, const Move &iMove);
+
+    /**
+     * Set the rack randomly for the player p
+     * Possible return values:
+     *  0: everything went fine
+     *  1: the game is over
+     *  3: there is no chance to set the rack with the vowels/consonants
+     *     constraints
+     *
+     * Completing a rack randomly is more complex than it seems, because we
+     * must take into account several constraints:
+     *  - if iCheck is true, we must ensure that the rack contains a minimum
+     *    number of vowels and consonants (2 of each in the 15 first moves of
+     *    the game, 1 of each after)
+     *  - the game is over if the (real) bag contains only vowels or only
+     *    consonants, and in particular if it contains only one letter
+     *  - some letters (in particular the joker) can count both as a vowel and
+     *    as a consonant (but not at the same time)
+     *  - in a joker game, the joker must be present in the rack unless there
+     *    is no joker left in the bag. In addition, we must prevent that both
+     *    jokers are present in the rack at the same time
+     *  - if completing a rack doesn't meet the requirements on the vowels and
+     *    consonants, we must reject the rack completely (but only once,
+     *    otherwise we have no guarantee that the rejects will stop 
eventually).
+     *    This also means we have to check whether completing the rack with the
+     *    requirements is possible...
+     */
+    int helperSetRackRandom(unsigned int p, bool iCheck, set_rack_mode mode);
+
+    /**
+     * Set the rack randomly for the player p
+     * Possible return values:
+     *  0: everything went fine
+     *  1: the game is over
+     *  2: the rack was checked and was not correct (try calling the
+     *     function again)
+     *  3: there is no chance to set the rack with the vowels/consonants
+     *     constraints
+     *
+     * @deprecated: use helperSetRackRandom instead
+     */
+    int helperSetRackRandomOld(unsigned int p, bool iCheck, set_rack_mode 
mode);
+
+    /**
+     * Set the rack for the player p with the given letters
+     * Possible return values:
+     *  0: everything went fine
+     *  1: the bag doesn't have the wanted letters
+     *  2: the rack was checked for vowels/consonants and was not correct
+     */
+    int helperSetRackManual(unsigned int p, bool iCheck, const wstring 
&iLetters);
 
     void prevPlayer();
     void nextPlayer();
+
+    /**
+     * Check if the players rack can be obtained from the bag.
+     * Since letters are removed from the bag only when the
+     * round is played we need to check that ALL the racks
+     * are in the bag simultaneously.
+     *
+     * FIXME: since we do not check for all racks it works
+     * for training and duplicate but it won't work for
+     * freegames.
+     */
     bool rackInBag(const Rack &iRack, const Bag &iBag) const;
+
+    /**
+     * The realBag is the current bag minus all the racks
+     * present in the game. It represents the actual
+     * letters that are left in the bag.
+     * FIXME: in Duplicate mode, this method uses m_currPlayer to find the
+     * rack of the player. Since not all the players played the same word,
+     * it is important to set m_currPlayer accurately before!
+     */
     void realBag(Bag &iBag) const;
+
+    /**
+     * This function checks whether it is legal to play the given word at the
+     * given coordinates. If so, the function fills a Round object, also given
+     * as a parameter.
+     * Possible return values: same as the play() method
+     */
     int  checkPlayedWord(const wstring &iCoord,
                          const wstring &iWord, Round &oRound);
 
@@ -236,6 +336,14 @@
      */
     void gameSaveFormat_15(ostream &out) const;
 
+private:
+
+    /**
+     * Play a round on the board.
+     * This should only be called by helperPlayMove().
+     */
+    void helperPlayRound(unsigned int iPlayerId, const Round &iRound);
+
 };
 
 #endif /* _GAME_H_ */

Index: game/game_factory.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game_factory.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- game/game_factory.cpp       11 Aug 2006 22:14:21 -0000      1.8
+++ game/game_factory.cpp       8 Jan 2008 13:52:38 -0000       1.9
@@ -1,6 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière & Antoine Fraboulet
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *          Antoine Fraboulet <antoine.fraboulet @@ free.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,12 +19,19 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *****************************************************************************/
 
+#include "config.h"
+
 #include <getopt.h>
 #include <string>
+#include <fstream>
+#include <exception>
 
-#include "config.h"
-#include "dic.h"
 #include "game_factory.h"
+#include "game.h"
+#include "training.h"
+#include "freegame.h"
+#include "duplicate.h"
+#include "dic.h"
 
 
 GameFactory *GameFactory::m_factory = NULL;
@@ -35,8 +44,7 @@
 
 GameFactory::~GameFactory()
 {
-    if (m_dic)
-        Dic_destroy(m_dic);
+    delete m_dic;
 }
 
 
@@ -50,7 +58,6 @@
 
 void GameFactory::Destroy()
 {
-    if (m_factory)
         delete m_factory;
     m_factory = NULL;
 }
@@ -139,16 +146,20 @@
             cerr << "dict";
         else if (!found_m)
             cerr << "mode";
-        cerr << "\n";
+        cerr << endl;
 
         printUsage(argv[0]);
         return NULL;
     }
 
     // 3) Try to load the dictionary
-    if (Dic_load(&m_dic, m_dicStr.c_str()))
+    try
     {
-        cerr << "Could not load dictionary '" << m_dicStr << "'\n";
+        m_dic = new Dictionary(m_dicStr);
+    }
+    catch (std::exception &e)
+    {
+        cerr << e.what() << endl;
         return NULL;
     }
 
@@ -156,19 +167,19 @@
     Game *game = NULL;
     if (m_modeStr == "training" || m_modeStr == "t")
     {
-        game = createTraining(m_dic);
+        game = createTraining(*m_dic);
     }
     else if (m_modeStr == "freegame" || m_modeStr == "f")
     {
-        game = createFreeGame(m_dic);
+        game = createFreeGame(*m_dic);
     }
     else if (m_modeStr == "duplicate" || m_modeStr == "d")
     {
-        game = createDuplicate(m_dic);
+        game = createDuplicate(*m_dic);
     }
     else
     {
-        cerr << "Invalid game mode '" << m_modeStr << "'\n";
+        cerr << "Invalid game mode '" << m_modeStr << "'" << endl;
         return NULL;
     }
 
@@ -185,21 +196,21 @@
     return game;
 }
 
-Game* GameFactory::load(string filename, const Dictionary &iDic)
+
+Game* GameFactory::load(const string &iFileName, const Dictionary &iDic)
 {
-    Game* game;
-    FILE* fin;
-    if ((fin = fopen(filename.c_str(), "r")) == NULL)
+    FILE* fin = fopen(iFileName.c_str(), "r");
+    if (fin == NULL)
         {
-            printf("impossible d'ouvrir %s\n",
-                   filename.c_str());
+        printf("Cannot open %s\n", iFileName.c_str());
             return NULL;
         }
-    game = Game::load(fin,iDic);
+    Game *game = Game::load(fin, iDic);
     fclose(fin);
     return game;
 }
 
+
 void GameFactory::releaseGame(Game &iGame)
 {
     delete &iGame;
@@ -208,25 +219,26 @@
 
 void GameFactory::printUsage(const string &iBinaryName) const
 {
-    cout << "Usage: " << iBinaryName << " [options]\n"
-         << "Options:\n"
-         << "  -h, --help               Print this help and exit\n"
-         << "  -v, --version            Print version information and exit\n"
-         << "  -m, --mode {duplicate,d,freegame,f,training,t}\n"
-         << "                           Choose game mode (mandatory)\n"
-         << "  -d, --dict <string>      Choose a dictionary (mandatory)\n"
-         << "      --human              Add a human player\n"
-         << "      --ai                 Add a AI (Artificial Intelligence) 
player\n"
-         << "      --joker              Play with the \"Joker game\" 
variant\n";
+    cout << "Usage: " << iBinaryName << " [options]" << endl
+         << "Options:" << endl
+         << "  -h, --help               Print this help and exit" << endl
+         << "  -v, --version            Print version information and exit" << 
endl
+         << "  -m, --mode {duplicate,d,freegame,f,training,t}" << endl
+         << "                           Choose game mode (mandatory)" << endl
+         << "  -d, --dict <string>      Choose a dictionary (mandatory)" << 
endl
+         << "      --human              Add a human player" << endl
+         << "      --ai                 Add a AI (Artificial Intelligence) 
player" << endl
+         << "      --joker              Play with the \"Joker game\" variant" 
<< endl;
 }
 
 
 void GameFactory::printVersion() const
 {
-    cout << PACKAGE_STRING << "\n"
+    cout << PACKAGE_STRING << endl
          << "This program comes with NO WARRANTY, to the extent permitted by "
-         << "law.\nYou may redistribute it under the terms of the GNU General "
-         << "Public License;\nsee the file named COPYING for details.\n";
+         << "law." << endl << "You may redistribute it under the terms of the "
+         << "GNU General Public License;" << endl
+         << "see the file named COPYING for details." << endl;
 }
 
 

Index: game/game_factory.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game_factory.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- game/game_factory.h 11 Aug 2006 22:14:21 -0000      1.8
+++ game/game_factory.h 8 Jan 2008 13:52:38 -0000       1.9
@@ -1,6 +1,7 @@
 /*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,10 +21,15 @@
 #ifndef _GAME_FACTORY_H_
 #define _GAME_FACTORY_H_
 
-#include "game.h"
-#include "training.h"
-#include "freegame.h"
-#include "duplicate.h"
+#include <string>
+
+using std::string;
+
+class Dictionary;
+class Game;
+class Training;
+class FreeGame;
+class Duplicate;
 
 
 /**
@@ -52,7 +58,7 @@
      * load() might need some more work to be robust enough to
      * handle "hand written" files
      */
-    Game *load(string filename, const Dictionary &iDic);
+    Game *load(const string &iFileName, const Dictionary &iDic);
 
     Game *createFromCmdLine(int argc, char **argv);
 
@@ -62,13 +68,13 @@
 private:
 
     GameFactory();
-    virtual ~GameFactory();
+    ~GameFactory();
 
     /// The unique instance of the class
     static GameFactory *m_factory;
 
     /// Initial dictionary (it could be changed later)
-    Dictionary m_dic;
+    Dictionary *m_dic;
 
     /** Parameters specified on the command-line */
     //@{

Index: game/game_io.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game_io.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- game/game_io.cpp    23 Dec 2006 16:48:15 -0000      1.5
+++ game/game_io.cpp    8 Jan 2008 13:52:38 -0000       1.6
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2002-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,12 +26,16 @@
  *  \date   2002 - 2005
  */
 
+#include "dic.h"
 #include "pldrack.h"
 #include "round.h"
 #include "turn.h"
 #include "player.h"
 #include "game.h"
 #include "game_factory.h"
+#include "training.h"
+#include "freegame.h"
+#include "duplicate.h"
 #include "encoding.h"
 #include "debug.h"
 
@@ -192,14 +197,7 @@
     Game *pGame = NULL;
 
     char buff[4096];
-    int num;
-    char rack[20];
-    char word[20];
-    char ref[4];
-    int pts;
-    int player;
     char *pos;
-    Tile tile;
 
     /*************/
     /* Game type */
@@ -322,9 +320,15 @@
         }
 
 
+        int num;
+        char rack[20];
+        char tmpWord[20];
+        char ref[4];
+        int pts;
+        unsigned int player;
         char bonus = 0;
         int res = sscanf(buff, "   %2d | %8s | %s | %3s | %3d | %1d | %c",
-                         &num, rack, word, ref, &pts, &player, &bonus);
+                         &num, rack, tmpWord, ref, &pts, &player, &bonus);
 
         debug("   -- line %s",buff);
 
@@ -335,7 +339,7 @@
         }
 
         debug("              %2d | %8s | %s | %3s | %3d | %1d | %c \n",
-              num, rack, word, ref, pts, player, bonus);
+              num, rack, tmpWord, ref, pts, player, bonus);
 
         // Integrity checks
         // TODO: add more checks
@@ -344,7 +348,7 @@
             debug("   Game::load15 line -%s- points < 0  ?\n",buff);
             continue;
         }
-        if (player < 0 || player > pGame->getNPlayers())
+        if (player > pGame->getNPlayers())
         {
             debug("   Game::load15 line -%s- too much player 
(%d>%d)",buff,player,pGame->getNPlayers());
             continue;
@@ -357,10 +361,11 @@
 
         // Build a rack for the correct player
         PlayedRack pldrack;
-        if ((res = pldrack.setManual(convertToWc(rack))) > 0)
+        if (!iDic.validateLetters(convertToWc(rack)))
         {
-            debug("   Game::load15 set rack manual returned with error 
%d\n",res);
+            debug("   Game::load15 rack invalid for the current dictionary\n");
         }
+        pldrack.setManual(convertToWc(rack));
         debug("    history rack %s\n", 
convertToMb(pldrack.toString()).c_str());
 
         // Build a round
@@ -369,6 +374,8 @@
         if (bonus == '*')
             round.setBonus(1);
 
+        wstring word = convertToWc(tmpWord);
+        Tile tile;
         if (isalpha(ref[0]))
         {
             // Horizontal word
@@ -376,7 +383,7 @@
             round.accessCoord().setRow(ref[0] - 'A' + 1);
             round.accessCoord().setCol(atoi(ref + 1));
 
-            for (unsigned int i = 0; i < strlen(word); i++)
+            for (unsigned int i = 0; i < word.size(); i++)
             {
                 tile = Tile(word[i]);
 
@@ -386,8 +393,8 @@
                 }
                 else
                 {
-                    round.addRightFromRack(tile, islower(word[i]));
-                    pGame->m_bag.takeTile((islower(word[i])) ? Tile::Joker() : 
tile);
+                    round.addRightFromRack(tile, iswlower(word[i]));
+                    pGame->m_bag.takeTile((iswlower(word[i])) ? Tile::Joker() 
: tile);
                 }
             }
         }
@@ -398,7 +405,7 @@
             round.accessCoord().setRow(ref[strlen(ref) - 1] - 'A' + 1);
             round.accessCoord().setCol(atoi(ref));
 
-            for (unsigned int i = 0; i < strlen(word); i++)
+            for (unsigned int i = 0; i < word.size(); i++)
             {
                 tile = Tile(word[i]);
 
@@ -408,20 +415,20 @@
                 }
                 else
                 {
-                    round.addRightFromRack(tile, islower(word[i]));
-                    pGame->m_bag.takeTile((islower(word[i])) ? Tile::Joker() : 
tile);
+                    round.addRightFromRack(tile, iswlower(word[i]));
+                    pGame->m_bag.takeTile((iswlower(word[i])) ? Tile::Joker() 
: tile);
                 }
             }
         }
 
-        //             pGame->m_currPlayer = player;
-        //             // Update the rack for the player
-        //             pGame->m_players[player]->setCurrentRack(pldrack);
-        //             // End the turn for the current player (this creates a 
new rack)
-        //             pGame->m_players[player]->endTurn(round,num - 1);
+//                     pGame->m_currPlayer = player;
+//                     // Update the rack for the player
+//                     pGame->m_players[player]->setCurrentRack(pldrack);
+//                     // End the turn for the current player (this creates a 
new rack)
+//                     pGame->m_players[player]->endTurn(round,num - 1);
 
         // Play the round
-        pGame->helperPlayRound(round);
+        pGame->helperPlayRound(pGame->m_currPlayer, round);
     }
 
     /**************************************/
@@ -452,7 +459,7 @@
     {
         // We don't really know whose turn it is, but at least we know that
         // the game was saved while a human was to play.
-        for (int i = 0; i < pGame->getNPlayers(); i++)
+        for (unsigned int i = 0; i < pGame->getNPlayers(); i++)
         {
             if (pGame->m_players[i]->isHuman())
             {
@@ -490,21 +497,21 @@
     const string decal = "   ";
     out << IDENT_STRING << endl << endl;
 
-    for (int i = 0; i < m_history.getSize(); i++)
+    for (unsigned int i = 0; i < m_history.getSize(); i++)
     {
         const Turn& turn = m_history.getTurn(i);
-        string rack = 
convertToMb(turn.getPlayedRack().toString(PlayedRack::RACK_EXTRA));
-        string word = convertToMb(turn.getRound().getWord());
-        string coord = 
convertToMb(turn.getRound().getCoord().toString(Coord::COORD_MODE_LONG));
+        wstring rack = turn.getPlayedRack().toString(PlayedRack::RACK_EXTRA);
+        // FIXME: this will not work if the move does not correspond to a 
played round!
+        const Round &round = turn.getMove().getRound();
+        wstring word = round.getWord();
+        string coord = 
convertToMb(round.getCoord().toString(Coord::COORD_MODE_LONG));
 
         // rack [space] word [space] bonus points coord
-        sprintf(line,"%s%s%s%s%c%4d %s",
-                rack.c_str(),
-                string(12 - rack.size(), ' ').c_str(),
-                word.c_str(),
-                string(16 - word.size(), ' ').c_str(),
-                turn.getRound().getBonus() ? '*' : ' ',
-                turn.getRound().getPoints(),
+        sprintf(line,"%s%s%c%4d %s",
+                padAndConvert(rack, 12, false).c_str(),
+                padAndConvert(word, 16, false).c_str(),
+                round.getBonus() ? '*' : ' ',
+                round.getPoints(),
                 coord.c_str()
                );
 
@@ -513,7 +520,7 @@
 
     out << endl;
     out << decal << "total" << string(24,' ');
-    sprintf(line,"%4d", getCurrentPlayer().getPoints());
+    sprintf(line, "%4d", getCurrentPlayer().getPoints());
     out << line << endl;
 }
 
@@ -526,7 +533,7 @@
     // Game type
     out << "Game type: " << getModeAsString() << endl;
     // Player list
-    for (int i = 0; i < getNPlayers(); i++)
+    for (unsigned int i = 0; i < getNPlayers(); i++)
     {
         out << "Player " << i << ": ";
         if (m_players[i]->isHuman())
@@ -542,21 +549,69 @@
     out << decal << "===|==========|=================|=====|=====|===|======" 
<< endl;
 
     // Print the game itself
-    for (int i = 0; i < m_history.getSize(); i++)
+    for (unsigned int i = 0; i < m_history.getSize(); i++)
     {
         const Turn& turn = m_history.getTurn(i);
-        string rack = 
convertToMb(turn.getPlayedRack().toString(PlayedRack::RACK_EXTRA));
-        string word = convertToMb(turn.getRound().getWord());
-        string coord = convertToMb(turn.getRound().getCoord().toString());
-        sprintf(line, "%2d | %8s | %s%s | %3s | %3d | %1d | %c",
+        wstring rack = turn.getPlayedRack().toString(PlayedRack::RACK_EXTRA);
+        const Move &move = turn.getMove();
+        switch (move.getType())
+        {
+            case Move::VALID_ROUND:
+            {
+                const Round &round = move.getRound();
+                wstring word = round.getWord();
+                string coord = convertToMb(round.getCoord().toString());
+                sprintf(line, "%2d | %s | %s | %3s | %3d | %1d | %c",
                 i + 1,
-                rack.c_str(),                               /* pldrack     */
-                word.c_str(),                               /* word        */
-                string(15 - word.size(), ' ').c_str(),      /* fill spaces */
+                        padAndConvert(rack, 8).c_str(),             /* pldrack 
    */
+                        padAndConvert(word, 15, false).c_str(),     /* word    
    */
                 coord.c_str(),                              /* coord       */
-                turn.getRound().getPoints(),
+                        move.getScore(),
                 turn.getPlayer(),
-                turn.getRound().getBonus() ? '*' : ' ');
+                        round.getBonus() ? '*' : ' ');
+                break;
+            }
+            case Move::INVALID_WORD:
+            {
+                wstring word = move.getBadWord();
+                string coord = convertToMb(move.getBadCoord());
+                sprintf(line, "%2d | %s | %s | %3s | %3d | %1d |",
+                        i + 1,
+                        padAndConvert(rack, 8).c_str(),             /* pldrack 
    */
+                        padAndConvert(word, 15, false).c_str(),     /* word    
    */
+                        coord.c_str(),                              /* coord   
    */
+                        move.getScore(),
+                        turn.getPlayer());
+                break;
+            }
+            case Move::PASS:
+            {
+                string action = "(PASS)";
+                string coord = " - ";
+                sprintf(line, "%2d | %s | %s | %3s | %3d | %1d |",
+                        i + 1,
+                        padAndConvert(rack, 8).c_str(),             /* pldrack 
    */
+                        truncOrPad(action, 15, ' ').c_str(),        /* word    
    */
+                        coord.c_str(),                              /* coord   
    */
+                        move.getScore(),
+                        turn.getPlayer());
+                break;
+            }
+            case Move::CHANGE_LETTERS:
+            {
+                wstring action = L"(-" + move.getChangedLetters() + L")";
+                string coord = " - ";
+                sprintf(line, "%2d | %s | %s | %3s | %3d | %1d |",
+                        i + 1,
+                        padAndConvert(rack, 8).c_str(),             /* pldrack 
    */
+                        padAndConvert(action, 15, false).c_str(),   /* word    
    */
+                        coord.c_str(),                              /* coord   
    */
+                        move.getScore(),
+                        turn.getPlayer());
+                break;
+            }
+
+        }
 
         out << decal << line << endl;
     }
@@ -577,7 +632,7 @@
 
     // Print current rack for all the players
     out << endl;
-    for (int i = 0; i < getNPlayers(); i++)
+    for (unsigned int i = 0; i < getNPlayers(); i++)
     {
         wstring rack = m_players[i]->getCurrentRack().toString();
         out << "Rack " << i << ": " << convertToMb(rack) << endl;

Index: game/history.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/history.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- game/history.cpp    4 Aug 2007 20:01:28 -0000       1.11
+++ game/history.cpp    8 Jan 2008 13:52:38 -0000       1.12
@@ -1,21 +1,23 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
 
 /**
  *  \file   history.cpp
@@ -27,7 +29,7 @@
 #include <string>
 #include "rack.h"
 #include "pldrack.h"
-#include "round.h"
+#include "move.h"
 #include "turn.h"
 #include "history.h"
 #include "encoding.h"
@@ -41,7 +43,7 @@
 
 History::History()
 {
-    Turn* t = new Turn ();
+    Turn* t = new Turn();
     m_history.clear();
     m_history.push_back(t);
 }
@@ -51,17 +53,14 @@
 {
     for (unsigned int i = 0; i < m_history.size(); i++)
     {
-        if (m_history[i] != NULL)
-        {
             delete m_history[i];
-            m_history[i] = NULL;
-        }
     }
 }
 
 
-int History::getSize() const
+unsigned int History::getSize() const
 {
+    ASSERT(!m_history.empty(), "Invalid history size");
     return m_history.size() - 1;
 }
 
@@ -88,33 +87,40 @@
 
 const Turn& History::getTurn(unsigned int n) const
 {
-    // ASSERT(0 <= n && n < m_history.size(), "Wrong turn number");
     ASSERT(n < m_history.size(), "Wrong turn number");
     return *(m_history[n]);
 }
 
-/*
- * This function increments the number of racks, and fills the new rack
- * with the unplayed tiles from the previous one.
- * 03 sept 2000 : We have to sort the tiles according to the new rules
- */
-void History::playRound(int player, int turn, const Round& round)
+
+bool History::beforeFirstRound() const
 {
-    Rack rack;
-    Turn * current_turn;
+    for (unsigned int i = 0; i < m_history.size() - 1; i++)
+    {
+        if (m_history[i]->getMove().getType() == Move::VALID_ROUND)
+            return false;
+    }
+    return true;
+}
+
 
-    current_turn = m_history.back();
+void History::playMove(unsigned int iPlayer, unsigned int iTurn, const Move 
&iMove)
+{
+    Turn * current_turn = m_history.back();
 
-    /* set the number and the round */
-    current_turn->setNum(turn);
-    current_turn->setPlayer(player);
-    current_turn->setRound(round);
+    // Set the number and the round
+    current_turn->setNum(iTurn);
+    current_turn->setPlayer(iPlayer);
+    current_turn->setMove(iMove);
 
-    /* get what was the rack for the current turn */
+    // Get what was the rack for the current turn
+    Rack rack;
     current_turn->getPlayedRack().getRack(rack);
 
-    /* remove the played tiles from the rack */
-    for (int i = 0; i < round.getWordLen(); i++)
+    if (iMove.getType() == Move::VALID_ROUND)
+    {
+        // Remove the played tiles from the rack
+        const Round &round = iMove.getRound();
+        for (unsigned int i = 0; i < round.getWordLen(); i++)
     {
         if (round.isPlayedFromRack(i))
         {
@@ -124,8 +130,18 @@
                 rack.remove(round.getTile(i));
         }
     }
+    }
+    else if (iMove.getType() == Move::CHANGE_LETTERS)
+    {
+        // Remove the changed tiles from the rack
+        const wstring & changed = iMove.getChangedLetters();
+        for (unsigned int i = 0; i < changed.size(); ++i)
+        {
+            rack.remove(Tile(changed[i]));
+        }
+    }
 
-    /* create a new turn */
+    // Create a new turn
     Turn * next_turn = new Turn();
     PlayedRack pldrack;
     pldrack.setOld(rack);
@@ -146,11 +162,11 @@
         delete t;
     }
 
-    // now we have the previous played round in back()
-    Turn* t = m_history.back();
+    // Now we have the previous played round in back()
+    Turn *t = m_history.back();
     t->setNum(0);
     t->setPlayer(0);
-    t->setRound(Round());
+    //t->setRound(Round());
 #ifdef BACK_REMOVE_RACK_NEW_PART
     t->getPlayedRound().setNew(Rack());
 #endif

Index: game/history.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/history.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- game/history.h      22 Jan 2006 12:23:53 -0000      1.11
+++ game/history.h      8 Jan 2008 13:52:38 -0000       1.12
@@ -1,21 +1,23 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
 
 /**
  *  \file   history.h
@@ -33,7 +35,7 @@
 using std::wstring;
 using std::vector;
 
-class Round;
+class Move;
 class Turn;
 class PlayedRack;
 
@@ -41,15 +43,12 @@
  * History stores all the turns that have been played
  * This class is used many times in the game
  *  - one for the complete game
- *  - one for each of the players
- *
- * A History is never void (getSize() can be used as the is the current turn
- * number for the complete game history).
- *
- * History starts at zero.
+ *  - one for each player
  *
- * The top of the history is an empty
- * Turn until it has been filled and game is up to a new round.
+ * The top of the history is an empty Turn until it has been filled
+ * and the game is up to a new turn. So a History object is never empty.
+ * However, the getSize() method only returns the number of complete
+ * turns, and can therefore return 0.
  *
  * getCurrentRack() can/should be used to store the current played rack.
  * setCurrentRack must be called whenever the current played rack is
@@ -58,15 +57,14 @@
  * History owns the turns that it stores. Do not delete a turn referenced
  * by History
  */
-
 class History
 {
  public:
     History();
-    virtual ~History();
+    ~History();
 
-    /// get the size of the history
-    int               getSize() const;
+    /// Get the size of the history (without the current incomplete turn)
+    unsigned int getSize() const;
 
     /// Get the (possibly incomplete) rack
     const PlayedRack& getCurrentRack() const;
@@ -74,15 +72,26 @@
     /// Set the current rack
     void              setCurrentRack(const PlayedRack &iPld);
 
-    /// Get the previous turn
+    /// Get the previous (complete) turn
     const Turn&       getPreviousTurn() const;
 
-    /// Get turn 'n'
+    /// Get turn 'n' (starting at 0)
     const Turn&       getTurn(unsigned int) const;
 
-    /// Update the "history" with the given round and complete the turn.
-    /// A new turn is created with the remaining letters in the rack
-    void playRound(int player, int turn, const Round& round);
+    /**
+     * Return true if the history doesn't contain at least one move
+     * corresponding to a valid round, false otherwise.
+     * Said differently, this method checks whether a word was already played
+     * on the board.
+     */
+    bool beforeFirstRound() const;
+
+    /**
+     * Update the history with the given move and complete the turn.
+     * A new turn is created with the unplayed letters in the rack
+     * 03 sept 2000: We have to sort the tiles according to the new rules
+     */
+    void playMove(unsigned int player, unsigned int turn, const Move &iMove);
 
     /// Remove last turn
     void removeLastTurn();

Index: game/player.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/player.cpp,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -b -r1.14 -r1.15
--- game/player.cpp     22 Jan 2006 12:23:53 -0000      1.14
+++ game/player.cpp     8 Jan 2008 13:52:39 -0000       1.15
@@ -1,6 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 2004-2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2004-2007 Olivier Teulière & Antoine Fraboulet
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *          Antoine Fraboulet <antoine.fraboulet @@ free.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,14 +33,8 @@
 #include "debug.h"
 
 
-Player::Player(int iId)
-{
-    m_id = iId;
-    m_score = 0;
-}
-
-
-Player::~Player()
+Player::Player(unsigned int iId)
+    : m_id(iId), m_score(0)
 {
 }
 
@@ -61,19 +57,22 @@
 }
 
 
-const Round & Player::getLastRound() const
+const Move & Player::getLastMove() const
 {
-    return m_history.getPreviousTurn().getRound();
+    return m_history.getPreviousTurn().getMove();
 }
 
 
-void Player::endTurn(const Round &iRound, int iTurn)
+void Player::endTurn(const Move &iMove, unsigned int iTurn)
 {
-    m_history.playRound(m_id,iTurn,iRound);
+    addPoints(iMove.getScore());
+    m_history.playMove(m_id, iTurn, iMove);
 }
 
 void Player::removeLastTurn()
 {
+    // Remove points of the last turn
+    addPoints(- m_history.getPreviousTurn().getMove().getScore());
     m_history.removeLastTurn();
 }
 

Index: game/player.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/player.h,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -b -r1.18 -r1.19
--- game/player.h       22 Jan 2006 12:23:53 -0000      1.18
+++ game/player.h       8 Jan 2008 13:52:39 -0000       1.19
@@ -1,6 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 2004-2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2004-2007 Olivier Teulière & Antoine Fraboulet
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *          Antoine Fraboulet <antoine.fraboulet @@ free.fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -35,8 +37,8 @@
 class Player
 {
 public:
-    Player(int iId);
-    virtual ~Player();
+    explicit Player(unsigned int iId);
+    virtual ~Player() {}
 
     // Pseudo RTTI
     virtual bool isHuman() const = 0;
@@ -48,8 +50,8 @@
     const PlayedRack & getCurrentRack() const;
     // Get the previous rack
     const PlayedRack & getLastRack() const;
-    // Get the previous round (corresponding to the previous rack...)
-    const Round & getLastRound() const;
+    /// Get the previous move (corresponding to the previous rack...)
+    const Move & getLastMove() const;
 
     void setCurrentRack(const PlayedRack &iPld);
 
@@ -65,15 +67,19 @@
     void addPoints(int iPoints) { m_score += iPoints; }
     int  getPoints() const      { return m_score; }
 
-    // Update the player "history", with the given round.
-    // A new rack is created with the remaining letters
-    void endTurn(const Round &iRound, int iTurn);
+    /**
+     * Update the player "history", with the given move.
+     * A new rack is created with the remaining letters.
+     * The score of the player is updated with the one of the move, if it is
+     * meaningful.
+     */
+    void endTurn(const Move &iMove, unsigned int iTurn);
 
     wstring toString() const;
 
 private:
     /// ID of the player
-    int m_id;
+    unsigned int m_id;
 
     /// Score of the player
     int m_score;
@@ -89,8 +95,6 @@
 class HumanPlayer: public Player
 {
 public:
-    string name;
-
     HumanPlayer(int iId): Player(iId) {}
     virtual ~HumanPlayer() {}
 

Index: game/pldrack.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/pldrack.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- game/pldrack.cpp    22 Jan 2006 12:23:53 -0000      1.9
+++ game/pldrack.cpp    8 Jan 2008 13:52:39 -0000       1.10
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2002-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,17 +26,17 @@
  *  \date   2002 - 2005
  */
 
-#include "rack.h"
+#include <algorithm>
 #include "pldrack.h"
-
-#include "debug.h"
+#include "rack.h"
 
 
 PlayedRack::PlayedRack()
+    : m_reject(false)
 {
-  reject = false;
 }
 
+
 void PlayedRack::addOld(const Tile &t)
 {
     m_oldTiles.push_back(t);
@@ -51,26 +52,22 @@
 void PlayedRack::getOldTiles(vector<Tile> &oTiles) const
 {
     oTiles.clear();
-    for (int i = 0; i < nOld(); i++)
-        oTiles.push_back(m_oldTiles[i]);
+    oTiles = m_oldTiles;
 }
 
 
 void PlayedRack::getNewTiles(vector<Tile> &oTiles) const
 {
     oTiles.clear();
-    for (int i = 0; i < nNew(); i++)
-        oTiles.push_back(m_newTiles[i]);
+    oTiles = m_newTiles;
 }
 
 
 void PlayedRack::getAllTiles(vector<Tile> &oTiles) const
 {
     oTiles.clear();
-    for (int i = 0; i < nOld(); i++)
-        oTiles.push_back(m_oldTiles[i]);
-    for (int j = 0; j < nNew(); j++)
-        oTiles.push_back(m_newTiles[j]);
+    oTiles = m_oldTiles;
+    oTiles.insert(oTiles.end(), m_newTiles.begin(), m_newTiles.end());
 }
 
 
@@ -78,6 +75,7 @@
 {
     m_oldTiles.clear();
     m_newTiles.clear();
+    m_reject = false;
 }
 
 
@@ -122,72 +120,47 @@
 
 void PlayedRack::setOld(const Rack &iRack)
 {
-    list<Tile> l;
-    iRack.getTiles(l);
-
     m_oldTiles.clear();
-    list<Tile>::const_iterator it;
-    for (it = l.begin(); it != l.end(); it++)
-    {
-        addOld(*it);
-    }
+    iRack.getTiles(m_oldTiles);
 }
 
 
 void PlayedRack::setNew(const Rack &iRack)
 {
-    list<Tile> l;
-    iRack.getTiles(l);
-
     m_newTiles.clear();
-    list<Tile>::const_iterator it;
-    for (it = l.begin(); it != l.end(); it++)
-    {
-        addNew(*it);
-    }
+    iRack.getTiles(m_newTiles);
 }
 
-int PlayedRack::setManual(const wstring& iLetters)
+
+void PlayedRack::setManual(const wstring& iLetters)
 {
-    unsigned int i;
     reset();
 
-    if (iLetters.size() == 0)
-    {
-        return 0; /* empty is ok */
-    }
+    // An empty rack is OK
+    if (iLetters.empty())
+        return;
 
+    unsigned int i;
     for (i = 0; i < iLetters.size() && iLetters[i] != L'+'; i++)
     {
-        Tile tile(iLetters[i]);
-        if (tile.isEmpty())
-        {
-            return 1; /* */
-        }
-        addOld(tile);
+        addOld(Tile(iLetters[i]));
     }
 
     if (i < iLetters.size() && iLetters[i] == L'+')
     {
         for (i++; i < iLetters.size(); i++)
         {
-            Tile tile(iLetters[i]);
-            if (tile.isEmpty())
-            {
-                return 1; /* */
-            }
-            addNew(tile);
+            addNew(Tile(iLetters[i]));
         }
     }
-
-    return 0;
 }
 
-bool PlayedRack::checkRack(int cMin, int vMin) const
+
+bool PlayedRack::checkRack(unsigned int cMin, unsigned int vMin) const
 {
     vector<Tile>::const_iterator it;
-    int v = 0;
-    int c = 0;
+    unsigned int v = 0;
+    unsigned int c = 0;
 
     for (it = m_oldTiles.begin(); it != m_oldTiles.end(); it++)
     {
@@ -203,10 +176,9 @@
 }
 
 
-void PlayedRack::operator=(const PlayedRack &iOther)
+void PlayedRack::shuffleNew()
 {
-    m_oldTiles = iOther.m_oldTiles;
-    m_newTiles = iOther.m_newTiles;
+    std::random_shuffle(m_newTiles.begin(), m_newTiles.end());
 }
 
 
@@ -215,25 +187,23 @@
     wstring s;
     vector<Tile>::const_iterator it;
 
-    if (nOld() > 0)
+    if (mode >= RACK_EXTRA && m_reject)
     {
-        for (it = m_oldTiles.begin(); it != m_oldTiles.end(); it++)
-            s += it->toChar();
+        s += L"-";
     }
 
-    if (mode > RACK_SIMPLE && nOld() > 0 && nNew() > 0)
+    if (getNbOld() > 0)
     {
-        s += L"+";
+        for (it = m_oldTiles.begin(); it != m_oldTiles.end(); it++)
+            s += it->toChar();
     }
 
-    if (mode > RACK_EXTRA  && reject)
+    if (mode > RACK_SIMPLE && getNbOld() > 0 && getNbNew() > 0)
     {
-        s += L"-";
-        // new rack: reject
-        // not after a scrabble
+        s += L"+";
     }
 
-    if (nNew() > 0)
+    if (getNbNew() > 0)
     {
         for (it = m_newTiles.begin(); it != m_newTiles.end(); it++)
             s += it->toChar();

Index: game/pldrack.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/pldrack.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- game/pldrack.h      22 Jan 2006 12:23:53 -0000      1.12
+++ game/pldrack.h      8 Jan 2008 13:52:39 -0000       1.13
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2002-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -47,7 +48,6 @@
 {
 public:
     PlayedRack();
-    virtual ~PlayedRack() {}
 
     void reset();
     void resetNew();
@@ -58,11 +58,12 @@
 
     void setOld(const Rack &iRack);
     void setNew(const Rack &iRack);
-    int  setManual(const wstring& iLetters);
+    void setManual(const wstring& iLetters);
+    void setReject(bool iReject = true) { m_reject = iReject; }
 
-    int nTiles() const  { return nNew() + nOld(); }
-    int nNew() const    { return m_newTiles.size(); }
-    int nOld() const    { return m_oldTiles.size(); }
+    unsigned int getNbTiles() const  { return getNbNew() + getNbOld(); }
+    unsigned int getNbNew() const    { return m_newTiles.size(); }
+    unsigned int getNbOld() const    { return m_oldTiles.size(); }
 
     void addNew(const Tile &t);
     void addOld(const Tile &t);
@@ -70,9 +71,10 @@
     void getOldTiles(vector<Tile> &oTiles) const;
     void getAllTiles(vector<Tile> &oTiles) const;
 
-    bool checkRack(int cMin, int vMin) const;
+    bool checkRack(unsigned int cMin, unsigned int vMin) const;
 
-    void operator=(const PlayedRack &iOther);
+    /// Randomly change the order of the "new" tiles
+    void shuffleNew();
 
     enum display_mode
     {
@@ -83,7 +85,7 @@
     wstring toString(display_mode iShowExtraSigns = RACK_EXTRA) const;
 
 private:
-    bool reject;
+    bool m_reject;
     vector<Tile> m_oldTiles;
     vector<Tile> m_newTiles;
 };

Index: game/rack.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/rack.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- game/rack.cpp       22 Jan 2006 12:23:53 -0000      1.7
+++ game/rack.cpp       8 Jan 2008 13:52:39 -0000       1.8
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2002-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,23 +23,21 @@
  *  \file   rack.cpp
  *  \brief  Rack class : multiset of tiles
  *  \author Antoine Fraboulet & Olivier Teuliere
- *  \date   2002 - 2005
+ *  \date   2002 - 2007
  */
 
 #include "rack.h"
+#include "dic.h"
 #include "encoding.h"
 #include "debug.h"
 
-// FIXME: should not be here (duplicated from tile.cpp)
-#define TILES_NUMBER 28
-#define MIN_CODE 1
-
 
 Rack::Rack()
-    : m_tiles(TILES_NUMBER, 0), m_ntiles(0)
+    : m_tiles(Dictionary::GetDic().getTileNumber() + 1, 0), m_ntiles(0)
 {
 }
 
+
 void Rack::remove(const Tile &t)
 {
     ASSERT(in(t),
@@ -58,14 +57,13 @@
 }
 
 
-void Rack::getTiles(list<Tile> &oTiles) const
+void Rack::getTiles(vector<Tile> &oTiles) const
 {
-    for (unsigned int i = MIN_CODE; i < m_tiles.size(); i++)
-    {
-        for (unsigned int j = 0; j < m_tiles[i]; j++)
+    oTiles.reserve(m_ntiles);
+    for (unsigned int i = 1; i < m_tiles.size(); i++)
         {
-            oTiles.push_back(Tile::GetTileFromCode(i));
-        }
+        // Add m_tiles[i] copies of the tile at the end of the vector
+        oTiles.insert(oTiles.end(), m_tiles[i], 
Dictionary::GetDic().getTileFromCode(i));
     }
 }
 
@@ -73,12 +71,10 @@
 wstring Rack::toString()
 {
     wstring rs;
-    for (unsigned int i = MIN_CODE; i < m_tiles.size(); i++)
-    {
-        for (unsigned int j = 0; j < m_tiles[i]; j++)
+    for (unsigned int i = 1; i < m_tiles.size(); i++)
         {
-            rs += Tile::GetTileFromCode(i).toChar();
-        }
+        // Append m_tiles[i] copies of the char
+        rs.append(m_tiles[i], 
Dictionary::GetDic().getTileFromCode(i).toChar());
     }
     return rs;
 }

Index: game/rack.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/rack.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- game/rack.h 22 Jan 2006 12:23:53 -0000      1.9
+++ game/rack.h 8 Jan 2008 13:52:39 -0000       1.10
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2002-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,17 +23,17 @@
  *  \file   rack.h
  *  \brief  Rack class : multiset of tiles
  *  \author Antoine Fraboulet & Olivier Teuliere
- *  \date   2002 - 2005
+ *  \date   2002 - 2007
  */
 
 #ifndef _RACK_H_
 #define _RACK_H_
 
-#include "tile.h"
-#include <set>
-#include <list>
+#include <vector>
 #include <string>
 
+#include "tile.h"
+
 using namespace std;
 
 
@@ -44,23 +45,22 @@
 {
 public:
     Rack();
-    virtual ~Rack() {}
 
-    int nTiles() const          { return m_ntiles; }
-    bool isEmpty() const        { return nTiles() == 0; }
+    unsigned int getNbTiles() const      { return m_ntiles; }
+    bool isEmpty() const        { return getNbTiles() == 0; }
 
     unsigned int in(const Tile &t) const { return m_tiles[t.toCode()]; }
     void add(const Tile &t)     { m_tiles[t.toCode()]++; m_ntiles++; }
     void remove(const Tile &t);
     void clear();
-    void getTiles(list<Tile> &oTiles) const;
+    void getTiles(vector<Tile> &oTiles) const;
 
     wstring toString();
 
 private:
     /// Vector indexed by tile codes, containing the number of tiles
     vector<unsigned int> m_tiles;
-    int m_ntiles;
+    unsigned int m_ntiles;
 };
 
 #endif

Index: game/results.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/results.cpp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- game/results.cpp    1 Jan 2006 19:49:35 -0000       1.10
+++ game/results.cpp    8 Jan 2008 13:52:39 -0000       1.11
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -46,19 +47,19 @@
 };
 
 
-const Round & Results::get(int i) const
+const Round & Results::get(unsigned int i) const
 {
-    ASSERT(0 <= i && i < size(), "Results index out of bounds");
+    ASSERT(i < size(), "Results index out of bounds");
     return m_rounds[i];
 }
 
 
 void Results::search(const Dictionary &iDic, Board &iBoard,
-                     const Rack &iRack, int iTurn)
+                     const Rack &iRack, bool iFirstWord)
 {
     clear();
 
-    if (iTurn == 0)
+    if (iFirstWord)
     {
         iBoard.searchFirst(iDic, iRack, *this);
     }
@@ -67,11 +68,11 @@
         iBoard.search(iDic, iRack, *this);
     }
 
-    sort_by_points();
+    sortByPoints();
 }
 
 
-void Results::sort_by_points()
+void Results::sortByPoints()
 {
     less_points lp;
     std::sort(m_rounds.begin(), m_rounds.end(), lp);

Index: game/results.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/results.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- game/results.h      1 Jan 2006 19:49:35 -0000       1.8
+++ game/results.h      8 Jan 2008 13:52:39 -0000       1.9
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -33,9 +34,9 @@
 
 using namespace std;
 
+class Dictionary;
 class Board;
 class Rack;
-typedef struct _Dictionary * Dictionary;
 
 
 /**
@@ -47,24 +48,22 @@
 class Results
 {
 public:
-    Results() {}
-    virtual ~Results() {}
-
-    int size() const    { return m_rounds.size(); }
+    unsigned int size() const    { return m_rounds.size(); }
     void clear()        { m_rounds.clear(); }
-    const Round & get(int) const;
+    const Round & get(unsigned int) const;
 
-    // Perform a search on the board
+    /// Perform a search on the board
     void search(const Dictionary &iDic, Board &iBoard,
-                const Rack &iRack, int iTurn);
+                const Rack &iRack, bool iFirstWord);
 
-    // FIXME: These methods are used to fill the container with the rounds,
-    // but they should not be part of the public interface
+    // FIXME: This method is used to fill the container with the rounds,
+    // but it should not be part of the public interface
     void add(const Round &iRound)   { m_rounds.push_back(iRound); }
 
-    void sort_by_points();
 private:
     vector<Round> m_rounds;
+
+    void sortByPoints();
 };
 
 #endif

Index: game/round.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/round.cpp,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- game/round.cpp      4 Aug 2007 20:01:28 -0000       1.12
+++ game/round.cpp      8 Jan 2008 13:52:39 -0000       1.13
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -52,33 +53,27 @@
 
 void Round::setWord(const vector<Tile> &iTiles)
 {
-    m_word.clear();
-
-    vector<Tile>::const_iterator it;
-    for (it = iTiles.begin(); it != iTiles.end(); it++)
-    {
-        m_word.push_back(*it);
+    m_word = iTiles;
         // XXX: always from rack?
-        m_tileOrigin.push_back(FROMRACK);
-    }
+    m_tileOrigin = vector<char>(iTiles.size(), FROMRACK);
 }
 
 
-void Round::setFromRack(int iIndex)
+void Round::setFromRack(unsigned int iIndex)
 {
     m_tileOrigin[iIndex] &= ~FROMBOARD;
     m_tileOrigin[iIndex] |= FROMRACK;
 }
 
 
-void Round::setFromBoard(int iIndex)
+void Round::setFromBoard(unsigned int iIndex)
 {
     m_tileOrigin[iIndex] &= ~FROMRACK;
     m_tileOrigin[iIndex] |= FROMBOARD;
 }
 
 
-void Round::setJoker(int iIndex, bool value)
+void Round::setJoker(unsigned int iIndex, bool value)
 {
     if (value)
         m_tileOrigin[iIndex] |= JOKER;
@@ -87,25 +82,19 @@
 }
 
 
-bool Round::isJoker(int iIndex) const
+bool Round::isJoker(unsigned int iIndex) const
 {
      return m_tileOrigin[iIndex] & JOKER;
 }
 
 
-const Tile& Round::getTile(int iIndex) const
+const Tile& Round::getTile(unsigned int iIndex) const
 {
      return m_word[iIndex];
 }
 
 
-int Round::getWordLen() const
-{
-     return m_word.size();
-}
-
-
-bool Round::isPlayedFromRack(int iIndex) const
+bool Round::isPlayedFromRack(unsigned int iIndex) const
 {
      return m_tileOrigin[iIndex] & FROMRACK;
 }
@@ -150,7 +139,7 @@
     wchar_t c;
     wstring s;
 
-    for (int i = 0; i < getWordLen(); i++)
+    for (unsigned int i = 0; i < getWordLen(); i++)
     {
         c = getTile(i).toChar();
         if (isJoker(i))

Index: game/round.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/round.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- game/round.h        22 Jan 2006 12:23:53 -0000      1.12
+++ game/round.h        8 Jan 2008 13:52:39 -0000       1.13
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -42,7 +43,6 @@
      *
      *************************/
     Round();
-    virtual ~Round() {}
     void init();
 
     /*************************
@@ -58,21 +58,21 @@
      *************************/
     void setPoints(int iPoints)    { m_points = iPoints; }
     void setBonus(bool iBonus)     { m_bonus = iBonus; }
-    void setTile(int iIndex, const Tile &iTile) { m_word[iIndex] = iTile; }
+    void setTile(unsigned int iIndex, const Tile &iTile) { m_word[iIndex] = 
iTile; }
     void setWord(const vector<Tile> &iTiles);
-    void setFromRack(int iIndex);
-    void setFromBoard(int iIndex);
-    void setJoker(int iIndex, bool value = true);
+    void setFromRack(unsigned int iIndex);
+    void setFromBoard(unsigned int iIndex);
+    void setJoker(unsigned int iIndex, bool value = true);
 
     /*************************
      * General getters
      *************************/
-    bool isJoker         (int iIndex) const;
-    bool isPlayedFromRack(int iIndex) const;
-    const Tile& getTile  (int iIndex) const;
+    bool isJoker         (unsigned int iIndex) const;
+    bool isPlayedFromRack(unsigned int iIndex) const;
+    const Tile& getTile  (unsigned int iIndex) const;
 
     wstring getWord() const;
-    int getWordLen()  const;
+    unsigned int getWordLen() const { return m_word.size(); }
     int getPoints()   const       { return m_points; }
     int getBonus()    const       { return m_bonus; }
 

Index: game/training.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/training.cpp,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- game/training.cpp   11 Aug 2006 22:15:13 -0000      1.17
+++ game/training.cpp   8 Jan 2008 13:52:40 -0000       1.18
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,10 +19,13 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *****************************************************************************/
 
+#include <algorithm>
+
 #include "dic.h"
 #include "tile.h"
 #include "rack.h"
 #include "round.h"
+#include "move.h"
 #include "pldrack.h"
 #include "player.h"
 #include "training.h"
@@ -30,12 +34,8 @@
 #include "debug.h"
 
 
-Training::Training(const Dictionary &iDic): Game(iDic)
-{
-}
-
-
-Training::~Training()
+Training::Training(const Dictionary &iDic)
+    : Game(iDic)
 {
 }
 
@@ -46,11 +46,10 @@
 
     int res;
     int try_number = 0;
-    int p = m_currPlayer;
     m_results.clear();
     do
     {
-        res = helperSetRackRandom(p, iCheck, mode);
+        res = helperSetRackRandomOld(m_currPlayer, iCheck, mode);
         try_number ++;
     } while (res == 2 && try_number < MAX_RANDOM_TRY);
     // 0 : ok
@@ -59,28 +58,27 @@
     return res;
 }
 
+
 int Training::setRackManual(bool iCheck, const wstring &iLetters)
 {
-    int res;
-    int p = m_currPlayer;
-    wstring::iterator it;
-    wstring uLetters; // uppercase letters
-    // letters can be lowercase or uppercase as they are
+    // Letters can be lowercase or uppercase as they are
     // coming from user input. We do not consider a lowercase
     // letter to be a joker which has been assigned to a letter.
+    // As a result, we simply make all the letters uppercase
+    wstring upperLetters = iLetters;
+    std::transform(upperLetters.begin(), upperLetters.end(),
+                   upperLetters.begin(), towupper);
+    int res = helperSetRackManual(m_currPlayer, iCheck, upperLetters);
+    // 0: ok
+    // 1: not enough tiles
+    // 2: check failed (number of vowels before round 15)
+    // 3: letters not in the dictionary
+    if (res == 0)
     m_results.clear();
-    uLetters = iLetters;
-    for (it = uLetters.begin(); it != uLetters.end(); it ++)
-    {
-        *it = towupper(*it);
-    }
-    res = helperSetRackManual(p, iCheck, uLetters);
-    // 0 : ok
-    // 1 : not enough tiles
-    // 2 : check failed (number of voyels before round 15)
     return res;
 }
 
+
 int Training::setRack(set_rack_mode iMode, bool iCheck, const wstring 
&iLetters)
 {
     int res = 0;
@@ -99,9 +97,10 @@
     return res;
 }
 
+
 int Training::play(const wstring &iCoord, const wstring &iWord)
 {
-    /* Perform all the validity checks, and fill a round */
+    // Perform all the validity checks, and fill a round
     Round round;
 
     int res = checkPlayedWord(iCoord, iWord, round);
@@ -111,23 +110,21 @@
         return res;
     }
 
-    /* Update the rack and the score of the current player */
     debug("play: %s %s %d\n",
           convertToMb(round.getWord()).c_str(),
           convertToMb(round.getCoord().toString()).c_str(),
           round.getPoints());
 
-    m_players[m_currPlayer]->addPoints(round.getPoints());
-    // see game.cpp::helperPlayRound():99 comment
-    m_players[m_currPlayer]->endTurn(round, m_history.getSize());
+    Move move(round);
+    // Update the rack and the score of the current player
+    // Player::endTurn() must be called before Game::helperPlayMove().
+    // See the big comment in game.cpp, line 96
+    m_players[m_currPlayer]->endTurn(move, m_history.getSize());
 
-    /* Everything is OK, we can play the word */
-    if (helperPlayRound(round))
-    {
-        debug("play: error during play\n");
-    }
+    // Everything is OK, we can play the word
+    helperPlayMove(m_currPlayer, move);
 
-    /* Next turn */
+    // Next turn
     endTurn();
 
     return 0;
@@ -146,10 +143,9 @@
 }
 
 
-int Training::endTurn()
+void Training::endTurn()
 {
-    // Nothing to do?
-    return 0;
+    // Nothing to do, but this method is kept for consistency with other modes
 }
 
 
@@ -159,31 +155,27 @@
     Rack r;
     m_players[m_currPlayer]->getCurrentRack().getRack(r);
     debug("Training::search for %s\n", convertToMb(r.toString()).c_str());
-    m_results.search(*m_dic, m_board, r, m_history.getSize());
+    m_results.search(m_dic, m_board, r, m_history.beforeFirstRound());
 }
 
 
-int Training::playResult(int n)
+int Training::playResult(unsigned int n)
 {
-    Player *player = m_players[m_currPlayer];
     if (n >= m_results.size())
         return 2;
-    const Round &round = m_results.get(n);
 
-    /* Update the rack and the score of the current player */
-    player->addPoints(round.getPoints());
-    player->endTurn(round, m_history.getSize());
+    Move move(m_results.get(n));
+    // Update the rack and the score of the current player
+    m_players[m_currPlayer]->endTurn(move, m_history.getSize());
 
-    int res = helperPlayRound(round);
-
-    if (res == 0)
+    // Update the game
+    helperPlayMove(m_currPlayer, move);
         m_results.clear();
 
-    /* Next turn */
-    // XXX: Should it be done by the interface instead?
+    // Next turn
     endTurn();
 
-    return res;
+    return 0;
 }
 
 
@@ -201,9 +193,9 @@
 }
 
 
-void Training::testPlay(int num)
+void Training::testPlay(unsigned int num)
 {
-    ASSERT(0 <= num && num < m_results.size(), "Wrong result number");
+    ASSERT(num < m_results.size(), "Wrong result number");
     m_testRound = m_results.get(num);
     m_board.testRound(m_results.get(num));
 }
@@ -215,6 +207,7 @@
     m_testRound = Round();
 }
 
+
 wstring Training::getTestPlayWord() const
 {
     return m_testRound.getWord();

Index: game/training.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/training.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- game/training.h     22 Jan 2006 12:23:53 -0000      1.15
+++ game/training.h     8 Jan 2008 13:52:40 -0000       1.16
@@ -1,7 +1,8 @@
 /*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Antoine Fraboulet <address@hidden>
- *          Olivier Teuliere  <address@hidden>
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,6 +25,7 @@
 #include <string>
 
 #include "game.h"
+#include "round.h"
 #include "results.h"
 
 using std::string;
@@ -34,6 +36,7 @@
  * This class handles the logic specific to a training game.
  * As its name indicates, it is not a game in the literal meaning of the word,
  * in particular because the rack can be set at will.
+ *
  * Note: No player should be added to this game, a human player is added
  * automatically (in the start() method)
  */
@@ -48,10 +51,13 @@
      * Game handling
      *************************/
     virtual int start();
+
+    /// See description of Game::play()
     virtual int play(const wstring &iCoord, const wstring &iWord);
-    virtual int endTurn();
+
     void search();
-    int playResult(int);
+    const Results& getResults() const { return m_results; };
+    int playResult(unsigned int);
 
     int setRackRandom(bool, set_rack_mode);
     int setRackManual(bool iCheck, const wstring &iLetters);
@@ -59,7 +65,7 @@
 
     /*************************
      * Override the default behaviour of these methods, because in training
-     * we only want a human player
+     * mode we only want a human player
      *************************/
     virtual void addHumanPlayer();
     virtual void addAIPlayer();
@@ -68,23 +74,25 @@
      * Functions to access the current search results
      * The int parameter should be 0 <= int < getNResults
      *************************/
-    const Results& getResults() const { return m_results; };
 
-    /// Place a temporary word on the board for preview purpose
-    void testPlay(int);
-    /// Remove the temporary word(s)
+    /// Place a temporary word on the board for preview purposes
+    void testPlay(unsigned int);
+    /// Remove the temporary word
     void removeTestPlay();
     /// Get the temporary word
     wstring getTestPlayWord() const;
 
 private:
-    // Private constructor and destructor to force using the GameFactory class
+    /// Private constructor and destructor to force using the GameFactory class
     Training(const Dictionary &iDic);
-    virtual ~Training();
 
-    // Search results, with all the possible rounds
-    Round   m_testRound;
+    void endTurn();
+
+    /// Search results, with all the possible rounds
     Results m_results;
+
+    /// Round corresponding to the last test play (if any)
+    Round m_testRound;
 };
 
 #endif /* _TRAINING_H_ */

Index: game/turn.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/turn.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- game/turn.cpp       22 Jan 2006 12:23:53 -0000      1.11
+++ game/turn.cpp       8 Jan 2008 13:52:40 -0000       1.12
@@ -1,67 +1,57 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
 
 /**
  *  \file   turn.cpp
- *  \brief  Game turn (= id + pldrack + round)
+ *  \brief  Game turn (= id + pldrack + move)
  *  \author Antoine Fraboulet
  *  \date   2005
  */
 
-#include <string>
-#include "pldrack.h"
-#include "round.h"
 #include "turn.h"
 
 
+// FIXME: move set to an invalid value. It would be better to get rid of this
+// constructor completely
 Turn::Turn()
+    : m_num(0), m_playerId(0), m_move(L"", L"")
 {
-    m_num      = 0;
-    m_playerId = 0;
-    m_pldrack  = PlayedRack();
-    m_round    = Round();
 }
 
-Turn::Turn(int iNum, int iPlayerId,
-           const PlayedRack& iPldRack, const Round& iRound)
-    : m_num(iNum), m_playerId(iPlayerId), m_pldrack(iPldRack), m_round(iRound)
-{
-}
 
-#if 0
-void Turn::operator=(const Turn &iOther)
+Turn::Turn(unsigned int iNum, unsigned int iPlayerId,
+           const PlayedRack& iPldRack, const Move& iMove)
+    : m_num(iNum), m_playerId(iPlayerId), m_pldrack(iPldRack), m_move(iMove)
 {
-    m_num      = iOther.m_num;
-    m_playerId = iOther.m_playerId;
-    m_pldrack  = iOther.m_pldrack;
-    m_round    = iOther.m_round;
 }
-#endif
+
 
 wstring Turn::toString(bool iShowExtraSigns) const
 {
-    wstring rs = L"";
+    wstring rs;
     if (iShowExtraSigns)
     {
         // TODO
     }
-    rs = rs + m_pldrack.toString() + L" " + m_round.toString();
+    rs = rs + m_pldrack.toString() + L" " + m_move.toString();
     return rs;
 }
 

Index: game/turn.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/turn.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- game/turn.h 22 Jan 2006 12:23:53 -0000      1.9
+++ game/turn.h 8 Jan 2008 13:52:40 -0000       1.10
@@ -1,25 +1,27 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
 
 /**
  *  \file   turn.h
- *  \brief  Game turn (= id + pldrack + round)
+ *  \brief  Game turn (= id + pldrack + move)
  *  \author Antoine Fraboulet
  *  \date   2005
  */
@@ -27,35 +29,45 @@
 #ifndef _TURN_H
 #define _TURN_H
 
+#include <string>
+#include "pldrack.h"
+#include "move.h"
+
+using std::wstring;
+
+
+/**
+ * A Turn is the information about one 'move' done by a player.
+ * It consists of the player who played, the rack, and the actual move.
+ * A turn also has an id (XXX: currently never read)
+ *
+ * This class has no logic, it is merely there to aggregate corresponding
+ * data.
+ */
 class Turn
 {
 public:
     Turn();
-    Turn(int iNum, int iPlayerId,
-         const PlayedRack& iPldRack, const Round& iRound);
-    virtual ~Turn() {};
+    Turn(unsigned int iNum, unsigned int iPlayerId,
+         const PlayedRack& iPldRack, const Move& iMove);
 
-    void setNum(int iNum)                          { m_num = iNum; }
-    void setPlayer(int iPlayerId)                  { m_playerId = iPlayerId; }
+    void setNum(unsigned int iNum)                 { m_num = iNum; }
+    void setPlayer(unsigned int iPlayerId)         { m_playerId = iPlayerId; }
     void setPlayedRack(const PlayedRack& iPldRack) { m_pldrack = iPldRack; }
-    void setRound(const Round& iRound)             { m_round = iRound; }
+    void setMove(const Move& iMove)             { m_move = iMove; }
 
-    int               getNum()        const { return m_num; }
-    int               getPlayer()     const { return m_playerId; }
+    unsigned int      getNum()        const { return m_num; }
+    unsigned int      getPlayer()     const { return m_playerId; }
     const PlayedRack& getPlayedRack() const { return m_pldrack; }
-    const Round&      getRound()      const { return m_round; }
+    const Move&       getMove()       const { return m_move; }
 
-#if 0
-    void operator=(const Turn &iOther);
-#endif
     wstring toString(bool iShowExtraSigns = false) const;
 
 private:
-    int        m_num;
-    int        m_playerId;
+    unsigned int m_num;
+    unsigned int m_playerId;
     PlayedRack m_pldrack;
-    Round      m_round;
-
+    Move         m_move;
 };
 
 #endif

Index: m4/.cvsignore
===================================================================
RCS file: /cvsroot/eliot/eliot/m4/.cvsignore,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- m4/.cvsignore       27 Feb 2005 20:11:53 -0000      1.1
+++ m4/.cvsignore       8 Jan 2008 13:52:40 -0000       1.2
@@ -1,18 +1,30 @@
 codeset.m4
 gettext.m4
+glibc2.m4
 glibc21.m4
 iconv.m4
 intdiv0.m4
+intl.m4
+intldir.m4
+intmax.m4
 inttypes-pri.m4
-inttypes.m4
 inttypes_h.m4
-isc-posix.m4
 lcmessage.m4
 lib-ld.m4
 lib-link.m4
 lib-prefix.m4
+lock.m4
+longdouble.m4
+longlong.m4
+nls.m4
+po.m4
+printf-posix.m4
 progtest.m4
+size_max.m4
 stdint_h.m4
 uintmax_t.m4
 ulonglong.m4
-
+visibility.m4
+wchar_t.m4
+wint_t.m4
+xsize.m4

Index: po/.cvsignore
===================================================================
RCS file: /cvsroot/eliot/eliot/po/.cvsignore,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- po/.cvsignore       6 Feb 2005 22:18:11 -0000       1.1
+++ po/.cvsignore       8 Jan 2008 13:52:40 -0000       1.2
@@ -1,6 +1,7 @@
 Makefile
 Makefile.in
 Makefile.in.in
+Makevars.template
 POTFILES
 *.mo
 *.gmo
@@ -8,3 +9,9 @@
 *.sin
 *.header
 Rules-quot
+stamp-po
address@hidden
address@hidden
address@hidden
address@hidden
+

Index: po/LINGUAS
===================================================================
RCS file: /cvsroot/eliot/eliot/po/LINGUAS,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- po/LINGUAS  6 Feb 2005 22:18:11 -0000       1.1
+++ po/LINGUAS  8 Jan 2008 13:52:40 -0000       1.2
@@ -1 +1 @@
-fr
+fr address@hidden address@hidden

Index: po/POTFILES.in
===================================================================
RCS file: /cvsroot/eliot/eliot/po/POTFILES.in,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- po/POTFILES.in      1 Jan 2006 19:34:31 -0000       1.3
+++ po/POTFILES.in      8 Jan 2008 13:52:40 -0000       1.4
@@ -1,16 +1,20 @@
-./dic/automaton.c
+./dic/automaton.cpp
 ./dic/automaton.h
-./dic/compdic.c
-./dic/dic.c
+./dic/header.cpp
+./dic/header.h
+./dic/dic.cpp
 ./dic/dic.h
 ./dic/dic_internals.h
-./dic/dic_search.c
-./dic/dic_search.h
-./dic/hashtable.c
+./dic/dic_search.cpp
+./dic/hashtable.cpp
 ./dic/hashtable.h
-./dic/listdic.c
-./dic/regexp.c
+./dic/regexp.cpp
 ./dic/regexp.h
+./dic/tile.cpp
+./dic/tile.h
+./dic/compdic.cpp
+./dic/listdic.cpp
+./dic/regexpmain.cpp
 ./game/bag.cpp
 ./game/bag.h
 ./game/board.cpp
@@ -39,11 +43,9 @@
 ./game/results.h
 ./game/round.cpp
 ./game/round.h
-./game/tile.cpp
-./game/tile.h
 ./game/training.cpp
 ./game/training.h
-./utils/eliottxt.cpp
+#./utils/eliottxt.cpp
 ./utils/game_io.h
 ./utils/game_io.cpp
 ./utils/ncurses.cpp
@@ -68,4 +70,3 @@
 ./wxwin/printout.cc
 ./wxwin/searchpanel.h
 ./wxwin/searchpanel.cc
-./config.h

Index: po/eliot.pot
===================================================================
RCS file: /cvsroot/eliot/eliot/po/eliot.pot,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- po/eliot.pot        2 Apr 2005 22:04:59 -0000       1.6
+++ po/eliot.pot        8 Jan 2008 13:52:40 -0000       1.7
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2005-04-03 00:04+0200\n"
+"POT-Creation-Date: 2007-12-23 23:08+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <address@hidden>\n"
 "Language-Team: LANGUAGE <address@hidden>\n"
@@ -16,247 +16,1163 @@
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: utils/ncurses.cpp:184
-msgid " Scores "
+#: dic/header.cpp:317 dic/header.cpp:318
+msgid "Unknown (old format)"
 msgstr ""
 
-#: utils/ncurses.cpp:190
+#: dic/header.cpp:492
+#, c-format
+msgid "dictionary name: %s\n"
+msgstr ""
+
+#: dic/header.cpp:497
+#, c-format
+msgid "compressed on: %s\n"
+msgstr ""
+
+#: dic/header.cpp:501
+#, c-format
+msgid "compressed on: Unknown date (old format)\n"
+msgstr ""
+
+#: dic/header.cpp:503
+#, c-format
+msgid "compressed using a binary compiled by: %s\n"
+msgstr ""
+
+#: dic/header.cpp:504
+#, c-format
+msgid "dictionary type: %s\n"
+msgstr ""
+
+#: dic/header.cpp:505
+#, c-format
+msgid "letters: %s\n"
+msgstr ""
+
+#: dic/header.cpp:506
+#, c-format
+msgid "number of letters: %d\n"
+msgstr ""
+
+#: dic/header.cpp:507
+#, c-format
+msgid "number of words: %d\n"
+msgstr ""
+
+#: dic/header.cpp:508
+#, c-format
+msgid "header size: %u bytes\n"
+msgstr ""
+
+#: dic/header.cpp:510
+#, c-format
+msgid "root: %d (edge)\n"
+msgstr ""
+
+#: dic/header.cpp:511
+#, c-format
+msgid "nodes: %d used + %d saved\n"
+msgstr ""
+
+#: dic/header.cpp:512
+#, c-format
+msgid "edges: %d used + %d saved\n"
+msgstr ""
+
+#: dic/header.cpp:514
+#, c-format
+msgid "letter | points | frequency | vowel | consonant\n"
+msgstr ""
+
+#: dic/compdic.cpp:392
+msgid "Mandatory options:"
+msgstr ""
+
+#: dic/compdic.cpp:393
+msgid "  -d, --dicname <string>  Set the dictionary name and version"
+msgstr ""
+
+#: dic/compdic.cpp:394
+msgid ""
+"  -l, --letters <string>  Path to the file containing the letters (see below)"
+msgstr ""
+
+#: dic/compdic.cpp:395
+msgid ""
+"  -i, --input <string>    Path to the uncompressed dictionary file (encoded "
+"in UTF-8)"
+msgstr ""
+
+#: dic/compdic.cpp:396
+msgid ""
+"  -o, --output <string    Path to the generated compressed dictionary file"
+msgstr ""
+
+#: dic/compdic.cpp:397
+msgid "Other options:"
+msgstr ""
+
+#: dic/compdic.cpp:398
+msgid "  -h, --help              Print this help and exit"
+msgstr ""
+
+#: dic/compdic.cpp:399
+msgid "Example:"
+msgstr ""
+
+#: dic/compdic.cpp:400
+msgid " -d 'ODS 5.0' -l letters.txt -i ods5.txt -o ods5.dawg"
+msgstr ""
+
+#: dic/compdic.cpp:402
+msgid ""
+"The file containing the letters (--letters switch) must be UTF-8 encoded."
+msgstr ""
+
+#: dic/compdic.cpp:403
+msgid ""
+"Each line corresponds to one letter, and must contain 5 fields separated "
+"with "
+msgstr ""
+
+#: dic/compdic.cpp:404
+msgid "one or more space(s)."
+msgstr ""
+
+#: dic/compdic.cpp:405
+msgid " - 1st field: the letter itself"
+msgstr ""
+
+#: dic/compdic.cpp:406
+msgid " - 2nd field: the points of the letter"
+msgstr ""
+
+#: dic/compdic.cpp:407
+msgid ""
+" - 3rd field: the frequency of the letter (how many letters of this kind in "
+"the game)"
+msgstr ""
+
+#: dic/compdic.cpp:408
+msgid ""
+" - 4th field: 1 if the letter is considered as a vowel in Scrabble game, 0 "
+"otherwise"
+msgstr ""
+
+#: dic/compdic.cpp:409
+msgid ""
+" - 5th field: 1 if the letter is considered as a consonant in Scrabble game, "
+"0 otherwise"
+msgstr ""
+
+#: dic/compdic.cpp:410
+msgid "Example for french:"
+msgstr ""
+
+#: dic/compdic.cpp:411
+msgid "A 1 9 1 0"
+msgstr ""
+
+#: dic/compdic.cpp:412
+msgid "[...]"
+msgstr ""
+
+#: dic/compdic.cpp:413
+msgid "Z 10 1 0 1"
+msgstr ""
+
+#: dic/compdic.cpp:414
+msgid "? 0 2 1 1"
+msgstr ""
+
+#: dic/compdic.cpp:484
+msgid "A mandatory option is missing"
+msgstr ""
+
+#: dic/compdic.cpp:492
+msgid "Cannot stat uncompressed dictionary "
+msgstr ""
+
+#: dic/compdic.cpp:500
+msgid "Cannot open output file "
+msgstr ""
+
+#: dic/compdic.cpp:548
+#, c-format
+msgid " Load time: %.3f s\n"
+msgstr ""
+
+#: dic/compdic.cpp:549
+#, c-format
+msgid " Compression time: %.3f s\n"
+msgstr ""
+
+#: dic/compdic.cpp:551
+#, c-format
+msgid " Maximum recursion level reached: %d\n"
+msgstr ""
+
+#: dic/listdic.cpp:100
+#, c-format
+msgid "offset binary   | structure\n"
+msgstr ""
+
+#: dic/listdic.cpp:109
+#, c-format
+msgid "usage: %s [-a|-h|-l|-x] dictionary\n"
+msgstr ""
+
+#: dic/listdic.cpp:110
+#, c-format
+msgid "  -a: print all\n"
+msgstr ""
+
+#: dic/listdic.cpp:111
+#, c-format
+msgid "  -h: print header\n"
+msgstr ""
+
+#: dic/listdic.cpp:112
+#, c-format
+msgid "  -l: print dictionary word list\n"
+msgstr ""
+
+#: dic/listdic.cpp:113
+#, c-format
+msgid "  -x: print dictionary in hex\n"
+msgstr ""
+
+#: dic/regexpmain.cpp:100
+#, c-format
+msgid "usage: %s dictionary"
+msgstr ""
+
+#: dic/regexpmain.cpp:101
+msgid "   dictionary: path to eliot dawg dictionary"
+msgstr ""
+
+#: dic/regexpmain.cpp:136
+msgid "enter a regular expression:"
+msgstr ""
+
+#: dic/regexpmain.cpp:148
+msgid "result:"
+msgstr ""
+
+#: utils/ncurses.cpp:270
+msgid "Scores"
+msgstr ""
+
+#: utils/ncurses.cpp:276
 #, c-format
 msgid "Player %d: %d"
 msgstr ""
 
-#: utils/ncurses.cpp:198
-msgid " Racks "
+#: utils/ncurses.cpp:285
+msgid "Racks"
 msgstr ""
 
-#: utils/ncurses.cpp:204
+#: utils/ncurses.cpp:292
 #, c-format
-msgid "Player %d: %s"
+msgid "Player %d: %ls"
 msgstr ""
 
-#: utils/ncurses.cpp:215 utils/ncurses.cpp:218
+#: utils/ncurses.cpp:303 utils/ncurses.cpp:306
 msgid "Search complete"
 msgstr ""
 
-#: utils/ncurses.cpp:229
-msgid " Search results "
+#: utils/ncurses.cpp:316
+msgid "Search results"
 msgstr ""
 
-#: utils/ncurses.cpp:258
-msgid " History of the game "
+#: utils/ncurses.cpp:345
+msgid "History of the game"
 msgstr ""
 
-#: utils/ncurses.cpp:265
+#: utils/ncurses.cpp:351
 msgid " N |   RACK   |    SOLUTION     | REF | PTS | P | BONUS"
 msgstr ""
 
-#: utils/ncurses.cpp:296
-msgid " Help "
+#: utils/ncurses.cpp:390
+msgid "(PASS)"
 msgstr ""
 
-#: utils/ncurses.cpp:301
+#: utils/ncurses.cpp:416
+msgid "Help"
+msgstr ""
+
+#: utils/ncurses.cpp:420
 msgid "[Global]"
 msgstr ""
 
-#: utils/ncurses.cpp:302
+#: utils/ncurses.cpp:421
 msgid "   h, H, ?          Show/hide help box"
 msgstr ""
 
-#: utils/ncurses.cpp:303
+#: utils/ncurses.cpp:422
 msgid "   y, Y             Show/hide history of the game"
 msgstr ""
 
-#: utils/ncurses.cpp:304
+#: utils/ncurses.cpp:423
+msgid ""
+"   b, B             Show/hide contents of the bag (including letters of the "
+"racks)"
+msgstr ""
+
+#: utils/ncurses.cpp:424
 msgid "   e, E             Show/hide dots on empty squares of the board"
 msgstr ""
 
-#: utils/ncurses.cpp:305
+#: utils/ncurses.cpp:425
 msgid "   d, D             Check the existence of a word in the dictionary"
 msgstr ""
 
-#: utils/ncurses.cpp:306
+#: utils/ncurses.cpp:426
 msgid "   j, J             Play a word"
 msgstr ""
 
-#: utils/ncurses.cpp:307
+#: utils/ncurses.cpp:427
 msgid "   s, S             Save the game"
 msgstr ""
 
-#: utils/ncurses.cpp:308
+#: utils/ncurses.cpp:428
 msgid "   l, L             Load a game"
 msgstr ""
 
-#: utils/ncurses.cpp:309
+#: utils/ncurses.cpp:429
 msgid "   q, Q             Quit"
 msgstr ""
 
-#: utils/ncurses.cpp:312
+#: utils/ncurses.cpp:432
 msgid "[Training mode]"
 msgstr ""
 
-#: utils/ncurses.cpp:313
+#: utils/ncurses.cpp:433
 msgid "   *                Take a random rack"
 msgstr ""
 
-#: utils/ncurses.cpp:314
+#: utils/ncurses.cpp:434
 msgid "   +                Complete the current rack randomly"
 msgstr ""
 
-#: utils/ncurses.cpp:315
+#: utils/ncurses.cpp:435
 msgid "   t, T             Set the rack manually"
 msgstr ""
 
-#: utils/ncurses.cpp:316
+#: utils/ncurses.cpp:436
 msgid "   c, C             Compute all the possible words"
 msgstr ""
 
-#: utils/ncurses.cpp:317
+#: utils/ncurses.cpp:437
 msgid "   r, R             Show/hide search results"
 msgstr ""
 
-#: utils/ncurses.cpp:320
+#: utils/ncurses.cpp:440
 msgid "[Duplicate mode]"
 msgstr ""
 
-#: utils/ncurses.cpp:321
+#: utils/ncurses.cpp:441
 msgid "   n, N             Switch to the next human player"
 msgstr ""
 
-#: utils/ncurses.cpp:324
+#: utils/ncurses.cpp:444
 msgid "[Free game mode]"
 msgstr ""
 
-#: utils/ncurses.cpp:325
+#: utils/ncurses.cpp:445
 msgid "   p, P             Pass your turn (with or without changing letters)"
 msgstr ""
 
-#: utils/ncurses.cpp:328
+#: utils/ncurses.cpp:448
 msgid "[Miscellaneous]"
 msgstr ""
 
-#: utils/ncurses.cpp:329
+#: utils/ncurses.cpp:449
 msgid "   <up>, <down>     Navigate in a box line by line"
 msgstr ""
 
-#: utils/ncurses.cpp:330
+#: utils/ncurses.cpp:450
 msgid "   <pgup>, <pgdown> Navigate in a box page by page"
 msgstr ""
 
-#: utils/ncurses.cpp:331
+#: utils/ncurses.cpp:451
 msgid "   Ctrl-l           Refresh the screen"
 msgstr ""
 
-#: utils/ncurses.cpp:339
-msgid " Play a word "
+#: utils/ncurses.cpp:462 wxwin/auxframes.cc:148
+msgid "Bag"
+msgstr ""
+
+#: utils/ncurses.cpp:469
+msgid " LETTER | POINTS | FREQUENCY | REMAINING"
+msgstr ""
+
+#: utils/ncurses.cpp:522
+msgid "Play a word"
 msgstr ""
 
 #. TRANSLATORS: Align the : when translating "Played word:" and
 #. "Coordinates:". For example:
 #. Pl. word   :
 #. Coordinates:
-#: utils/ncurses.cpp:340 utils/ncurses.cpp:348
+#: utils/ncurses.cpp:523 utils/ncurses.cpp:531
 msgid "Played word:"
 msgstr ""
 
-#: utils/ncurses.cpp:341 utils/ncurses.cpp:349
+#: utils/ncurses.cpp:524 utils/ncurses.cpp:532
 msgid "Coordinates:"
 msgstr ""
 
-#: utils/ncurses.cpp:363
+#: utils/ncurses.cpp:546
 msgid "Incorrect or misplaced word"
 msgstr ""
 
-#: utils/ncurses.cpp:373
-msgid " Dictionary "
+#: utils/ncurses.cpp:556
+msgid "Dictionary"
 msgstr ""
 
-#: utils/ncurses.cpp:374
+#: utils/ncurses.cpp:557
 msgid "Enter the word to check:"
 msgstr ""
 
-#: utils/ncurses.cpp:383
+#: utils/ncurses.cpp:566
 #, c-format
-msgid "The word '%s' exists"
+msgid "The word '%ls' exists"
 msgstr ""
 
-#: utils/ncurses.cpp:385
+#: utils/ncurses.cpp:568
 #, c-format
-msgid "The word '%s' does not exist"
+msgid "The word '%ls' does not exist"
 msgstr ""
 
-#: utils/ncurses.cpp:395
-msgid " Save the game "
+#: utils/ncurses.cpp:578 wxwin/mainframe.cc:460 wxwin/mainframe.cc:468
+msgid "Save the game"
 msgstr ""
 
-#: utils/ncurses.cpp:396 utils/ncurses.cpp:425
+#: utils/ncurses.cpp:579 utils/ncurses.cpp:609
 msgid "Enter the file name:"
 msgstr ""
 
-#: utils/ncurses.cpp:406
+#: utils/ncurses.cpp:589
 #, c-format
-msgid "Cannot open file %s for writing"
+msgid "Cannot open file %ls for writing"
 msgstr ""
 
-#: utils/ncurses.cpp:413
+#: utils/ncurses.cpp:597
 #, c-format
-msgid "Game saved in %s"
+msgid "Game saved in '%ls'"
 msgstr ""
 
-#: utils/ncurses.cpp:424
-msgid " Load a game "
+#: utils/ncurses.cpp:608 wxwin/mainframe.cc:269 wxwin/mainframe.cc:390
+#: wxwin/mainframe.cc:414
+msgid "Load a game"
 msgstr ""
 
-#: utils/ncurses.cpp:435
+#: utils/ncurses.cpp:619
 #, c-format
-msgid "Cannot open file %s for reading"
+msgid "Cannot open file '%ls' for reading"
 msgstr ""
 
-#: utils/ncurses.cpp:443
+#: utils/ncurses.cpp:627
 #, c-format
 msgid "Invalid saved game"
 msgstr ""
 
-#: utils/ncurses.cpp:447
+#: utils/ncurses.cpp:632
 #, c-format
 msgid "Game loaded"
 msgstr ""
 
-#: utils/ncurses.cpp:462
-msgid " Pass your turn "
+#: utils/ncurses.cpp:647
+msgid "Pass your turn"
 msgstr ""
 
-#: utils/ncurses.cpp:463
+#: utils/ncurses.cpp:648
 msgid "Enter the letters to change:"
 msgstr ""
 
-#: utils/ncurses.cpp:472
+#: utils/ncurses.cpp:657
 msgid "Cannot pass the turn"
 msgstr ""
 
-#: utils/ncurses.cpp:482
-msgid " Set rack "
+#: utils/ncurses.cpp:667
+msgid "Set rack"
 msgstr ""
 
-#: utils/ncurses.cpp:483
+#: utils/ncurses.cpp:668
 msgid "Enter the new letters:"
 msgstr ""
 
-#: utils/ncurses.cpp:798
+#: utils/ncurses.cpp:677
+msgid "Cannot take these letters from the bag"
+msgstr ""
+
+#: utils/ncurses.cpp:1071
 msgid "Training mode"
 msgstr ""
 
-#: utils/ncurses.cpp:800
+#: utils/ncurses.cpp:1073
 msgid "Free game mode"
 msgstr ""
 
-#: utils/ncurses.cpp:802
+#: utils/ncurses.cpp:1075
 msgid "Duplicate mode"
 msgstr ""
 
-#: utils/ncurses.cpp:805
+#: utils/ncurses.cpp:1078
 msgid "Joker game"
 msgstr ""
 
-#: utils/ncurses.cpp:806
+#: utils/ncurses.cpp:1079
 msgid "[h for help]"
 msgstr ""
+
+#: wxwin/auxframes.cc:123
+msgid "Grid"
+msgstr ""
+
+#: wxwin/auxframes.cc:203
+msgid "Search"
+msgstr ""
+
+#: wxwin/auxframes.cc:234
+msgid "Check"
+msgstr ""
+
+#: wxwin/auxframes.cc:239
+msgid "Word to check"
+msgstr ""
+
+#: wxwin/auxframes.cc:257 wxwin/configdb.cc:203 wxwin/searchpanel.cc:107
+msgid "No dictionary"
+msgstr ""
+
+#: wxwin/auxframes.cc:261
+msgid "exists"
+msgstr ""
+
+#: wxwin/auxframes.cc:263
+msgid "doesn't exist"
+msgstr ""
+
+#: wxwin/auxframes.cc:304
+msgid "Copy"
+msgstr ""
+
+#: wxwin/auxframes.cc:348 wxwin/mainframe.cc:487 wxwin/mainframe.cc:507
+#: wxwin/mainframe.cc:538
+msgid "No on going game"
+msgstr ""
+
+#: wxwin/auxframes.cc:363 wxwin/searchpanel.cc:119
+msgid "No result"
+msgstr ""
+
+#: wxwin/auxframes.cc:409
+msgid "Rack: "
+msgstr ""
+
+#: wxwin/auxframes.cc:525 wxwin/mainframe.cc:319
+msgid "Game history"
+msgstr ""
+
+#: wxwin/auxframes.cc:557 wxwin/mainframe.cc:321
+msgid "Results"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:62
+msgid "left"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:63
+msgid "centered"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:64
+msgid "right"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:118
+msgid "Alignment"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:120
+msgid "Spacing"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:124 wxwin/confdimdlg.cc:135
+msgid "Font..."
+msgstr ""
+
+#: wxwin/confdimdlg.cc:129
+msgid "Title column "
+msgstr ""
+
+#: wxwin/confdimdlg.cc:140
+msgid "Text column "
+msgstr ""
+
+#: wxwin/confdimdlg.cc:150
+msgid "Column heading"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:154
+msgid "Alignment of the column heading"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:158
+msgid "Spacing of the heading characters"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:167
+msgid "Inner dimension of the column (in mm)"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:176
+msgid "Alignment of the column text"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:180
+msgid "Characters spacing"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:231
+msgid "Title spc. top"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:233
+msgid "Text spc. top"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:235
+msgid "Text spc. left"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:252
+msgid "Title spc. bot."
+msgstr ""
+
+#: wxwin/confdimdlg.cc:254
+msgid "Text spc. bot."
+msgstr ""
+
+#: wxwin/confdimdlg.cc:256
+msgid "Text spc. right"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:286
+msgid "Printer"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:288
+msgid "Configure the printer"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:290
+msgid "Page"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:292
+msgid "Configure the dimensions of the page"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:298
+msgid "Cancel the last changes"
+msgstr ""
+
+#: wxwin/confdimdlg.cc:304 wxwin/confsearch.cc:42
+msgid "Save the changes"
+msgstr ""
+
+#: wxwin/configdb.cc:322
+msgid "Nb"
+msgstr ""
+
+#: wxwin/configdb.cc:323 wxwin/mainframe.cc:174
+msgid "Rack"
+msgstr ""
+
+#: wxwin/configdb.cc:324
+msgid "Solution"
+msgstr ""
+
+#: wxwin/configdb.cc:325 wxwin/gfxresult.cc:69
+msgid "Pos"
+msgstr ""
+
+#: wxwin/configdb.cc:326 wxwin/gfxresult.cc:70
+msgid "Pts"
+msgstr ""
+
+#: wxwin/confsearch.cc:36
+msgid "Search on joker in 7+1 panel"
+msgstr ""
+
+#: wxwin/confsearch.cc:37
+msgid "Check rack validity"
+msgstr ""
+
+#: wxwin/confsearch.cc:40
+msgid "Cancel last changes"
+msgstr ""
+
+#: wxwin/gfxresult.cc:67
+msgid "Word"
+msgstr ""
+
+#: wxwin/gfxresult.cc:71
+msgid "Results of the search"
+msgstr ""
+
+#: wxwin/mainframe.cc:205
+msgid " Rack "
+msgstr ""
+
+#: wxwin/mainframe.cc:206
+msgid " Complement "
+msgstr ""
+
+#: wxwin/mainframe.cc:207
+msgid " Search "
+msgstr ""
+
+#: wxwin/mainframe.cc:208
+msgid " Back "
+msgstr ""
+
+#: wxwin/mainframe.cc:209
+msgid " Play "
+msgstr ""
+
+#: wxwin/mainframe.cc:211
+msgid "Random rack"
+msgstr ""
+
+#: wxwin/mainframe.cc:212
+msgid "Random complement of the rack"
+msgstr ""
+
+#: wxwin/mainframe.cc:213
+msgid "Search with the current rack"
+msgstr ""
+
+#: wxwin/mainframe.cc:214
+msgid "Go back one turn"
+msgstr ""
+
+#: wxwin/mainframe.cc:215
+msgid "Play the selected word"
+msgstr ""
+
+#: wxwin/mainframe.cc:266
+msgid "&New game\tctrl+n"
+msgstr ""
+
+#: wxwin/mainframe.cc:266
+msgid "Start a new game"
+msgstr ""
+
+#: wxwin/mainframe.cc:267
+msgid "New &joker game\tctrl+j"
+msgstr ""
+
+#: wxwin/mainframe.cc:267
+msgid "Start a new joker game"
+msgstr ""
+
+#: wxwin/mainframe.cc:269
+msgid "&Load...\tctrl+l"
+msgstr ""
+
+#: wxwin/mainframe.cc:270
+msgid "&Save as...\tctrl+s"
+msgstr ""
+
+#: wxwin/mainframe.cc:270
+msgid "Save the current game"
+msgstr ""
+
+#: wxwin/mainframe.cc:272
+msgid "&Print...\tctrl+p"
+msgstr ""
+
+#: wxwin/mainframe.cc:272
+msgid "Print this game"
+msgstr ""
+
+#: wxwin/mainframe.cc:273
+msgid "Print pre&view..."
+msgstr ""
+
+#: wxwin/mainframe.cc:273
+msgid "Print preview of the game"
+msgstr ""
+
+#: wxwin/mainframe.cc:275
+msgid "Print in PostS&cript..."
+msgstr ""
+
+#: wxwin/mainframe.cc:275
+msgid "Print in a PostScript file"
+msgstr ""
+
+#: wxwin/mainframe.cc:278
+msgid "&Quit"
+msgstr ""
+
+#: wxwin/mainframe.cc:278
+msgid "Quit Eliot"
+msgstr ""
+
+#: wxwin/mainframe.cc:281
+msgid "&Dictionary..."
+msgstr ""
+
+#: wxwin/mainframe.cc:281 wxwin/mainframe.cc:589
+msgid "Choose a dictionary"
+msgstr ""
+
+#: wxwin/mainframe.cc:282
+msgid "&Search..."
+msgstr ""
+
+#: wxwin/mainframe.cc:282
+msgid "Search options"
+msgstr ""
+
+#: wxwin/mainframe.cc:285
+msgid "&Background..."
+msgstr ""
+
+#: wxwin/mainframe.cc:285
+msgid "Background color"
+msgstr ""
+
+#: wxwin/mainframe.cc:286
+msgid "L&ines..."
+msgstr ""
+
+#: wxwin/mainframe.cc:286
+msgid "Color of the lines"
+msgstr ""
+
+#: wxwin/mainframe.cc:288
+msgid "&Played letters..."
+msgstr ""
+
+#: wxwin/mainframe.cc:288
+msgid "Color of the letters played on the board"
+msgstr ""
+
+#: wxwin/mainframe.cc:289
+msgid "&Temporary letters..."
+msgstr ""
+
+#: wxwin/mainframe.cc:289
+msgid "Color of the letters of the temporary word"
+msgstr ""
+
+#: wxwin/mainframe.cc:290
+msgid "B&ackground of played letters..."
+msgstr ""
+
+#: wxwin/mainframe.cc:290
+msgid "Background color of the letters played on the board"
+msgstr ""
+
+#: wxwin/mainframe.cc:291
+msgid "Ba&ckground of temporary letters..."
+msgstr ""
+
+#: wxwin/mainframe.cc:291
+msgid "Background color of the temporary letters on the board"
+msgstr ""
+
+#: wxwin/mainframe.cc:293
+msgid "Double &letter..."
+msgstr ""
+
+#: wxwin/mainframe.cc:293
+msgid "Color of the \"double letter\" squares"
+msgstr ""
+
+#: wxwin/mainframe.cc:294
+msgid "Triple l&etter..."
+msgstr ""
+
+#: wxwin/mainframe.cc:294
+msgid "Color of the \"triple letter\" squares"
+msgstr ""
+
+#: wxwin/mainframe.cc:295
+msgid "Double &word..."
+msgstr ""
+
+#: wxwin/mainframe.cc:295
+msgid "Color of the \"double word\" squares"
+msgstr ""
+
+#: wxwin/mainframe.cc:296
+msgid "Triple w&ord..."
+msgstr ""
+
+#: wxwin/mainframe.cc:296
+msgid "Color of the \"triple word\" squares"
+msgstr ""
+
+#: wxwin/mainframe.cc:298
+msgid "&Default colors"
+msgstr ""
+
+#: wxwin/mainframe.cc:298
+msgid "Restore the default colors"
+msgstr ""
+
+#: wxwin/mainframe.cc:301
+msgid "&Search letters..."
+msgstr ""
+
+#: wxwin/mainframe.cc:301
+msgid "Font for the search"
+msgstr ""
+
+#: wxwin/mainframe.cc:304 wxwin/mainframe.cc:328
+msgid "&Game"
+msgstr ""
+
+#: wxwin/mainframe.cc:304
+msgid "Configuration of the game"
+msgstr ""
+
+#: wxwin/mainframe.cc:305
+msgid "&Fonts"
+msgstr ""
+
+#: wxwin/mainframe.cc:305
+msgid "Configuration of the fonts"
+msgstr ""
+
+#: wxwin/mainframe.cc:306
+msgid "&Colors"
+msgstr ""
+
+#: wxwin/mainframe.cc:306
+msgid "Configuration of the colors"
+msgstr ""
+
+#: wxwin/mainframe.cc:307
+msgid "&Printing..."
+msgstr ""
+
+#: wxwin/mainframe.cc:307
+msgid "Configuration of the printing parameters"
+msgstr ""
+
+#: wxwin/mainframe.cc:310
+msgid "&Board"
+msgstr ""
+
+#: wxwin/mainframe.cc:310
+msgid "Game board"
+msgstr ""
+
+#: wxwin/mainframe.cc:311
+msgid "Ba&g"
+msgstr ""
+
+#: wxwin/mainframe.cc:311
+msgid "Remaining letters in the bag"
+msgstr ""
+
+#: wxwin/mainframe.cc:312
+msgid "&Check"
+msgstr ""
+
+#: wxwin/mainframe.cc:312
+msgid "Check a word in the dictionary"
+msgstr ""
+
+#: wxwin/mainframe.cc:313
+msgid "&Search"
+msgstr ""
+
+#: wxwin/mainframe.cc:313
+msgid "Search in the dictionary"
+msgstr ""
+
+#: wxwin/mainframe.cc:315
+msgid "&Rack + 1"
+msgstr ""
+
+#: wxwin/mainframe.cc:315
+msgid "Letters of the rack plus one"
+msgstr ""
+
+#: wxwin/mainframe.cc:316
+msgid "R&accords"
+msgstr ""
+
+#: wxwin/mainframe.cc:316
+msgid "Raccords on a word of the search"
+msgstr ""
+
+#: wxwin/mainframe.cc:317
+msgid "&Benjamins"
+msgstr ""
+
+#: wxwin/mainframe.cc:317
+msgid "Benjamins on a word of the search"
+msgstr ""
+
+#: wxwin/mainframe.cc:319
+msgid "Game &history"
+msgstr ""
+
+#: wxwin/mainframe.cc:321
+msgid "R&esults"
+msgstr ""
+
+#: wxwin/mainframe.cc:325
+msgid "&About..."
+msgstr ""
+
+#: wxwin/mainframe.cc:325 wxwin/mainframe.cc:718
+msgid "About Eliot"
+msgstr ""
+
+#: wxwin/mainframe.cc:329
+msgid "&Settings"
+msgstr ""
+
+#: wxwin/mainframe.cc:330
+msgid "&Windows"
+msgstr ""
+
+#: wxwin/mainframe.cc:331
+msgid "&Help"
+msgstr ""
+
+#: wxwin/mainframe.cc:355 wxwin/mainframe.cc:393
+msgid "No dictionary selected"
+msgstr ""
+
+#: wxwin/mainframe.cc:355 wxwin/mainframe.cc:393 wxwin/mainframe.cc:487
+#: wxwin/mainframe.cc:507 wxwin/mainframe.cc:538
+msgid "Eliot: error"
+msgstr ""
+
+#: wxwin/mainframe.cc:413
+msgid "Cannot open "
+msgstr ""
+
+#: wxwin/mainframe.cc:425 wxwin/mainframe.cc:434
+msgid "Error while loading the game"
+msgstr ""
+
+#: wxwin/mainframe.cc:426
+msgid "Invalid game"
+msgstr ""
+
+#: wxwin/mainframe.cc:435
+msgid "The game is empty"
+msgstr ""
+
+#: wxwin/mainframe.cc:467
+msgid "Cannot create "
+msgstr ""
+
+#: wxwin/mainframe.cc:496 wxwin/mainframe.cc:560
+msgid "Printing not done"
+msgstr ""
+
+#: wxwin/mainframe.cc:496 wxwin/mainframe.cc:524
+msgid "Printing"
+msgstr ""
+
+#: wxwin/mainframe.cc:519
+msgid "Print preview problem.\n"
+msgstr ""
+
+#: wxwin/mainframe.cc:520
+msgid "The printer may not be correctly initialized"
+msgstr ""
+
+#: wxwin/mainframe.cc:521
+msgid "Print preview"
+msgstr ""
+
+#: wxwin/mainframe.cc:542
+msgid "Print to a PostScript file"
+msgstr ""
+
+#: wxwin/mainframe.cc:561 wxwin/mainframe.cc:567
+msgid "PostScript printing"
+msgstr ""
+
+#: wxwin/mainframe.cc:566
+msgid "Cannot initialize PostScript printer"
+msgstr ""
+
+#: wxwin/mainframe.cc:714
+msgid ""
+"This program is free software; you can redistribute it and/or modify it "
+"under the terms of the GNU General Public License as published by the Free "
+"Software Foundation; either version 2 of the License, or (at your option) "
+"any later version."
+msgstr ""
+
+#: wxwin/mainframe.cc:912
+msgid "turn:"
+msgstr ""
+
+#: wxwin/mainframe.cc:913
+msgid "points:"
+msgstr ""
+
+#: wxwin/mainframe.cc:948
+msgid ""
+"The bag doesn't contain enough letters\n"
+"for a new rack."
+msgstr ""
+
+#: wxwin/mainframe.cc:949 wxwin/mainframe.cc:953 wxwin/mainframe.cc:957
+msgid "Rack validation"
+msgstr ""
+
+#: wxwin/mainframe.cc:952
+msgid "The rack must contain at least 2 consonants and 2 vowels."
+msgstr ""
+
+#: wxwin/mainframe.cc:956
+msgid "The rack contains invalid letters for the current dictionary"
+msgstr ""
+
+#: wxwin/mainframe.cc:960
+msgid "The rack has been modified manually"
+msgstr ""
+
+#: wxwin/searchpanel.cc:146 wxwin/searchpanel.cc:190
+#, c-format
+msgid "The search is limited to %d letters"
+msgstr ""
+
+#: wxwin/searchpanel.cc:301
+msgid "Minimum length"
+msgstr ""
+
+#: wxwin/searchpanel.cc:303
+msgid "Maximum length"
+msgstr ""
+
+#: wxwin/searchpanel.cc:366
+msgid "Cross words"
+msgstr ""
+
+#: wxwin/searchpanel.cc:367
+msgid "Plus 1"
+msgstr ""
+
+#: wxwin/searchpanel.cc:368
+msgid "Regular expressions"
+msgstr ""

Index: po/fr.po
===================================================================
RCS file: /cvsroot/eliot/eliot/po/fr.po,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- po/fr.po    2 Apr 2005 22:04:59 -0000       1.6
+++ po/fr.po    8 Jan 2008 13:52:40 -0000       1.7
@@ -8,271 +8,1265 @@
 msgstr ""
 "Project-Id-Version: eliot 1.4\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2005-04-03 00:04+0200\n"
+"POT-Creation-Date: 2007-12-23 23:08+0100\n"
 "PO-Revision-Date: 2005-02-06 20:03+0100\n"
 "Last-Translator: Olivier Teuliere <address@hidden>\n"
 "Language-Team: French <address@hidden>\n"
 "MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: utils/ncurses.cpp:184
-msgid " Scores "
-msgstr " Scores "
+#: dic/header.cpp:317 dic/header.cpp:318
+msgid "Unknown (old format)"
+msgstr "Inconnu (vieux format)"
 
-#: utils/ncurses.cpp:190
+#: dic/header.cpp:492
+#, c-format
+msgid "dictionary name: %s\n"
+msgstr "Nom du dictionnaire : %s\n"
+
+#: dic/header.cpp:497
+#, c-format
+msgid "compressed on: %s\n"
+msgstr "Compressé le : %s\n"
+
+#: dic/header.cpp:501
+#, c-format
+msgid "compressed on: Unknown date (old format)\n"
+msgstr "Compressé le : Date inconnue (vieux format)\n"
+
+#: dic/header.cpp:503
+#, c-format
+msgid "compressed using a binary compiled by: %s\n"
+msgstr "Compressé avec un binaire compilé par : %s\n"
+
+#: dic/header.cpp:504
+#, c-format
+msgid "dictionary type: %s\n"
+msgstr "Type de dictionnaire : %s\n"
+
+#: dic/header.cpp:505
+#, c-format
+msgid "letters: %s\n"
+msgstr "Lettres : %s\n"
+
+#: dic/header.cpp:506
+#, c-format
+msgid "number of letters: %d\n"
+msgstr "Nombre de lettres : %d\n"
+
+#: dic/header.cpp:507
+#, c-format
+msgid "number of words: %d\n"
+msgstr "Nombre de mots : %d\n"
+
+#: dic/header.cpp:508
+#, c-format
+msgid "header size: %u bytes\n"
+msgstr "Taille du header : %u octets\n"
+
+#: dic/header.cpp:510
+#, c-format
+msgid "root: %d (edge)\n"
+msgstr "Racine : %d (arcs)\n"
+
+#: dic/header.cpp:511
+#, c-format
+msgid "nodes: %d used + %d saved\n"
+msgstr "Noeuds : %d utilisés + %d évités\n"
+
+#: dic/header.cpp:512
+#, c-format
+msgid "edges: %d used + %d saved\n"
+msgstr "Arcs : %d utilisés + %d évités\n"
+
+#: dic/header.cpp:514
+#, c-format
+msgid "letter | points | frequency | vowel | consonant\n"
+msgstr "lettre | points | frequence | voye. | consonne\n"
+
+#: dic/compdic.cpp:392
+msgid "Mandatory options:"
+msgstr "Options obligatoires :"
+
+#: dic/compdic.cpp:393
+msgid "  -d, --dicname <string>  Set the dictionary name and version"
+msgstr "  -d, --dicname <string>  Choisir le nom et la version du dictionnaire"
+
+#: dic/compdic.cpp:394
+msgid ""
+"  -l, --letters <string>  Path to the file containing the letters (see below)"
+msgstr ""
+"  -l, --letters <string>  Chemin vers un fichier contenant les lettres (voir "
+"ci-dessous)"
+
+#: dic/compdic.cpp:395
+msgid ""
+"  -i, --input <string>    Path to the uncompressed dictionary file (encoded "
+"in UTF-8)"
+msgstr ""
+"  -i, --input <string>    Chemin vers le fichier de dictionnaire non "
+"compressé (encodé en UTF-8)"
+
+#: dic/compdic.cpp:396
+msgid ""
+"  -o, --output <string    Path to the generated compressed dictionary file"
+msgstr ""
+"  -o, --output <string    Chemin vers le fichier de dictionnaire compressé "
+"généré"
+
+#: dic/compdic.cpp:397
+msgid "Other options:"
+msgstr "Autres options :"
+
+#: dic/compdic.cpp:398
+msgid "  -h, --help              Print this help and exit"
+msgstr "  -h, --help              Affiche cette aide et quitte"
+
+#: dic/compdic.cpp:399
+msgid "Example:"
+msgstr "Exemple :"
+
+#: dic/compdic.cpp:400
+msgid " -d 'ODS 5.0' -l letters.txt -i ods5.txt -o ods5.dawg"
+msgstr " -d 'ODS 5.0' -l lettres.txt -i ods5.txt -o ods5.dawg"
+
+#: dic/compdic.cpp:402
+msgid ""
+"The file containing the letters (--letters switch) must be UTF-8 encoded."
+msgstr ""
+"Le fichier contenant les lettres (option --letters) doit être encodé en 
UTF-"
+"8."
+
+#: dic/compdic.cpp:403
+msgid ""
+"Each line corresponds to one letter, and must contain 5 fields separated "
+"with "
+msgstr ""
+"Chaque ligne correspond à une lettre, et doit contenir 5 champs séparés 
par "
+
+#: dic/compdic.cpp:404
+msgid "one or more space(s)."
+msgstr "un ou plusieurs espace(s)."
+
+#: dic/compdic.cpp:405
+msgid " - 1st field: the letter itself"
+msgstr " - 1er champ : la lettre elle-même"
+
+#: dic/compdic.cpp:406
+msgid " - 2nd field: the points of the letter"
+msgstr " - 2e champ : les points de cette lettre"
+
+#: dic/compdic.cpp:407
+msgid ""
+" - 3rd field: the frequency of the letter (how many letters of this kind in "
+"the game)"
+msgstr ""
+" - 3e champ : la fréquance de la lettre (nombre de lettres de ce genre dans "
+"le jeu)"
+
+#: dic/compdic.cpp:408
+msgid ""
+" - 4th field: 1 if the letter is considered as a vowel in Scrabble game, 0 "
+"otherwise"
+msgstr ""
+" - 4e champ : 1 si la lettre est considérée comme une voyelle au jeu de "
+"Scrabble, 0 sinon"
+
+#: dic/compdic.cpp:409
+msgid ""
+" - 5th field: 1 if the letter is considered as a consonant in Scrabble game, "
+"0 otherwise"
+msgstr ""
+" - 5e champ : 1 si la lettre est considérée comme une consonne au jeu de "
+"Scrabble, 0 sinon"
+
+#: dic/compdic.cpp:410
+msgid "Example for french:"
+msgstr "Exemple pour le Français :"
+
+#: dic/compdic.cpp:411
+msgid "A 1 9 1 0"
+msgstr "A 1 9 1 0"
+
+#: dic/compdic.cpp:412
+msgid "[...]"
+msgstr "[...]"
+
+#: dic/compdic.cpp:413
+msgid "Z 10 1 0 1"
+msgstr "Z 10 1 0 1"
+
+#: dic/compdic.cpp:414
+msgid "? 0 2 1 1"
+msgstr "? 0 2 1 1"
+
+#: dic/compdic.cpp:484
+msgid "A mandatory option is missing"
+msgstr "Une option obligatoire est manquante"
+
+#: dic/compdic.cpp:492
+msgid "Cannot stat uncompressed dictionary "
+msgstr "Impossible de trouver le dictionnaire non compressé "
+
+#: dic/compdic.cpp:500
+msgid "Cannot open output file "
+msgstr "Impossible d'ouvrir le fichier d'output "
+
+#: dic/compdic.cpp:548
+#, c-format
+msgid " Load time: %.3f s\n"
+msgstr " Temps de chargement : %.3f s\n"
+
+#: dic/compdic.cpp:549
+#, c-format
+msgid " Compression time: %.3f s\n"
+msgstr " Temps de compression : %.3f s\n"
+
+#: dic/compdic.cpp:551
+#, c-format
+msgid " Maximum recursion level reached: %d\n"
+msgstr " Niveau maximum de rcursion atteint : %d\n"
+
+#: dic/listdic.cpp:100
+#, c-format
+msgid "offset binary   | structure\n"
+msgstr "offset binaire  | structure\n"
+
+#: dic/listdic.cpp:109
+#, c-format
+msgid "usage: %s [-a|-h|-l|-x] dictionary\n"
+msgstr "Usage : %s [-a|-h|-l|-x] dictionnaire\n"
+
+#: dic/listdic.cpp:110
+#, c-format
+msgid "  -a: print all\n"
+msgstr "  -a : affiche tout\n"
+
+#: dic/listdic.cpp:111
+#, c-format
+msgid "  -h: print header\n"
+msgstr "  -h : affiche l'en-tête\n"
+
+#: dic/listdic.cpp:112
+#, c-format
+msgid "  -l: print dictionary word list\n"
+msgstr "  -l : affiche la liste de mots du dictionnaire\n"
+
+#: dic/listdic.cpp:113
+#, c-format
+msgid "  -x: print dictionary in hex\n"
+msgstr "  -x : affiche le dictionnaire en hexadécimal\n"
+
+#: dic/regexpmain.cpp:100
+#, c-format
+msgid "usage: %s dictionary"
+msgstr "Usage : %s dictionnaire"
+
+#: dic/regexpmain.cpp:101
+msgid "   dictionary: path to eliot dawg dictionary"
+msgstr "   dictionnaire : chemin vers un dictionnaire de type dawg pour Eliot"
+
+#: dic/regexpmain.cpp:136
+msgid "enter a regular expression:"
+msgstr "Entrer une expression régulière :"
+
+#: dic/regexpmain.cpp:148
+msgid "result:"
+msgstr "résultat :"
+
+#: utils/ncurses.cpp:270
+msgid "Scores"
+msgstr "Scores"
+
+#: utils/ncurses.cpp:276
 #, c-format
 msgid "Player %d: %d"
 msgstr "Joueur %d : %d"
 
-#: utils/ncurses.cpp:198
-msgid " Racks "
-msgstr " Tirages "
+#: utils/ncurses.cpp:285
+msgid "Racks"
+msgstr "Tirages"
 
-#: utils/ncurses.cpp:204
+#: utils/ncurses.cpp:292
 #, c-format
-msgid "Player %d: %s"
-msgstr "Joueur %d : %s"
+msgid "Player %d: %ls"
+msgstr "Joueur %d : %ls"
 
-#: utils/ncurses.cpp:215 utils/ncurses.cpp:218
+#: utils/ncurses.cpp:303 utils/ncurses.cpp:306
 msgid "Search complete"
-msgstr "Recherche terminée"
+msgstr "Recherche terminée"
 
-#: utils/ncurses.cpp:229
-msgid " Search results "
-msgstr " Résultats de la recherche "
+#: utils/ncurses.cpp:316
+msgid "Search results"
+msgstr "Résultats de la recherche"
 
-#: utils/ncurses.cpp:258
-msgid " History of the game "
-msgstr " Historique de la partie "
+#: utils/ncurses.cpp:345
+msgid "History of the game"
+msgstr "Historique de la partie"
 
-#: utils/ncurses.cpp:265
+#: utils/ncurses.cpp:351
 msgid " N |   RACK   |    SOLUTION     | REF | PTS | P | BONUS"
 msgstr " N |  TIRAGE  |    SOLUTION     | REF | PTS | J | BONUS"
 
-#: utils/ncurses.cpp:296
-msgid " Help "
-msgstr " Aide "
+#: utils/ncurses.cpp:390
+msgid "(PASS)"
+msgstr "(PASSE)"
+
+#: utils/ncurses.cpp:416
+msgid "Help"
+msgstr "Aide"
 
-#: utils/ncurses.cpp:301
+#: utils/ncurses.cpp:420
 msgid "[Global]"
-msgstr "[Général]"
+msgstr "[Général]"
 
-#: utils/ncurses.cpp:302
+#: utils/ncurses.cpp:421
 msgid "   h, H, ?          Show/hide help box"
-msgstr "   h, H, ?          Afficher/cacher la boîte d'aide"
+msgstr "   h, H, ?          Afficher/cacher la boîte d'aide"
 
-#: utils/ncurses.cpp:303
+#: utils/ncurses.cpp:422
 msgid "   y, Y             Show/hide history of the game"
 msgstr "   y, Y             Afficher/cacher l'historique de la partie"
 
-#: utils/ncurses.cpp:304
+#: utils/ncurses.cpp:423
+msgid ""
+"   b, B             Show/hide contents of the bag (including letters of the "
+"racks)"
+msgstr ""
+"   b, B             Afficher/cacher le contenu du sac (avec les lettres des "
+"tirages)"
+
+#: utils/ncurses.cpp:424
 msgid "   e, E             Show/hide dots on empty squares of the board"
 msgstr ""
 "   e, E             Afficher/cacher les points sur les cases vides du "
 "plateau de jeu"
 
-#: utils/ncurses.cpp:305
+#: utils/ncurses.cpp:425
 msgid "   d, D             Check the existence of a word in the dictionary"
-msgstr "   d, D             Vérifier l'existence d'un mot dans le dictionnaire"
+msgstr "   d, D             Vérifier l'existence d'un mot dans le 
dictionnaire"
 
-#: utils/ncurses.cpp:306
+#: utils/ncurses.cpp:426
 msgid "   j, J             Play a word"
 msgstr "   j, J             Jouer un mot"
 
-#: utils/ncurses.cpp:307
+#: utils/ncurses.cpp:427
 msgid "   s, S             Save the game"
-msgstr "   s, S             Sauver la partie"
+msgstr "   s, S             Sauvegarder la partie"
 
-#: utils/ncurses.cpp:308
+#: utils/ncurses.cpp:428
 msgid "   l, L             Load a game"
 msgstr "   l, L             Charger une partie"
 
-#: utils/ncurses.cpp:309
+#: utils/ncurses.cpp:429
 msgid "   q, Q             Quit"
 msgstr "   q, Q             Quitter"
 
-#: utils/ncurses.cpp:312
+#: utils/ncurses.cpp:432
 msgid "[Training mode]"
-msgstr "[Mode entraînement]"
+msgstr "[Mode entraînement]"
 
-#: utils/ncurses.cpp:313
+#: utils/ncurses.cpp:433
 msgid "   *                Take a random rack"
-msgstr "   *                Tirage aléatoire"
+msgstr "   *                Tirage aléatoire"
 
-#: utils/ncurses.cpp:314
+#: utils/ncurses.cpp:434
 msgid "   +                Complete the current rack randomly"
-msgstr "   +                Compléter le tirage courant de manière aléatoire"
+msgstr "   +                Compléter le tirage courant de manière 
aléatoire"
 
-#: utils/ncurses.cpp:315
+#: utils/ncurses.cpp:435
 msgid "   t, T             Set the rack manually"
 msgstr "   t, T             Entrer le tirage manuellement"
 
-#: utils/ncurses.cpp:316
+#: utils/ncurses.cpp:436
 msgid "   c, C             Compute all the possible words"
 msgstr "   c, C             Calculer tous les mots possibles"
 
-#: utils/ncurses.cpp:317
+#: utils/ncurses.cpp:437
 msgid "   r, R             Show/hide search results"
-msgstr "   r, R             Afficher/cacher les résultats de la recherche"
+msgstr "   r, R             Afficher/cacher les résultats de la recherche"
 
-#: utils/ncurses.cpp:320
+#: utils/ncurses.cpp:440
 msgid "[Duplicate mode]"
 msgstr "[Mode duplicate]"
 
-#: utils/ncurses.cpp:321
+#: utils/ncurses.cpp:441
 msgid "   n, N             Switch to the next human player"
 msgstr "   n, N             Passer au joueur humain suivant"
 
-#: utils/ncurses.cpp:324
+#: utils/ncurses.cpp:444
 msgid "[Free game mode]"
 msgstr "[Mode partie libre]"
 
-#: utils/ncurses.cpp:325
+#: utils/ncurses.cpp:445
 msgid "   p, P             Pass your turn (with or without changing letters)"
 msgstr ""
 "   p, P             Passer son tour (en changeant ou pas certaines lettres)"
 
-#: utils/ncurses.cpp:328
+#: utils/ncurses.cpp:448
 msgid "[Miscellaneous]"
 msgstr "[Divers]"
 
-#: utils/ncurses.cpp:329
+#: utils/ncurses.cpp:449
 msgid "   <up>, <down>     Navigate in a box line by line"
-msgstr "   <haut>, <bas>    Naviguer dans une boîte ligne par ligne"
+msgstr "   <haut>, <bas>    Naviguer dans une boîte ligne par ligne"
 
-#: utils/ncurses.cpp:330
+#: utils/ncurses.cpp:450
 msgid "   <pgup>, <pgdown> Navigate in a box page by page"
-msgstr "   <pgup>, <pgdown> Naviguer dans une boîte page par page"
+msgstr "   <pgup>, <pgdown> Naviguer dans une boîte page par page"
 
-#: utils/ncurses.cpp:331
+#: utils/ncurses.cpp:451
 msgid "   Ctrl-l           Refresh the screen"
-msgstr "   Ctrl-l           Rafraîchir l'écran"
+msgstr "   Ctrl-l           Rafraîchir l'écran"
 
-#: utils/ncurses.cpp:339
-msgid " Play a word "
-msgstr " Jouer un mot "
+#: utils/ncurses.cpp:462 wxwin/auxframes.cc:148
+msgid "Bag"
+msgstr "Sac"
+
+#: utils/ncurses.cpp:469
+msgid " LETTER | POINTS | FREQUENCY | REMAINING"
+msgstr " LETTRE | POINTS | FREQUENCE | RESTANT"
+
+#: utils/ncurses.cpp:522
+msgid "Play a word"
+msgstr "Jouer un mot"
 
 #. TRANSLATORS: Align the : when translating "Played word:" and
 #. "Coordinates:". For example:
 #. Pl. word   :
 #. Coordinates:
-#: utils/ncurses.cpp:340 utils/ncurses.cpp:348
+#: utils/ncurses.cpp:523 utils/ncurses.cpp:531
 msgid "Played word:"
-msgstr "Mot joué    :"
+msgstr "Mot joué    :"
 
-#: utils/ncurses.cpp:341 utils/ncurses.cpp:349
+#: utils/ncurses.cpp:524 utils/ncurses.cpp:532
 msgid "Coordinates:"
-msgstr "Coordonnées :"
+msgstr "Coordonnées :"
 
-#: utils/ncurses.cpp:363
+#: utils/ncurses.cpp:546
 msgid "Incorrect or misplaced word"
-msgstr "Mot incorrect ou mal placé"
+msgstr "Mot incorrect ou mal placé"
 
-#: utils/ncurses.cpp:373
-msgid " Dictionary "
-msgstr " Dictionnaire "
+#: utils/ncurses.cpp:556
+msgid "Dictionary"
+msgstr "Dictionnaire"
 
-#: utils/ncurses.cpp:374
+#: utils/ncurses.cpp:557
 msgid "Enter the word to check:"
-msgstr "Entrer le mot à vérifier:"
+msgstr "Entrer le mot à vérifier:"
 
-#: utils/ncurses.cpp:383
+#: utils/ncurses.cpp:566
 #, c-format
-msgid "The word '%s' exists"
-msgstr "Le mot '%s' existe"
+msgid "The word '%ls' exists"
+msgstr "Le mot '%ls' existe"
 
-#: utils/ncurses.cpp:385
+#: utils/ncurses.cpp:568
 #, c-format
-msgid "The word '%s' does not exist"
-msgstr "Le mot '%s' n'existe pas"
+msgid "The word '%ls' does not exist"
+msgstr "Le mot '%ls' n'existe pas"
 
-#: utils/ncurses.cpp:395
-msgid " Save the game "
-msgstr " Sauver la partie "
+#: utils/ncurses.cpp:578 wxwin/mainframe.cc:460 wxwin/mainframe.cc:468
+msgid "Save the game"
+msgstr "Sauvegarder la partie"
 
-#: utils/ncurses.cpp:396 utils/ncurses.cpp:425
+#: utils/ncurses.cpp:579 utils/ncurses.cpp:609
 msgid "Enter the file name:"
 msgstr "Entrer le nom du fichier :"
 
-#: utils/ncurses.cpp:406
+#: utils/ncurses.cpp:589
 #, c-format
-msgid "Cannot open file %s for writing"
-msgstr "Impossible d'ouvrir le fichier %s en écriture"
+msgid "Cannot open file %ls for writing"
+msgstr "Impossible d'ouvrir le fichier %ls en écriture"
 
-#: utils/ncurses.cpp:413
+#: utils/ncurses.cpp:597
 #, c-format
-msgid "Game saved in %s"
-msgstr "Partie sauvée dans %s"
+msgid "Game saved in '%ls'"
+msgstr "Partie sauvée dans '%ls'"
 
-#: utils/ncurses.cpp:424
-msgid " Load a game "
-msgstr " Charger une partie "
+#: utils/ncurses.cpp:608 wxwin/mainframe.cc:269 wxwin/mainframe.cc:390
+#: wxwin/mainframe.cc:414
+msgid "Load a game"
+msgstr "Charger une partie"
 
-#: utils/ncurses.cpp:435
+#: utils/ncurses.cpp:619
 #, c-format
-msgid "Cannot open file %s for reading"
-msgstr "Impossible d'ouvrir le fichier %s en lecture"
+msgid "Cannot open file '%ls' for reading"
+msgstr "Impossible d'ouvrir le fichier '%ls' en lecture"
 
-#: utils/ncurses.cpp:443
+#: utils/ncurses.cpp:627
 #, c-format
 msgid "Invalid saved game"
-msgstr "Partie sauvée invalide"
+msgstr "Partie sauvée invalide"
 
-#: utils/ncurses.cpp:447
+#: utils/ncurses.cpp:632
 #, c-format
 msgid "Game loaded"
-msgstr "Partie chargée"
+msgstr "Partie chargée"
 
-#: utils/ncurses.cpp:462
-msgid " Pass your turn "
-msgstr " Passer son tour "
+#: utils/ncurses.cpp:647
+msgid "Pass your turn"
+msgstr "Passer son tour"
 
-#: utils/ncurses.cpp:463
+#: utils/ncurses.cpp:648
 msgid "Enter the letters to change:"
-msgstr "Entrer les lettres à changer:"
+msgstr "Entrer les lettres à changer:"
 
-#: utils/ncurses.cpp:472
+#: utils/ncurses.cpp:657
 msgid "Cannot pass the turn"
 msgstr "Impossible de passer le tour"
 
-#: utils/ncurses.cpp:482
-msgid " Set rack "
-msgstr " Choix du tirage "
+#: utils/ncurses.cpp:667
+msgid "Set rack"
+msgstr "Choix du tirage"
 
-#: utils/ncurses.cpp:483
+#: utils/ncurses.cpp:668
 msgid "Enter the new letters:"
 msgstr "Entrer les nouvelles lettres:"
 
-#: utils/ncurses.cpp:798
+#: utils/ncurses.cpp:677
+msgid "Cannot take these letters from the bag"
+msgstr "Impossible de retirer ces lettres du sac"
+
+#: utils/ncurses.cpp:1071
 msgid "Training mode"
-msgstr "Mode entraînement"
+msgstr "Mode entraînement"
 
-#: utils/ncurses.cpp:800
+#: utils/ncurses.cpp:1073
 msgid "Free game mode"
 msgstr "Mode partie libre"
 
-#: utils/ncurses.cpp:802
+#: utils/ncurses.cpp:1075
 msgid "Duplicate mode"
 msgstr "Mode duplicate"
 
-#: utils/ncurses.cpp:805
+#: utils/ncurses.cpp:1078
 msgid "Joker game"
 msgstr "Partie joker"
 
-#: utils/ncurses.cpp:806
+#: utils/ncurses.cpp:1079
 msgid "[h for help]"
 msgstr "[h pour l'aide]"
 
+#: wxwin/auxframes.cc:123
+msgid "Grid"
+msgstr "Grille"
+
+#: wxwin/auxframes.cc:203
+msgid "Search"
+msgstr "Recherche"
+
+#: wxwin/auxframes.cc:234
+msgid "Check"
+msgstr "Vérification"
+
+#: wxwin/auxframes.cc:239
+msgid "Word to check"
+msgstr "Mot à vérifier"
+
+#: wxwin/auxframes.cc:257 wxwin/configdb.cc:203 wxwin/searchpanel.cc:107
+msgid "No dictionary"
+msgstr "Pas de dictionnaire"
+
+#: wxwin/auxframes.cc:261
+msgid "exists"
+msgstr "existe"
+
+#: wxwin/auxframes.cc:263
+msgid "doesn't exist"
+msgstr "n'existe pas"
+
+#: wxwin/auxframes.cc:304
+msgid "Copy"
+msgstr "Copier"
+
+#: wxwin/auxframes.cc:348 wxwin/mainframe.cc:487 wxwin/mainframe.cc:507
+#: wxwin/mainframe.cc:538
+msgid "No on going game"
+msgstr "Pas de partie en cours"
+
+#: wxwin/auxframes.cc:363 wxwin/searchpanel.cc:119
+msgid "No result"
+msgstr "Pas de résultat"
+
+#: wxwin/auxframes.cc:409
+msgid "Rack: "
+msgstr "Tirage :"
+
+#: wxwin/auxframes.cc:525 wxwin/mainframe.cc:319
+msgid "Game history"
+msgstr "Historique de la partie"
+
+#: wxwin/auxframes.cc:557 wxwin/mainframe.cc:321
+msgid "Results"
+msgstr "Résultats"
+
+#: wxwin/confdimdlg.cc:62
+msgid "left"
+msgstr "gauche"
+
+#: wxwin/confdimdlg.cc:63
+msgid "centered"
+msgstr "centré"
+
+#: wxwin/confdimdlg.cc:64
+msgid "right"
+msgstr "droite"
+
+#: wxwin/confdimdlg.cc:118
+msgid "Alignment"
+msgstr "Justification"
+
+#: wxwin/confdimdlg.cc:120
+msgid "Spacing"
+msgstr "Espacement"
+
+#: wxwin/confdimdlg.cc:124 wxwin/confdimdlg.cc:135
+msgid "Font..."
+msgstr "Police..."
+
+#: wxwin/confdimdlg.cc:129
+msgid "Title column "
+msgstr "titre colomne "
+
+#: wxwin/confdimdlg.cc:140
+msgid "Text column "
+msgstr "Texte colomne "
+
+#: wxwin/confdimdlg.cc:150
+msgid "Column heading"
+msgstr "Titre de la colomne"
+
+#: wxwin/confdimdlg.cc:154
+msgid "Alignment of the column heading"
+msgstr "Justification du titre de la colomne"
+
+#: wxwin/confdimdlg.cc:158
+msgid "Spacing of the heading characters"
+msgstr "Espacement des caractères du titre"
+
+#: wxwin/confdimdlg.cc:167
+msgid "Inner dimension of the column (in mm)"
+msgstr "Dimension interne de la colomne (en mm)"
+
+#: wxwin/confdimdlg.cc:176
+msgid "Alignment of the column text"
+msgstr "Justification du texte de la colomne"
+
+#: wxwin/confdimdlg.cc:180
+msgid "Characters spacing"
+msgstr "Espacement des caractères"
+
+#: wxwin/confdimdlg.cc:231
+msgid "Title spc. top"
+msgstr "Titre esp. haut"
+
+#: wxwin/confdimdlg.cc:233
+msgid "Text spc. top"
+msgstr "Texte esp. haut"
+
+#: wxwin/confdimdlg.cc:235
+msgid "Text spc. left"
+msgstr "Texte esp. gauche"
+
+#: wxwin/confdimdlg.cc:252
+msgid "Title spc. bot."
+msgstr "Titre esp. bas"
+
+#: wxwin/confdimdlg.cc:254
+msgid "Text spc. bot."
+msgstr "Texte esp. bas"
+
+#: wxwin/confdimdlg.cc:256
+msgid "Text spc. right"
+msgstr "Text esp. droite"
+
+#: wxwin/confdimdlg.cc:286
+msgid "Printer"
+msgstr "Imprimante"
+
+#: wxwin/confdimdlg.cc:288
+msgid "Configure the printer"
+msgstr "Configuration de l'imprimante"
+
+#: wxwin/confdimdlg.cc:290
+msgid "Page"
+msgstr "Page"
+
+#: wxwin/confdimdlg.cc:292
+msgid "Configure the dimensions of the page"
+msgstr "Configuration des dimensions de la page"
+
+#: wxwin/confdimdlg.cc:298
+msgid "Cancel the last changes"
+msgstr "Annuler les derniers changements"
+
+#: wxwin/confdimdlg.cc:304 wxwin/confsearch.cc:42
+msgid "Save the changes"
+msgstr "Sauvegarder les changements"
+
+#: wxwin/configdb.cc:322
+msgid "Nb"
+msgstr "Num"
+
+#: wxwin/configdb.cc:323 wxwin/mainframe.cc:174
+msgid "Rack"
+msgstr "Tirage"
+
+#: wxwin/configdb.cc:324
+msgid "Solution"
+msgstr "Solution"
+
+#: wxwin/configdb.cc:325 wxwin/gfxresult.cc:69
+msgid "Pos"
+msgstr "Pos"
+
+#: wxwin/configdb.cc:326 wxwin/gfxresult.cc:70
+msgid "Pts"
+msgstr "Pts"
+
+#: wxwin/confsearch.cc:36
+msgid "Search on joker in 7+1 panel"
+msgstr "Rechercher sur joker dans la fenêtre 7+1"
+
+#: wxwin/confsearch.cc:37
+msgid "Check rack validity"
+msgstr "Vérifier la validité du tirage"
+
+#: wxwin/confsearch.cc:40
+msgid "Cancel last changes"
+msgstr "Annuler les derniers changements"
+
+#: wxwin/gfxresult.cc:67
+msgid "Word"
+msgstr "Mot"
+
+#: wxwin/gfxresult.cc:71
+msgid "Results of the search"
+msgstr "Résultats de la recherche"
+
+#: wxwin/mainframe.cc:205
+msgid " Rack "
+msgstr " Tirage "
+
+#: wxwin/mainframe.cc:206
+msgid " Complement "
+msgstr " Complément "
+
+#: wxwin/mainframe.cc:207
+msgid " Search "
+msgstr " Rechercher "
+
+#: wxwin/mainframe.cc:208
+msgid " Back "
+msgstr " Arrière "
+
+#: wxwin/mainframe.cc:209
+msgid " Play "
+msgstr " Jouer "
+
+#: wxwin/mainframe.cc:211
+msgid "Random rack"
+msgstr "Tirage aléatoire"
+
+#: wxwin/mainframe.cc:212
+msgid "Random complement of the rack"
+msgstr "Complément aléatoire du tirage"
+
+#: wxwin/mainframe.cc:213
+msgid "Search with the current rack"
+msgstr "Recherche sur le tirage courant"
+
+#: wxwin/mainframe.cc:214
+msgid "Go back one turn"
+msgstr "Revenir un coup en arrière"
+
+#: wxwin/mainframe.cc:215
+msgid "Play the selected word"
+msgstr "Jouer le mot selectionné"
+
+#: wxwin/mainframe.cc:266
+msgid "&New game\tctrl+n"
+msgstr "&Nouvelle partie\tctrl+n"
+
+#: wxwin/mainframe.cc:266
+msgid "Start a new game"
+msgstr "Démarrer une nouvelle partie"
+
+#: wxwin/mainframe.cc:267
+msgid "New &joker game\tctrl+j"
+msgstr "Nouvelle partie &joker\tctrl+j"
+
+#: wxwin/mainframe.cc:267
+msgid "Start a new joker game"
+msgstr "Démarrer une nouvelle partie joker"
+
+#: wxwin/mainframe.cc:269
+msgid "&Load...\tctrl+l"
+msgstr "&Charger...\tctrl+l"
+
+#: wxwin/mainframe.cc:270
+msgid "&Save as...\tctrl+s"
+msgstr "&Enregistrer sous...\tctrl+s"
+
+#: wxwin/mainframe.cc:270
+msgid "Save the current game"
+msgstr "Sauvegarder la partie en cours"
+
+#: wxwin/mainframe.cc:272
+msgid "&Print...\tctrl+p"
+msgstr "&Imprimer...\tctrl+p"
+
+#: wxwin/mainframe.cc:272
+msgid "Print this game"
+msgstr "Imprimer la partie en cours"
+
+#: wxwin/mainframe.cc:273
+msgid "Print pre&view..."
+msgstr "&Aperçu avant impression..."
+
+#: wxwin/mainframe.cc:273
+msgid "Print preview of the game"
+msgstr "Aperçu avant impression de la partie"
+
+#: wxwin/mainframe.cc:275
+msgid "Print in PostS&cript..."
+msgstr "Imprimer au format &PostScript..."
+
+#: wxwin/mainframe.cc:275
+msgid "Print in a PostScript file"
+msgstr "Imprimer dans un fichier PostScript"
+
+#: wxwin/mainframe.cc:278
+msgid "&Quit"
+msgstr "&Quitter"
+
+#: wxwin/mainframe.cc:278
+msgid "Quit Eliot"
+msgstr "Quitter Eliot"
+
+#: wxwin/mainframe.cc:281
+msgid "&Dictionary..."
+msgstr "&Dictionnaire..."
+
+#: wxwin/mainframe.cc:281 wxwin/mainframe.cc:589
+msgid "Choose a dictionary"
+msgstr "Choisir un dictionnaire"
+
+#: wxwin/mainframe.cc:282
+msgid "&Search..."
+msgstr "&Recherche..."
+
+#: wxwin/mainframe.cc:282
+msgid "Search options"
+msgstr "Options de recherche"
+
+#: wxwin/mainframe.cc:285
+msgid "&Background..."
+msgstr "&Fond..."
+
+#: wxwin/mainframe.cc:285
+msgid "Background color"
+msgstr "Couleur de fond"
+
+#: wxwin/mainframe.cc:286
+msgid "L&ines..."
+msgstr "L&ignes..."
+
+#: wxwin/mainframe.cc:286
+msgid "Color of the lines"
+msgstr "Couleur des lignes"
+
+#: wxwin/mainframe.cc:288
+msgid "&Played letters..."
+msgstr "Lettres &jouées..."
+
+#: wxwin/mainframe.cc:288
+msgid "Color of the letters played on the board"
+msgstr "Couleur des lettres jouées sur la grille"
+
+#: wxwin/mainframe.cc:289
+msgid "&Temporary letters..."
+msgstr "Lettres &temporaires..."
+
+#: wxwin/mainframe.cc:289
+msgid "Color of the letters of the temporary word"
+msgstr "Couleur des lettres du mot temporaire"
+
+#: wxwin/mainframe.cc:290
+msgid "B&ackground of played letters..."
+msgstr "Fo&nd des lettres jouées..."
+
+#: wxwin/mainframe.cc:290
+msgid "Background color of the letters played on the board"
+msgstr "Couleur de fond des lettres jouées sur la grille"
+
+#: wxwin/mainframe.cc:291
+msgid "Ba&ckground of temporary letters..."
+msgstr "Fon&d des lettres temporaires..."
+
+#: wxwin/mainframe.cc:291
+msgid "Background color of the temporary letters on the board"
+msgstr "Couleur de fond des lettres temporaires sur la grille"
+
+#: wxwin/mainframe.cc:293
+msgid "Double &letter..."
+msgstr "&Lettre compte double..."
+
+#: wxwin/mainframe.cc:293
+msgid "Color of the \"double letter\" squares"
+msgstr "Couleur des cases \"mot compte double\""
+
+#: wxwin/mainframe.cc:294
+msgid "Triple l&etter..."
+msgstr "L&ettre compte triple..."
+
+#: wxwin/mainframe.cc:294
+msgid "Color of the \"triple letter\" squares"
+msgstr "Couleur des cases \"mot compte triple\""
+
+#: wxwin/mainframe.cc:295
+msgid "Double &word..."
+msgstr "&Mot compte double..."
+
+#: wxwin/mainframe.cc:295
+msgid "Color of the \"double word\" squares"
+msgstr "Couleur des cases \"mot compte double\""
+
+#: wxwin/mainframe.cc:296
+msgid "Triple w&ord..."
+msgstr "M&ot compte triple..."
+
+#: wxwin/mainframe.cc:296
+msgid "Color of the \"triple word\" squares"
+msgstr "Couleur des cases \"mot compte triple\""
+
+#: wxwin/mainframe.cc:298
+msgid "&Default colors"
+msgstr "&Couleurs d'origine"
+
+#: wxwin/mainframe.cc:298
+msgid "Restore the default colors"
+msgstr "Restaurer les couleurs d'origine"
+
+#: wxwin/mainframe.cc:301
+msgid "&Search letters..."
+msgstr "&Lettres de recherche..."
+
+#: wxwin/mainframe.cc:301
+msgid "Font for the search"
+msgstr "Police de caractères pour la recherche"
+
+#: wxwin/mainframe.cc:304 wxwin/mainframe.cc:328
+msgid "&Game"
+msgstr "&Partie"
+
+#: wxwin/mainframe.cc:304
+msgid "Configuration of the game"
+msgstr "Configuration de la partie"
+
+#: wxwin/mainframe.cc:305
+msgid "&Fonts"
+msgstr "P&olices de caractères"
+
+#: wxwin/mainframe.cc:305
+msgid "Configuration of the fonts"
+msgstr "Configuration des polices de caractères"
+
+#: wxwin/mainframe.cc:306
+msgid "&Colors"
+msgstr "&Couleurs"
+
+#: wxwin/mainframe.cc:306
+msgid "Configuration of the colors"
+msgstr "Configuration des couleurs"
+
+#: wxwin/mainframe.cc:307
+msgid "&Printing..."
+msgstr "&Impression..."
+
+#: wxwin/mainframe.cc:307
+msgid "Configuration of the printing parameters"
+msgstr "Configuration des paramètres d'impression"
+
+#: wxwin/mainframe.cc:310
+msgid "&Board"
+msgstr "&Grille"
+
+#: wxwin/mainframe.cc:310
+msgid "Game board"
+msgstr "Plateau de jeu"
+
+#: wxwin/mainframe.cc:311
+msgid "Ba&g"
+msgstr "&Sac"
+
+#: wxwin/mainframe.cc:311
+msgid "Remaining letters in the bag"
+msgstr "Lettres restantes dans le sac"
+
+#: wxwin/mainframe.cc:312
+msgid "&Check"
+msgstr "&Vérification"
+
+#: wxwin/mainframe.cc:312
+msgid "Check a word in the dictionary"
+msgstr "Vérifier l'existence d'un mot dans le dictionnaire"
+
+#: wxwin/mainframe.cc:313
+msgid "&Search"
+msgstr "&Recherche"
+
+#: wxwin/mainframe.cc:313
+msgid "Search in the dictionary"
+msgstr "Recherche dans le dictionnaire"
+
+#: wxwin/mainframe.cc:315
+msgid "&Rack + 1"
+msgstr "&Tirage + 1"
+
+#: wxwin/mainframe.cc:315
+msgid "Letters of the rack plus one"
+msgstr "Lettres du tirage plus une"
+
+#: wxwin/mainframe.cc:316
+msgid "R&accords"
+msgstr "R&accords"
+
+#: wxwin/mainframe.cc:316
+msgid "Raccords on a word of the search"
+msgstr "Raccords sur un mot de la recherche"
+
+#: wxwin/mainframe.cc:317
+msgid "&Benjamins"
+msgstr "&Benjamins"
+
+#: wxwin/mainframe.cc:317
+msgid "Benjamins on a word of the search"
+msgstr "Benjamins sur un mot de la recherche"
+
+#: wxwin/mainframe.cc:319
+msgid "Game &history"
+msgstr "&Historique de la partie"
+
+#: wxwin/mainframe.cc:321
+msgid "R&esults"
+msgstr "Ré&sultats"
+
+#: wxwin/mainframe.cc:325
+msgid "&About..."
+msgstr "À &propos..."
+
+#: wxwin/mainframe.cc:325 wxwin/mainframe.cc:718
+msgid "About Eliot"
+msgstr "À propos d'Eliot"
+
+#: wxwin/mainframe.cc:329
+msgid "&Settings"
+msgstr "&Paramètres"
+
+#: wxwin/mainframe.cc:330
+msgid "&Windows"
+msgstr "&Fenêtres"
+
+#: wxwin/mainframe.cc:331
+msgid "&Help"
+msgstr "&Aide"
+
+#: wxwin/mainframe.cc:355 wxwin/mainframe.cc:393
+msgid "No dictionary selected"
+msgstr "Pas de dictionnaire sélectionné"
+
+#: wxwin/mainframe.cc:355 wxwin/mainframe.cc:393 wxwin/mainframe.cc:487
+#: wxwin/mainframe.cc:507 wxwin/mainframe.cc:538
+msgid "Eliot: error"
+msgstr "Eliot : erreur"
+
+#: wxwin/mainframe.cc:413
+msgid "Cannot open "
+msgstr "Impossible d'ouvrir "
+
+#: wxwin/mainframe.cc:425 wxwin/mainframe.cc:434
+msgid "Error while loading the game"
+msgstr "Erreur pendant le chargement de la partie"
+
+#: wxwin/mainframe.cc:426
+msgid "Invalid game"
+msgstr "Partie invalide"
+
+#: wxwin/mainframe.cc:435
+msgid "The game is empty"
+msgstr "La partie est vide"
+
+#: wxwin/mainframe.cc:467
+msgid "Cannot create "
+msgstr "Impossible de créer "
+
+#: wxwin/mainframe.cc:496 wxwin/mainframe.cc:560
+msgid "Printing not done"
+msgstr "Impression non effectuée"
+
+#: wxwin/mainframe.cc:496 wxwin/mainframe.cc:524
+msgid "Printing"
+msgstr "Impression"
+
+#: wxwin/mainframe.cc:519
+msgid "Print preview problem.\n"
+msgstr "Problème avec l'aperçu avant impression.\n"
+
+#: wxwin/mainframe.cc:520
+msgid "The printer may not be correctly initialized"
+msgstr "Il se peut que l'imprimante soit mal initialisée"
+
+#: wxwin/mainframe.cc:521
+msgid "Print preview"
+msgstr "Aperçu avant impression"
+
+#: wxwin/mainframe.cc:542
+msgid "Print to a PostScript file"
+msgstr "Imprimer dans un fichier PostScript"
+
+#: wxwin/mainframe.cc:561 wxwin/mainframe.cc:567
+msgid "PostScript printing"
+msgstr "Impression PostScript"
+
+#: wxwin/mainframe.cc:566
+msgid "Cannot initialize PostScript printer"
+msgstr "Impossible d'initialiser l'impression PostScript"
+
+#: wxwin/mainframe.cc:714
+msgid ""
+"This program is free software; you can redistribute it and/or modify it "
+"under the terms of the GNU General Public License as published by the Free "
+"Software Foundation; either version 2 of the License, or (at your option) "
+"any later version."
+msgstr ""
+"Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le "
+"modifier selon les termes de la licence \"GNU General Public License\" "
+"publiée par la Free Software Fundation ; soit la version 2 de la Licence, "
+"soit (comme vous le préférez), n'importe quelle version ultérieure."
+
+#: wxwin/mainframe.cc:912
+msgid "turn:"
+msgstr "coup :"
+
+#: wxwin/mainframe.cc:913
+msgid "points:"
+msgstr "points :"
+
+#: wxwin/mainframe.cc:948
+msgid ""
+"The bag doesn't contain enough letters\n"
+"for a new rack."
+msgstr ""
+"Le sac ne contient pas assez de lettres\n"
+"pour un nouveau tirage."
+
+#: wxwin/mainframe.cc:949 wxwin/mainframe.cc:953 wxwin/mainframe.cc:957
+msgid "Rack validation"
+msgstr "Validation du tirage"
+
+#: wxwin/mainframe.cc:952
+msgid "The rack must contain at least 2 consonants and 2 vowels."
+msgstr "Le tirage doit contenir au moins 2 consonnes et 2 voyelles."
+
+#: wxwin/mainframe.cc:956
+msgid "The rack contains invalid letters for the current dictionary"
+msgstr ""
+"Le tirage contient des lettres incorrectes pour le dictionnaire courant"
+
+#: wxwin/mainframe.cc:960
+msgid "The rack has been modified manually"
+msgstr "Le tirage a été modifié manuellement"
+
+#: wxwin/searchpanel.cc:146 wxwin/searchpanel.cc:190
+#, c-format
+msgid "The search is limited to %d letters"
+msgstr "La recherche est limitée à %d lettres"
+
+#: wxwin/searchpanel.cc:301
+msgid "Minimum length"
+msgstr "Longueur minimum"
+
+#: wxwin/searchpanel.cc:303
+msgid "Maximum length"
+msgstr "Longueur maximum"
+
+#: wxwin/searchpanel.cc:366
+msgid "Cross words"
+msgstr "Mots croisés"
+
+#: wxwin/searchpanel.cc:367
+msgid "Plus 1"
+msgstr "Plus 1"
+
+#: wxwin/searchpanel.cc:368
+msgid "Regular expressions"
+msgstr "Expressions régulières"
+
+#~ msgid " Racks "
+#~ msgstr " Tirages "
+
+#~ msgid " Help "
+#~ msgstr " Aide "
+
+#~ msgid " Save the game "
+#~ msgstr " Sauvegarder la partie "
+
+#~ msgid " Load a game "
+#~ msgstr " Charger une partie "
+
+#~ msgid "The rack must contain at least 2 consonants and 2 vowels\n"
+#~ msgstr "Le tirage doit contenir au moins 2 consonnes et 2 voyelles\n"
+
+#~ msgid "but the bag doesn't contain enough letters.\n"
+#~ msgstr "mais le sac ne contient plus assez de lettres.\n"
+
+#~ msgid "&Configuration"
+#~ msgstr "&Configuration"
+
+#~ msgid "Game"
+#~ msgstr "Partie"
+
+#~ msgid "Word counts double..."
+#~ msgstr "Mot compte double..."
+
+#~ msgid "Word counts triple..."
+#~ msgstr "Mot compte triple..."
+
+#~ msgid "Letter counts double..."
+#~ msgstr "Lettre compte double..."
+
+#~ msgid "Color of the \"letter counts double\" squares"
+#~ msgstr "Couleur des cases \"lettre compte double\""
+
+#~ msgid "Letter counts triple..."
+#~ msgstr "Lettre compte triple..."
+
+#~ msgid "Color of the \"letter counts triple\" squares"
+#~ msgstr "Couleur des cases \"lettre compte triple\""
+
+#, fuzzy
+#~ msgid "Fonte des lettres"
+#~ msgstr "Entrer les nouvelles lettres:"
+
+#~ msgid "Game..."
+#~ msgstr "Partie..."
+
+#, fuzzy
+#~ msgid "Results..."
+#~ msgstr "Résultat"
+
+#, fuzzy
+#~ msgid "Dictionnaire"
+#~ msgstr " Dictionnaire "
+
 #~ msgid "Usage: eliotcurses /path/to/ods4.dawg\n"
 #~ msgstr "Usage: eliotcurses /chemin vers/ods4.dawg\n"
 
 #~ msgid "Played word: "
-#~ msgstr "Mot joué    :"
-
-#~ msgid "Training"
-#~ msgstr "Entraînement"
+#~ msgstr "Mot joué    :"
 
 #~ msgid "Duplicate"
 #~ msgstr "Duplicate"

Index: test/.cvsignore
===================================================================
RCS file: /cvsroot/eliot/eliot/test/.cvsignore,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/.cvsignore     16 Apr 2005 15:47:59 -0000      1.1
+++ test/.cvsignore     8 Jan 2008 13:52:41 -0000       1.2
@@ -1 +1,2 @@
 *.run
+load_saved_game.elt

Index: test/driver
===================================================================
RCS file: /cvsroot/eliot/eliot/test/driver,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- test/driver 5 Nov 2006 13:34:27 -0000       1.6
+++ test/driver 8 Jan 2008 13:52:41 -0000       1.7
@@ -20,6 +20,12 @@
 training_bag        0  # randseed unused
 # Enter a rack, then display all the possibilities
 training_search     0  # randseed unused
+# Display the benjamins for several words
+training_benj       0  # randseed unused
+# Display the "raccords" for several words
+training_racc       0  # randseed unused
+# Test the 7 + 1 feature
+training_7pl1       0  # randseed unused
 # Several ways of getting a rack and playing a word
 training_play       4
 # Training rack+search+play+back 
@@ -47,6 +53,8 @@
 
 # 2 AI players
 duplicate_2_ai      5
+# 2 human players, one IA, with manual change of human player
+duplicate_humans_ai 6
 
 #################
 # Free game mode

Index: test/duplicate_2_ai.input
===================================================================
RCS file: /cvsroot/eliot/eliot/test/duplicate_2_ai.input,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/duplicate_2_ai.input   16 Apr 2005 15:47:59 -0000      1.1
+++ test/duplicate_2_ai.input   8 Jan 2008 13:52:41 -0000       1.2
@@ -3,6 +3,7 @@
 a T
 a l
 a p
+a g
 q
 q
 

Index: test/duplicate_2_ai.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/duplicate_2_ai.ref,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- test/duplicate_2_ai.ref     1 Jan 2006 19:25:10 -0000       1.3
+++ test/duplicate_2_ai.ref     8 Jan 2008 13:52:41 -0000       1.4
@@ -3,14 +3,14 @@
 mode duplicate
 [?] pour l'aide
 commande> a S
-Joueur 0:  866
-Joueur 1:  866
+Joueur 0:  918
+Joueur 1:  918
 commande> a T
-Joueur 0: RTTUW
-Joueur 1: RTTUW
+Joueur 0: DQRU
+Joueur 1: DQRU
 commande> a l
  A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ?
- 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 1 0 1 0 0 0 0
+ 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0
 commande> a p
 Eliot 1.5
 
@@ -20,30 +20,50 @@
 
     N |   RACK   |    SOLUTION     | REF | PTS | P | BONUS
    ===|==========|=================|=====|=====|===|======
-    1 |  EA?AEBF | FABAcEE         |  H4 |  80 | 0 | *
-    2 |  LMUAEYE | YEBLE           |  6F |  38 | 0 |  
-    3 | AMU+JEIG | MEJUGEAI        |  9G |  78 | 0 | *
-    4 |  LEHNMGA | HALE            |  8L |  46 | 0 |  
-    5 | GMN+NSEO | MENSONGE        |  O1 |  83 | 0 | *
-    6 |  ARAURIU | RAIRA           |  5B |  21 | 0 |  
-    7 | UU+TSDEA | RUSTAUDE        |  B5 |  63 | 0 | *
-    8 |  ONIAVPD | VIDA            | A12 |  45 | 0 |  
-    9 | NOP+SONE | PENONS          |  K1 |  33 | 0 |  
-   10 | O+OXTOLN | LUX             |  J8 |  32 | 0 |  
-   11 | NOOOT+SZ | ZOOS            | 11E |  38 | 0 |  
-   12 | NOT+MIAI | DOMINAIT        | 14A |  74 | 0 | *
-   13 |  CERPFEO | FEROCE          | 15G |  47 | 0 |  
-   14 | P+BSVQIU | PIQUAS          |  C1 |  32 | 0 |  
-   15 | BV+ETLIE | LEVITE          |  A1 |  39 | 0 |  
-   16 | B+RLD?UC | PUBLiC          |  1C |  36 | 0 |  
-   17 | DR+NTERR | DENREE          |  2J |  22 | 0 |  
-   18 | RRT+TUKE | TREK            | 13F |  36 | 0 |  
-   19 | RTU+THWI | HAI             |  7G |  23 | 0 |  
+    1 |  ?EBAAEF | FABAcEE         |  H4 |  80 | 0 | *
+    2 |  KEELIFE | KIEF            | 10F |  36 | 0 |  
+    3 | EEEL+IJX | FIXEE           |  4H |  34 | 0 |  
+    4 | EJL+RANS | JEANS           | 11D |  49 | 0 |  
+    5 | LR+OAHPU | LOPE            |  9E |  29 | 0 |  
+    6 | AHRU+OAE | HOUE            | 12A |  40 | 0 |  
+    7 | AAR+AVOC | HAVA            | A12 |  30 | 0 |  
+    8 | ACOR+WDN | WAX             |  J2 |  41 | 0 |  
+    9 | -VNIALZO | OZONAI          | B10 |  48 | 0 |  
+   10 | LV+NDULU | VIN             |  I3 |  21 | 0 |  
+   11 | DLLUU+NO | DUNE            |  K1 |  22 | 0 |  
+   12 | LLOU+DAM | DOUMA           |  1K |  24 | 0 |  
+   13 | DLL+TOBI | MOLLIT          |  N1 |  18 | 0 |  
+   14 | -ELTCUBE | CUBEBE          |  6F |  31 | 0 |  
+   15 | -PE?STIE | SEPTImE         |  L6 |  85 | 0 | *
+   16 |  LNRSISE | SERINS          | J10 |  29 | 0 |  
+   17 | L+RGYAET | STYLER          | 15J |  75 | 0 |  
+   18 | AG+CURGI | CARGUE          | N10 |  30 | 0 |  
+   19 | GI+EDRSS | DEGRISAS        |  7B |  79 | 0 | *
+   20 |  TOEHLRT | PHOT            |  8L |  27 | 0 |  
+   21 | ELRT+NME | REMELENT        |  C2 |  70 | 0 | *
+   22 |  QDRMUTI | MITAN           |  5E |  20 | 0 |  
 
-   Total: 866
+   Total: 918
 
-Rack 0: RTTUW
-Rack 1: RTTUW
+Rack 0: DQRU
+Rack 1: DQRU
+commande> a g
+     1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+ A   -  -  -  -  -  -  -  -  -  -  -  H  A  V  A
+ B   -  -  -  -  -  -  D  -  -  O  Z  O  N  A  I
+ C   -  R  E  M  E  L  E  N  T  -  -  U  -  -  -
+ D   -  -  -  -  -  -  G  -  -  -  J  E  -  -  -
+ E   -  -  -  -  M  -  R  -  L  -  E  -  -  -  -
+ F   -  -  -  -  I  C  I  -  O  K  A  -  -  -  -
+ G   -  -  -  -  T  U  S  -  P  I  N  -  -  -  -
+ H   -  -  -  F  A  B  A  c  E  E  S  -  -  -  -
+ I   -  -  V  I  N  E  S  -  -  F  -  -  -  -  -
+ J   -  W  A  X  -  B  -  -  -  S  E  R  I  N  S
+ K   D  U  N  E  -  E  -  -  -  -  -  -  -  -  T
+ L   O  -  -  E  -  S  E  P  T  I  m  E  -  -  Y
+ M   U  -  -  -  -  -  -  H  -  -  -  -  -  -  L
+ N   M  O  L  L  I  T  -  O  -  C  A  R  G  U  E
+ O   A  -  -  -  -  -  -  T  -  -  -  -  -  -  R
 commande> q
 fin du mode duplicate
 commande> q

Index: test/freegame_3_ai.input
===================================================================
RCS file: /cvsroot/eliot/eliot/test/freegame_3_ai.input,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/freegame_3_ai.input    16 Apr 2005 15:47:59 -0000      1.1
+++ test/freegame_3_ai.input    8 Jan 2008 13:52:41 -0000       1.2
@@ -2,6 +2,7 @@
 a T
 a S
 a p
+a g
 q
 q
 

Index: test/freegame_3_ai.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/freegame_3_ai.ref,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- test/freegame_3_ai.ref      1 Jan 2006 19:25:10 -0000       1.3
+++ test/freegame_3_ai.ref      8 Jan 2008 13:52:41 -0000       1.4
@@ -4,12 +4,12 @@
 [?] pour l'aide
 commande> a T
 Joueur 0: 
-Joueur 1: DEPKAS
-Joueur 2: DILMQ
+Joueur 1: ADLT
+Joueur 2: AIU
 commande> a S
-Joueur 0:  398
-Joueur 1:  266
-Joueur 2:  205
+Joueur 0:  319
+Joueur 1:  286
+Joueur 2:  303
 commande> a p
 Eliot 1.5
 
@@ -20,31 +20,51 @@
 
     N |   RACK   |    SOLUTION     | REF | PTS | P | BONUS
    ===|==========|=================|=====|=====|===|======
-    1 |  RTADHIR | HARDI           |  H4 |  26 | 0 |  
-    2 |  ANO?EEA | ANEE            |  I4 |  18 | 1 |  
-    3 |  WIG?TEN | IWaN            |  J1 |  38 | 2 |  
-    4 | RT+NTEIU | INTUITER        |  1F |  77 | 0 | *
-    5 | AO?+TFBA | BAFOuAT         |  J7 |  69 | 1 | *
-    6 | EGT+OSTR | GROTTES         |  9B |  70 | 2 | *
-    7 |  UEEOERE | GOUREE          |  B9 |  18 | 0 |  
-    8 |  EAMIZUO | INTUITEREZ      |  1F |  57 | 1 |  
-    9 |  XRUMGRQ | GRAUX           | 12H |  34 | 2 |  
-   10 | EE+ONLAS | ENOLATES        |  E4 |  82 | 0 | *
-   11 | AIMOU+NN | NOMINAUX        |  L5 |  69 | 1 | *
-   12 | MQR+LIHJ | HI              |  F6 |  28 | 2 |  
-   13 |  PLCYEFE | CAPEYE          |  3I |  52 | 0 |  
-   14 |  EVLETDE | VOLETE          |  D8 |  39 | 1 |  
-   15 | JLMQR+OB | ROB             |  O3 |  25 | 2 |  
-   16 | FL+UUSML | FULL            |  D1 |  26 | 0 |  
-   17 | DE+ICPEV | VICE            |  C2 |  32 | 1 |  
-   18 | JLMQ+DSI | JANS            |  5G |  24 | 2 |  
-   19 | MSU+SAAI | ASSUMAI         | 15A |  85 | 0 | *
+    1 |  RAHITRD | HARDI           |  H4 |  26 | 0 |  
+    2 |  ?TIEXFA | FAXAIEnT        |  5E | 126 | 1 | *
+    3 |  ATOSBUF | BOUTEFAS        |  J1 |  73 | 2 | *
+    4 | RT+AREEN | RENTERAI        |  8A |  77 | 0 | *
+    5 |  RZUGNSS | AZURS           |  F5 |  34 | 1 |  
+    6 |  MIMLLOP | PLOMB           |  1F |  30 | 2 |  
+    7 |  EEMNETV | VETEMENT        |  L3 |  76 | 0 | *
+    8 | GNRS+PEN | REPS            | 11I |  25 | 1 |  
+    9 | ILM+HSVI | VIZIR           |  6D |  33 | 2 |  
+   10 |  AWELOUB | WEB             | J10 |  34 | 0 |  
+   11 | GNN+EELE | EGEENNE         |  B8 |  20 | 1 |  
+   12 | HLMS+OJC | LOCHS           | 13F |  30 | 2 |  
+   13 | AELOU+TA | TAULE           | A11 |  27 | 0 |  
+   14 | L+ADSALY | LYS             |  M1 |  34 | 1 |  
+   15 | JM+U?EKO | TOKaJ           |  D8 |  40 | 2 |  
+   16 | AO+QRSED | COQ             | H13 |  36 | 0 |  
+   17 | AADL+INN | YIN             |  2M |  24 | 1 |  
+   18 | EMU+IGRO | GOUMIER         |  2B |  82 | 2 | *
+   19 | ADERS+IC | ENCRAIS         |  O1 |  30 | 0 |  
+   20 | AADLN+TE | ANE             | E10 |  28 | 1 |  
+   21 |    EUIAU | TUEE            |  4J |  18 | 2 |  
+   22 |        D | DU              |  D1 |   5 | 0 |  
 
-   Total: 869
+   Total: 908
 
 Rack 0: 
-Rack 1: DEP+KAS
-Rack 2: DILMQ
+Rack 1: ADLT
+Rack 2: AIU
+commande> a g
+     1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+ A   -  -  -  -  -  -  -  R  -  -  T  A  U  L  E
+ B   -  G  -  -  -  -  -  E  G  E  E  N  N  E  -
+ C   -  O  -  -  -  -  -  N  -  -  -  -  -  -  -
+ D   D  U  -  -  -  V  -  T  O  K  a  J  -  -  -
+ E   -  M  -  -  F  I  -  E  -  A  N  E  -  -  -
+ F   P  I  -  -  A  Z  U  R  S  -  -  -  L  -  -
+ G   L  E  -  -  X  I  -  A  -  -  -  -  O  -  -
+ H   O  R  -  H  A  R  D  I  -  -  -  -  C  O  Q
+ I   M  -  -  -  I  -  -  -  -  -  R  -  H  -  -
+ J   B  O  U  T  E  F  A  S  -  W  E  B  S  -  -
+ K   -  -  -  U  n  -  -  -  -  -  P  -  -  -  -
+ L   -  -  V  E  T  E  M  E  N  T  S  -  -  -  -
+ M   L  Y  S  E  -  -  -  -  -  -  -  -  -  -  -
+ N   -  I  -  -  -  -  -  -  -  -  -  -  -  -  -
+ O   E  N  C  R  A  I  S  -  -  -  -  -  -  -  -
 commande> q
 fin du mode partie libre
 commande> q

Index: test/freegame_change.input
===================================================================
RCS file: /cvsroot/eliot/eliot/test/freegame_change.input,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/freegame_change.input  16 Apr 2005 15:47:59 -0000      1.1
+++ test/freegame_change.input  8 Jan 2008 13:52:41 -0000       1.2
@@ -2,14 +2,15 @@
 a T
 p JID
 a T
-p auouel
+p aowalt
 a T
-p WX
+p MA
 a T
-p WA
+p MN
 a T
-p KEEEAAI
+p SGEEEAI
 a T
+a p
 q
 q
 

Index: test/freegame_change.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/freegame_change.ref,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- test/freegame_change.ref    24 Dec 2005 17:50:11 -0000      1.2
+++ test/freegame_change.ref    8 Jan 2008 13:52:41 -0000       1.3
@@ -3,28 +3,46 @@
 mode partie libre
 [?] pour l'aide
 commande> a T
-Joueur 0: NEIJEDN
-Joueur 1: UUEALEO
+Joueur 0: JNNEDEI
+Joueur 1: TLAEOWA
 commande> p JID
 commande> a T
-Joueur 0: EENNWTA
-Joueur 1: UUEALEO
-commande> p auouel
+Joueur 0: EENNMEN
+Joueur 1: TLAEOWA
+commande> p aowalt
 commande> a T
-Joueur 0: EENNWTA
-Joueur 1: EEAKEIA
-commande> p WX
+Joueur 0: EENNMEN
+Joueur 1: EEEGAIS
+commande> p MA
 commande> a T
-Joueur 0: EENNWTA
-Joueur 1: EEAKEIA
-commande> p WA
+Joueur 0: EENNMEN
+Joueur 1: EEEGAIS
+commande> p MN
 commande> a T
-Joueur 0: EENNTOD
-Joueur 1: EEAKEIA
-commande> p KEEEAAI
+Joueur 0: EEENNER
+Joueur 1: EEEGAIS
+commande> p SGEEEAI
 commande> a T
-Joueur 0: EENNTOD
-Joueur 1: UNLEUSS
+Joueur 0: EEENNER
+Joueur 1: HAAUAUO
+commande> a p
+Eliot 1.5
+
+Game type: Free game
+Player 0: Human
+Player 1: Human
+
+    N |   RACK   |    SOLUTION     | REF | PTS | P | BONUS
+   ===|==========|=================|=====|=====|===|======
+    1 |  JNNEDEI | (-JID)          |  -  |   0 | 0 |
+    2 |  TLAEOWA | (-AOWALT)       |  -  |   0 | 1 |
+    3 | EENN+MEN | (-MN)           |  -  |   0 | 0 |
+    4 | E+EEGAIS | (-SGEEEAI)      |  -  |   0 | 1 |
+
+   Total: 0
+
+Rack 0: EEENN+ER
+Rack 1: HAAUAUO
 commande> q
 fin du mode partie libre
 commande> q

Index: test/freegame_passing.input
===================================================================
RCS file: /cvsroot/eliot/eliot/test/freegame_passing.input,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/freegame_passing.input 16 Apr 2005 15:47:59 -0000      1.1
+++ test/freegame_passing.input 8 Jan 2008 13:52:41 -0000       1.2
@@ -2,6 +2,9 @@
 a S
 p
 p
+a t
+p UIET
+a t
 p
 p
 p
@@ -22,6 +25,9 @@
 p
 p
 p
+p
+a S
+a T
 a p
 q
 q

Index: test/freegame_passing.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/freegame_passing.ref,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- test/freegame_passing.ref   1 Jan 2006 19:25:10 -0000       1.3
+++ test/freegame_passing.ref   8 Jan 2008 13:52:41 -0000       1.4
@@ -7,6 +7,11 @@
 Joueur 1:    0
 commande> p
 commande> p
+commande> a t
+EGISSTU
+commande> p UIET
+commande> a t
+GSSTAUV
 commande> p
 commande> p
 commande> p
@@ -27,6 +32,13 @@
 commande> p
 commande> p
 commande> p
+commande> p
+commande> a S
+Joueur 0:  -11
+Joueur 1:  777
+commande> a T
+Joueur 0: AGSSTUV
+Joueur 1: 
 commande> a p
 Eliot 1.5
 
@@ -36,28 +48,59 @@
 
     N |   RACK   |    SOLUTION     | REF | PTS | P | BONUS
    ===|==========|=================|=====|=====|===|======
-    1 |  RENLOHL | HERON           |  H4 |  24 | 1 |  
-    2 | LL+XUORC | OCREUX          |  5E |  34 | 1 |  
-    3 | LL+NAECT | CALLENT         |  I7 |  73 | 1 | *
-    4 |  DIBB?EM | BIBENDuM        | 12E |  78 | 1 | *
-    5 |  TOEOMLZ | TOMIEZ          |  F9 |  38 | 1 |  
-    6 | LO+ESLSI | SOLEILS         |  M6 |  73 | 1 | *
-    7 |  UEGTVAW | VAGUEZ          | 14A |  38 | 1 |  
-    8 | TW+LAEPU | PAVE            | A12 |  36 | 1 |  
-    9 | LTUW+FAA | FATWA           |  N2 |  42 | 1 |  
-   10 | LU+JAEYU | LAYE            |  O1 |  61 | 1 |  
-   11 | JUU+SENI | JEUNE           | H11 |  47 | 1 |  
-   12 | ISU+RMPN | SPRAY           |  3K |  32 | 1 |  
-   13 | IMNU+AIV | VLAN            |  8L |  33 | 1 |  
-   14 | IIMU+UQE | QUI             | B10 |  30 | 1 |  
-   15 | EIMU+RNF | UNIFORME        |  E1 |  62 | 1 | *
-   16 |  ODITREE | ETOURDIE        |  1B |  80 | 1 | *
-   17 |  TEN?IKR | jERKE           |  8A |  69 | 1 |  
+    1 |  SEUTISG | (PASS)          |  -  |   0 | 0 |
+    2 |  LXCORNU | ROUX            |  H8 |  26 | 1 |  
+    3 |  EGISSTU | (PASS)          |  -  |   0 | 0 |
+    4 | CLN+?BEC | CiNECLUB        | 10B |  75 | 1 | *
+    5 |  EGISSTU | (-UIET)         |  -  |   0 | 0 |
+    6 |  LLESYEO | YOLES           |  J6 |  52 | 1 |  
+    7 | GSS+TAUV | (PASS)          |  -  |   0 | 0 |
+    8 | EL+AAOGT | GALETA          | 11A |  29 | 1 |  
+    9 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   10 | O+RTEUMI | MORUTIER        |  8A |  80 | 1 | *
+   11 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   12 |  EUNPFUP | PFUT            |  E5 |  18 | 1 |  
+   13 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   14 | ENPU+FTE | FETE            | 12B |  33 | 1 |  
+   15 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   16 | NPU+NSIM | LUPINS          |  8J |  33 | 1 |  
+   17 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   18 | MN+UEWOI | WON             |  N6 |  32 | 1 |  
+   19 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   20 | EIMNU+MI | IMMUNS          |  O3 |  23 | 1 |  
+   21 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   22 | EI+IDRED | BIRDIE          | I10 |  22 | 1 |  
+   23 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   24 | DE+RJAAT | DEJETA          | 15H |  45 | 1 |  
+   25 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   26 | AR+ENQEE | CAFRE           | B10 |  20 | 1 |  
+   27 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   28 | AEENQ+BR | BADERNE         | 13G |  26 | 1 |  
+   29 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   30 | Q+EAZAEL | ZEN             | L11 |  24 | 1 |  
+   31 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   32 | AAELQ+RA | ALEA            |  I3 |  16 | 1 |  
+   33 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   34 | AQR+LDEH | ADHERAI         |  3I |  22 | 1 |  
+   35 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   36 | LQ+SI?AI | QuASI           | N10 |  65 | 1 |  
+   37 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   38 | IL+TVHEO | OHE             |  4K |  29 | 1 |  
+   39 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   40 | ILTV+ONK | KOHOL           |  K1 |  34 | 1 |  
+   41 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   42 | INTV+SIN | NAYS            |  6H |  31 | 1 |  
+   43 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   44 |    IINTV | TIKI            |  1I |  14 | 1 |  
+   45 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   46 |       NV | VU              |  D7 |  10 | 1 |  
+   47 |  AGSSTUV | (PASS)          |  -  |   0 | 0 |
+   48 |        N | NI              |  M7 |   7 | 1 |  
 
-   Total: 850
+   Total: 766
 
-Rack 0: EGISSTU
-Rack 1: INT+ESDO
+Rack 0: AGSSTUV
+Rack 1: 
 commande> q
 fin du mode partie libre
 commande> q

Index: test/load_saved_game.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/load_saved_game.ref,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/load_saved_game.ref    1 Jan 2006 19:25:10 -0000       1.1
+++ test/load_saved_game.ref    8 Jan 2008 13:52:41 -0000       1.2
@@ -12,16 +12,16 @@
 LMUAEYE
 commande> r
 commande> a r
-  1: YEBLE              38 6F
-  2: BAYLE              36 6H
-  3: AMYLE              35 10D
-  4: ELYME              35 10D
-  5: ELYME              35 10H
+  1: AY                 46 I6
+  2: YEBLE              38 6F
+  3: MAYE               36 I3
+  4: BAYLE              36 6H
+  5: AMYLE              35 10D
   6: BAYE               35 6H
-  7: BEY                34 6H
-  8: LAYEE              34 10D
-  9: YUE                32 10F
- 10: AMYLE              30 5H
+  7: ELYME              35 10D
+  8: ELYME              35 10H
+  9: LAYE               34 I3
+ 10: LAYEE              34 10D
 commande> n 2
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -30,13 +30,13 @@
  C   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  D   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  E   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
- F   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
- G   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ F   -  -  -  -  -  Y  -  -  -  -  -  -  -  -  -
+ G   -  -  -  -  -  E  -  -  -  -  -  -  -  -  -
  H   -  -  -  F  A  B  A  c  E  E  -  -  -  -  -
- I   -  -  -  -  -  A  -  -  -  -  -  -  -  -  -
- J   -  -  -  -  -  Y  -  -  -  -  -  -  -  -  -
- K   -  -  -  -  -  L  -  -  -  -  -  -  -  -  -
- L   -  -  -  -  -  E  -  -  -  -  -  -  -  -  -
+ I   -  -  -  -  -  L  -  -  -  -  -  -  -  -  -
+ J   -  -  -  -  -  E  -  -  -  -  -  -  -  -  -
+ K   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ L   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  M   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  N   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  O   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
@@ -48,19 +48,19 @@
 commande> 
 commande> +
 commande> a t
-AMUJEIG
+EELMUJE
 commande> r
 commande> a r
-  1: MEJUGEAI        *  78 9G
-  2: MEJUGEAI        *  72 9C
-  3: MEJUGEAI        *  71 10G
-  4: MEJUGEAI        *  71 10C
-  5: MEJUGEAI        *  69 J5
-  6: MEJUGEAI        *  69 J1
-  7: JUGEA              37 5B
-  8: JUGEAI             37 5J
-  9: JAUGE              35 5J
- 10: JUGEA              35 5J
+  1: JUMEL              38 J2
+  2: JUMELEE            33 10B
+  3: JUMELA             28 5C
+  4: JUMELEE            25 9C
+  5: JUMELE             24 G10
+  6: JUMEL              23 G10
+  7: JUMELE             23 9C
+  8: JEU                19 9G
+  9: JEU                19 G10
+ 10: JUMELEE            19 10E
 commande> n 1
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -69,50 +69,50 @@
  C   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  D   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  E   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
- F   -  -  -  -  -  Y  -  -  -  -  -  -  -  -  -
- G   -  -  -  -  -  E  -  -  M  -  -  -  -  -  -
+ F   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ G   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  H   -  -  -  F  A  B  A  c  E  E  -  -  -  -  -
- I   -  -  -  -  -  L  -  -  J  -  -  -  -  -  -
- J   -  -  -  -  -  E  -  -  U  -  -  -  -  -  -
- K   -  -  -  -  -  -  -  -  G  -  -  -  -  -  -
- L   -  -  -  -  -  -  -  -  E  -  -  -  -  -  -
- M   -  -  -  -  -  -  -  -  A  -  -  -  -  -  -
- N   -  -  -  -  -  -  -  -  I  -  -  -  -  -  -
+ I   -  -  -  -  -  A  Y  -  -  -  -  -  -  -  -
+ J   -  J  U  M  E  L  -  -  -  -  -  -  -  -  -
+ K   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ L   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ M   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ N   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  O   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
 commande> 
 commande> +
 commande> a t
-LEHNMGA
+EEIGLEH
 commande> r
 commande> a r
-  1: HALE               46 8L
-  2: MALE               30 8L
-  3: ENGAMA             30 5C
-  4: HALA               27 5E
-  5: LAME               26 8L
-  6: HAN                25 8M
-  7: HELA               25 5C
-  8: GLANA              25 5D
-  9: EMANA              25 5D
- 10: EGALA              25 5D
+  1: HELIEE             34 K5
+  2: HELEE              32 K5
+  3: EGAYEE             32 7F
+  4: EGAYE              31 7F
+  5: HELE               30 K5
+  6: LAYEE              29 7G
+  7: LAYE               28 7G
+  8: HUILEE             26 3I
+  9: HE                 26 K5
+ 10: HUILE              24 3I
 commande> n 3
 commande> 
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
  A   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  B   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
- C   -  -  -  -  E  -  -  -  -  -  -  -  -  -  -
- D   -  -  -  -  N  -  -  -  -  -  -  -  -  -  -
- E   -  -  -  -  G  -  -  -  -  -  -  -  -  -  -
- F   -  -  -  -  A  Y  -  -  -  -  -  -  -  -  -
- G   -  -  -  -  M  E  -  -  M  -  -  -  -  -  -
+ C   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ D   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ E   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ F   -  -  -  -  -  -  E  -  -  -  -  -  -  -  -
+ G   -  -  -  -  -  -  G  -  -  -  -  -  -  -  -
  H   -  -  -  F  A  B  A  c  E  E  -  -  -  -  -
- I   -  -  -  -  -  L  -  -  J  -  -  -  -  -  -
- J   -  -  -  -  -  E  -  -  U  -  -  -  -  -  -
- K   -  -  -  -  -  -  -  -  G  -  -  -  -  -  -
- L   -  -  -  -  -  -  -  -  E  -  -  -  -  -  -
- M   -  -  -  -  -  -  -  -  A  -  -  -  -  -  -
- N   -  -  -  -  -  -  -  -  I  -  -  -  -  -  -
+ I   -  -  -  -  -  A  Y  -  -  -  -  -  -  -  -
+ J   -  J  U  M  E  L  E  -  -  -  -  -  -  -  -
+ K   -  -  -  -  -  -  E  -  -  -  -  -  -  -  -
+ L   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ M   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ N   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  O   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
 commande> a p
 Eliot 1.5
@@ -123,16 +123,16 @@
     N |   RACK   |    SOLUTION     | REF | PTS | P | BONUS
    ===|==========|=================|=====|=====|===|======
     1 |  EA?AEBF | FABAcEE         |  H4 |  80 | 0 | *
-    2 |  LMUAEYE | YEBLE           |  6F |  38 | 0 |  
-    3 | AMU+JEIG | MEJUGEAI        |  9G |  78 | 0 | *
-    4 |  LEHNMGA | ENGAMA          |  5C |  30 | 0 |  
+    2 |  LMUAEYE | AY              |  I6 |  46 | 0 |  
+    3 | EELMU+JE | JUMEL           |  J2 |  38 | 0 |  
+    4 | EE+IGLEH | EGAYEE          |  7F |  32 | 0 |  
 
-   Total: 226
+   Total: 196
 
-Rack 0: HL
+Rack 0: HIL
 commande> a l
  A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ?
- 5 1 2 3 9 1 0 2 7 0 1 4 1 5 6 2 1 6 6 6 5 2 1 1 0 1 1
+ 6 1 2 3 9 1 1 2 8 0 1 4 2 6 6 2 1 6 6 6 5 2 1 1 0 1 1
 commande> 
 commande> s load_saved_game.elt
 commande> q
@@ -145,18 +145,18 @@
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
  A   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  B   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
- C   -  -  -  -  E  -  -  -  -  -  -  -  -  -  -
- D   -  -  -  -  N  -  -  -  -  -  -  -  -  -  -
- E   -  -  -  -  G  -  -  -  -  -  -  -  -  -  -
- F   -  -  -  -  A  Y  -  -  -  -  -  -  -  -  -
- G   -  -  -  -  M  E  -  -  M  -  -  -  -  -  -
+ C   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ D   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ E   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ F   -  -  -  -  -  -  E  -  -  -  -  -  -  -  -
+ G   -  -  -  -  -  -  G  -  -  -  -  -  -  -  -
  H   -  -  -  F  A  B  A  c  E  E  -  -  -  -  -
- I   -  -  -  -  -  L  -  -  J  -  -  -  -  -  -
- J   -  -  -  -  -  E  -  -  U  -  -  -  -  -  -
- K   -  -  -  -  -  -  -  -  G  -  -  -  -  -  -
- L   -  -  -  -  -  -  -  -  E  -  -  -  -  -  -
- M   -  -  -  -  -  -  -  -  A  -  -  -  -  -  -
- N   -  -  -  -  -  -  -  -  I  -  -  -  -  -  -
+ I   -  -  -  -  -  A  Y  -  -  -  -  -  -  -  -
+ J   -  J  U  M  E  L  E  -  -  -  -  -  -  -  -
+ K   -  -  -  -  -  -  E  -  -  -  -  -  -  -  -
+ L   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ M   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ N   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  O   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
 commande> a p
 Eliot 1.5
@@ -167,16 +167,16 @@
     N |   RACK   |    SOLUTION     | REF | PTS | P | BONUS
    ===|==========|=================|=====|=====|===|======
     1 |  EA?AEBF | FABAcEE         |  H4 |  80 | 0 | *
-    2 |  LMUAEYE | YEBLE           |  6F |  38 | 0 |  
-    3 | AMU+JEIG | MEJUGEAI        |  9G |  78 | 0 | *
-    4 |  LEHNMGA | ENGAMA          |  5C |  30 | 0 |  
+    2 |  LMUAEYE | AY              |  I6 |  46 | 0 |  
+    3 | EELMU+JE | JUMEL           |  J2 |  38 | 0 |  
+    4 | EE+IGLEH | EGAYEE          |  7F |  32 | 0 |  
 
-   Total: 226
+   Total: 196
 
-Rack 0: HL
+Rack 0: HIL
 commande> a l
  A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ?
- 5 1 2 3 9 1 0 2 7 0 1 4 1 5 6 2 1 6 6 6 5 2 1 1 0 1 1
+ 6 1 2 3 9 1 1 2 8 0 1 4 2 6 6 2 1 6 6 6 5 2 1 1 0 1 1
 commande> 
 commande> q
 fin du mode entraînement

Index: test/regexp.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/regexp.ref,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/regexp.ref     1 Jan 2006 19:25:10 -0000       1.1
+++ test/regexp.ref     8 Jan 2008 13:52:41 -0000       1.2
@@ -2,6 +2,10 @@
 commande> x a.* 50
 search for a.* (50,1,15)
 aa
+aalenien
+aalenienne
+aaleniennes
+aaleniens
 aas
 abaca
 abacas
@@ -47,14 +51,14 @@
 abaisseriez
 abaisserions
 abaisserons
-abaisseront
-abaisses
-abaisseur
-abaisseurs
 50 printed results
 commande> x a.* 200
 search for a.* (200,1,15)
 aa
+aalenien
+aalenienne
+aaleniennes
+aaleniens
 aas
 abaca
 abacas
@@ -250,10 +254,6 @@
 abattant
 abattants
 abatte
-abattee
-abattees
-abattement
-abattements
 200 printed results
 commande> x .*a.*e.*i.*o.*u.* 50 10
 search for .*a.*e.*i.*o.*u.* (50,10,15)
@@ -329,13 +329,13 @@
 anthophages
 bishop
 bishops
+bronchopathie
+bronchopathies
 cenesthopathie
 cenesthopathies
 chop
 chopa
 chopai
-chopaient
-chopais
 50 printed results
 commande> x a.*b 50
 search for a.*b (50,1,15)
@@ -352,13 +352,14 @@
 bob
 bulb
 cab
+cheb
 cineclub
 club
 cob
 coulomb
 crib
 cuproplomb
-13 printed results
+14 printed results
 commande> x [abc]*b
 search for [abc]*b (50,1,15)
 cab
@@ -378,6 +379,7 @@
 bob
 bulb
 cab
+cheb
 cineclub
 club
 cob
@@ -386,14 +388,17 @@
 cuproplomb
 dab
 deb
+dub
 fob
 guib
 hidjab
+hijab
 hub
 jab
 job
 kebab
 kob
+lamb
 lob
 mahaleb
 mihrab
@@ -417,16 +422,14 @@
 surplomb
 toubab
 toubib
-tub
-videoclub
-web
-winstub
 50 printed results
 commande> x .*(cba)+b
 search for .*(cba)+b (50,1,15)
 0 printed results
 commande> x .*(nn)+.*
 search for .*(nn)+.* (50,1,15)
+aalenienne
+aaleniennes
 abandonna
 abandonnai
 abandonnaient
@@ -475,11 +478,10 @@
 abandonniques
 abandonnons
 abbevillienne
-abbevilliennes
-abelienne
 50 printed results
 commande> x .*(nn)+.*x 200
 search for .*(nn)+.*x (200,1,15)
+actionnariaux
 annaux
 anneaux
 baronniaux
@@ -515,6 +517,7 @@
 panneaux
 paonneaux
 pigeonneaux
+pitonneux
 poissonneux
 precautionneux
 processionnaux
@@ -535,5 +538,5 @@
 vallonneux
 vanneaux
 vicennaux
-55 printed results
+57 printed results
 commande> q

Index: test/regression.pl
===================================================================
RCS file: /cvsroot/eliot/eliot/test/regression.pl,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/regression.pl  16 Apr 2005 15:47:59 -0000      1.1
+++ test/regression.pl  8 Jan 2008 13:52:41 -0000       1.2
@@ -3,9 +3,19 @@
 use strict;
 use warnings;
 
+use Cwd 'abs_path';
+
+my $root_path = $0;
+$root_path =~ s/regression.pl/../;
+$root_path = abs_path($root_path);
+
+# Change to the test/ directory, because some scenarii expect
+# to find saved games in there
+chdir("$root_path/test");
+
 my $driver_file = "driver";
-# Look for ~/ods4.dawg
-my $ods = "$ENV{HOME}/ods4.dawg";
+# Look for ~/ods5.dawg
+my $ods = "$ENV{HOME}/ods5.dawg";
 
 # File extensions
 my $input_ext = ".input";
@@ -16,18 +26,18 @@
 # Find the dictionary
 if (not -f $ods)
 {
-    die "Cannot find dictionary: $!";
+    die "Cannot find dictionary $ods: $!";
 }
 
 # Find the text interface
 my $eliottxt;
-if (-x "../utils/eliottxt")
+if (-x "$root_path/utils/eliottxt")
 {
-    $eliottxt = "../utils/eliottxt";
+    $eliottxt = "$root_path/utils/eliottxt";
 }
-elsif (-x "../utils/eliottxt.exe")
+elsif (-x "$root_path/utils/eliottxt.exe")
 {
-    $eliottxt = "../utils/eliottxt.exe";
+    $eliottxt = "$root_path/utils/eliottxt.exe";
 }
 else
 {

Index: test/training_back.input
===================================================================
RCS file: /cvsroot/eliot/eliot/test/training_back.input,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/training_back.input    27 Dec 2005 01:04:49 -0000      1.1
+++ test/training_back.input    8 Jan 2008 13:52:41 -0000       1.2
@@ -9,17 +9,22 @@
 a r
 n 2
 a g
+a s
 n -1
+a s
 a g
 a p
 n -1
+a s
 a p
 a g
 a l
 n -1
+a s
 *
 r
 n 1
+a s
 a l
 a p
 q

Index: test/training_back.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/training_back.ref,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- test/training_back.ref      1 Jan 2006 19:25:10 -0000       1.2
+++ test/training_back.ref      8 Jan 2008 13:52:42 -0000       1.3
@@ -12,16 +12,16 @@
 LMUAEYE
 commande> r
 commande> a r
-  1: YEBLE              38 6F
-  2: BAYLE              36 6H
-  3: AMYLE              35 10D
-  4: ELYME              35 10D
-  5: ELYME              35 10H
+  1: AY                 46 I6
+  2: YEBLE              38 6F
+  3: MAYE               36 I3
+  4: BAYLE              36 6H
+  5: AMYLE              35 10D
   6: BAYE               35 6H
-  7: BEY                34 6H
-  8: LAYEE              34 10D
-  9: YUE                32 10F
- 10: AMYLE              30 5H
+  7: ELYME              35 10D
+  8: ELYME              35 10H
+  9: LAYE               34 I3
+ 10: LAYEE              34 10D
 commande> n 2
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -30,17 +30,21 @@
  C   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  D   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  E   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
- F   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
- G   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ F   -  -  -  -  -  Y  -  -  -  -  -  -  -  -  -
+ G   -  -  -  -  -  E  -  -  -  -  -  -  -  -  -
  H   -  -  -  F  A  B  A  c  E  E  -  -  -  -  -
- I   -  -  -  -  -  A  -  -  -  -  -  -  -  -  -
- J   -  -  -  -  -  Y  -  -  -  -  -  -  -  -  -
- K   -  -  -  -  -  L  -  -  -  -  -  -  -  -  -
- L   -  -  -  -  -  E  -  -  -  -  -  -  -  -  -
+ I   -  -  -  -  -  L  -  -  -  -  -  -  -  -  -
+ J   -  -  -  -  -  E  -  -  -  -  -  -  -  -  -
+ K   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ L   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  M   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  N   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  O   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+commande> a s
+118
 commande> n -1
+commande> a s
+80
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
  A   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
@@ -72,6 +76,8 @@
 
 Rack 0: LMUAEYE
 commande> n -1
+commande> a s
+0
 commande> a p
 Eliot 1.5
 
@@ -105,9 +111,13 @@
  A B C D  E F G H I J K L M N O P Q R S T U V W X Y Z ?
  9 2 2 3 15 2 2 2 8 1 1 5 3 6 6 2 1 6 6 6 6 2 1 1 1 1 2
 commande> n -1
+commande> a s
+0
 commande> *
 commande> r
 commande> n 1
+commande> a s
+14
 commande> a l
  A B C D  E F G H I J K L M N O P Q R S T U V W X Y Z ?
  9 2 2 3 13 1 2 2 7 1 1 5 3 6 6 2 1 6 6 6 6 2 1 1 1 1 2

Index: test/training_cross.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/training_cross.ref,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/training_cross.ref     1 Jan 2006 19:25:10 -0000       1.1
+++ test/training_cross.ref     8 Jan 2008 13:52:42 -0000       1.2
@@ -46,15 +46,15 @@
 commande> r
 commande> a r
   1: KIMONO             38 6F
-  2: AMOK               34 6G
-  3: MOKA               34 6H
-  4: MOKO               34 6H
-  5: MAKI               34 6H
-  6: KAMI               34 6F
-  7: KINA               33 I3
+  2: KEMIA              37 6F
+  3: MOKO               34 6H
+  4: AMOK               34 6G
+  5: MOKA               34 6H
+  6: MAKI               34 6H
+  7: KAMI               34 6F
   8: KINE               33 I3
-  9: KAN                29 I3
- 10: OKA                27 I2
+  9: KINA               33 I3
+ 10: KAN                29 I3
 commande> n 1
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -88,9 +88,9 @@
   4: SWEAT              32 L6
   5: ETAIES             31 L1
   6: AISEE              29 L4
-  7: ETAIS              27 L2
+  7: TAIES              27 L2
   8: TAISE              27 L3
-  9: TAIES              27 L2
+  9: ETAIS              27 L2
  10: WESTIE             27 9F
 commande> n 1 
 commande> a g
@@ -124,8 +124,8 @@
   3: LAVASSE         *  78 10G
   4: VASSALE         *  75 K9
   5: LAVASSE         *  73 9C
-  6: LAVASSE         *  72 9D
-  7: LAVASSE         *  72 K9
+  6: LAVASSE         *  72 K9
+  7: LAVASSE         *  72 9D
   8: VASSALE         *  67 G8
   9: LAVASSE         *  64 G8
  10: EVASAS             35 10I
@@ -160,12 +160,12 @@
   2: BIQUE              42 8K
   3: OTIQUE             39 8J
   4: TIQUE              36 8K
-  5: BEQUET             30 N9
-  6: MAQUE              29 K9
-  7: EMBUT              29 M1
-  8: MOQUE              28 11D
-  9: QUETE              28 N6
- 10: TAQUE              26 K9
+  5: BAQUET             34 K9
+  6: BAQUE              32 K9
+  7: BEQUET             30 N9
+  8: EMBUT              29 M1
+  9: MAQUE              29 K9
+ 10: MOQUE              28 11D
 commande> n 1 
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -196,13 +196,13 @@
   1: OMNIBUS         *  94 O4
   2: EMBUIONS        *  84 14H
   3: BITUMONS        *  62 15F
-  4: SIMOUN             38 O10
-  5: BOUSIN             38 O7
-  6: NIMBUS             38 O5
-  7: BISON              35 O8
-  8: BISOU              35 O8
-  9: BOUMS              35 O6
- 10: IMBUS              35 O6
+  4: NIMBUS             38 O5
+  5: SIMOUN             38 O10
+  6: BOUSIN             38 O7
+  7: IMBUS              35 O6
+  8: BISON              35 O8
+  9: BISOU              35 O8
+ 10: BOUMS              35 O6
 commande> n 1 
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -236,9 +236,9 @@
   4: AXEZ               44 K10
   5: IXEE               33 14E
   6: EXPIEZ             32 14D
-  7: ZEE                32 14F
-  8: ZOE                32 14F
-  9: EXPIEZ             32 14H
+  7: GEX                32 5K
+  8: EXPIEZ             32 14H
+  9: EPIEZ              32 N10
  10: EXPIE              32 N10
 commande> n 1 
 commande> a g
@@ -306,14 +306,14 @@
 commande> a r
   1: VAINCU             28 13C
   2: VAINC              25 K9
-  3: CONVOI             24 11D
-  4: CAVAI              24 K9
-  5: CONVIA             23 7A
-  6: VAGIN              23 K9
-  7: CONVIA             22 13J
+  3: VACOA              25 K9
+  4: CONVOI             24 11D
+  5: CAVAI              24 K9
+  6: CONVIA             23 7A
+  7: VAGIN              23 K9
   8: VINA               22 7C
   9: CAVA               22 K9
- 10: CANE               21 7E
+ 10: CONVIA             22 13J
 commande> n 1 
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -349,8 +349,8 @@
   6: AGRESSA            20 D7
   7: OSES               19 11H
   8: OSAS               19 11H
-  9: ESSORA             18 7A
- 10: GERA               18 7C
+  9: AGES               18 5J
+ 10: GOSSERA            18 D7
 commande> n 1 
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -386,8 +386,8 @@
   6: JEUDIS             30 C3
   7: JUDD               29 N1
   8: JAR                29 K9
-  9: JUPE               28 12L
- 10: JARD               28 D12
+  9: JARD               28 D12
+ 10: JUPE               28 12L
 commande> n 1 
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -422,9 +422,9 @@
   5: DYADES             36 C3
   6: DYADE              34 D11
   7: LAYES              34 B4
-  8: DELAYA             34 D10
-  9: YAWL               34 4J
- 10: DRAYE              30 E7
+  8: YAWL               34 4J
+  9: DELAYA             34 D10
+ 10: ALYA               33 F8
 commande> n 1 
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -453,14 +453,14 @@
 commande> r
 commande> a r
   1: HEU                32 10B
-  2: BEDE               31 10B
-  3: HE                 31 10B
+  2: HE                 31 10B
+  3: BEDE               31 10B
   4: BEE                29 10B
-  5: DEB                28 10B
-  6: IDEE               27 10A
-  7: HIEE               27 10A
-  8: HUEE               27 10A
-  9: BUEE               26 10A
+  5: BE                 28 10B
+  6: DEB                28 10B
+  7: IDEE               27 10A
+  8: HIEE               27 10A
+  9: HUEE               27 10A
  10: HIE                26 10A
 commande> n 1 
 commande> a g
@@ -491,13 +491,13 @@
 commande> a r
   1: CIEL               25 D1
   2: CLE                22 12D
-  3: BLINDE             19 F10
-  4: ALBEDO             18 K10
-  5: DEY                18 7A
-  6: DELAVASSES         18 10F
-  7: LAIC               18 D12
-  8: BLIND              18 F10
-  9: CAID               18 D12
+  3: BLE                22 12D
+  4: BEY                20 7A
+  5: BLINDE             19 F10
+  6: BIPE               18 12L
+  7: CAID               18 D12
+  8: LAIC               18 D12
+  9: BLIND              18 F10
  10: CIBLE              18 4B
 commande> n 1 
 commande> a g
@@ -529,13 +529,13 @@
   1: BRADeRIE        *  86 A1
   2: BRIARDEs        *  61 A2
   3: BAuDRIER        *  60 A2
-  4: BRoCARD            33 1A
-  5: pARFUMEE           33 H1
-  6: CRoBARD            33 1D
-  7: CRABIeR            30 1D
-  8: BICARRe            30 1B
+  4: pARFUMEE           33 H1
+  5: CRoBARD            33 1D
+  6: BRoCARD            33 1A
+  7: BICARRe            30 1B
+  8: CRABIeR            30 1D
   9: CIBARe             27 1D
- 10: DuRCIRA            27 1A
+ 10: CRoBAR             27 1D
 commande> n 1 
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -568,10 +568,10 @@
   3: CAUDEE             27 1D
   4: DAW                25 4J
   5: CETEAU             24 1D
-  6: CADET              24 1D
-  7: CAGEE              24 1D
-  8: CEDAT              24 1D
-  9: CAUDE              24 1D
+  6: CEDAT              24 1D
+  7: QUETE              24 12H
+  8: CAUDE              24 1D
+  9: CAGUE              24 1D
  10: CAGET              24 1D
 commande> n 1 
 commande> a g
@@ -601,14 +601,14 @@
 commande> r
 commande> a r
   1: CERcLAGE        *  80 1D
-  2: RELEGuAT        *  77 15A
-  3: GELERAiT        *  77 15A
-  4: GALEREnT        *  77 15A
-  5: dEREGLAT        *  77 15A
-  6: REGALEnT        *  77 15A
-  7: AiGRELET        *  77 15A
-  8: REGELAiT        *  77 15A
-  9: REGELAnT        *  77 15A
+  2: REGELAnT        *  77 15A
+  3: REGELAiT        *  77 15A
+  4: REGALEnT        *  77 15A
+  5: RELEGuAT        *  77 15A
+  6: GELERAiT        *  77 15A
+  7: dEREGLAT        *  77 15A
+  8: AiGRELET        *  77 15A
+  9: GALEREnT        *  77 15A
  10: GREnELAT        *  74 15A
 commande> n 1 
 commande> a g
@@ -645,8 +645,8 @@
   6: FLAN               21 14A
   7: FAN                19 14B
   8: FANON              18 11E
-  9: FLA                17 14A
- 10: NAKFA              17 F4
+  9: NAKFA              17 F4
+ 10: FLA                17 14A
 commande> n 1 
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
@@ -714,12 +714,12 @@
   1: FANON              23 I3
   2: KRAFT              19 F6
   3: FRET               19 14A
-  4: REAI               18 E10
+  4: REFAIT             18 13J
   5: FANON              18 11E
-  6: FREON              18 11E
-  7: REFAIT             18 13J
-  8: FERAIT             18 13J
-  9: FRETIN             18 13J
+  6: FRETIN             18 13J
+  7: FERAIT             18 13J
+  8: FREON              18 11E
+  9: REAI               18 E10
  10: EN                 18 I13
 commande> n 1 
 commande> a g
@@ -750,14 +750,14 @@
 commande> a r
   1: ET                 18 I13
   2: RELAVASSES         15 10F
-  3: VAINCUE            13 13C
+  3: SE                 13 M10
   4: EX                 13 11M
-  5: SE                 13 M10
+  5: VAINCUE            13 13C
   6: TREK               13 F3
-  7: TEK                12 F4
-  8: TES                11 M8
-  9: RE                 11 E10
- 10: TET                11 14B
+  7: KEA                12 F6
+  8: TEK                12 F4
+  9: TET                11 14B
+ 10: RE                 11 E10
 commande> n 1 
 commande> a g
      1  2  3  4  5  6  7  8  9 10 11 12 13 14 15

Index: test/training_cross2.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/training_cross2.ref,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/training_cross2.ref    5 Nov 2006 13:34:27 -0000       1.1
+++ test/training_cross2.ref    8 Jan 2008 13:52:42 -0000       1.2
@@ -79,7 +79,7 @@
  Dr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Er 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Fr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Gr [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000200: 4][00ddf036: 
1][00000000: 2][005c7518: 1][005c7518: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
+ Gr [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000200: 4][00ddf036: 
1][00000000: 2][005c751c: 1][005c751c: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Hr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ir [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000202: 4][00184000: 
1][00200222: 2][01384100: 1][01384100: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Jr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]

Index: test/training_cross3.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/training_cross3.ref,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- test/training_cross3.ref    5 Nov 2006 13:34:27 -0000       1.1
+++ test/training_cross3.ref    8 Jan 2008 13:52:42 -0000       1.2
@@ -45,7 +45,7 @@
  Dr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Er 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Fr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Gr [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000200: 4][00ddf036: 
1][00000000: 2][005c7518: 1][005c7518: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
+ Gr [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000200: 4][00ddf036: 
1][00000000: 2][005c751c: 1][005c751c: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Hr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ir [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000202: 4][00184000: 
1][00200222: 2][01384100: 1][01384100: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Jr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
@@ -114,7 +114,7 @@
  Dr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Er 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Fr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Gr [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000200: 4][00ddf036: 
1][00000000: 2][005c7518: 1][005c7518: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
+ Gr [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000200: 4][00ddf036: 
1][00000000: 2][005c751c: 1][005c751c: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Hr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ir [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000202: 4][00184000: 
1][00200222: 2][01384100: 1][01384100: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Jr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
@@ -150,7 +150,7 @@
  Dr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:13][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Er 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Fr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Gr [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000200: 4][00ddf036: 
1][00000000: 2][005c7518: 1][005c7518: 
1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
+ Gr [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000200: 4][00ddf036: 
1][00000000: 2][005c751c: 1][005c751c: 
1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Hr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ir [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000202: 4][00184000: 
1][00200222: 2][01384100: 1][01384100: 
1][00000000:13][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Jr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
@@ -165,7 +165,7 @@
  Cc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Dc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ec 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00208222:
 1][00000000:-1][00208222: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Fc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c7518:
 1][00000000:-1][01384100: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
+ Fc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c751c:
 1][00000000:-1][01384100: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Gc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:10][00000000:-1][00200000:10][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Hc 
[ffffffff:-1][ffffffff:-1][00000000:10][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:10][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ic 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
@@ -184,7 +184,7 @@
  Br 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Cr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Dr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:13][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Er 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000: 
4][010d714e: 1][00000000: 2][00000000:-1][00008000: 1][005c795a: 0][010d714e: 
1][00200020: 1][ffffffff:-1][ffffffff:-1]
+ Er 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000: 
4][010d714e: 1][00000000: 2][00000000:-1][00008000: 1][005c795e: 0][010d714e: 
1][00200020: 1][ffffffff:-1][ffffffff:-1]
  Fr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][ffffffff:-1][ffffffff:-1]
  Gr [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000200: 4][00ddf036: 
1][00000000: 6][01451010: 2][00200000: 3][00000000:-1][00200222: 1][02284302: 
0][00005040: 1][00200022: 1][ffffffff:-1][ffffffff:-1]
  Hr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
@@ -220,7 +220,7 @@
  Dr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:13][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Er 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Fr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Gr [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000200: 4][00ddf036: 
1][00000000: 2][005c7518: 1][005c7518: 
1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
+ Gr [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000200: 4][00ddf036: 
1][00000000: 2][005c751c: 1][005c751c: 
1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Hr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ir [ffffffff:-1][ffffffff:-1][ffffffff:-1][00000202: 4][00184000: 
1][00200222: 2][01384100: 1][01384100: 
1][00000000:13][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Jr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
@@ -235,7 +235,7 @@
  Cc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Dc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ec 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00208222:
 1][00000000:-1][00208222: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Fc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c7518:
 1][00000000:-1][01384100: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
+ Fc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c751c:
 1][00000000:-1][01384100: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Gc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:10][00000000:-1][00200000:10][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Hc 
[ffffffff:-1][ffffffff:-1][00000000:10][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:10][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ic 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]

Index: test/training_joker2.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/training_joker2.ref,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- test/training_joker2.ref    5 Nov 2006 17:04:39 -0000       1.2
+++ test/training_joker2.ref    8 Jan 2008 13:52:42 -0000       1.3
@@ -46,20 +46,20 @@
  Dr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Er 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000008:
 6][ffffffff:-1]
  Fr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:16][00000000:-1][ffffffff:-1]
- Gr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:
 5][00608022: 1][005c795a: 1][00008000: 3][00000000:-1][00000000:-1][00000000: 
8]
+ Gr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:
 5][00608022: 1][005c795e: 1][00008000: 3][00000000:-1][00000000:-1][00000000: 
8]
  Hr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  Ir 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00200222:
 1][02284302: 1][00000222: 3][00000000:-1][040c0020: 6][00000000:-1]
  Jr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00080200:12][00002020:
 
5][ffffffff:-1][ffffffff:-1][00000000:12][00000000:-1][ffffffff:-1][00000000:-1]
  Kr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00000000:-1]
  Lr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00000000:-1]
  Mr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00080000:
 8]
- Nr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:26][00000000:
 3][005c7518: 1]
+ Nr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:26][00000000:
 3][005c751c: 1]
  Or 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  -
  Ac 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:12][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  Bc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Cc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:
 4][00000000:-1][00280022: 
4][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Dc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c7518:
 0][00000000:-1][01384100: 
0][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
+ Dc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c751c:
 0][00000000:-1][01384100: 
0][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ec 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00008000:
 1][00000000:-1][00200222: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Fc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00200020:
 1][00000000:-1][00200022: 1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00008022: 
4][00000000:-1][00008222: 4]
  Gc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 
1][ffffffff:-1][ffffffff:-1][00000000:11][00000000:-1][00000000:-1][00080000:11]
@@ -67,20 +67,20 @@
  Ic 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000004:
 5][00000000:-1][00000000:-1][00000000: 5][ffffffff:-1][00608022: 
1][00000000:-1][00210800: 2][00000000:-1]
  Jc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00200020:
 1][00000000:-1][00008000: 3][00000000:-1]
  Kc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:
 9][00000000:-1][00000000:-1][00000000:12][00000000:-1]
- Lc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000048:
 2][00000000:-1][00000000:-1][00004000: 3][00000000:-1]
+ Lc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00002048:
 2][00000000:-1][00000000:-1][00004000: 3][00000000:-1]
  Mc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000144:
 2][00000000:-1][00000000:-1][00080220: 2][ffffffff:-1]
  Nc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 1][ffffffff:-1][ffffffff:-1]
  Oc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:15][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
 commande> r
 commande> a r
   1: SaUGRENU        *  82 E4
-  2: eNjUGUES        *  66 D8
-  3: NUaGEUSe        *  66 D1
+  2: NUaGEUSe        *  66 D1
+  3: eNjUGUES        *  66 D8
   4: GUEUSANt        *  66 11C
   5: GUeUSENt        *  64 D6
-  6: NUaGeUSE        *  64 D4
+  6: ENjUGUeS        *  64 D2
   7: GUEUSeNt        *  64 D3
-  8: ENjUGUeS        *  64 D2
+  8: NUaGeUSE        *  64 D4
   9: GUeUSENT        *  62 F1
  10: GUEUSeNT        *  60 F1
 commande> q

Index: test/training_rosace.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/training_rosace.ref,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- test/training_rosace.ref    5 Nov 2006 17:24:32 -0000       1.2
+++ test/training_rosace.ref    8 Jan 2008 13:52:42 -0000       1.3
@@ -64,20 +64,20 @@
  Dr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Er 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000008:
 6][ffffffff:-1]
  Fr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:16][00000000:-1][ffffffff:-1]
- Gr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:
 5][00608022: 1][005c795a: 1][00008000: 3][00000000:-1][00000000:-1][00000000: 
8]
+ Gr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:
 5][00608022: 1][005c795e: 1][00008000: 3][00000000:-1][00000000:-1][00000000: 
8]
  Hr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  Ir 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00200222:
 1][02284302: 1][00000222: 3][00000000:-1][040c0020: 6][00000000:-1]
  Jr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00080200:12][00002020:
 
5][ffffffff:-1][ffffffff:-1][00000000:12][00000000:-1][ffffffff:-1][00000000:-1]
  Kr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00000000:-1]
  Lr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00000000:-1]
  Mr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00080000:
 8]
- Nr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:26][00000000:
 3][005c7518: 1]
+ Nr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:26][00000000:
 3][005c751c: 1]
  Or 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  -
  Ac 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:12][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  Bc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Cc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:
 4][00000000:-1][00280022: 
4][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Dc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c7518:
 0][00000000:-1][01384100: 
0][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
+ Dc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c751c:
 0][00000000:-1][01384100: 
0][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ec 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00008000:
 1][00000000:-1][00200222: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Fc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00200020:
 1][00000000:-1][00200022: 1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00008022: 
4][00000000:-1][00008222: 4]
  Gc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 
1][ffffffff:-1][ffffffff:-1][00000000:11][00000000:-1][00000000:-1][00080000:11]
@@ -85,7 +85,7 @@
  Ic 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000004:
 5][00000000:-1][00000000:-1][00000000: 5][ffffffff:-1][00608022: 
1][00000000:-1][00210800: 2][00000000:-1]
  Jc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00200020:
 1][00000000:-1][00008000: 3][00000000:-1]
  Kc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:
 9][00000000:-1][00000000:-1][00000000:12][00000000:-1]
- Lc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000048:
 2][00000000:-1][00000000:-1][00004000: 3][00000000:-1]
+ Lc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00002048:
 2][00000000:-1][00000000:-1][00004000: 3][00000000:-1]
  Mc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000144:
 2][00000000:-1][00000000:-1][00080220: 2][ffffffff:-1]
  Nc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 1][ffffffff:-1][ffffffff:-1]
  Oc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:15][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
@@ -139,20 +139,20 @@
  Dr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Er 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000008:
 6][ffffffff:-1]
  Fr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:16][00000000:-1][ffffffff:-1]
- Gr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:
 5][00608022: 1][005c795a: 1][00008000: 3][00000000:-1][00000000:-1][00000000: 
8]
+ Gr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:
 5][00608022: 1][005c795e: 1][00008000: 3][00000000:-1][00000000:-1][00000000: 
8]
  Hr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  Ir 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00200222:
 1][02284302: 1][00000222: 3][00000000:-1][040c0020: 6][00000000:-1]
  Jr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00080200:12][00002020:
 
5][ffffffff:-1][ffffffff:-1][00000000:12][00000000:-1][ffffffff:-1][00000000:-1]
  Kr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00000000:-1]
  Lr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00000000:-1]
  Mr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00080000:
 8]
- Nr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:26][00000000:
 3][005c7518: 1]
+ Nr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:26][00000000:
 3][005c751c: 1]
  Or 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  -
  Ac 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:12][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  Bc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Cc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:
 4][00000000:-1][00280022: 
4][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Dc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c7518:
 0][00000000:-1][01384100: 
0][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
+ Dc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c751c:
 0][00000000:-1][01384100: 
0][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ec 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00008000:
 1][00000000:-1][00200222: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Fc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00200020:
 1][00000000:-1][00200022: 1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00008022: 
4][00000000:-1][00008222: 4]
  Gc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 
1][ffffffff:-1][ffffffff:-1][00000000:11][00000000:-1][00000000:-1][00080000:11]
@@ -160,7 +160,7 @@
  Ic 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000004:
 5][00000000:-1][00000000:-1][00000000: 5][ffffffff:-1][00608022: 
1][00000000:-1][00210800: 2][00000000:-1]
  Jc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00200020:
 1][00000000:-1][00008000: 3][00000000:-1]
  Kc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:
 9][00000000:-1][00000000:-1][00000000:12][00000000:-1]
- Lc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000048:
 2][00000000:-1][00000000:-1][00004000: 3][00000000:-1]
+ Lc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00002048:
 2][00000000:-1][00000000:-1][00004000: 3][00000000:-1]
  Mc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000144:
 2][00000000:-1][00000000:-1][00080220: 2][ffffffff:-1]
  Nc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 1][ffffffff:-1][ffffffff:-1]
  Oc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:15][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
@@ -169,13 +169,13 @@
 commande> 
 commande> a r
   1: SaUGRENU        *  82 E4
-  2: ENjUGUES        *  66 D8
-  3: NUaGEUSE        *  66 D1
+  2: NUaGEUSE        *  66 D1
+  3: ENjUGUES        *  66 D8
   4: GUEUSANt        *  66 11C
   5: GUEUSENt        *  64 D6
-  6: NUaGEUSE        *  64 D4
+  6: ENjUGUES        *  64 D2
   7: GUEUSENt        *  64 D3
-  8: ENjUGUES        *  64 D2
+  8: NUaGEUSE        *  64 D4
   9: GUeUSENT        *  62 F1
  10: GUEUSeNT        *  60 F1
 commande> 
@@ -186,20 +186,20 @@
  Dr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Er 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000008:
 6][ffffffff:-1]
  Fr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:16][00000000:-1][ffffffff:-1]
- Gr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:
 5][00608022: 1][005c795a: 1][00008000: 3][00000000:-1][00000000:-1][00000000: 
8]
+ Gr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:
 5][00608022: 1][005c795e: 1][00008000: 3][00000000:-1][00000000:-1][00000000: 
8]
  Hr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  Ir 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00200222:
 1][02284302: 1][00000222: 3][00000000:-1][040c0020: 6][00000000:-1]
  Jr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00080200:12][00002020:
 
5][ffffffff:-1][ffffffff:-1][00000000:12][00000000:-1][ffffffff:-1][00000000:-1]
  Kr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00000000:-1]
  Lr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00000000:-1]
  Mr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][ffffffff:-1][00080000:
 8]
- Nr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:26][00000000:
 3][005c7518: 1]
+ Nr 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:26][00000000:
 3][005c751c: 1]
  Or 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  -
  Ac 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:12][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1][00000000:-1]
  Bc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Cc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:
 4][00000000:-1][00280022: 
4][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
- Dc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c7518:
 0][00000000:-1][01384100: 
0][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
+ Dc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][005c751c:
 0][00000000:-1][01384100: 
0][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Ec 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00008000:
 1][00000000:-1][00200222: 
1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1]
  Fc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00200020:
 1][00000000:-1][00200022: 1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00008022: 
4][00000000:-1][00008222: 4]
  Gc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 
1][ffffffff:-1][ffffffff:-1][00000000:11][00000000:-1][00000000:-1][00080000:11]
@@ -207,7 +207,7 @@
  Ic 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000004:
 5][00000000:-1][00000000:-1][00000000: 5][ffffffff:-1][00608022: 
1][00000000:-1][00210800: 2][00000000:-1]
  Jc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00200020:
 1][00000000:-1][00008000: 3][00000000:-1]
  Kc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:
 9][00000000:-1][00000000:-1][00000000:12][00000000:-1]
- Lc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000048:
 2][00000000:-1][00000000:-1][00004000: 3][00000000:-1]
+ Lc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00002048:
 2][00000000:-1][00000000:-1][00004000: 3][00000000:-1]
  Mc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000144:
 2][00000000:-1][00000000:-1][00080220: 2][ffffffff:-1]
  Nc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][010d714e:
 1][00000000:-1][00005040: 1][ffffffff:-1][ffffffff:-1]
  Oc 
[ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][ffffffff:-1][00000000:15][00000000:-1][00000000:-1][00000000:-1][00000000:-1]

Index: test/training_search.ref
===================================================================
RCS file: /cvsroot/eliot/eliot/test/training_search.ref,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- test/training_search.ref    5 Nov 2006 17:04:39 -0000       1.4
+++ test/training_search.ref    8 Jan 2008 13:52:42 -0000       1.5
@@ -8,847 +8,892 @@
 commande> r
 commande> a r 1000
   1: SPItZ              50 H8
-  2: ZINcS              46 H4
+  2: ZaNIS              46 H4
   3: ZaINS              46 H4
-  4: ZaNIS              46 H4
-  5: QuIZ               38 H8
-  6: QuIZ               38 H5
-  7: QuIZ               38 H6
-  8: QuIZ               38 H7
-  9: SPItZ              32 H4
- 10: ZIPS               30 H5
- 11: SPItZ              30 H5
+  4: ZINcS              46 H4
+  5: QuIZ               38 H7
+  6: QuIZ               38 H8
+  7: QuIZ               38 H5
+  8: QuIZ               38 H6
+  9: QINgS              38 H4
+ 10: SPItZ              32 H4
+ 11: SPItZ              30 H6
  12: ZIPS               30 H6
- 13: SPItZ              30 H6
- 14: ZIPS               30 H7
- 15: ZIPS               30 H8
- 16: SPItZ              30 H7
- 17: ZIPs               28 H8
- 18: ZaNIS              28 H8
- 19: ZIP                28 H6
- 20: ZIPs               28 H6
- 21: ZIP                28 H8
- 22: ZaINS              28 H8
- 23: NaZIS              28 H8
- 24: ZuPS               28 H7
- 25: ZiPS               28 H8
- 26: ZINcS              28 H8
- 27: ZuPS               28 H5
- 28: ZIPs               28 H5
- 29: ZiPS               28 H7
- 30: ZIP                28 H7
- 31: ZuPS               28 H8
- 32: ZuPS               28 H6
- 33: NaZIS              28 H4
- 34: ZiPS               28 H6
- 35: ZiPS               28 H5
- 36: ZIPs               28 H7
- 37: ZaINS              26 H7
- 38: ZINcS              26 H7
- 39: ZaNIS              26 H7
- 40: ZaNIS              26 H5
- 41: ZiP                26 H7
- 42: ZaINS              26 H5
- 43: NaZIS              26 H5
- 44: ZaNIS              26 H6
- 45: ZaINS              26 H6
- 46: NaZIS              26 H6
- 47: ZuP                26 H7
- 48: ZINcS              26 H5
- 49: ZuP                26 H8
- 50: ZiP                26 H8
- 51: ZiP                26 H6
- 52: ZuP                26 H6
- 53: NaZIS              26 H7
- 54: ZINcS              26 H6
- 55: bINZ               24 H5
- 56: ZaNI               24 H7
- 57: NaZI               24 H5
- 58: NIeZ               24 H8
- 59: ZIpS               24 H5
- 60: NIeZ               24 H7
- 61: ZaIN               24 H7
- 62: ZISt               24 H5
- 63: bINZ               24 H6
- 64: ZISt               24 H7
- 65: ZIpS               24 H7
- 66: NIeZ               24 H5
- 67: ZIgS               24 H7
- 68: NIeZ               24 H6
- 69: NaZI               24 H7
- 70: bINZ               24 H8
- 71: ZINc               24 H7
- 72: bINZ               24 H7
- 73: ZINc               24 H8
- 74: ZIgS               24 H8
- 75: ZeNS               24 H5
- 76: ZeNS               24 H6
- 77: ZeNS               24 H8
- 78: ZIgS               24 H6
- 79: ZINc               24 H6
+ 13: ZIPS               30 H8
+ 14: SPItZ              30 H5
+ 15: ZIPS               30 H5
+ 16: ZIPS               30 H7
+ 17: SPItZ              30 H7
+ 18: ZIPs               28 H7
+ 19: ZiPS               28 H7
+ 20: ZuPS               28 H7
+ 21: ZaINS              28 H8
+ 22: ZIP                28 H7
+ 23: ZiPS               28 H8
+ 24: NaZIS              28 H8
+ 25: ZaNIS              28 H8
+ 26: ZIPs               28 H8
+ 27: ZuPS               28 H8
+ 28: ZiPS               28 H6
+ 29: ZiPS               28 H5
+ 30: ZIPs               28 H5
+ 31: ZuPS               28 H6
+ 32: NaZIS              28 H4
+ 33: ZIP                28 H8
+ 34: ZuPS               28 H5
+ 35: ZIPs               28 H6
+ 36: ZINcS              28 H8
+ 37: ZIP                28 H6
+ 38: ZiP                26 H6
+ 39: ZiP                26 H8
+ 40: ZaINS              26 H7
+ 41: ZINcS              26 H7
+ 42: ZaNIS              26 H7
+ 43: NaZIS              26 H6
+ 44: ZuP                26 H6
+ 45: NaZIS              26 H7
+ 46: ZINcS              26 H5
+ 47: ZiP                26 H7
+ 48: ZINcS              26 H6
+ 49: ZuP                26 H7
+ 50: ZuP                26 H8
+ 51: ZaINS              26 H6
+ 52: ZaNIS              26 H6
+ 53: ZaNIS              26 H5
+ 54: ZaINS              26 H5
+ 55: NaZIS              26 H5
+ 56: bINZ               24 H7
+ 57: NIeZ               24 H8
+ 58: ZaIN               24 H8
+ 59: NaZI               24 H7
+ 60: NIeZ               24 H5
+ 61: ZISt               24 H8
+ 62: ZINc               24 H8
+ 63: NIeZ               24 H6
+ 64: ZIpS               24 H8
+ 65: ZIgS               24 H8
+ 66: ZeNS               24 H8
+ 67: ZaNI               24 H8
+ 68: NIeZ               24 H7
+ 69: NaZI               24 H6
+ 70: NaZI               24 H5
+ 71: ZIgS               24 H5
+ 72: ZISt               24 H6
+ 73: ZIpS               24 H6
+ 74: QINgS              24 H8
+ 75: ZINc               24 H6
+ 76: ZIgS               24 H6
+ 77: ZINc               24 H5
+ 78: ZeNS               24 H5
+ 79: ZeNS               24 H6
  80: ZaNI               24 H5
- 81: ZeNS               24 H7
- 82: ZaNI               24 H8
- 83: ZIpS               24 H8
- 84: ZIpS               24 H6
- 85: ZISt               24 H8
- 86: NaZI               24 H8
- 87: ZISt               24 H6
- 88: ZaIN               24 H5
- 89: ZaIN               24 H8
- 90: ZaNI               24 H6
- 91: ZIgS               24 H5
- 92: NaZI               24 H6
- 93: ZaIN               24 H6
- 94: ZINc               24 H5
- 95: ZIg                22 H7
- 96: ZeN                22 H7
- 97: rIZ                22 H8
- 98: NeZ                22 H6
- 99: ZeN                22 H8
-100: ZIg                22 H8
-101: ZIp                22 H8
-102: NeZ                22 H7
-103: rIZ                22 H6
+ 81: ZaIN               24 H5
+ 82: ZaNI               24 H6
+ 83: ZaIN               24 H6
+ 84: ZISt               24 H7
+ 85: ZIpS               24 H7
+ 86: bINZ               24 H8
+ 87: ZINc               24 H7
+ 88: ZIgS               24 H7
+ 89: ZeNS               24 H7
+ 90: ZaNI               24 H7
+ 91: ZaIN               24 H7
+ 92: NaZI               24 H8
+ 93: ZIpS               24 H5
+ 94: ZISt               24 H5
+ 95: bINZ               24 H5
+ 96: bINZ               24 H6
+ 97: QINS               22 H8
+ 98: ZIg                22 H8
+ 99: QINgS              22 H6
+100: ZeN                22 H8
+101: QINS               22 H6
+102: QINgS              22 H5
+103: QINS               22 H5
 104: rIZ                22 H7
-105: ZIp                22 H7
-106: NeZ                22 H8
-107: ZIg                22 H6
-108: ZeN                22 H6
-109: ZIp                22 H6
-110: cINQ               20 H8
-111: cINQ               20 H7
-112: cINQ               20 H6
-113: cINQ               20 H5
-114: PISaN              18 H4
-115: PIoNS              18 H4
-116: PuNIS              18 H4
-117: QuI                18 H7
-118: QuI                18 H6
-119: PINeS              18 H4
-120: PoINS              18 H4
-121: QuI                18 H8
-122: PaINS              18 H4
-123: PeINS              18 H4
-124: PeNIS              18 H4
-125: PIaNS              18 H4
-126: PIaNS              14 H8
-127: SPINs              14 H4
-128: SaPIN              14 H4
-129: sPINS              14 H8
-130: SuPIN              14 H8
-131: PaINS              14 H8
-132: PINeS              14 H8
-133: SaPIN              14 H8
-134: PeINS              14 H8
-135: PeNIS              14 H8
-136: PuNIS              14 H8
-137: PIoNS              14 H8
-138: SuPIN              14 H4
-139: PoINS              14 H8
-140: PISaN              14 H8
-141: PIoNS              12 H7
-142: PINS               12 H7
-143: PINeS              12 H7
-144: sPINS              12 H5
-145: SPIN               12 H8
-146: SPINs              12 H8
-147: PIaNS              12 H7
-148: PeNIS              12 H7
-149: PeINS              12 H7
-150: PaINS              12 H7
-151: sPINS              12 H4
-152: SPINs              12 H5
-153: PIaNS              12 H6
-154: SPIN               12 H7
-155: SPINs              12 H7
-156: PISaN              12 H6
-157: PuNIS              12 H5
-158: PIoNS              12 H5
-159: SuPIN              12 H7
-160: PISaN              12 H5
-161: PIaNS              12 H5
-162: PuNIS              12 H6
-163: SaPIN              12 H6
-164: SaPIN              12 H5
-165: SaPIN              12 H7
-166: PoINS              12 H6
-167: PoINS              12 H5
-168: SuPIN              12 H5
-169: PINS               12 H8
-170: PuNIS              12 H7
-171: PeNIS              12 H5
-172: PaINS              12 H6
-173: PIoNS              12 H6
-174: SPIN               12 H5
-175: PINS               12 H5
-176: SuPIN              12 H6
-177: PeINS              12 H5
-178: PINeS              12 H5
-179: SPIN               12 H6
-180: SPINs              12 H6
-181: PeNIS              12 H6
-182: PaINS              12 H5
-183: PeINS              12 H6
-184: PINS               12 H6
-185: sPINS              12 H7
-186: PISaN              12 H7
-187: sPINS              12 H6
-188: PoINS              12 H7
-189: PINeS              12 H6
-190: SPIs               10 H5
-191: PuIS               10 H5
-192: kIPS               10 H5
-193: IPeS               10 H7
-194: PuNI               10 H6
-195: SPIc               10 H5
-196: lISP               10 H6
-197: SPIs               10 H6
-198: SkIP               10 H5
-199: PuIS               10 H6
-200: lISP               10 H7
-201: PSI                10 H6
-202: SlIP               10 H5
-203: SlIP               10 H6
-204: PrIS               10 H5
-205: SIPo               10 H7
-206: IPeS               10 H5
-207: mIPS               10 H5
-208: kIPS               10 H7
-209: mIPS               10 H6
-210: SkIP               10 H7
-211: SlIP               10 H7
-212: SPiN               10 H6
-213: IPeS               10 H6
-214: kIPS               10 H6
-215: SIPo               10 H6
-216: SPI                10 H6
-217: SPIc               10 H6
-218: SIPo               10 H5
-219: SPIn               10 H6
-220: mIPS               10 H7
-221: SkIP               10 H6
-222: SPIn               10 H5
-223: PuNI               10 H5
-224: lISP               10 H5
-225: PoIS               10 H7
-226: PrIS               10 H7
-227: PSI                10 H7
-228: PuIS               10 H7
-229: PuNI               10 H7
-230: PaIN               10 H6
-231: PaIS               10 H6
-232: PInS               10 H5
-233: PINs               10 H5
-234: PaNS               10 H6
-235: PINe               10 H5
-236: PIlS               10 H5
-237: PaIN               10 H5
-238: PaIS               10 H5
-239: PaNS               10 H5
-240: PIaN               10 H6
-241: PIcS               10 H6
-242: PIeS               10 H6
-243: PIfS               10 H6
-244: PIlS               10 H6
-245: PIN                10 H6
-246: PINe               10 H6
-247: PINs               10 H6
-248: PInS               10 H6
-249: PIoN               10 H6
-250: PIS                10 H6
-251: PISe               10 H6
-252: PIaN               10 H5
-253: PIcS               10 H5
-254: PIeS               10 H5
-255: PIfS               10 H5
-256: PrIS               10 H6
-257: PoIS               10 H5
-258: PoIS               10 H6
-259: PlIS               10 H5
-260: PlIS               10 H6
-261: PiNS               10 H5
-262: PiNS               10 H6
-263: PISe               10 H5
-264: SPiN               10 H7
-265: PIoN               10 H5
-266: SPIs               10 H7
-267: SPIn               10 H7
-268: SPIc               10 H7
-269: SPI                10 H7
-270: PaIN               10 H7
-271: PaIS               10 H7
-272: PaNS               10 H7
-273: PIaN               10 H7
-274: PIcS               10 H7
-275: PIeS               10 H7
-276: PIfS               10 H7
-277: PIlS               10 H7
-278: PIN                10 H7
-279: PINe               10 H7
-280: PINs               10 H7
-281: PInS               10 H7
-282: PIoN               10 H7
-283: PIS                10 H7
-284: PISe               10 H7
-285: PiNS               10 H7
-286: PlIS               10 H7
-287: PlIS               10 H8
-288: PoIS               10 H8
-289: PrIS               10 H8
-290: PSI                10 H8
-291: PuIS               10 H8
-292: PuNI               10 H8
-293: SIPo               10 H8
-294: SkIP               10 H8
-295: SlIP               10 H8
-296: SPI                10 H8
-297: SPIc               10 H8
-298: SPIn               10 H8
-299: SPIs               10 H8
-300: SPiN               10 H8
-301: sPIN               10 H8
-302: sPIS               10 H8
-303: tIPS               10 H8
-304: tIPS               10 H5
-305: tIPS               10 H6
-306: tIPS               10 H7
-307: zIPS               10 H8
-308: sPIS               10 H5
-309: aPIS               10 H7
-310: aSPI               10 H7
-311: sPIN               10 H5
-312: sPIS               10 H6
-313: aPIS               10 H6
-314: zIPS               10 H5
-315: zIPS               10 H6
-316: zIPS               10 H7
-317: aPIS               10 H8
-318: aSPI               10 H8
-319: bIPS               10 H8
-320: ePIS               10 H8
-321: IPeS               10 H8
-322: kIPS               10 H8
-323: lISP               10 H8
-324: mIPS               10 H8
-325: PaIN               10 H8
-326: PaIS               10 H8
-327: PaNS               10 H8
-328: PIaN               10 H8
-329: PIcS               10 H8
-330: PIeS               10 H8
-331: PIfS               10 H8
-332: PIlS               10 H8
-333: PIN                10 H8
-334: PINe               10 H8
-335: PINs               10 H8
-336: PInS               10 H8
-337: PIoN               10 H8
-338: PIS                10 H8
-339: PISe               10 H8
-340: PiNS               10 H8
-341: sPIN               10 H6
-342: bIPS               10 H5
-343: aSPI               10 H5
-344: ePIS               10 H5
-345: bIPS               10 H7
-346: ePIS               10 H7
-347: aSPI               10 H6
-348: ePIS               10 H6
-349: aPIS               10 H5
-350: bIPS               10 H6
-351: SPiN               10 H5
-352: sPIS               10 H7
-353: sPIN               10 H7
-354: PaS                 8 H7
-355: SPa                 8 H8
-356: PhI                 8 H7
-357: PI                  8 H7
-358: SPi                 8 H8
-359: bIP                 8 H6
-360: PIc                 8 H7
-361: PIf                 8 H7
-362: IPe                 8 H6
-363: PIe                 8 H7
-364: PIn                 8 H8
-365: sPI                 8 H7
-366: PaN                 8 H7
-367: SPi                 8 H6
-368: PIs                 8 H6
-369: PIu                 8 H6
-370: ePI                 8 H7
-371: PIf                 8 H8
-372: sPI                 8 H8
-373: PIe                 8 H8
-374: PIc                 8 H8
-375: ePI                 8 H6
-376: PI                  8 H8
-377: PhI                 8 H8
-378: tIP                 8 H8
-379: PaS                 8 H8
-380: PuS                 8 H8
-381: PaS                 8 H6
-382: SPa                 8 H6
-383: PaN                 8 H6
-384: PsI                 8 H8
-385: PuS                 8 H7
-386: PSy                 8 H8
-387: PSt                 8 H8
-388: SeP                 8 H8
-389: PSi                 8 H8
-390: PsI                 8 H7
-391: PSy                 8 H7
-392: PSt                 8 H7
-393: PSi                 8 H7
-394: sPI                 8 H6
-395: PhI                 8 H6
-396: PlI                 8 H7
-397: PiS                 8 H7
-398: PlI                 8 H8
-399: PiN                 8 H7
-400: PIc                 8 H6
-401: PIu                 8 H7
-402: PIs                 8 H7
-403: PiS                 8 H8
-404: PIe                 8 H6
-405: PIf                 8 H6
-406: PiN                 8 H8
-407: PIu                 8 H8
-408: PIn                 8 H7
-409: PIs                 8 H8
-410: IPe                 8 H7
-411: PIn                 8 H6
-412: kIP                 8 H6
-413: kIP                 8 H8
-414: IPe                 8 H8
-415: tIP                 8 H7
-416: PSi                 8 H6
-417: zIP                 8 H8
-418: PSt                 8 H6
-419: PSy                 8 H6
-420: PsI                 8 H6
-421: SeP                 8 H6
-422: bIP                 8 H7
-423: hIP                 8 H8
-424: PuS                 8 H6
-425: ePI                 8 H8
-426: SPa                 8 H7
-427: aPI                 8 H7
-428: bIP                 8 H8
-429: zIP                 8 H7
-430: aPI                 8 H8
-431: zIP                 8 H6
-432: SeP                 8 H7
-433: aPI                 8 H6
-434: SPi                 8 H7
-435: PiN                 8 H6
-436: hIP                 8 H7
-437: PiS                 8 H6
-438: PlI                 8 H6
-439: PaN                 8 H8
-440: tIP                 8 H6
-441: hIP                 8 H6
-442: kIP                 8 H7
-443: SNIf                6 H7
-444: pINS                6 H6
-445: gINS                6 H7
-446: pINS                6 H5
-447: IbNS                6 H6
-448: IbNS                6 H5
-449: IbNS                6 H7
-450: NuIS                6 H8
-451: fINS                6 H7
-452: oINS                6 H8
-453: SIeN                6 H7
-454: fINS                6 H5
-455: SeIN                6 H7
-456: SkIN                6 H7
-457: aNIS                6 H8
-458: fINS                6 H6
-459: SaIN                6 H7
-460: Pu                  6 H8
-461: gINS                6 H6
-462: lINS                6 H8
-463: mINS                6 H8
-464: SpIN                6 H5
-465: INSu                6 H7
-466: IoNS                6 H8
-467: gINS                6 H5
-468: NaIS                6 H8
-469: NIaS                6 H8
-470: IoNS                6 H7
-471: INSu                6 H8
-472: NIdS                6 H8
-473: Pi                  6 H8
-474: IbNS                6 H8
-475: NIeS                6 H8
-476: NIfS                6 H8
-477: gINS                6 H8
-478: fINS                6 H8
-479: SpIN                6 H6
-480: NItS                6 H8
-481: pINS                6 H7
-482: SoIN                6 H7
+105: rIZ                22 H6
+106: rIZ                22 H8
+107: NeZ                22 H8
+108: NeZ                22 H6
+109: ZeN                22 H6
+110: QINS               22 H7
+111: QINgS              22 H7
+112: ZIp                22 H8
+113: ZIp                22 H7
+114: NeZ                22 H7
+115: ZIp                22 H6
+116: ZIg                22 H7
+117: ZIg                22 H6
+118: ZeN                22 H7
+119: QIN                20 H8
+120: QIN                20 H6
+121: QINs               20 H6
+122: QiNS               20 H5
+123: QiNS               20 H6
+124: QInS               20 H6
+125: QInS               20 H5
+126: QINs               20 H5
+127: QINg               20 H6
+128: QINg               20 H5
+129: cINQ               20 H5
+130: QINs               20 H7
+131: QInS               20 H7
+132: QINg               20 H7
+133: QIN                20 H7
+134: QiNS               20 H8
+135: QiNS               20 H7
+136: QInS               20 H8
+137: QINs               20 H8
+138: cINQ               20 H7
+139: cINQ               20 H8
+140: cINQ               20 H6
+141: QINg               20 H8
+142: QIn                18 H6
+143: QiN                18 H8
+144: QIn                18 H8
+145: QuI                18 H8
+146: QiN                18 H6
+147: QuI                18 H6
+148: PeINS              18 H4
+149: PISaN              18 H4
+150: PeNIS              18 H4
+151: PIaNS              18 H4
+152: PaINS              18 H4
+153: PINeS              18 H4
+154: PuNIS              18 H4
+155: QuI                18 H7
+156: PoINS              18 H4
+157: QiN                18 H7
+158: PIoNS              18 H4
+159: QIn                18 H7
+160: SaPIN              14 H8
+161: sPINS              14 H8
+162: SuPIN              14 H4
+163: SPINs              14 H4
+164: PaINS              14 H8
+165: PeINS              14 H8
+166: PeNIS              14 H8
+167: PIaNS              14 H8
+168: SaPIN              14 H4
+169: PINeS              14 H8
+170: PIoNS              14 H8
+171: PISaN              14 H8
+172: SuPIN              14 H8
+173: PoINS              14 H8
+174: PuNIS              14 H8
+175: PIoNS              12 H5
+176: PoINS              12 H7
+177: PISaN              12 H5
+178: SPINs              12 H8
+179: PINS               12 H5
+180: PINeS              12 H5
+181: PIaNS              12 H5
+182: PISaN              12 H6
+183: PuNIS              12 H7
+184: PIoNS              12 H6
+185: PaINS              12 H6
+186: PINS               12 H6
+187: PINeS              12 H6
+188: PaINS              12 H5
+189: PIaNS              12 H6
+190: PeNIS              12 H5
+191: PeINS              12 H5
+192: PeNIS              12 H6
+193: PeINS              12 H6
+194: PIaNS              12 H7
+195: SPIN               12 H7
+196: SPINs              12 H7
+197: PeNIS              12 H7
+198: PeINS              12 H7
+199: PINS               12 H8
+200: SuPIN              12 H7
+201: SaPIN              12 H6
+202: SaPIN              12 H5
+203: PaINS              12 H7
+204: SPIN               12 H6
+205: SPINs              12 H6
+206: SPIN               12 H5
+207: SPINs              12 H5
+208: SuPIN              12 H6
+209: SuPIN              12 H5
+210: sPINS              12 H7
+211: sPINS              12 H6
+212: sPINS              12 H5
+213: sPINS              12 H4
+214: PoINS              12 H6
+215: PoINS              12 H5
+216: PIoNS              12 H7
+217: PISaN              12 H7
+218: SPIN               12 H8
+219: SaPIN              12 H7
+220: PuNIS              12 H5
+221: PINS               12 H7
+222: PINeS              12 H7
+223: PuNIS              12 H6
+224: PiNS               10 H7
+225: mIPS               10 H5
+226: mIPS               10 H6
+227: mIPS               10 H7
+228: lISP               10 H5
+229: PaIS               10 H6
+230: PaNS               10 H6
+231: PaIN               10 H5
+232: PISe               10 H7
+233: PaIS               10 H5
+234: lISP               10 H6
+235: PaNS               10 H5
+236: lISP               10 H7
+237: kIPS               10 H5
+238: kIPS               10 H6
+239: kIPS               10 H7
+240: IPeS               10 H5
+241: IPeS               10 H6
+242: PrIS               10 H7
+243: PSI                10 H7
+244: PuIS               10 H7
+245: PIlS               10 H7
+246: PIfS               10 H7
+247: PIeS               10 H7
+248: PuNI               10 H7
+249: PIcS               10 H7
+250: PoIS               10 H7
+251: PaIN               10 H6
+252: PIaN               10 H7
+253: PIN                10 H7
+254: PINe               10 H7
+255: PlIS               10 H7
+256: PaNS               10 H7
+257: PaIS               10 H7
+258: PINs               10 H7
+259: PaIN               10 H7
+260: PInS               10 H7
+261: PIoN               10 H7
+262: PIS                10 H7
+263: SPIn               10 H6
+264: SPIc               10 H6
+265: SPI                10 H6
+266: SlIP               10 H5
+267: SlIP               10 H6
+268: SkIP               10 H5
+269: SkIP               10 H6
+270: SIPo               10 H5
+271: SIPo               10 H6
+272: SPiN               10 H7
+273: SPIs               10 H7
+274: SPIn               10 H7
+275: SPIc               10 H7
+276: SPI                10 H7
+277: SlIP               10 H7
+278: SkIP               10 H7
+279: SIPo               10 H7
+280: zIPS               10 H5
+281: zIPS               10 H6
+282: zIPS               10 H7
+283: tIPS               10 H5
+284: tIPS               10 H6
+285: tIPS               10 H7
+286: sPIS               10 H5
+287: sPIN               10 H5
+288: sPIS               10 H6
+289: sPIN               10 H6
+290: sPIS               10 H7
+291: sPIN               10 H7
+292: SPiN               10 H5
+293: SPIs               10 H5
+294: SPIn               10 H5
+295: SPIc               10 H5
+296: SPiN               10 H6
+297: SPIs               10 H6
+298: PIlS               10 H5
+299: PIfS               10 H5
+300: PIeS               10 H5
+301: PIcS               10 H5
+302: PIaN               10 H5
+303: PISe               10 H6
+304: PIS                10 H6
+305: PIoN               10 H6
+306: PInS               10 H6
+307: PINs               10 H6
+308: PINe               10 H6
+309: PIN                10 H6
+310: PIlS               10 H6
+311: PIfS               10 H6
+312: PIeS               10 H6
+313: PIcS               10 H6
+314: PIaN               10 H6
+315: PuNI               10 H5
+316: PuIS               10 H5
+317: PuNI               10 H6
+318: PuIS               10 H6
+319: PSI                10 H6
+320: PrIS               10 H5
+321: PrIS               10 H6
+322: PoIS               10 H5
+323: PoIS               10 H6
+324: PlIS               10 H5
+325: PlIS               10 H6
+326: PiNS               10 H5
+327: PiNS               10 H6
+328: PISe               10 H5
+329: PIoN               10 H5
+330: PInS               10 H5
+331: PINs               10 H5
+332: PINe               10 H5
+333: SPiN               10 H8
+334: SPIs               10 H8
+335: lISP               10 H8
+336: SPIn               10 H8
+337: SPIc               10 H8
+338: SPI                10 H8
+339: kIPS               10 H8
+340: PaIN               10 H8
+341: PaIS               10 H8
+342: SlIP               10 H8
+343: IPeS               10 H8
+344: SkIP               10 H8
+345: PaNS               10 H8
+346: SIPo               10 H8
+347: PIaN               10 H8
+348: PIcS               10 H8
+349: PIeS               10 H8
+350: ePIS               10 H5
+351: ePIS               10 H6
+352: ePIS               10 H7
+353: bIPS               10 H5
+354: bIPS               10 H6
+355: bIPS               10 H7
+356: aSPI               10 H5
+357: aSPI               10 H6
+358: aPIS               10 H5
+359: aPIS               10 H6
+360: aSPI               10 H7
+361: aPIS               10 H7
+362: zIPS               10 H8
+363: tIPS               10 H8
+364: sPIS               10 H8
+365: mIPS               10 H8
+366: sPIN               10 H8
+367: PSI                10 H8
+368: PrIS               10 H8
+369: PoIS               10 H8
+370: PlIS               10 H8
+371: PIfS               10 H8
+372: bIPS               10 H8
+373: aSPI               10 H8
+374: IPeS               10 H7
+375: PIlS               10 H8
+376: aPIS               10 H8
+377: PIN                10 H8
+378: PiNS               10 H8
+379: PINe               10 H8
+380: PINs               10 H8
+381: PInS               10 H8
+382: PISe               10 H8
+383: PIS                10 H8
+384: PIoN               10 H8
+385: PuNI               10 H8
+386: PuIS               10 H8
+387: ePIS               10 H8
+388: bIP                 8 H6
+389: SPa                 8 H7
+390: PuS                 8 H7
+391: bIP                 8 H7
+392: PaN                 8 H6
+393: PaS                 8 H6
+394: PIn                 8 H8
+395: PiN                 8 H8
+396: SPi                 8 H7
+397: aPI                 8 H6
+398: PIe                 8 H8
+399: PhI                 8 H6
+400: SeP                 8 H8
+401: PIc                 8 H6
+402: aPI                 8 H7
+403: PuS                 8 H8
+404: ePI                 8 H6
+405: PIf                 8 H8
+406: PIn                 8 H7
+407: ePI                 8 H7
+408: tIP                 8 H6
+409: tIP                 8 H7
+410: PIs                 8 H7
+411: PIu                 8 H7
+412: PiN                 8 H7
+413: PiS                 8 H7
+414: PlI                 8 H7
+415: PIs                 8 H8
+416: PIu                 8 H8
+417: PSi                 8 H7
+418: PSt                 8 H7
+419: PSy                 8 H7
+420: PsI                 8 H7
+421: PI                  8 H8
+422: PiS                 8 H8
+423: PiS                 8 H6
+424: PhI                 8 H8
+425: PlI                 8 H6
+426: PuS                 8 H6
+427: PlI                 8 H8
+428: PaS                 8 H8
+429: SPa                 8 H8
+430: SeP                 8 H6
+431: PSt                 8 H8
+432: PaN                 8 H8
+433: PsI                 8 H6
+434: PSi                 8 H8
+435: PSi                 8 H6
+436: PSt                 8 H6
+437: PSy                 8 H6
+438: PIe                 8 H6
+439: sPI                 8 H6
+440: PIf                 8 H6
+441: PsI                 8 H8
+442: zIP                 8 H8
+443: PIn                 8 H6
+444: sPI                 8 H7
+445: PIs                 8 H6
+446: PIu                 8 H6
+447: PIc                 8 H8
+448: tIP                 8 H8
+449: SeP                 8 H7
+450: SPa                 8 H6
+451: sPI                 8 H8
+452: SPi                 8 H6
+453: PSy                 8 H8
+454: SPi                 8 H8
+455: PiN                 8 H6
+456: kIP                 8 H6
+457: aPI                 8 H8
+458: hIP                 8 H7
+459: hIP                 8 H6
+460: bIP                 8 H8
+461: kIP                 8 H7
+462: kIP                 8 H8
+463: IPe                 8 H8
+464: IPe                 8 H7
+465: hIP                 8 H8
+466: IPe                 8 H6
+467: PaN                 8 H7
+468: PaS                 8 H7
+469: zIP                 8 H7
+470: PIc                 8 H7
+471: zIP                 8 H6
+472: ePI                 8 H8
+473: PIe                 8 H7
+474: PIf                 8 H7
+475: PhI                 8 H7
+476: PI                  8 H7
+477: SkIN                6 H8
+478: NIeS                6 H7
+479: SNIf                6 H8
+480: NIfS                6 H7
+481: SoIN                6 H8
+482: mINS                6 H6
 483: NItS                6 H7
 484: SeIN                6 H6
-485: yINS                6 H8
-486: SaIN                6 H5
-487: NuIS                6 H7
-488: SaIN                6 H6
+485: lINS                6 H7
+486: lINS                6 H8
+487: SaIN                6 H7
+488: NuIS                6 H7
 489: NaIS                6 H6
-490: NaIS                6 H5
-491: tINS                6 H6
-492: vINS                6 H8
-493: tINS                6 H5
-494: NIaS                6 H6
-495: SpIN                6 H7
-496: NIdS                6 H6
-497: uNIS                6 H8
-498: NIeS                6 H6
-499: NIfS                6 H6
-500: NItS                6 H6
-501: NIaS                6 H5
-502: NIdS                6 H5
-503: NIeS                6 H5
-504: NIfS                6 H5
-505: lINS                6 H6
-506: SkIN                6 H5
-507: aNIS                6 H5
-508: lINS                6 H5
-509: lINS                6 H7
-510: aNIS                6 H6
-511: SkIN                6 H6
-512: mINS                6 H7
-513: SNIf                6 H6
-514: mINS                6 H6
-515: SNIf                6 H5
-516: SIeN                6 H5
-517: mINS                6 H5
-518: NaIS                6 H7
-519: aNIS                6 H7
-520: tINS                6 H7
-521: NIaS                6 H7
-522: SIeN                6 H6
-523: NIdS                6 H7
-524: SeIN                6 H5
-525: NIeS                6 H7
-526: NIfS                6 H7
-527: IoNS                6 H5
-528: IoNS                6 H6
-529: uNIS                6 H5
-530: SoIN                6 H8
-531: SNIf                6 H8
-532: SoIN                6 H5
-533: INSu                6 H5
-534: SkIN                6 H8
-535: vINS                6 H7
-536: vINS                6 H6
-537: Pi                  6 H7
-538: INSu                6 H6
-539: vINS                6 H5
-540: SIeN                6 H8
-541: yINS                6 H7
-542: Pu                  6 H7
-543: SeIN                6 H8
-544: yINS                6 H6
-545: SaIN                6 H8
-546: yINS                6 H5
-547: pINS                6 H8
-548: NItS                6 H5
-549: tINS                6 H8
-550: SpIN                6 H8
-551: NuIS                6 H6
-552: uNIS                6 H6
-553: uNIS                6 H7
-554: NuIS                6 H5
-555: oINS                6 H5
-556: oINS                6 H6
-557: oINS                6 H7
-558: SoIN                6 H6
-559: vIS                 4 H6
-560: SoN                 4 H6
-561: yIN                 4 H7
-562: SpI                 4 H6
-563: SkI                 4 H6
-564: SkI                 4 H7
-565: SIx                 4 H7
-566: uNI                 4 H7
-567: SIs                 4 H7
-568: SIr                 4 H7
-569: yIN                 4 H6
-570: SIl                 4 H7
-571: uNS                 4 H6
-572: tIN                 4 H6
-573: sIS                 4 H7
-574: vIN                 4 H7
-575: SeN                 4 H6
-576: SaI                 4 H6
-577: SoI                 4 H6
-578: uNI                 4 H6
-579: uNS                 4 H7
-580: SIc                 4 H6
-581: vIS                 4 H7
-582: sIS                 4 H6
-583: SIl                 4 H6
-584: vIN                 4 H6
-585: SoN                 4 H7
-586: tIN                 4 H7
-587: SIr                 4 H6
-588: SoI                 4 H7
-589: SIs                 4 H6
-590: SpI                 4 H7
-591: SIx                 4 H6
-592: aIS                 4 H7
-593: yIN                 4 H8
-594: vIS                 4 H8
-595: vIN                 4 H8
-596: uNS                 4 H8
-597: uNI                 4 H8
-598: tIN                 4 H8
-599: sIS                 4 H8
-600: SpI                 4 H8
-601: SoN                 4 H8
-602: SoI                 4 H8
-603: SkI                 4 H8
-604: SIx                 4 H8
-605: SIs                 4 H8
-606: SIr                 4 H8
-607: SIl                 4 H8
-608: SIc                 4 H8
-609: SI                  4 H8
-610: gIS                 4 H6
-611: gIN                 4 H6
-612: gIS                 4 H7
-613: gIN                 4 H7
-614: fIS                 4 H6
-615: fIN                 4 H6
-616: fIS                 4 H7
-617: fIN                 4 H7
-618: dIS                 4 H6
-619: dIN                 4 H6
-620: dIS                 4 H7
-621: dIN                 4 H7
-622: cIS                 4 H6
-623: cIS                 4 H7
-624: bIS                 4 H6
-625: bIS                 4 H7
-626: aNS                 4 H6
-627: aIS                 4 H6
-628: aNS                 4 H7
-629: lIS                 4 H8
-630: lIN                 4 H8
-631: kSI                 4 H8
-632: ISo                 4 H8
-633: IoN                 4 H8
-634: IN                  4 H8
-635: IlS                 4 H8
-636: IfS                 4 H8
-637: IbN                 4 H8
-638: gIS                 4 H8
-639: gIN                 4 H8
-640: fIS                 4 H8
-641: fIN                 4 H8
-642: dIS                 4 H8
-643: dIN                 4 H8
-644: cIS                 4 H8
-645: bIS                 4 H8
-646: aNS                 4 H8
-647: aIS                 4 H8
-648: SeN                 4 H8
-649: SaI                 4 H8
-650: rIS                 4 H8
-651: pSI                 4 H8
-652: pIS                 4 H8
-653: pIN                 4 H8
-654: NuS                 4 H8
-655: NuI                 4 H8
-656: NoS                 4 H8
-657: NIt                 4 H8
-658: NIf                 4 H8
-659: NIe                 4 H8
-660: NId                 4 H8
-661: NIb                 4 H8
-662: NIa                 4 H8
-663: NI                  4 H8
-664: NeS                 4 H8
-665: mIS                 4 H8
-666: mIN                 4 H8
-667: lIS                 4 H6
-668: mIN                 4 H7
-669: pSI                 4 H6
-670: mIS                 4 H7
-671: mIN                 4 H6
-672: pIS                 4 H6
-673: pIN                 4 H6
-674: mIS                 4 H6
-675: pSI                 4 H7
-676: NeS                 4 H7
-677: pIS                 4 H7
-678: pIN                 4 H7
-679: NI                  4 H7
-680: NIa                 4 H7
-681: NIb                 4 H7
-682: NId                 4 H7
-683: NIe                 4 H7
-684: NIf                 4 H7
-685: NIt                 4 H7
-686: NoS                 4 H7
-687: NuI                 4 H7
-688: NuS                 4 H6
-689: NuI                 4 H6
-690: NuS                 4 H7
-691: NeS                 4 H6
-692: NoS                 4 H6
-693: NIa                 4 H6
-694: NIt                 4 H6
-695: NIf                 4 H6
-696: NIe                 4 H6
-697: NIb                 4 H6
-698: NId                 4 H6
-699: IbN                 4 H7
-700: SIc                 4 H7
-701: IfS                 4 H7
-702: IlS                 4 H7
-703: IN                  4 H7
-704: SI                  4 H7
-705: SeN                 4 H7
-706: IoN                 4 H7
-707: ISo                 4 H7
-708: IbN                 4 H6
-709: IfS                 4 H6
-710: IlS                 4 H6
-711: IoN                 4 H6
-712: ISo                 4 H6
-713: SaI                 4 H7
-714: rIS                 4 H6
-715: lIN                 4 H7
-716: lIS                 4 H7
-717: rIS                 4 H7
-718: kSI                 4 H6
-719: lIN                 4 H6
-720: kSI                 4 H7
-721: rI                  2 H7
-722: aN                  2 H8
-723: hI                  2 H8
-724: Si                  2 H7
-725: aI                  2 H8
-726: aS                  2 H8
-727: bI                  2 H8
-728: Ne                  2 H8
-729: Na                  2 H8
-730: If                  2 H8
-731: nI                  2 H7
-732: cI                  2 H8
-733: mI                  2 H8
-734: oN                  2 H7
-735: oS                  2 H7
-736: lI                  2 H8
-737: pI                  2 H7
-738: fI                  2 H8
-739: Il                  2 H8
-740: iN                  2 H8
-741: eS                  2 H8
-742: eN                  2 H8
-743: Se                  2 H7
-744: In                  2 H8
-745: Sa                  2 H7
-746: uN                  2 H8
-747: uN                  2 H7
-748: mI                  2 H7
-749: uS                  2 H8
-750: vS                  2 H8
-751: xI                  2 H8
-752: aI                  2 H7
-753: aN                  2 H7
-754: lI                  2 H7
-755: aS                  2 H7
-756: bI                  2 H7
-757: iN                  2 H7
-758: cI                  2 H7
-759: sI                  2 H7
-760: eN                  2 H7
-761: eS                  2 H7
-762: fI                  2 H7
-763: In                  2 H7
-764: Il                  2 H7
-765: If                  2 H7
-766: hI                  2 H7
-767: Su                  2 H7
-768: Ni                  2 H8
-769: No                  2 H8
-770: Nu                  2 H8
-771: nI                  2 H8
-772: oN                  2 H8
-773: oS                  2 H8
-774: pI                  2 H8
-775: Nu                  2 H7
-776: rI                  2 H8
-777: No                  2 H7
-778: Sa                  2 H8
-779: Ni                  2 H7
-780: Se                  2 H8
-781: xI                  2 H7
-782: vS                  2 H7
-783: Si                  2 H8
-784: Ne                  2 H7
-785: Na                  2 H7
-786: Su                  2 H8
-787: sI                  2 H8
-788: uS                  2 H7
+490: Pu                  6 H8
+491: IbNS                6 H7
+492: mINS                6 H7
+493: NaIS                6 H5
+494: fINS                6 H8
+495: SpIN                6 H8
+496: oINS                6 H8
+497: aSIN                6 H8
+498: NuIS                6 H8
+499: NIaS                6 H6
+500: mINS                6 H8
+501: gINS                6 H5
+502: SeIN                6 H7
+503: tINS                6 H8
+504: SaIN                6 H5
+505: SIeN                6 H5
+506: INSu                6 H7
+507: lINS                6 H6
+508: qINS                6 H8
+509: SkIN                6 H6
+510: SaIN                6 H8
+511: SIeN                6 H6
+512: IoNS                6 H7
+513: SeIN                6 H8
+514: SkIN                6 H5
+515: lINS                6 H5
+516: mINS                6 H5
+517: gINS                6 H8
+518: qINS                6 H7
+519: SIeN                6 H8
+520: NaIS                6 H7
+521: pINS                6 H5
+522: SNIf                6 H6
+523: pINS                6 H6
+524: SNIf                6 H5
+525: SoIN                6 H6
+526: pINS                6 H7
+527: qINS                6 H6
+528: SoIN                6 H5
+529: pINS                6 H8
+530: qINS                6 H5
+531: IbNS                6 H8
+532: SeIN                6 H5
+533: INSu                6 H8
+534: NIaS                6 H7
+535: IoNS                6 H8
+536: NIdS                6 H7
+537: oINS                6 H5
+538: oINS                6 H6
+539: Pu                  6 H7
+540: SNIf                6 H7
+541: NIaS                6 H8
+542: vINS                6 H7
+543: oINS                6 H7
+544: Pi                  6 H8
+545: IbNS                6 H5
+546: NuIS                6 H5
+547: SkIN                6 H7
+548: aSIN                6 H5
+549: NuIS                6 H6
+550: vINS                6 H6
+551: aSIN                6 H6
+552: IbNS                6 H6
+553: NItS                6 H5
+554: NaIS                6 H8
+555: fINS                6 H7
+556: tINS                6 H5
+557: uNIS                6 H7
+558: fINS                6 H6
+559: tINS                6 H6
+560: INSu                6 H6
+561: INSu                6 H5
+562: Pi                  6 H7
+563: fINS                6 H5
+564: tINS                6 H7
+565: uNIS                6 H6
+566: IoNS                6 H6
+567: IoNS                6 H5
+568: SoIN                6 H7
+569: gINS                6 H7
+570: uNIS                6 H5
+571: vINS                6 H8
+572: NItS                6 H8
+573: SaIN                6 H6
+574: SIeN                6 H7
+575: NIdS                6 H6
+576: NIfS                6 H8
+577: yINS                6 H6
+578: yINS                6 H8
+579: NIeS                6 H6
+580: yINS                6 H7
+581: NIeS                6 H8
+582: yINS                6 H5
+583: aNIS                6 H7
+584: SpIN                6 H7
+585: NIfS                6 H6
+586: vINS                6 H5
+587: NItS                6 H6
+588: NIaS                6 H5
+589: NIdS                6 H5
+590: SpIN                6 H5
+591: NIeS                6 H5
+592: SpIN                6 H6
+593: aSIN                6 H7
+594: gINS                6 H6
+595: NIdS                6 H8
+596: aNIS                6 H6
+597: aNIS                6 H8
+598: uNIS                6 H8
+599: aNIS                6 H5
+600: NIfS                6 H5
+601: dIS                 4 H8
+602: aIS                 4 H8
+603: dIN                 4 H8
+604: SaI                 4 H6
+605: aNS                 4 H8
+606: SpI                 4 H7
+607: SIc                 4 H6
+608: bIS                 4 H8
+609: SeN                 4 H6
+610: cIS                 4 H8
+611: NoS                 4 H8
+612: SpI                 4 H6
+613: NIt                 4 H8
+614: sIS                 4 H7
+615: yIN                 4 H6
+616: NIf                 4 H8
+617: sIS                 4 H6
+618: yIN                 4 H7
+619: NIe                 4 H8
+620: NId                 4 H8
+621: vIS                 4 H6
+622: vIN                 4 H6
+623: NIb                 4 H8
+624: vIS                 4 H7
+625: vIN                 4 H7
+626: uNS                 4 H6
+627: NIa                 4 H8
+628: NI                  4 H8
+629: tIN                 4 H7
+630: uNI                 4 H6
+631: NeS                 4 H8
+632: tIN                 4 H6
+633: uNS                 4 H7
+634: uNI                 4 H7
+635: fIN                 4 H8
+636: fIS                 4 H8
+637: SIl                 4 H6
+638: SIr                 4 H6
+639: SIs                 4 H6
+640: SIx                 4 H6
+641: SkI                 4 H6
+642: gIN                 4 H8
+643: gIS                 4 H8
+644: SoI                 4 H6
+645: SoN                 4 H6
+646: IbN                 4 H8
+647: IfS                 4 H8
+648: IlS                 4 H8
+649: IN                  4 H8
+650: IoN                 4 H8
+651: ISo                 4 H8
+652: kSI                 4 H8
+653: lIN                 4 H8
+654: lIS                 4 H8
+655: mIN                 4 H8
+656: NuS                 4 H8
+657: NuI                 4 H8
+658: mIS                 4 H8
+659: fIS                 4 H7
+660: fIN                 4 H7
+661: IlS                 4 H7
+662: IN                  4 H7
+663: dIS                 4 H6
+664: dIN                 4 H6
+665: dIS                 4 H7
+666: dIN                 4 H7
+667: cIS                 4 H6
+668: cIS                 4 H7
+669: mIS                 4 H6
+670: bIS                 4 H6
+671: bIS                 4 H7
+672: mIN                 4 H6
+673: aNS                 4 H6
+674: aIS                 4 H6
+675: mIS                 4 H7
+676: aNS                 4 H7
+677: aIS                 4 H7
+678: yIN                 4 H8
+679: mIN                 4 H7
+680: vIS                 4 H8
+681: vIN                 4 H8
+682: IoN                 4 H7
+683: uNS                 4 H8
+684: uNI                 4 H8
+685: lIS                 4 H6
+686: lIN                 4 H6
+687: NIt                 4 H7
+688: NIf                 4 H7
+689: NIe                 4 H7
+690: NoS                 4 H7
+691: NId                 4 H7
+692: NuI                 4 H7
+693: NuS                 4 H7
+694: NIb                 4 H7
+695: IbN                 4 H7
+696: NeS                 4 H6
+697: NIa                 4 H6
+698: NIa                 4 H7
+699: NIb                 4 H6
+700: NId                 4 H6
+701: NIe                 4 H6
+702: gIS                 4 H6
+703: NIf                 4 H6
+704: NI                  4 H7
+705: NIt                 4 H6
+706: NoS                 4 H6
+707: NuI                 4 H6
+708: NuS                 4 H6
+709: IfS                 4 H7
+710: NeS                 4 H7
+711: gIN                 4 H6
+712: gIS                 4 H7
+713: gIN                 4 H7
+714: fIS                 4 H6
+715: fIN                 4 H6
+716: SI                  4 H8
+717: SeN                 4 H8
+718: kSI                 4 H7
+719: SaI                 4 H8
+720: IbN                 4 H6
+721: rIS                 4 H8
+722: qIN                 4 H8
+723: pSI                 4 H8
+724: pIS                 4 H8
+725: pIN                 4 H8
+726: ISo                 4 H6
+727: qIN                 4 H7
+728: qIN                 4 H6
+729: IoN                 4 H6
+730: rIS                 4 H7
+731: rIS                 4 H6
+732: SaI                 4 H7
+733: IlS                 4 H6
+734: SeN                 4 H7
+735: SI                  4 H7
+736: SIc                 4 H7
+737: SIl                 4 H7
+738: SIr                 4 H7
+739: IfS                 4 H6
+740: SIs                 4 H7
+741: SIx                 4 H7
+742: SkI                 4 H7
+743: SoI                 4 H7
+744: SoN                 4 H7
+745: tIN                 4 H8
+746: sIS                 4 H8
+747: lIS                 4 H7
+748: lIN                 4 H7
+749: kSI                 4 H6
+750: SpI                 4 H8
+751: SoN                 4 H8
+752: SoI                 4 H8
+753: SkI                 4 H8
+754: ISo                 4 H7
+755: SIx                 4 H8
+756: SIs                 4 H8
+757: SIr                 4 H8
+758: SIl                 4 H8
+759: SIc                 4 H8
+760: pIN                 4 H7
+761: pIS                 4 H7
+762: pSI                 4 H7
+763: pIN                 4 H6
+764: pSI                 4 H6
+765: pIS                 4 H6
+766: cI                  2 H8
+767: If                  2 H7
+768: Na                  2 H7
+769: aI                  2 H8
+770: hI                  2 H8
+771: eN                  2 H8
+772: lI                  2 H7
+773: bI                  2 H8
+774: In                  2 H8
+775: mI                  2 H7
+776: Il                  2 H7
+777: eS                  2 H8
+778: fI                  2 H8
+779: aN                  2 H8
+780: In                  2 H7
+781: Ne                  2 H7
+782: iN                  2 H7
+783: aS                  2 H8
+784: Il                  2 H8
+785: If                  2 H8
+786: xI                  2 H8
+787: vS                  2 H8
+788: sI                  2 H7
+789: Ni                  2 H8
+790: uS                  2 H8
+791: No                  2 H8
+792: uN                  2 H8
+793: Nu                  2 H8
+794: sI                  2 H8
+795: nI                  2 H8
+796: Su                  2 H8
+797: oN                  2 H8
+798: oS                  2 H8
+799: Si                  2 H8
+800: pI                  2 H7
+801: Se                  2 H8
+802: Sa                  2 H8
+803: rI                  2 H8
+804: pI                  2 H8
+805: rI                  2 H7
+806: Sa                  2 H7
+807: Se                  2 H7
+808: Su                  2 H7
+809: Si                  2 H7
+810: iN                  2 H8
+811: Ni                  2 H7
+812: No                  2 H7
+813: lI                  2 H8
+814: Nu                  2 H7
+815: mI                  2 H8
+816: hI                  2 H7
+817: Na                  2 H8
+818: xI                  2 H7
+819: vS                  2 H7
+820: nI                  2 H7
+821: oN                  2 H7
+822: oS                  2 H7
+823: uS                  2 H7
+824: uN                  2 H7
+825: fI                  2 H7
+826: eS                  2 H7
+827: Ne                  2 H8
+828: eN                  2 H7
+829: cI                  2 H7
+830: bI                  2 H7
+831: aS                  2 H7
+832: aN                  2 H7
+833: aI                  2 H7
 commande> j QuIZ H6
 commande> t E?
 commande> r
 commande> a r 50
   1: ZEn                12 9H
-  2: ZEf                12 9H
-  3: ZEe                12 9H
-  4: ZEc                12 9H
-  5: rEZ                12 9F
-  6: nEZ                12 9F
-  7: lEZ                12 9F
-  8: fEZ                12 9F
-  9: ZoE                11 9H
- 10: ZeE                11 9H
- 11: QuE                11 6H
- 12: Eh                  5 G7
- 13: En                  5 G7
- 14: Es                  5 G7
- 15: Ex                  5 G7
- 16: pIE                 2 8G
- 17: oIE                 2 8G
- 18: nIE                 2 8G
- 19: mIE                 2 8G
- 20: lIE                 2 8G
- 21: hIE                 2 8G
- 22: fIE                 2 8G
- 23: aIE                 2 8G
- 24: pEu                 2 7F
- 25: lEu                 2 7F
- 26: jEu                 2 7F
- 27: hEu                 2 7F
- 28: fEu                 2 7F
- 29: rIE                 2 8G
- 30: vIE                 2 8G
- 31: EpI                 2 8F
- 32: lEI                 2 8F
- 33: IdE                 2 8H
- 34: IlE                 2 8H
- 35: IpE                 2 8H
- 36: IrE                 2 8H
- 37: IvE                 2 8H
- 38: IxE                 2 8H
- 39: Eu                  2 7G
- 40: duE                 2 7G
- 41: buE                 2 7G
- 42: Eue                 2 7G
- 43: Euh                 2 7G
- 44: Eus                 2 7G
- 45: Eut                 2 7G
- 46: Eux                 2 7G
- 47: euE                 2 7G
- 48: guE                 2 7G
- 49: huE                 2 7G
- 50: luE                 2 7G
+  2: ZEk                12 9H
+  3: ZEf                12 9H
+  4: ZEe                12 9H
+  5: ZEc                12 9H
+  6: rEZ                12 9F
+  7: nEZ                12 9F
+  8: lEZ                12 9F
+  9: fEZ                12 9F
+ 10: ZoE                11 9H
+ 11: ZeE                11 9H
+ 12: QuE                11 6H
+ 13: Eh                  5 G7
+ 14: En                  5 G7
+ 15: Es                  5 G7
+ 16: Ex                  5 G7
+ 17: pIE                 2 8G
+ 18: oIE                 2 8G
+ 19: nIE                 2 8G
+ 20: mIE                 2 8G
+ 21: lIE                 2 8G
+ 22: hIE                 2 8G
+ 23: fIE                 2 8G
+ 24: aIE                 2 8G
+ 25: pEu                 2 7F
+ 26: lEu                 2 7F
+ 27: jEu                 2 7F
+ 28: hEu                 2 7F
+ 29: fEu                 2 7F
+ 30: rIE                 2 8G
+ 31: vIE                 2 8G
+ 32: EpI                 2 8F
+ 33: lEI                 2 8F
+ 34: IdE                 2 8H
+ 35: IlE                 2 8H
+ 36: IpE                 2 8H
+ 37: IrE                 2 8H
+ 38: IvE                 2 8H
+ 39: IxE                 2 8H
+ 40: Eue                 2 7G
+ 41: Eu                  2 7G
+ 42: duE                 2 7G
+ 43: buE                 2 7G
+ 44: suE                 2 7G
+ 45: ruE                 2 7G
+ 46: tuE                 2 7G
+ 47: quE                 2 7G
+ 48: puE                 2 7G
+ 49: vuE                 2 7G
+ 50: nuE                 2 7G
 commande> q
 fin du mode entraînement
 commande> q

Index: utils/Makefile.am
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/Makefile.am,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- utils/Makefile.am   4 Nov 2005 20:00:06 -0000       1.9
+++ utils/Makefile.am   8 Jan 2008 13:52:42 -0000       1.10
@@ -16,24 +16,26 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-top_srcdir = @top_srcdir@
+localedir = $(datadir)/locale
+AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\"
+
+INCLUDES = -I$(top_srcdir)/dic -I$(top_srcdir)/game -I../intl 
-I$(top_srcdir)/intl
 
-INCLUDES = -I$(top_srcdir)/dic -I$(top_srcdir)/game -I$(top_srcdir)/intl
 noinst_PROGRAMS =
+bin_PROGRAMS =
 
 if BUILD_TEXT
 noinst_PROGRAMS += eliottxt
 eliottxt_SOURCES = game_io.h game_io.cpp eliottxt.cpp
-eliottxt_LDADD = ../game/libgame.a ../dic/libdic.a -lreadline
+eliottxt_LDADD = $(top_builddir)/game/libgame.a $(top_builddir)/dic/libdic.a 
@LIBINTL@
+if HAS_READLINE
+eliottxt_LDADD += -lreadline
+endif
 endif
 
 if BUILD_NCURSES
-noinst_PROGRAMS += eliotcurses
-eliotcurses_SOURCES = ncurses.cpp
-eliotcurses_LDADD = ../game/libgame.a ../dic/libdic.a -lncurses @LIBINTL@
+bin_PROGRAMS += eliotcurses
+eliotcurses_SOURCES = ncurses.cpp ncurses.h
+eliotcurses_LDADD = ../game/libgame.a ../dic/libdic.a -lncursesw @LIBINTL@
 endif
 
-datadir = @datadir@
-localedir = $(datadir)/locale
-DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
-

Index: utils/eliottxt.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/eliottxt.cpp,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -b -r1.18 -r1.19
--- utils/eliottxt.cpp  4 Aug 2007 20:01:27 -0000       1.18
+++ utils/eliottxt.cpp  8 Jan 2008 13:52:42 -0000       1.19
@@ -18,19 +18,23 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *****************************************************************************/
 
+#include "config.h"
+
+#include <wchar.h>
+#include <fstream>
+#include <iostream>
 #include <stdlib.h>
-#include <stdio.h>
 #include <time.h>
 #include <string.h>
 #include <locale.h>
 #include <wctype.h>
-#include <wchar.h>
-#include <fstream>
-#include <readline/readline.h>
-#include <readline/history.h>
+#if HAVE_READLINE_READLINE_H
+#   include <stdio.h>
+#   include <readline/readline.h>
+#   include <readline/history.h>
+#endif
 
 #include "dic.h"
-#include "dic_search.h"
 #include "regexp.h"
 #include "game_io.h"
 #include "game_factory.h"
@@ -41,8 +45,6 @@
 
 
 /* A static variable for holding the line. */
-static char *line_read = NULL;
-/* Wide version of the line */
 static wchar_t *wline_read = NULL;
 
 /**
@@ -51,20 +53,16 @@
  */
 wchar_t *rl_gets()
 {
+#if HAVE_READLINE_READLINE_H
     // If the buffer has already been allocated, return the memory to the free
     // pool
-    if (line_read)
-    {
-        free(line_read);
-        line_read = NULL;
-    }
     if (wline_read)
     {
         delete[] wline_read;
-        wline_read = NULL;
     }
 
     // Get a line from the user
+    static char *line_read;
     line_read = readline("commande> ");
 
     // If the line has any text in it, save it on the history
@@ -78,7 +76,28 @@
         return NULL;
 
     wline_read = new wchar_t[len + 1];
-    len = mbstowcs(wline_read, line_read, len + 1);
+    mbstowcs(wline_read, line_read, len + 1);
+
+    if (line_read)
+    {
+        free(line_read);
+    }
+#else
+    if (!cin.good())
+        return NULL;
+
+    cout << "commande> ";
+    string line;
+    std::getline(cin, line);
+
+    // Get the needed length (we _can't_ use string::size())
+    size_t len = mbstowcs(NULL, line.c_str(), 0);
+    if (len == (size_t)-1)
+        return NULL;
+
+    wline_read = new wchar_t[len + 1];
+    mbstowcs(wline_read, line.c_str(), len + 1);
+#endif
 
     return wline_read;
 }
@@ -86,7 +105,7 @@
 
 wchar_t * next_token_alpha(wchar_t *cmd, const wchar_t *delim, wchar_t **state)
 {
-    wchar_t *token = wcstok(cmd, delim, state);
+    wchar_t *token = _wcstok(cmd, delim, state);
     if (token == NULL)
         return NULL;
     int i;
@@ -99,7 +118,7 @@
 
 wchar_t * next_token_alphanum(wchar_t *cmd, const wchar_t *delim, wchar_t 
**state)
 {
-    wchar_t *token = wcstok(cmd, delim, state);
+    wchar_t *token = _wcstok(cmd, delim, state);
     if (token == NULL)
         return NULL;
     int i;
@@ -112,7 +131,7 @@
 
 wchar_t * next_token_alphaplusjoker(wchar_t *cmd, const wchar_t *delim, 
wchar_t **state)
 {
-    wchar_t *token = wcstok(cmd, delim, state);
+    wchar_t *token = _wcstok(cmd, delim, state);
     if (token == NULL)
         return NULL;
     int i;
@@ -128,7 +147,7 @@
 
 wchar_t * next_token_digit(wchar_t *cmd, const wchar_t *delim, wchar_t **state)
 {
-    wchar_t *token = wcstok(cmd, delim, state);
+    wchar_t *token = _wcstok(cmd, delim, state);
     if (token == NULL)
         return NULL;
     int i;
@@ -141,7 +160,7 @@
 
 wchar_t * next_token_cross(wchar_t *cmd, const wchar_t *delim, wchar_t **state)
 {
-    wchar_t *token = wcstok(cmd, delim, state);
+    wchar_t *token = _wcstok(cmd, delim, state);
     if (token == NULL)
         return NULL;
     int i;
@@ -156,7 +175,7 @@
 
 wchar_t * next_token_filename(wchar_t *cmd, const wchar_t *delim, wchar_t 
**state)
 {
-    wchar_t *token = wcstok(cmd, delim, state);
+    wchar_t *token = _wcstok(cmd, delim, state);
     if (token == NULL)
         return NULL;
     int i;
@@ -169,13 +188,15 @@
 }
 
 
-void eliottxt_get_cross(const Dictionary &iDic, wchar_t *cros)
+void eliottxt_get_cross(const Dictionary &iDic, const wstring &iCros)
 {
-    wchar_t wordlist[RES_CROS_MAX][DIC_WORD_MAX];
-    Dic_search_Cros(iDic, cros, wordlist);
-    for (int i = 0; i < RES_CROS_MAX && wordlist[i][0]; i++)
+    list<wstring> wordList;
+    iDic.searchCross(iCros, wordList);
+
+    list<wstring>::const_iterator it;
+    for (it = wordList.begin(); it != wordList.end(); it++)
     {
-        printf("  %s\n", convertToMb(wordlist[i]).c_str());
+        printf("  %s\n", convertToMb(*it).c_str());
     }
 }
 
@@ -198,6 +219,10 @@
     printf("            S -- score de tous les joueurs\n");
     printf("            t -- tirage\n");
     printf("  d [] : vérifier le mot []\n");
+    printf("  b [b|p|r] [] : effectuer une recherche speciale à partir de 
[]\n");
+    printf("            b -- benjamins\n");
+    printf("            p -- 7 + 1\n");
+    printf("            r -- raccords\n");
     printf("  *    : tirage aléatoire\n");
     printf("  +    : tirage aléatoire ajouts\n");
     printf("  t [] : changer le tirage\n");
@@ -278,7 +303,7 @@
 
 void display_data(const Game &iGame, const wchar_t *delim, wchar_t **state)
 {
-    wchar_t *token;
+    const wchar_t *token;
 
     token = next_token_alpha(NULL, delim, state);
     if (token == NULL)
@@ -365,7 +390,7 @@
 
 void loop_training(Training &iGame)
 {
-    wchar_t *token;
+    const wchar_t *token;
     wchar_t *state;
     wchar_t *commande = NULL;
     wchar_t delim[] = L" \t";
@@ -376,7 +401,7 @@
     while (quit == 0)
     {
         commande = rl_gets();
-        token = wcstok(commande, delim, &state);
+        token = _wcstok(commande, delim, &state);
         if (token)
         {
             switch (token[0])
@@ -387,13 +412,65 @@
                 case L'a':
                     display_data(iGame, delim, &state);
                     break;
+                case L'b':
+                    token = next_token_alpha(NULL, delim, &state);
+                    if (token == NULL)
+                        help_training();
+                    else
+                    {
+                        const wchar_t *word = next_token_alpha(NULL, delim, 
&state);
+                        if (word == NULL)
+                            help_training();
+                        else
+                        {
+                            switch (token[0])
+                            {
+                                case L'b':
+                                {
+                                    list<wstring> wordList;
+                                    iGame.getDic().searchBenj(word, wordList);
+                                    list<wstring>::const_iterator it;
+                                    for (it = wordList.begin(); it != 
wordList.end(); ++it)
+                                        cout << convertToMb(*it) << endl;
+                                    break;
+                                }
+                                case L'p':
+                                {
+                                    map<wchar_t, list<wstring> > wordMap;
+                                    iGame.getDic().search7pl1(word, wordMap, 
false);
+                                    map<wchar_t, list<wstring> 
>::const_iterator it;
+                                    for (it = wordMap.begin(); it != 
wordMap.end(); ++it)
+                                    {
+                                        if (it->first)
+                                            cout << "+" << 
convertToMb(it->first) << endl;
+                                        list<wstring>::const_iterator itWord;;
+                                        for (itWord = it->second.begin(); 
itWord != it->second.end(); itWord++)
+                                        {
+                                            cout << "  " << 
convertToMb(*itWord) << endl;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case L'r':
+                                {
+                                    list<wstring> wordList;
+                                    iGame.getDic().searchRacc(word, wordList);
+                                    list<wstring>::const_iterator it;
+                                    for (it = wordList.begin(); it != 
wordList.end(); ++it)
+                                        cout << convertToMb(*it) << endl;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    break;
                 case L'd':
                     token = next_token_alpha(NULL, delim, &state);
                     if (token == NULL)
                         help_training();
                     else
                     {
-                        if (Dic_search_word(iGame.getDic(), token))
+                        if (iGame.getDic().searchWord(token))
                         {
                             printf("le mot -%s- existe\n",
                                    convertToMb(token).c_str());
@@ -499,7 +576,7 @@
 
 void loop_freegame(FreeGame &iGame)
 {
-    wchar_t *token;
+    const wchar_t *token;
     wchar_t *state;
     wchar_t *commande = NULL;
     wchar_t delim[] = L" \t";
@@ -510,7 +587,7 @@
     while (quit == 0)
     {
         commande = rl_gets();
-        token = wcstok(commande, delim, &state);
+        token = _wcstok(commande, delim, &state);
         if (token)
         {
             switch (token[0])
@@ -527,7 +604,7 @@
                         help_freegame();
                     else
                     {
-                        if (Dic_search_word(iGame.getDic(), token))
+                        if (iGame.getDic().searchWord(token))
                         {
                             printf("le mot -%s- existe\n",
                                    convertToMb(token).c_str());
@@ -566,7 +643,7 @@
                     if (token == NULL)
                         token = L"";
 
-                    if (iGame.pass(token, iGame.currPlayer()) != 0)
+                    if (iGame.pass(token) != 0)
                         break;
                     break;
                 case L's':
@@ -600,7 +677,7 @@
 
 void loop_duplicate(Duplicate &iGame)
 {
-    wchar_t *token;
+    const wchar_t *token;
     wchar_t *state;
     wchar_t *commande = NULL;
     wchar_t delim[] = L" \t";
@@ -611,7 +688,7 @@
     while (quit == 0)
     {
         commande = rl_gets();
-        token = wcstok(commande, delim, &state);
+        token = _wcstok(commande, delim, &state);
         if (token)
         {
             switch (token[0])
@@ -628,7 +705,7 @@
                         help_duplicate();
                     else
                     {
-                        if (Dic_search_word(iGame.getDic(), token))
+                        if (iGame.getDic().searchWord(token))
                         {
                             printf("le mot -%s- existe\n",
                                    convertToMb(token).c_str());
@@ -667,10 +744,14 @@
                         help_duplicate();
                     else
                     {
+                        int n = _wtoi(token);
+                        if (n < 0 || n >= (int)iGame.getNPlayers())
+                        {
+                            fprintf(stderr, "Numéro de joueur invalide\n");
+                            break;
+                        }
                         int res = iGame.setPlayer(_wtoi(token));
                         if (res == 1)
-                            fprintf(stderr, "Numéro de joueur invalide\n");
-                        else if (res == 2)
                             fprintf(stderr, "Impossible de choisir un joueur 
non humain\n");
                     }
                     break;
@@ -703,7 +784,8 @@
 }
 
 
-void eliot_regexp_build_default_llist(struct search_RegE_list_t &llist)
+void eliot_regexp_build_default_llist(const Dictionary &iDic,
+                                      struct search_RegE_list_t &llist)
 {
     memset(&llist, 0, sizeof(llist));
 
@@ -727,8 +809,8 @@
         memset(llist.letters[i], 0, sizeof(llist.letters[i]));
     }
 
-    const list<Tile>& allTiles = Tile::getAllTiles();
-    list<Tile>::const_iterator it;
+    const vector<Tile>& allTiles = iDic.getAllTiles();
+    vector<Tile>::const_iterator it;
     for (it = allTiles.begin(); it != allTiles.end(); it++)
     {
         if (! it->isJoker() && ! it->isEmpty())
@@ -763,16 +845,14 @@
 #define DIC_RE_MAX (3*DIC_WORD_MAX) // yes, it's 3
 
     struct search_RegE_list_t llist;
-    eliot_regexp_build_default_llist(llist);
-
-    wchar_t *exp, *cnres, *clmin, *clmax;
+    eliot_regexp_build_default_llist(iDic, llist);
 
-    exp   = wcstok(NULL, delim, state);
-    cnres = wcstok(NULL, delim, state);
-    clmin = wcstok(NULL, delim, state);
-    clmax = wcstok(NULL, delim, state);
+    wchar_t *regexp = _wcstok(NULL, delim, state);
+    wchar_t *cnres = _wcstok(NULL, delim, state);
+    wchar_t *clmin = _wcstok(NULL, delim, state);
+    wchar_t *clmax = _wcstok(NULL, delim, state);
 
-    if (exp == NULL)
+    if (regexp == NULL)
     {
         return;
     }
@@ -791,18 +871,17 @@
         return;
     }
 
-    wchar_t re[DIC_RE_MAX];
-    wcsncpy(re, exp, DIC_RE_MAX);
-    wchar_t buff[RES_REGE_MAX][DIC_WORD_MAX];
-
-    printf("search for %s (%d,%d,%d)\n", convertToMb(exp).c_str(),
+    printf("search for %s (%d,%d,%d)\n", convertToMb(regexp).c_str(),
            nres, lmin, lmax);
-    Dic_search_RegE(iDic, re, buff, &llist);
+
+    list<wstring> wordList;
+    iDic.searchRegExp(regexp, wordList, &llist);
 
     int nresult = 0;
-    for (int i = 0; i < RES_REGE_MAX && i < nres && buff[i][0]; i++)
+    list<wstring>::const_iterator it;
+    for (it = wordList.begin(); it != wordList.end() && nresult < nres; it++)
     {
-        printf("%s\n", convertToMb(buff[i]).c_str());
+        printf("%s\n", convertToMb(*it).c_str());
         nresult++;
     }
     printf("%d printed results\n", nresult);
@@ -811,7 +890,7 @@
 
 void main_loop(const Dictionary &iDic)
 {
-    wchar_t *token;
+    const wchar_t *token;
     wchar_t *state;
     wchar_t *commande = NULL;
     wchar_t delim[] = L" \t";
@@ -821,7 +900,7 @@
     while (quit == 0)
     {
         commande = rl_gets();
-        token = wcstok(commande, delim, &state);
+        token = _wcstok(commande, delim, &state);
         if (token)
         {
             switch (token[0])
@@ -960,13 +1039,11 @@
 
 int main(int argc, char *argv[])
 {
-    char dic_path[100];
+    string dicPath;
 
     // Let the user choose the locale
     setlocale(LC_ALL, "");
 
-    Dictionary dic = NULL;
-
     if (argc != 2 && argc != 3)
     {
         fprintf(stdout, "Usage: eliot /chemin/vers/ods4.dawg [random_seed]\n");
@@ -974,39 +1051,12 @@
     }
     else
     {
-        strcpy(dic_path, argv[1]);
+        dicPath = argv[1];
     }
 
-    switch (Dic_load(&dic, dic_path))
+    try
     {
-        case 0:
-            /* Normal case */
-            break;
-        case 1:
-            printf("chargement: problème d'ouverture de %s\n", argv[1]);
-            exit(1);
-            break;
-        case 2:
-            printf("chargement: mauvais en-tete de dictionnaire\n");
-            exit(2);
-            break;
-        case 3:
-            printf("chargement: problème 3 d'allocation mémoire\n");
-            exit(3);
-            break;
-        case 4:
-            printf("chargement: problème 4 d'alocation mémoire\n");
-            exit(4);
-            break;
-        case 5:
-            printf("chargement: problème de lecture des arcs du 
dictionnaire\n");
-            exit(5);
-            break;
-        default:
-            printf("chargement: problème non-repertorié\n");
-            exit(6);
-            break;
-    }
+        Dictionary dic(dicPath);
 
     if (argc == 3)
         srand(atoi(argv[2]));
@@ -1016,13 +1066,14 @@
     main_loop(dic);
     GameFactory::Destroy();
 
-    Dic_destroy(dic);
-
-    // Free the readline static variable and its wide equivalent
-    if (line_read)
-        free(line_read);
+        // Free the readline static variable
     if (wline_read)
         delete[] wline_read;
+    }
+    catch (std::exception &e)
+    {
+        cerr << e.what() << endl;
+    }
 
     return 0;
 }

Index: utils/game_io.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/game_io.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- utils/game_io.cpp   4 Aug 2007 20:01:27 -0000       1.11
+++ utils/game_io.cpp   8 Jan 2008 13:52:42 -0000       1.12
@@ -20,8 +20,9 @@
 
 #include <iomanip>
 #include <string>
-#include "stdlib.h"
+#include <stdlib.h>
 
+#include <dic.h>
 #include "game_io.h"
 #include "game.h"
 #include "training.h"
@@ -45,8 +46,11 @@
         out << " " << (char)(row - BOARD_MIN + 'A') << " ";
         for (col = BOARD_MIN; col <= BOARD_MAX; col++)
         {
-            char l = iGame.getBoard().getChar(row, col);
-            out << setw(3) << (l ? l : '-');
+            wchar_t l = iGame.getBoard().getChar(row, col);
+            if (l == 0)
+                out << "  -";
+            else
+                out << padAndConvert(wstring(1, l), 3);
         }
         out << endl;
     }
@@ -93,11 +97,13 @@
         out << " " << (char)(row - BOARD_MIN + 'A') << " ";
         for (col = BOARD_MIN; col <= BOARD_MAX; col++)
         {
-            char l = iGame.getBoard().getChar(row, col);
+            wchar_t l = iGame.getBoard().getChar(row, col);
             bool j = (iGame.getBoard().getCharAttr(row, col) & ATTR_JOKER);
 
-            out << " " << (j ? '.' : (l ? ' ' : '-'));
-            out << (l ? l : '-');
+            if (l == 0)
+                out << " " << (j ? "." : "--");
+            else
+                out << " " << (j ? "." : " ") << convertToMb(l);
         }
         out << endl;
     }
@@ -118,9 +124,9 @@
         out << " " << (char)(row - BOARD_MIN + 'A') << " ";
         for (col = BOARD_MIN; col <= BOARD_MAX; col++)
         {
-            char l = iGame.getBoard().getChar(row, col);
+            wchar_t l = iGame.getBoard().getChar(row, col);
             if (l != 0)
-                out << "  " << l;
+                out << padAndConvert(wstring(1, l), 3);
             else
             {
                 int wm = iGame.getBoard().getWordMultiplier(row, col);
@@ -172,12 +178,12 @@
 
 void GameIO::printNonPlayed(ostream &out, const Game &iGame)
 {
-    const list<Tile>& allTiles = Tile::getAllTiles();
-    list<Tile>::const_iterator it;
+    const vector<Tile>& allTiles = iGame.getDic().getAllTiles();
+    vector<Tile>::const_iterator it;
 
     for (it = allTiles.begin(); it != allTiles.end(); it++)
     {
-        if (iGame.getBag().in(it->toChar()) > 9)
+        if (iGame.getBag().in(*it) > 9)
             out << " ";
         out << setw(2) << convertToMb(it->toChar());
     }
@@ -185,7 +191,7 @@
 
     for (it = allTiles.begin(); it != allTiles.end(); it++)
     {
-        out << " " << iGame.getBag().in(it->toChar());
+        out << " " << iGame.getBag().in(*it);
     }
     out << endl;
 }
@@ -199,7 +205,7 @@
 
 void GameIO::printAllRacks(ostream &out, const Game &iGame)
 {
-    for (int j = 0; j < iGame.getNPlayers(); j++)
+    for (unsigned int j = 0; j < iGame.getNPlayers(); j++)
     {
         out << "Joueur " << j << ": ";
         out << 
convertToMb(iGame.getPlayer(j).getCurrentRack().toString(PlayedRack::RACK_SIMPLE))
 << endl;
@@ -241,7 +247,7 @@
 
 void GameIO::printAllPoints(ostream &out, const Game &iGame)
 {
-    for (int i = 0; i < iGame.getNPlayers(); i++)
+    for (unsigned int i = 0; i < iGame.getNPlayers(); i++)
     {
         out << "Joueur " << i << ": "
             << setw(4) << iGame.getPlayer(i).getPoints() << endl;

Index: utils/ncurses.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/ncurses.cpp,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- utils/ncurses.cpp   29 Jan 2006 12:40:49 -0000      1.22
+++ utils/ncurses.cpp   8 Jan 2008 13:52:42 -0000       1.23
@@ -30,7 +30,6 @@
 
 #include "ncurses.h"
 #include "dic.h"
-#include "dic_search.h"
 #include "game_factory.h"
 #include "training.h"
 #include "duplicate.h"
@@ -43,48 +42,126 @@
 using namespace std;
 
 
-CursesIntf::CursesIntf(WINDOW *win, Game& iGame)
-    : m_win(win), m_game(&iGame), m_state(DEFAULT), m_dying(false),
-    m_boxStart(0), m_boxLines(0), m_boxLinesData(0), m_boxY(0),
-    m_showDots(false)
+Box::Box(WINDOW *win, int y, int x, int h, int w,
+         unsigned int iHeadingLines)
+    : m_win(win),  m_x(x), m_y(y), m_w(w), m_h(h),
+    m_topLine(y + 1 + iHeadingLines),
+    m_nbLines(h - 2 - iHeadingLines), m_dataStart(0), m_dataSize(0)
 {
 }
 
 
-CursesIntf::~CursesIntf()
+void Box::draw(const string& iTitle) const
 {
-    GameFactory::Instance()->releaseGame(*m_game);
-    GameFactory::Destroy();
+    if (m_w > 3 && m_h > 2)
+    {
+        // Add one space before and after the title for readability
+        string title;
+        if (!iTitle.empty())
+            title = " " + iTitle + " ";
+        unsigned int l = title.size();
+        // Truncate the title if needed
+        if ((int)l > m_w - 2)
+            l = m_w - 2;
+
+        mvwaddch(m_win, m_y, m_x,    ACS_ULCORNER);
+        mvwhline(m_win, m_y, m_x + 1,  ACS_HLINE, (m_w - l - 2)/2);
+        mvwprintw(m_win,m_y, m_x + 1 + (m_w - l - 2)/2, "%s", title.c_str());
+        mvwhline(m_win, m_y, m_x + (m_w - l)/2 + l,
+                 ACS_HLINE, m_w - 1 - ((m_w - l)/2 + l));
+        mvwaddch(m_win, m_y, m_x + m_w - 1, ACS_URCORNER);
+
+        mvwvline(m_win, m_y + 1, m_x, ACS_VLINE, m_h - 2);
+        mvwvline(m_win, m_y + 1, m_x + m_w - 1, ACS_VLINE, m_h - 2);
+
+        mvwaddch(m_win, m_y + m_h - 1, m_x, ACS_LLCORNER);
+        mvwhline(m_win, m_y + m_h - 1, m_x + 1, ACS_HLINE, m_w - 2);
+        mvwaddch(m_win, m_y + m_h - 1, m_x + m_w - 1, ACS_LRCORNER);
+    }
 }
 
 
-void CursesIntf::drawBox(WINDOW *win, int y, int x, int h, int w,
-                         const string& iTitle)
+void Box::printDataLine(int n, int x, const char *fmt, ...) const
 {
-    if (w > 3 && h > 2)
+    if (n < getFirstLine() || n >= getLastLine() || m_w <= x - m_x + 1)
+        return;
+
+    va_list vl_args;
+    char *buf = NULL;
+    va_start(vl_args, fmt);
+    vasprintf(&buf, fmt, vl_args);
+    va_end(vl_args);
+
+    if (buf == NULL)
     {
-        int i_len = iTitle.size();
+        return;
+    }
 
-        if (i_len > w - 2) i_len = w - 2;
+    mvwprintw(m_win, m_topLine + n - m_dataStart, x, "%s",
+              truncString(buf, m_w - 1 - x + m_x).c_str());
+    free(buf);
+}
 
-        mvwaddch(win, y, x,    ACS_ULCORNER);
-        mvwhline(win, y, x+1,  ACS_HLINE, ( w-i_len-2)/2);
-        mvwprintw(win,y, x+1+(w-i_len-2)/2, "%s", iTitle.c_str());
-        mvwhline(win, y, x+(w-i_len)/2+i_len,
-                 ACS_HLINE, w - 1 - ((w-i_len)/2+i_len));
-        mvwaddch(win, y, x+w-1,ACS_URCORNER);
 
-        mvwvline(win, y+1, x,     ACS_VLINE, h-2);
-        mvwvline(win, y+1, x+w-1, ACS_VLINE, h-2);
+bool Box::scrollOneLineUp()
+{
+    if (m_dataSize <= m_nbLines || m_dataStart == 0)
+        return false;
+    m_dataStart--;
+    return true;
+}
 
-        mvwaddch(win, y+h-1, x,     ACS_LLCORNER);
-        mvwhline(win, y+h-1, x+1,   ACS_HLINE, w - 2);
-        mvwaddch(win, y+h-1, x+w-1, ACS_LRCORNER);
-    }
+
+bool Box::scrollOneLineDown()
+{
+    if (m_dataSize <= m_nbLines || m_dataStart >= m_dataSize - 1)
+        return false;
+    m_dataStart++;
+    return true;
+}
+
+
+bool Box::scrollOnePageUp()
+{
+    if (m_dataSize <= m_nbLines)
+        return false;
+    m_dataStart -= m_nbLines;
+    if (m_dataStart < 0)
+        m_dataStart = 0;
+    return true;
+}
+
+
+bool Box::scrollOnePageDown()
+{
+    if (m_dataSize <= m_nbLines)
+        return false;
+    m_dataStart += m_nbLines;
+    if (m_dataStart > m_dataSize - 1)
+        m_dataStart = m_dataSize - 1;
+    return true;
+}
+
+
+bool Box::scrollBeginning()
+{
+    if (m_dataSize <= m_nbLines || m_dataStart == 0)
+        return false;
+    m_dataStart = 0;
+    return true;
+}
+
+
+bool Box::scrollEnd()
+{
+    if (m_dataSize <= m_nbLines || m_dataStart == m_dataSize - 1)
+        return false;
+    m_dataStart = m_dataSize - 1;
+    return true;
 }
 
 
-void CursesIntf::clearRect(WINDOW *win, int y, int x, int h, int w)
+void Box::clearRect(WINDOW *win, int y, int x, int h, int w)
 {
     for (int i = 0; i < h; i++)
     {
@@ -93,32 +170,30 @@
 }
 
 
-void CursesIntf::boxPrint(WINDOW *win, int y, int x, const char *fmt, ...)
+CursesIntf::CursesIntf(WINDOW *win, Game& iGame)
+    : m_win(win), m_game(&iGame), m_state(DEFAULT), m_dying(false),
+    m_box(win, 0, 0, 0, 0), m_showDots(false)
 {
-    if (y < m_boxStart || y - m_boxStart >= m_boxLines)
-        return;
+}
 
-    va_list vl_args;
-    char *buf = NULL;
-    va_start(vl_args, fmt);
-    vasprintf(&buf, fmt, vl_args);
-    va_end(vl_args);
 
-    if (buf == NULL)
-    {
-        return;
-    }
-    mvwprintw(win, m_boxY + y - m_boxStart, x, "%s", buf);
+CursesIntf::~CursesIntf()
+{
+    GameFactory::Instance()->releaseGame(*m_game);
+    GameFactory::Destroy();
 }
 
 
-void CursesIntf::drawStatus(WINDOW *win, int y, int x,
-                            const string& iMessage, bool error)
+void CursesIntf::drawStatus(WINDOW *win, const string& iMessage, bool error)
 {
+    int cols;
+    int lines;
+    getmaxyx(win, lines, cols);
+    int x = 0;
+    int y = lines - 1;
     if (error)
         wattron(win, COLOR_PAIR(COLOR_YELLOW));
-    mvwprintw(win, y, x, iMessage.c_str());
-    whline(win, ' ', COLS - x - 1 - iMessage.size());
+    mvwprintw(win, y, x, truncOrPad(iMessage, cols).c_str());
     if (error)
         wattron(win, COLOR_PAIR(COLOR_WHITE));
 }
@@ -127,7 +202,8 @@
 void CursesIntf::drawBoard(WINDOW *win, int y, int x) const
 {
     // Box around the board
-    drawBox(win, y + 1, x + 3, 17, 47, "");
+    Box box(win, y + 1, x + 3, 17, 47);
+    box.draw();
 
     // Print the coordinates
     for (int i = 0; i < 15; i++)
@@ -161,14 +237,20 @@
             mvwprintw(win, y + row + 1, x + 3 * col + 1, "   ");
 
             // Now add the letter
-            char c = m_game->getBoard().getChar(row, col);
+            wchar_t c = m_game->getBoard().getChar(row, col);
             if (c)
             {
-                if (islower(c))
-                    mvwaddch(win, y + row + 1, x + 3 * col + 2,
-                             c | A_BOLD | COLOR_PAIR(COLOR_GREEN));
+                cchar_t cc;
+                if (iswlower(c))
+                {
+                    setcchar(&cc, &c, A_BOLD, COLOR_GREEN, NULL);
+                    mvwadd_wch(win, y + row + 1, x + 3 * col + 2, &cc);
+                }
                 else
-                    mvwaddch(win, y + row + 1, x + 3 * col + 2, c);
+                {
+                    setcchar(&cc, &c, 0, 0, NULL);
+                    mvwadd_wch(win, y + row + 1, x + 3 * col + 2, &cc);
+                }
             }
             else
             {
@@ -184,8 +266,9 @@
 
 void CursesIntf::drawScoresRacks(WINDOW *win, int y, int x) const
 {
-    drawBox(win, y, x, m_game->getNPlayers() + 2, 25, _(" Scores "));
-    for (int i = 0; i < m_game->getNPlayers(); i++)
+    Box box(win, y, x, m_game->getNPlayers() + 2, 25);
+    box.draw(_("Scores"));
+    for (unsigned int i = 0; i < m_game->getNPlayers(); i++)
     {
         if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
             attron(A_BOLD);
@@ -196,16 +279,17 @@
     }
 
     // Distance between the 2 boxes
-    int yOff = m_game->getNPlayers() + 3;
+    unsigned int yOff = m_game->getNPlayers() + 3;
 
-    drawBox(win, y + yOff, x, m_game->getNPlayers() + 2, 25, _(" Racks "));
-    for (int i = 0; i < m_game->getNPlayers(); i++)
+    Box box2(win, y + yOff, x, m_game->getNPlayers() + 2, 25);
+    box2.draw(_("Racks"));
+    for (unsigned int i = 0; i < m_game->getNPlayers(); i++)
     {
         if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
             attron(A_BOLD);
-        string rack = 
convertToMb(m_game->getPlayer(i).getCurrentRack().toString(PlayedRack::RACK_SIMPLE));
+        wstring rack = 
m_game->getPlayer(i).getCurrentRack().toString(PlayedRack::RACK_SIMPLE);
         mvwprintw(win, y + yOff + i + 1, x + 2,
-                  _("Player %d: %s"), i, rack.c_str());
+                  _("Player %d: %ls"), i, rack.c_str());
         if (m_game->getMode() != Game::kTRAINING && i == m_game->currPlayer())
             attroff(A_BOLD);
         // Force to refresh the whole rack
@@ -223,127 +307,219 @@
 }
 
 
-void CursesIntf::drawResults(WINDOW *win, int y, int x)
+void CursesIntf::drawResults(Box &ioBox) const
 {
     if (m_game->getMode() != Game::kTRAINING)
         return;
     Training *tr_game = static_cast<Training*>(m_game);
 
-    int h = 17;
-    drawBox(win, y, x, h, 25, _(" Search results "));
-    m_boxY = y + 1;
-    m_boxLines = h - 2;
-    m_boxLinesData = tr_game->getResults().size();
+    ioBox.draw(_("Search results"));
+    ioBox.setDataSize(tr_game->getResults().size());
 
-    int i;
+    unsigned int i;
     const Results& res = tr_game->getResults();
-    for (i = m_boxStart; i < res.size() &&
-                         i < m_boxStart + m_boxLines; i++)
+    int x = ioBox.getLeft();
+    for (i = (unsigned int)ioBox.getFirstLine();
+         i < res.size() && i < (unsigned int)ioBox.getLastLine(); i++)
     {
         const Round &r = res.get(i);
         wstring coord = r.getCoord().toString();
-        boxPrint(win, i, x + 1, "%3d %s%s %3s",
+        ioBox.printDataLine(i, x, "%3d %s %3s",
                  r.getPoints(),
-                 convertToMb(r.getWord()).c_str(),
-                 string(h - 3 - r.getWordLen(), ' ').c_str(),
+                            padAndConvert(r.getWord(), ioBox.getWidth() - 9, 
false).c_str(),
                  convertToMb(coord).c_str());
     }
     // Complete the list with empty lines, to avoid trails
-    for (; i < m_boxStart + m_boxLines; i++)
+    for (; i < (unsigned int)ioBox.getLastLine(); i++)
     {
-        boxPrint(win, i, x + 1, string(23, ' ').c_str());
+        ioBox.printDataLine(i, x + 1, string(ioBox.getWidth(), ' ').c_str());
     }
 }
 
 
-void CursesIntf::drawHistory(WINDOW *win, int y, int x)
+void CursesIntf::drawHistory(Box &ioBox) const
 {
     // To allow pseudo-scrolling, without leaving trails
-    clear();
+    ioBox.clearData();
 
-    drawBox(win, y, x, LINES - y, COLS - x, _(" History of the game "));
-    m_boxY = y + 1;
-    m_boxLines = LINES - y - 2;
-    m_boxLinesData = m_game->getHistory().getSize();
+    ioBox.draw(_("History of the game"));
+    ioBox.setDataSize((int)m_game->getHistory().getSize());
+    int x = ioBox.getLeft();
+    int y = ioBox.getTop();
 
     // Heading
-    boxPrint(win, m_boxStart, x + 2,
-             _(" N |   RACK   |    SOLUTION     | REF | PTS | P | BONUS"));
-    mvwhline(win, y + 2, x + 2, ACS_HLINE, 55);
+    string heading = truncString(_(" N |   RACK   |    SOLUTION     | REF | 
PTS | P | BONUS"),
+                                 ioBox.getWidth() - 1);
+    mvwprintw(m_win, y, x + 1, "%s", heading.c_str());
+    mvwhline(m_win, y + 1, x + 1, ACS_HLINE, heading.size());
 
     int i;
-    for (i = m_boxStart + 0; i < m_game->getHistory().getSize() &&
-                         i < m_boxStart + m_boxLines; i++)
+    for (i = ioBox.getFirstLine();
+         i < (int)m_game->getHistory().getSize() && i < ioBox.getLastLine(); 
i++)
     {
         const Turn& t = m_game->getHistory().getTurn(i);
-        const Round& r = t.getRound();
-        string word = convertToMb(r.getWord());
-        string coord = convertToMb(r.getCoord().toString());
-        boxPrint(win, i + 2, x + 2,
-                 "%2d   %8s   %s%s   %3s   %3d   %1d   %c",
-                 i + 1, convertToMb(t.getPlayedRack().toString()).c_str(),
-                 word.c_str(), string(15 - word.size(), ' ').c_str(),
-                 coord.c_str(), r.getPoints(),
+        const Move& m = t.getMove();
+        if (m.getType() == Move::VALID_ROUND)
+        {
+            // The move corresponds to a played round: display it
+            const Round &r = m.getRound();
+            wstring coord = r.getCoord().toString();
+            ioBox.printDataLine(i, x,
+                " %2d   %s   %s   %s   %3d   %1d   %c",
+                i + 1, padAndConvert(t.getPlayedRack().toString(), 8).c_str(),
+                padAndConvert(r.getWord(), 15, false).c_str(),
+                padAndConvert(coord, 3).c_str(), r.getPoints(),
                  t.getPlayer(), r.getBonus() ? '*' : ' ');
     }
-    mvwvline(win, y + 1, x + 5,  ACS_VLINE, min(i + 2 - m_boxStart, 
m_boxLines));
-    mvwvline(win, y + 1, x + 16, ACS_VLINE, min(i + 2 - m_boxStart, 
m_boxLines));
-    mvwvline(win, y + 1, x + 34, ACS_VLINE, min(i + 2 - m_boxStart, 
m_boxLines));
-    mvwvline(win, y + 1, x + 40, ACS_VLINE, min(i + 2 - m_boxStart, 
m_boxLines));
-    mvwvline(win, y + 1, x + 46, ACS_VLINE, min(i + 2 - m_boxStart, 
m_boxLines));
-    mvwvline(win, y + 1, x + 50, ACS_VLINE, min(i + 2 - m_boxStart, 
m_boxLines));
+        else if (m.getType() == Move::INVALID_WORD)
+        {
+            // The move corresponds to an invalid word: display it
+            wstring invWord = L"<" + m.getBadWord() + L">";
+            ioBox.printDataLine(i, x,
+                " %2d   %s   %s   %s   %3d   %1d",
+                i + 1, padAndConvert(t.getPlayedRack().toString(), 8).c_str(),
+                padAndConvert(invWord, 15, false).c_str(),
+                padAndConvert(m.getBadCoord(), 3).c_str(), m.getScore(),
+                t.getPlayer());
+        }
+        else
+        {
+            // The move corresponds to a passed turn or changed letters
+            wstring action;
+            if (m.getType() == Move::PASS)
+                action = convertToWc(_("(PASS)"));
+            else if (m.getType() == Move::CHANGE_LETTERS)
+                action = L"(-" + m.getChangedLetters() + L")";
+
+            ioBox.printDataLine(i, x,
+                " %2d   %s   %s   %s   %3d   %1d",
+                i + 1, padAndConvert(t.getPlayedRack().toString(), 8).c_str(),
+                padAndConvert(action, 15, false).c_str(),
+                " - ", m.getScore(), t.getPlayer());
+        }
+    }
+    int nbLines = min(i + 2 - ioBox.getFirstLine(),
+                      ioBox.getLastLine() - ioBox.getFirstLine() + 2);
+    mvwvline(m_win, y, x + 4,  ACS_VLINE, nbLines);
+    mvwvline(m_win, y, x + 15, ACS_VLINE, nbLines);
+    mvwvline(m_win, y, x + 33, ACS_VLINE, nbLines);
+    mvwvline(m_win, y, x + 39, ACS_VLINE, nbLines);
+    mvwvline(m_win, y, x + 45, ACS_VLINE, nbLines);
+    mvwvline(m_win, y, x + 49, ACS_VLINE, nbLines);
 }
 
 
-void CursesIntf::drawHelp(WINDOW *win, int y, int x)
+void CursesIntf::drawHelp(Box &ioBox) const
 {
     // To allow pseudo-scrolling, without leaving trails
-    clear();
-
-    drawBox(win, y, x, LINES - y, COLS - x, _(" Help "));
-    m_boxY = y + 1;
-    m_boxLines = LINES - y - 2;
+    ioBox.clearData();
+    ioBox.draw(_("Help"));
 
+    int x = ioBox.getLeft() + 1;
     int n = 0;
-    boxPrint(win, n++, x + 2, _("[Global]"));
-    boxPrint(win, n++, x + 2, _("   h, H, ?          Show/hide help box"));
-    boxPrint(win, n++, x + 2, _("   y, Y             Show/hide history of the 
game"));
-    boxPrint(win, n++, x + 2, _("   e, E             Show/hide dots on empty 
squares of the board"));
-    boxPrint(win, n++, x + 2, _("   d, D             Check the existence of a 
word in the dictionary"));
-    boxPrint(win, n++, x + 2, _("   j, J             Play a word"));
-    boxPrint(win, n++, x + 2, _("   s, S             Save the game"));
-    boxPrint(win, n++, x + 2, _("   l, L             Load a game"));
-    boxPrint(win, n++, x + 2, _("   q, Q             Quit"));
-    boxPrint(win, n++, x + 2, "");
-
-    boxPrint(win, n++, x + 2, _("[Training mode]"));
-    boxPrint(win, n++, x + 2, _("   *                Take a random rack"));
-    boxPrint(win, n++, x + 2, _("   +                Complete the current rack 
randomly"));
-    boxPrint(win, n++, x + 2, _("   t, T             Set the rack manually"));
-    boxPrint(win, n++, x + 2, _("   c, C             Compute all the possible 
words"));
-    boxPrint(win, n++, x + 2, _("   r, R             Show/hide search 
results"));
-    boxPrint(win, n++, x + 2, "");
-
-    boxPrint(win, n++, x + 2, _("[Duplicate mode]"));
-    boxPrint(win, n++, x + 2, _("   n, N             Switch to the next human 
player"));
-    boxPrint(win, n++, x + 2, "");
-
-    boxPrint(win, n++, x + 2, _("[Free game mode]"));
-    boxPrint(win, n++, x + 2, _("   p, P             Pass your turn (with or 
without changing letters)"));
-    boxPrint(win, n++, x + 2, "");
-
-    boxPrint(win, n++, x + 2, _("[Miscellaneous]"));
-    boxPrint(win, n++, x + 2, _("   <up>, <down>     Navigate in a box line by 
line"));
-    boxPrint(win, n++, x + 2, _("   <pgup>, <pgdown> Navigate in a box page by 
page"));
-    boxPrint(win, n++, x + 2, _("   Ctrl-l           Refresh the screen"));
+    ioBox.printDataLine(n++, x, _("[Global]"));
+    ioBox.printDataLine(n++, x, _("   h, H, ?          Show/hide help box"));
+    ioBox.printDataLine(n++, x, _("   y, Y             Show/hide history of 
the game"));
+    ioBox.printDataLine(n++, x, _("   b, B             Show/hide contents of 
the bag (including letters of the racks)"));
+    ioBox.printDataLine(n++, x, _("   e, E             Show/hide dots on empty 
squares of the board"));
+    ioBox.printDataLine(n++, x, _("   d, D             Check the existence of 
a word in the dictionary"));
+    ioBox.printDataLine(n++, x, _("   j, J             Play a word"));
+    ioBox.printDataLine(n++, x, _("   s, S             Save the game"));
+    ioBox.printDataLine(n++, x, _("   l, L             Load a game"));
+    ioBox.printDataLine(n++, x, _("   q, Q             Quit"));
+    ioBox.printDataLine(n++, x, "");
+
+    ioBox.printDataLine(n++, x, _("[Training mode]"));
+    ioBox.printDataLine(n++, x, _("   *                Take a random rack"));
+    ioBox.printDataLine(n++, x, _("   +                Complete the current 
rack randomly"));
+    ioBox.printDataLine(n++, x, _("   t, T             Set the rack 
manually"));
+    ioBox.printDataLine(n++, x, _("   c, C             Compute all the 
possible words"));
+    ioBox.printDataLine(n++, x, _("   r, R             Show/hide search 
results"));
+    ioBox.printDataLine(n++, x, "");
+
+    ioBox.printDataLine(n++, x, _("[Duplicate mode]"));
+    ioBox.printDataLine(n++, x, _("   n, N             Switch to the next 
human player"));
+    ioBox.printDataLine(n++, x, "");
+
+    ioBox.printDataLine(n++, x, _("[Free game mode]"));
+    ioBox.printDataLine(n++, x, _("   p, P             Pass your turn (with or 
without changing letters)"));
+    ioBox.printDataLine(n++, x, "");
+
+    ioBox.printDataLine(n++, x, _("[Miscellaneous]"));
+    ioBox.printDataLine(n++, x, _("   <up>, <down>     Navigate in a box line 
by line"));
+    ioBox.printDataLine(n++, x, _("   <pgup>, <pgdown> Navigate in a box page 
by page"));
+    ioBox.printDataLine(n++, x, _("   Ctrl-l           Refresh the screen"));
+
+    ioBox.setDataSize(n);
+}
+
 
-    m_boxLinesData = n;
+void CursesIntf::drawBag(Box &ioBox) const
+{
+    // To allow pseudo-scrolling, without leaving trails
+    ioBox.clearData();
+
+    ioBox.draw(_("Bag"));
+    vector<Tile> allTiles = m_game->getDic().getAllTiles();
+    ioBox.setDataSize(allTiles.size());
+    int x = ioBox.getLeft();
+    int y = ioBox.getTop();
+
+    // Heading
+    string heading = truncString(_(" LETTER | POINTS | FREQUENCY | REMAINING"),
+                                 ioBox.getWidth() - 1);
+    mvwprintw(m_win, y, x + 1, "%s", heading.c_str());
+    mvwhline(m_win, y + 1, x + 1, ACS_HLINE, heading.size());
+
+    int i;
+    for (i = ioBox.getFirstLine(); i < (int)allTiles.size() && i < 
ioBox.getLastLine(); i++)
+    {
+        ioBox.printDataLine(i, ioBox.getLeft() + 1,
+                            "  %s        %2d        %2d       %s",
+                            padAndConvert(wstring(1, allTiles[i].toChar()), 
2).c_str(),
+                            allTiles[i].getPoints(),
+                            allTiles[i].maxNumber(),
+                            
convertToMb(wstring(m_game->getBag().in(allTiles[i]),
+                                                
allTiles[i].toChar())).c_str());
+    }
+
+    int nbLines = min(i + 2 - ioBox.getFirstLine(),
+                      ioBox.getLastLine() - ioBox.getFirstLine() + 2);
+    mvwvline(m_win, y, x + 9,  ACS_VLINE, nbLines);
+    mvwvline(m_win, y, x + 18, ACS_VLINE, nbLines);
+    mvwvline(m_win, y, x + 30, ACS_VLINE, nbLines);
+}
+
+
+void CursesIntf::setState(State iState)
+{
+    // Clear the previous box
+    m_box.clear();
+
+    // Get the size of the screen (better than using COLS and LINES directly,
+    // according to the manual)
+    int lines;
+    int cols;
+    getmaxyx(m_win, lines, cols);
+
+    m_state = iState;
+    if (m_state == DEFAULT)
+        m_box = Box(m_win, 0, 0, 0, 0);
+    else if (m_state == RESULTS)
+        m_box = Box(m_win, 3, 54, 17, 25);
+    else if (m_state == HISTORY)
+        m_box = Box(m_win, 1, 0, lines - 1, cols, 2);
+    else if (m_state == HELP)
+        m_box = Box(m_win, 1, 0, lines - 1, cols);
+    else if (m_state == BAG)
+        m_box = Box(m_win, 1, 0, lines - 1, cols, 2);
 }
 
 
 void CursesIntf::playWord(WINDOW *win, int y, int x)
 {
-    drawBox(win, y, x, 4, 32, _(" Play a word "));
+    Box box(win, y, x, 4, 32);
+    box.draw(_("Play a word"));
     mvwprintw(win, y + 1, x + 2, _("Played word:"));
     mvwprintw(win, y + 2, x + 2, _("Coordinates:"));
     wrefresh(win);
@@ -360,86 +536,87 @@
     else
         xOff = l2 + 3;
 
-    string word, coord;
+    wstring word, coord;
     if (readString(win, y + 1, x + xOff, 15, word) &&
         readString(win, y + 2, x + xOff, 3, coord))
     {
-        int res = m_game->play(convertToWc(coord), convertToWc(word));
+        int res = m_game->play(coord, word);
         if (res)
         {
-            drawStatus(win, LINES - 1, 0, _("Incorrect or misplaced word"));
+            drawStatus(win, _("Incorrect or misplaced word"));
         }
     }
-    m_state = DEFAULT;
-    clearRect(win, y, x, 4, 32);
+    box.clear();
 }
 
 
 void CursesIntf::checkWord(WINDOW *win, int y, int x)
 {
-    drawBox(win, y, x, 4, 32, _(" Dictionary "));
+    Box box(win, y, x, 4, 32);
+    box.draw(_("Dictionary"));
     mvwprintw(win, y + 1, x + 2, _("Enter the word to check:"));
     wrefresh(win);
 
-    string word;
+    wstring word;
     if (readString(win, y + 2, x + 2, 15, word))
     {
-        int res = Dic_search_word(m_game->getDic(), convertToWc(word).c_str());
+        bool res = m_game->getDic().searchWord(word);
         char s[100];
         if (res)
-            snprintf(s, 100, _("The word '%s' exists"), word.c_str());
+            snprintf(s, 100, _("The word '%ls' exists"), word.c_str());
         else
-            snprintf(s, 100, _("The word '%s' does not exist"), word.c_str());
-        drawStatus(win, LINES - 1, 0, s);
+            snprintf(s, 100, _("The word '%ls' does not exist"), word.c_str());
+        drawStatus(win, s, false);
     }
-    m_state = DEFAULT;
-    clearRect(win, y, x, 4, 32);
+    box.clear();
 }
 
 
 void CursesIntf::saveGame(WINDOW *win, int y, int x)
 {
-    drawBox(win, y, x, 4, 32, _(" Save the game "));
+    Box box(win, y, x, 4, 32);
+    box.draw(_("Save the game"));
     mvwprintw(win, y + 1, x + 2, _("Enter the file name:"));
     wrefresh(win);
 
-    string filename;
+    wstring filename;
     if (readString(win, y + 2, x + 2, 28, filename, kFILENAME))
     {
-        ofstream fout(filename.c_str());
+        ofstream fout(convertToMb(filename).c_str());
         char s[100];
         if (fout.rdstate() == ios::failbit)
         {
-            snprintf(s, 100, _("Cannot open file %s for writing"),
+            snprintf(s, 100, _("Cannot open file %ls for writing"),
                      filename.c_str());
+            drawStatus(win, s);
         }
         else
         {
-            m_game->save(fout);
+            m_game->save(fout, Game::FILE_FORMAT_ADVANCED);
             fout.close();
-            snprintf(s, 100, _("Game saved in %s"), filename.c_str());
+            snprintf(s, 100, _("Game saved in '%ls'"), filename.c_str());
+            drawStatus(win, s, false);
         }
-        drawStatus(win, LINES - 1, 0, s);
     }
-    m_state = DEFAULT;
-    clearRect(win, y, x, 4, 32);
+    box.clear();
 }
 
 
 void CursesIntf::loadGame(WINDOW *win, int y, int x)
 {
-    drawBox(win, y, x, 4, 32, _(" Load a game "));
+    Box box(win, y, x, 4, 32);
+    box.draw(_("Load a game"));
     mvwprintw(win, y + 1, x + 2, _("Enter the file name:"));
     wrefresh(win);
 
-    string filename;
+    wstring filename;
     if (readString(win, y + 2, x + 2, 28, filename, kFILENAME))
     {
         char s[100];
         FILE *fin;
-        if ((fin = fopen(filename.c_str(), "r")) == NULL)
+        if ((fin = fopen(convertToMb(filename).c_str(), "r")) == NULL)
         {
-            snprintf(s, 100, _("Cannot open file %s for reading"),
+            snprintf(s, 100, _("Cannot open file '%ls' for reading"),
                      filename.c_str());
         }
         else
@@ -448,118 +625,184 @@
             if (loaded == NULL)
             {
                 snprintf(s, 100, _("Invalid saved game"));
+                drawStatus(win, s);
             }
             else
             {
                 snprintf(s, 100, _("Game loaded"));
                 GameFactory::Instance()->releaseGame(*m_game);
                 m_game = loaded;
+                drawStatus(win, s, false);
             }
             fclose(fin);
         }
-        drawStatus(win, LINES - 1, 0, s);
     }
-    m_state = DEFAULT;
-    clearRect(win, y, x, 4, 32);
+    box.clear();
 }
 
 
 void CursesIntf::passTurn(WINDOW *win, int y, int x, FreeGame &iGame)
 {
-    drawBox(win, y, x, 4, 32, _(" Pass your turn "));
+    Box box(win, y, x, 4, 32);
+    box.draw(_("Pass your turn"));
     mvwprintw(win, y + 1, x + 2, _("Enter the letters to change:"));
     wrefresh(win);
 
-    string letters;
+    wstring letters;
     if (readString(win, y + 2, x + 2, 7, letters))
     {
-        int res = iGame.pass(convertToWc(letters), m_game->currPlayer());
+        int res = iGame.pass(letters);
         if (res)
         {
-            drawStatus(win, LINES - 1, 0, _("Cannot pass the turn"));
+            drawStatus(win, _("Cannot pass the turn"));
         }
     }
-    m_state = DEFAULT;
-    clearRect(win, y, x, 4, 32);
+    box.clear();
 }
 
 
 void CursesIntf::setRack(WINDOW *win, int y, int x, Training &iGame)
 {
-    drawBox(win, y, x, 4, 32, _(" Set rack "));
+    Box box(win, y, x, 4, 32);
+    box.draw(_("Set rack"));
     mvwprintw(win, y + 1, x + 2, _("Enter the new letters:"));
     wrefresh(win);
 
-    string letters;
+    wstring letters;
     if (readString(win, y + 2, x + 2, 7, letters, kJOKER))
     {
-        iGame.setRackManual(false, convertToWc(letters));
+        int res = iGame.setRackManual(false, letters);
+        if (res)
+        {
+            drawStatus(win, _("Cannot take these letters from the bag"));
+        }
     }
     m_state = DEFAULT;
-    clearRect(win, y, x, 4, 32);
+    box.clear();
 }
 
 
-bool CursesIntf::readString(WINDOW *win, int y, int x, int n, string &oString,
+bool CursesIntf::readString(WINDOW *win, int y, int x, int n, wstring &oString,
                             unsigned int flag)
 {
-    int c;
+    // Save the initial position
+    int x0 = x;
+    wint_t c;
     wmove(win, y, x);
     curs_set(1);
-    while ((c = getch()) != 0)
+    int res;
+    // Position in the string before which to insert the next character
+    // (the character will be added at the end if pos == oString.size())
+    unsigned int pos = 0;
+    while ((res = get_wch(&c)) != ERR)
     {
         if (c == 0x1b )  // Esc
         {
             curs_set(0);
             return false;
         }
-        else if (c == KEY_ENTER || c == 0xD)
+        else if ((c == KEY_ENTER && res == KEY_CODE_YES) || c == 0xD)
         {
             curs_set(0);
             return true;
         }
         else if (c == 0x0c)  // Ctrl-L
         {
-//             clear();
             redraw(win);
             wmove(win, y, x);
         }
-        else if (c == KEY_BACKSPACE && oString.size() > 0)
+        else if (c == 0x0b)  // Ctrl-K
+        {
+            // Remove everything after the cursor position
+            int len = oString.size() - pos;
+            oString = oString.erase(pos);
+            mvwprintw(win, y, x, string(len, ' ').c_str());
+            wmove(win, y, x);
+        }
+        else if (c == 0x15)  // Ctrl-U
+        {
+            // Remove everything before the cursor position
+            oString.erase(0, pos);
+            int len = pos;
+            x = x0;
+            pos = 0;
+            mvwprintw(win, y, x0, "%s", convertToMb(oString + wstring(len, L' 
')).c_str());
+            wmove(win, y, x);
+        }
+        else if (res == KEY_CODE_YES)
+        {
+            if (c == KEY_BACKSPACE && pos != 0)
+            {
+                x--;
+                pos--;
+                oString.erase(pos, 1);
+                mvwprintw(win, y, x0, "%s", convertToMb(oString + L" 
").c_str());
+                wmove(win, y, x);
+            }
+            else if (c == KEY_DC)
+            {
+                oString.erase(pos, 1);
+                mvwprintw(win, y, x0, "%s", convertToMb(oString + L" 
").c_str());
+                wmove(win, y, x);
+            }
+            else if (c == KEY_LEFT && pos != 0)
         {
             x--;
-            mvwprintw(win, y, x, " ");
+                pos--;
             wmove(win, y, x);
-            oString.erase(oString.size() - 1);
         }
-        else if (isalnum(c) && oString.size() < (unsigned int)n)
+            else if (c == KEY_RIGHT && pos != oString.size())
         {
-            mvwprintw(win, y, x, "%c", c);
             x++;
-            oString += (char)c;
+                pos++;
+                wmove(win, y, x);
+            }
+            else if (c == KEY_HOME)
+            {
+                x = x0;
+                pos = 0;
+                wmove(win, y, x);
+            }
+            else if (c == KEY_END)
+            {
+                x = x0 + oString.size();
+                pos = oString.size();
+                wmove(win, y, x);
         }
         else
+                beep();
+        }
+        else if (res == OK && iswalnum(c) && oString.size() < (unsigned int)n)
         {
-            if (flag & kJOKER && c == '?')
+            x++;
+            oString.insert(pos++, 1, c);
+            mvwprintw(win, y, x0, "%s", convertToMb(oString).c_str());
+            wmove(win, y, x);
+        }
+        else if (flag & kJOKER && c == L'?')
             {
-                mvwprintw(win, y, x, "%c", c);
                 x++;
-                oString += (char)c;
+            oString.insert(pos++, 1, c);
+            mvwprintw(win, y, x0, "%s", convertToMb(oString).c_str());
+            wmove(win, y, x);
             }
-            if (flag & kFILENAME)
+        else if (flag & kFILENAME)
             {
-                if (c == '/' || c == '.' || c == '-' || c == '_' || c == ' ')
+            if (c == L'/' || c == L'.' || c == L'-' || c == L'_' || c == L' ')
                 {
-                    mvwprintw(win, y, x, "%c", c);
                     x++;
-                    oString += (char)c;
-                }
+                oString += c;
+                mvwprintw(win, y, x0, "%s", convertToMb(oString).c_str());
+                wmove(win, y, x);
             }
+            else
+                beep();
         }
-//         else
-//             mvwprintw(win, 0, 0, "%3d", c);
+        else
+            beep();
     }
     curs_set(0);
-    return 0;
+    return false;
 }
 
 
@@ -568,15 +811,30 @@
     switch (iKey)
     {
         case '*':
+            if (m_state != DEFAULT)
+            {
+                setState(DEFAULT);
+                redraw(m_win);
+            }
             iGame.setRackRandom(false, Game::RACK_ALL);
             return 1;
 
         case '+':
+            if (m_state != DEFAULT)
+            {
+                setState(DEFAULT);
+                redraw(m_win);
+            }
             iGame.setRackRandom(false, Game::RACK_NEW);
             return 1;
 
         case 't':
         case 'T':
+            if (m_state != DEFAULT)
+            {
+                setState(DEFAULT);
+                redraw(m_win);
+            }
             setRack(m_win, 22, 10, iGame);
             return 1;
 
@@ -623,8 +881,11 @@
 
 int CursesIntf::handleKey(int iKey)
 {
-    if (m_state == DEFAULT)
-    {
+    // Remove any error message in the status line
+    if (m_state == DEFAULT || m_state == RESULTS)
+        drawStatus(m_win, "", false);
+
+    // Handle game-specific keys
         int res;
         if (m_game->getMode() == Game::kTRAINING)
         {
@@ -638,53 +899,30 @@
         {
             res = handleKeyForGame(iKey, (FreeGame&)*m_game);
         }
-
         if (res != 2)
             return res;
-    }
-    else // m_state is in {HELP, RESULTS, HISTORY}
+
+    // Handle scrolling keys
+    if (m_state != DEFAULT)
     {
         switch (iKey)
         {
             case KEY_HOME:
-                if (m_boxLinesData <= m_boxLines && m_boxStart > 0)
-                    return 0;
-                m_boxStart = 0;
-                return 1;
+                return m_box.scrollBeginning() ? 1 : 0;
             case KEY_END:
-                if (m_boxLinesData <= m_boxLines &&
-                    m_boxStart < m_boxLinesData - 1)
-                    return 0;
-                m_boxStart = m_boxLinesData - 1;
-                return 1;
+                return m_box.scrollEnd() ? 1 : 0;
             case KEY_UP:
-                if (m_boxLinesData <= m_boxLines || m_boxStart <= 0)
-                    return 0;
-                m_boxStart--;
-                return 1;
+                return m_box.scrollOneLineUp() ? 1 : 0;
             case KEY_DOWN:
-                if (m_boxLinesData <= m_boxLines ||
-                    m_boxStart >= m_boxLinesData - 1)
-                    return 0;
-                m_boxStart++;
-                return 1;
+                return m_box.scrollOneLineDown() ? 1 : 0;
             case KEY_PPAGE:
-                if (m_boxLinesData <= m_boxLines)
-                    return 0;
-                m_boxStart -= m_boxLines;
-                if (m_boxStart < 0)
-                    m_boxStart = 0;
-                return 1;
+                return m_box.scrollOnePageUp() ? 1 : 0;
             case KEY_NPAGE:
-                if (m_boxLinesData <= m_boxLines)
-                    return 0;
-                m_boxStart += m_boxLines;
-                if (m_boxStart > m_boxLinesData - 1)
-                    m_boxStart = m_boxLinesData - 1;
-                return 1;
+                return m_box.scrollOnePageDown() ? 1 : 0;
         }
     }
 
+    // Handle other global keys
     switch (iKey)
     {
         // Toggle help
@@ -692,10 +930,9 @@
         case 'H':
         case '?':
             if (m_state == HELP)
-                m_state = DEFAULT;
+                setState(DEFAULT);
             else
-                m_state = HELP;
-            m_boxStart = 0;
+                setState(HELP);
             clear();
             return 1;
 
@@ -703,10 +940,9 @@
         case 'y':
         case 'Y':
             if (m_state == HISTORY)
-                m_state = DEFAULT;
+                setState(DEFAULT);
             else
-                m_state = HISTORY;
-            m_boxStart = 0;
+                setState(HISTORY);
             clear();
             return 1;
 
@@ -714,13 +950,25 @@
         case 'r':
         case 'R':
             if (m_game->getMode() != Game::kTRAINING)
+            {
+                beep();
                 return 0;
+            }
             if (m_state == RESULTS)
-                m_state = DEFAULT;
+                setState(DEFAULT);
             else
-                m_state = RESULTS;
-            m_boxStart = 0;
-            clearRect(m_win, 3, 54, 30, 25);
+                setState(RESULTS);
+            Box::clearRect(m_win, 3, 54, 30, 25);
+            return 1;
+
+        // Toggle bag
+        case 'b':
+        case 'B':
+            if (m_state == BAG)
+                setState(DEFAULT);
+            else
+                setState(BAG);
+            clear();
             return 1;
 
         // Toggle dots display
@@ -729,49 +977,63 @@
             m_showDots = !m_showDots;
             return 1;
 
+        // Ctrl-L should clear and redraw the screen
+        case 0x0c:
+            clear();
+            // Force the re-definition of the current box
+            setState(m_state);
+            return 1;
+
         // Check a word in the dictionary
         case 'd':
         case 'D':
-            if (m_state != DEFAULT)
-                return 0;
+            if (m_state != DEFAULT && m_state != RESULTS)
+            {
+                setState(DEFAULT);
+                redraw(m_win);
+            }
             checkWord(m_win, 22, 10);
-            return 1;
+            return 0;
 
         // Play a word
         case 'j':
         case 'J':
-            if (m_state != DEFAULT)
-                return 0;
+            if (m_state != DEFAULT && m_state != RESULTS)
+            {
+                setState(DEFAULT);
+                redraw(m_win);
+            }
             playWord(m_win, 22, 10);
             return 1;
 
-        // Ctrl-L should clear and redraw the screen
-        case 0x0c:
-            clear();
-            return 1;
-
         case 'l':
         case 'L':
             if (m_state != DEFAULT)
-                return 0;
+            {
+                setState(DEFAULT);
+                redraw(m_win);
+            }
             loadGame(m_win, 22, 10);
             return 1;
 
         case 's':
         case 'S':
             if (m_state != DEFAULT)
-                return 0;
+            {
+                setState(DEFAULT);
+                redraw(m_win);
+            }
             saveGame(m_win, 22, 10);
-            return 1;
+            return 0;
 
         // Quit
         case 'q':
         case 'Q':
-        case 0x1b: // Esc
             m_dying = true;
             return 0;
 
         default:
+            beep();
             return 0;
     }
 }
@@ -786,16 +1048,20 @@
     }
     else if (m_state == RESULTS)
     {
-        drawResults(win, 3, 54);
+        drawResults(m_box);
         drawBoard(win, 2, 0);
     }
     else if (m_state == HELP)
     {
-        drawHelp(win, 1, 0);
+        drawHelp(m_box);
     }
     else if (m_state == HISTORY)
     {
-        drawHistory(win, 1, 0);
+        drawHistory(m_box);
+    }
+    else if (m_state == BAG)
+    {
+        drawBag(m_box);
     }
 
     // Title
@@ -811,8 +1077,11 @@
     if (m_game->getVariant() == Game::kJOKER)
         variant = string(" - ") + _("Joker game");
     string title = "Eliot (" + mode + variant + ") " + _("[h for help]");
-    mvwprintw(win, 0, 0, title.c_str());
-    whline(win, ' ', COLS - title.size());
+
+    int lines;
+    int cols;
+    getmaxyx(m_win, lines, cols);
+    mvwprintw(win, 0, 0, truncOrPad(title, cols).c_str());
     attroff(A_REVERSE);
 
     wrefresh(win);
@@ -821,7 +1090,7 @@
 
 int main(int argc, char ** argv)
 {
-#ifdef HAVE_SETLOCALE
+#if HAVE_SETLOCALE
     // Set locale via LC_ALL
     setlocale(LC_ALL, "");
 #endif
@@ -861,7 +1130,7 @@
         init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
         init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
         init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
-        init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
+        init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_RED);
 
         init_pair(COLOR_BLUE, COLOR_BLACK, COLOR_BLUE);
         init_pair(COLOR_CYAN, COLOR_BLACK, COLOR_CYAN);
@@ -872,7 +1141,7 @@
     // Do not echo
     noecho();
 
-    // mainIntf will take care of destroying game for us.
+    // mainIntf will take care of destroying game for us
     CursesIntf mainIntf(wBoard, *game);
     mainIntf.redraw(wBoard);
 

Index: utils/ncurses.h
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/ncurses.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- utils/ncurses.h     4 Nov 2005 20:00:06 -0000       1.6
+++ utils/ncurses.h     8 Jan 2008 13:52:42 -0000       1.7
@@ -20,7 +20,7 @@
 #ifndef _NCURSES_H_
 #define _NCURSES_H_
 
-#include <curses.h>
+#include <ncursesw/curses.h>
 #include <string>
 
 class Game;
@@ -29,6 +29,70 @@
 class FreeGame;
 
 using std::string;
+using std::wstring;
+
+
+class Box
+{
+    public:
+        // Create a titled box with the specified position and size,
+        // containing iHeadingLines non-scrolling lines.
+        // The number of data to display (with the printLine() method)
+        // can be set later using the setDataSize() method.
+        Box(WINDOW *win, int y, int x, int h, int w,
+            unsigned int iHeadingLines = 0);
+
+        // Simply draw the box (without any content)
+        void draw(const string& iTitle = "") const;
+
+        // Print data line number n (starting at 0), taking care of
+        // the current scrolling state
+        void printDataLine(int n, int x, const char *fmt, ...) const;
+
+        // Set the number of lines of the data to display
+        void setDataSize(unsigned int iNbLines) { m_dataSize = iNbLines; }
+
+        // Control scrolling
+        // Return true if redrawing is needed, false otherwise
+        bool scrollOneLineUp();
+        bool scrollOneLineDown();
+        bool scrollOnePageUp();
+        bool scrollOnePageDown();
+        bool scrollBeginning();
+        bool scrollEnd();
+
+        // Clear the box completely
+        void clear() const { clearRect(m_win, m_y, m_x, m_h, m_w); }
+        // Clear the scrolling zone of the box
+        void clearData() const { clearRect(m_win, m_topLine, m_x + 1,
+                                           m_nbLines, getWidth()); }
+        // Clear an arbitrary rectangular zone
+        static void clearRect(WINDOW *win, int y, int x, int h, int w);
+
+        // First line of data to display (included)
+        int getFirstLine() const { return m_dataStart; }
+        // Last line of data to display (excluded)
+        int getLastLine() const { return m_dataStart + m_nbLines; }
+
+        // First line inside the box
+        int getTop() const { return m_y + 1; }
+        // First column available for writing
+        int getLeft() const { return m_x + 1; }
+        // Client width
+        int getWidth() const { return m_w - 2; }
+
+    private:
+        WINDOW *m_win;
+        int m_x;
+        int m_y;
+        int m_w;
+        int m_h;
+        string m_title;
+        int m_topLine;
+        int m_nbLines;
+        int m_dataStart;
+        int m_dataSize;
+};
 
 
 /**
@@ -52,28 +116,27 @@
         DEFAULT,    // Default state
         HELP,       // Help panel is shown
         HISTORY,    // Game history panel is shown
-        RESULTS     // Search results panel is shown
+        RESULTS,    // Search results panel is shown
+        BAG         // Bag contents panel is shown
     };
-    // Draw a titled box with the specified position and size
-    static void drawBox(WINDOW *win, int y, int x, int h, int w,
-                        const string& iTitle);
-    // Clear a rectangular zone
-    static void clearRect(WINDOW *win, int y, int x, int h, int w);
-    // Print a line in a box, taking care of the current offset
-    void boxPrint(WINDOW *win, int y, int x, const char *fmt, ...);
+
     // Write a message in the "status line"
-    void drawStatus(WINDOW *win, int y, int x,
-                    const string& iMessage, bool error = true);
+    void drawStatus(WINDOW *win, const string& iMessage, bool error = true);
     // Draw the board, with the coordinates
     void drawBoard(WINDOW *win, int y, int x) const;
     // Draw the boxes for scores and racks
     void drawScoresRacks(WINDOW *win, int y, int x) const;
     // Draw the results panel
-    void drawResults(WINDOW *win, int y, int x);
+    void drawResults(Box &ioBox) const;
     // Draw the history panel
-    void drawHistory(WINDOW *win, int y, int x);
+    void drawHistory(Box &ioBox) const;
     // Draw the help panel
-    void drawHelp(WINDOW *win, int y, int x);
+    void drawHelp(Box &ioBox) const;
+    // Draw the bag panel
+    void drawBag(Box &ioBox) const;
+
+    // Change the inner state, and initialize the corresponding box
+    void setState(State iState);
     // Draw the "Play word" box, and handle the played word
     void playWord(WINDOW *win, int y, int x);
     void checkWord(WINDOW *win, int y, int x);
@@ -81,17 +144,18 @@
     void loadGame(WINDOW *win, int y, int x);
     void passTurn(WINDOW *win, int y, int x, FreeGame &iGame);
     void setRack(WINDOW *win, int y, int x, Training &iGame);
+
     // Get a string from the user, with a maximum length
     // The string is validated if the user presses Enter (return value: true)
     // and it is cancelled if the user presses Esc (return value: false)
-    bool readString(WINDOW *win, int y, int x, int n, string &oString,
+    bool readString(WINDOW *win, int y, int x, int n, wstring &oString,
                     unsigned int flag = 0);
     // Any combination of the following constants can be used as the "flag"
     // parameter of the readString() method.
     // Indicate that the '?' character is accepted
     static const unsigned int kJOKER = 1 << 0;
     // Accept characters for a file name
-    static const unsigned int kFILENAME = 1 << 0;
+    static const unsigned int kFILENAME = 1 << 1;
 
     // Handle the key in Training mode
     int handleKeyForGame(int iKey, Training &iGame);
@@ -109,14 +173,8 @@
     State m_state;
     // True when the user requested to quit
     bool m_dying;
-    // Index of the first line of data to be displayed in the current box
-    int m_boxStart;
-    // Number of lines of the current box (border excluded)
-    int m_boxLines;
-    // Number of lines of the data to be displayed in the current box
-    int m_boxLinesData;
-    // Index of the first line of the box where to write
-    int m_boxY;
+    // Scrolling box for the current panel
+    Box m_box;
     // True if dots must be shown on empty squares
     bool m_showDots;
 };

Index: wxwin/Makefile.am
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/Makefile.am,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- wxwin/Makefile.am   4 Aug 2007 20:01:27 -0000       1.10
+++ wxwin/Makefile.am   8 Jan 2008 13:52:43 -0000       1.11
@@ -16,13 +16,15 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
+localedir = $(datadir)/locale
+
 if BUILD_WXWIDGETS
 
 bin_PROGRAMS = eliot
 
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/dic -I$(top_srcdir)/game
+AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" @WX_CPPFLAGS@ ## 
-Wno-strict-aliasing
 
-AM_CPPFLAGS = @WX_CPPFLAGS@ ## -Wno-strict-aliasing
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/dic -I$(top_srcdir)/game
 
 eliot_SOURCES = \
     configdb.cc configdb.h \
@@ -36,8 +38,7 @@
     mainframe.cc mainframe.h  \
     main.cc ewx.h
 
-## eliot_CPPFLAGS=
-eliot_LDADD = @WX_LIBS@ ../dic/libdic.a ../game/libgame.a
+eliot_LDADD = @WX_LIBS@ ../game/libgame.a ../dic/libdic.a @LIBINTL@
 
 EXTRA_DIST = \
     eliot.xpm \

Index: wxwin/auxframes.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/auxframes.cc,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -b -r1.23 -r1.24
--- wxwin/auxframes.cc  4 Aug 2007 20:01:27 -0000       1.23
+++ wxwin/auxframes.cc  8 Jan 2008 13:52:43 -0000       1.24
@@ -26,6 +26,8 @@
 
 #include <iostream>
 #include <sstream>
+#include <list>
+#include <string>
 
 #include "wx/sizer.h"
 #include "wx/button.h"
@@ -37,7 +39,6 @@
 #include "ewx.h"
 
 #include "dic.h"
-#include "dic_search.h"
 #include "training.h"
 #include "player.h"
 #include "game.h"
@@ -119,7 +120,7 @@
 /****************************************************************/
 
 BoardFrame::BoardFrame(wxFrame* parent, Game& iGame):
-    AuxFrame(parent, ID_Frame_Board, _("Grille"), FRAMEBOARD)
+    AuxFrame(parent, ID_Frame_Board, _("Grid"), FRAMEBOARD)
 {
     board = new GfxBoard(this, iGame);
     wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
@@ -144,7 +145,7 @@
 /****************************************************************/
 
 BagFrame::BagFrame(wxFrame* parent, Game& iGame):
-    AuxFrame(parent, ID_Frame_Bag, _("sac"), FRAMEBAG),
+    AuxFrame(parent, ID_Frame_Bag, _("Bag"), FRAMEBAG),
     m_game(iGame)
 {
     tiles = new wxListCtrl(this, -1);
@@ -180,8 +181,8 @@
 
     tiles->ClearAll();
 
-    std::list<Tile>::const_iterator it;
-    const std::list<Tile>& allTiles = Tile::getAllTiles();
+    std::vector<Tile>::const_iterator it;
+    const std::vector<Tile>& allTiles = m_game.getDic().getAllTiles();
     for (index = 0, it = allTiles.begin(); it != allTiles.end(); index++, it++)
     {
        n = m_game.getBag().in(*it);
@@ -198,8 +199,8 @@
 /* RECHERCHE */
 /****************************************************************/
 
-SearchFrame::SearchFrame(wxFrame *parent, Dictionary _dic):
-    AuxFrame(parent, ID_Frame_Search, _("recherche"), FRAMESEARCH)
+SearchFrame::SearchFrame(wxFrame *parent, const Dictionary &_dic):
+    AuxFrame(parent, ID_Frame_Search, _("Search"), FRAMESEARCH)
 {
     panel = new SearchPanel(this, _dic);
     wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
@@ -222,20 +223,20 @@
 enum
 {
     Word_Id,
-    Result_Id,
+    Result_Id
 };
 
 BEGIN_EVENT_TABLE(VerifFrame, AuxFrame)
   EVT_TEXT(Word_Id, VerifFrame::OnText)
 END_EVENT_TABLE()
 
-VerifFrame::VerifFrame(wxFrame* parent, Dictionary _dic):
-  AuxFrame(parent, ID_Frame_Verif, _("verification"), FRAMEVERIF)
+VerifFrame::VerifFrame(wxFrame* parent, const Dictionary &_dic):
+  AuxFrame(parent, ID_Frame_Verif, _("Check"), FRAMEVERIF)
 {
-    dic = _dic;
+    dic = &_dic;
     word = new wxTextCtrl(this, Word_Id, wxT(""));
     word->SetFont(config.getFont(LISTFONT));
-    word->SetToolTip(_("Mot a verifier"));
+    word->SetToolTip(_("Word to check"));
     result = new wxStaticText(this, Result_Id, wxT(""));
     result->SetFont(config.getFont(LISTFONT));
     wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
@@ -253,13 +254,13 @@
 {
     if (dic == NULL)
     {
-        result->SetLabel(_("pas de dictionnaire"));
+        result->SetLabel(_("No dictionary"));
         return;
     }
-    if (Dic_search_word(dic, word->GetValue().wc_str()))
-        result->SetLabel(_("existe"));
+    if (dic->searchWord(word->GetValue().wc_str()))
+        result->SetLabel(_("exists"));
     else
-        result->SetLabel(_("n'existe pas"));
+        result->SetLabel(_("doesn't exist"));
 }
 
 void
@@ -300,7 +301,7 @@
     listbox->SetToolTip(name);
     sizer_v->Add(listbox, 1, wxEXPAND | wxALL, 1);
 
-    button = new wxButton(this, ButtonCopyID, _("Copier"), wxPoint(0, 0), 
wxSize(-1, -1));
+    button = new wxButton(this, ButtonCopyID, _("Copy"), wxPoint(0, 0), 
wxSize(-1, -1));
     sizer_v->Add(button, 0, wxEXPAND | wxALL, 1);
 
     wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
@@ -344,17 +345,10 @@
     if (game == NULL)
        {
            listbox->Clear();
-           listbox->Append(_("Pas de partie en cours"));
+        listbox->Append(_("No on going game"));
            //debug("  %s : Refresh end - no game\n",(const 
char*)name.mb_str());
            return;
        }
-    if (game->getDic() == NULL)
-       {
-           listbox->Clear();
-           listbox->Append(_("Pas de dictionnaire"));
-           //debug("  %s : Refresh end - no dictionnary\n",(const 
char*)name.mb_str());
-           return;
-       }
     if (show == 0)
        {
            //debug("  %s : Refresh end - no window\n",(const 
char*)name.mb_str());
@@ -366,7 +360,7 @@
        {
            //debug("      %s : noresult == true\n",(const char*)name.mb_str());
            listbox->Clear();
-           listbox->Append(_("Aucun resultat"));
+        listbox->Append(_("No result"));
        }
     //debug("  %s : Refresh end\n",(const char*)name.mb_str());
 }
@@ -390,27 +384,41 @@
     }
     savedword = rack;
 
-    wchar_t buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX];
-    Dic_search_7pl1(game->getDic(), rack.c_str(), buff, 
config.getJokerPlus1());
+    map<wchar_t, list<wstring> > wordList;
+    game->getDic().search7pl1(rack, wordList, config.getJokerPlus1());
+
+    // Count the results
+    int sum = 0;
+    map<wchar_t, list<wstring> >::const_iterator it;
+    for (it = wordList.begin(); it != wordList.end(); it++)
+    {
+        if (it->first)
+            sum += 1;
+        sum += it->second.size();
+    }
+    // For the line containing the rack
+    sum += 1;
 
+    noresult = (sum == 0);
     listbox->Clear();
-    wxString res[DIC_LETTERS*(RES_7PL1_MAX+1)];
+    if (noresult)
+        return;
+
+    wxString *res = new wxString[sum];
     int resnum = 0;
-    res[resnum++] = wxString(_("Tirage: ")) + wxString(wxU(rack.c_str()));
-    for (int i = 0; i < DIC_LETTERS; i++)
-    {
-        if (i && buff[i][0][0])
+    res[resnum++] = wxString(_("Rack: ")) + wxString(wxU(rack.c_str()));
+    for (it = wordList.begin(); it != wordList.end(); it++)
         {
-            res[resnum++] = wxString(wxT("+")) + (wxChar)(i + 'A' - 1);
-            noresult = false;
-        }
-        for (int j = 0; j < RES_7PL1_MAX && buff[i][j][0]; j++)
+        if (it->first)
+            res[resnum++] = wxString(wxT("+")) + wxU((wxString)it->first);
+        list<wstring>::const_iterator itWord;
+        for (itWord = it->second.begin(); itWord != it->second.end(); itWord++)
         {
-            res[resnum++] = wxString(wxT("  ")) + wxU(buff[i][j]);
-            noresult = false;
+            res[resnum++] = wxString(wxT("  ")) + wxU(itWord->c_str());
         }
     }
     listbox->Set(resnum, res);
+    delete[] res;
     //debug("      Plus1Frame::refresh end\n");
 }
 
@@ -424,7 +432,7 @@
     if (game->getMode() != Game::kTRAINING)
         return;
 
-    std::wstring word = static_cast<Training*>(game)->getTestPlayWord();
+    wstring word = static_cast<Training*>(game)->getTestPlayWord();
     if (savedword == word)
     {
         noresult = false; // keep old results
@@ -432,18 +440,20 @@
     }
     savedword = word;
     //debug("   BenjFrame::refresh : %s\n",word.c_str());
-    wchar_t wordlist[RES_BENJ_MAX][DIC_WORD_MAX];
-    Dic_search_Benj(game->getDic(), word.c_str(), wordlist);
+    list<wstring> wordList;
+    game->getDic().searchBenj(word, wordList);
 
-    wxString res[RES_BENJ_MAX];
+    wxString *res = new wxString[wordList.size()];
     int resnum = 0;
-    for (int i = 0; (i < RES_BENJ_MAX) && (wordlist[i][0]); i++)
+    list<wstring>::const_iterator it;
+    for (it = wordList.begin(); it != wordList.end(); it++)
     {
-        res[resnum++] = wxU(wordlist[i]);
+        res[resnum++] = wxU(it->c_str());
         //debug("      BenjFrame : %s (%d)\n",wordlist[i],resnum);
         noresult = false;
     }
     listbox->Set(resnum, res);
+    delete[] res;
 }
 
 
@@ -457,7 +467,7 @@
     if (game->getMode() != Game::kTRAINING)
         return;
 
-    std::wstring word = static_cast<Training*>(game)->getTestPlayWord();
+    wstring word = static_cast<Training*>(game)->getTestPlayWord();
     if (savedword == word)
     {
         noresult = false; // keep old results
@@ -465,18 +475,20 @@
     }
     savedword = word;
     //debug("   RaccFrame::refresh : %s\n",word.c_str());
-    wchar_t wordlist[RES_RACC_MAX][DIC_WORD_MAX];
-    Dic_search_Racc(game->getDic(), word.c_str(), wordlist);
+    list<wstring> wordList;
+    game->getDic().searchRacc(word, wordList);
 
-    wxString res[RES_RACC_MAX];
+    wxString *res = new wxString[wordList.size()];
     int resnum = 0;
-    for (int i = 0; (i < RES_RACC_MAX) && (wordlist[i][0]); i++)
+    list<wstring>::const_iterator it;
+    for (it = wordList.begin(); it != wordList.end(); it++)
     {
-        res[resnum++] = wxU(wordlist[i]);
+        res[resnum++] = wxU(it->c_str());
         //debug("      RaccFrame : %s (%d)\n",wordlist[i],resnum);
         noresult = false;
     }
     listbox->Set(resnum, res);
+    delete[] res;
 }
 
 /****************************************************************/
@@ -510,7 +522,7 @@
 /****************************************************************/
 
 GameFrame::GameFrame(wxFrame* parent, Game& iGame):
-    AuxFrameText(parent, ID_Frame_Game, _("partie"), FRAMEGAME, wxTE_MULTILINE 
| wxTE_READONLY | wxTE_DONTWRAP),
+    AuxFrameText(parent, ID_Frame_Game, _("Game history"), FRAMEGAME, 
wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP),
     m_game(iGame)
 {
     textbox->Clear();
@@ -542,7 +554,7 @@
 END_EVENT_TABLE()
 
 ResultFrame::ResultFrame(wxFrame* parent, Game* iGame):
-    AuxFrame(parent, ID_Frame_Result, _("results"), FRAMERESULT)
+    AuxFrame(parent, ID_Frame_Result, _("Results"), FRAMERESULT)
 {
     reslist = new GfxResult(this, (MainFrame*)parent, iGame);
 

Index: wxwin/auxframes.h
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/auxframes.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- wxwin/auxframes.h   4 Aug 2007 20:01:27 -0000       1.8
+++ wxwin/auxframes.h   8 Jan 2008 13:52:43 -0000       1.9
@@ -160,7 +160,7 @@
 private:
     SearchPanel *panel;
 public:
-    SearchFrame(wxFrame*, Dictionary);
+    SearchFrame(wxFrame*, const Dictionary &);
     void Refresh(refresh_t force = REFRESH);
 };
 
@@ -171,12 +171,12 @@
 class VerifFrame: public AuxFrame
 {
 protected:
-    Dictionary dic;
+    const Dictionary *dic;
     wxTextCtrl *word;
     wxStaticText *result;
     void verif();
 public:
-    VerifFrame(wxFrame*, Dictionary);
+    VerifFrame(wxFrame*, const Dictionary&);
     void OnText(wxCommandEvent& event);
     void Refresh(refresh_t force = REFRESH);
     DECLARE_EVENT_TABLE()

Index: wxwin/confdimdlg.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/confdimdlg.cc,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- wxwin/confdimdlg.cc 4 Aug 2007 20:01:27 -0000       1.9
+++ wxwin/confdimdlg.cc 8 Jan 2008 13:52:43 -0000       1.10
@@ -28,8 +28,6 @@
 #include "confdimdlg.h"
 
 enum {
-  Button_Ok,
-  Button_Cancel,
   Button_Printer,
   Button_Page,
   Button_Save,
@@ -39,10 +37,9 @@
 
 BEGIN_EVENT_TABLE(ConfDimDlg,wxDialog)
   EVT_CLOSE (ConfDimDlg::OnCloseWindow)
-  EVT_BUTTON(Button_Ok,         ConfDimDlg::OnButtonOk)
+  EVT_BUTTON(wxID_OK,           ConfDimDlg::OnButtonOk)
+  EVT_BUTTON(wxID_CANCEL,       ConfDimDlg::OnButtonCancel)
   EVT_BUTTON(Button_Save,       ConfDimDlg::OnButtonSave)
-  EVT_BUTTON(Button_Ok,         ConfDimDlg::OnButtonOk)
-  EVT_BUTTON(Button_Cancel,     ConfDimDlg::OnButtonCancel)
   EVT_BUTTON(Button_Printer,    ConfDimDlg::OnConfPrinter)
   EVT_BUTTON(Button_Page,       ConfDimDlg::OnConfPage)
   EVT_BUTTON(Button_FontHeader, ConfDimDlg::OnConfFontHead)
@@ -58,14 +55,13 @@
 
 
 ConfDimDlg::ConfDimDlg(wxWindow* parent, wxPrintData pd, wxPageSetupData psd)
-  : wxDialog(parent, -1, wxString(wxT("Eliot : Impression")))
+  : wxDialog(parent, -1, wxString(wxT("Eliot: Printing")))
 {
   int i;
   wxString choices[3];
-  choices[0] = wxT("gauche");
-// XXX:  choices[1] = wxT("centré");
-  choices[1] = wxT("centre");
-  choices[2] = wxT("droite");
+  choices[0] = _("left");
+  choices[1] = _("centered");
+  choices[2] = _("right");
   wxStaticText* Hcomment[5];
   wxRect        Hcommentrect[5];
   wxRect        Htitlerect[5];
@@ -119,31 +115,29 @@
 #define ESPSIZE      wxSize(spacerect.GetRight() - spacerect.GetLeft(),-1)
 
 
-  wxStaticText* justif = new 
wxStaticText(this,-1,wxT("Justification"),wxPoint(0,0));
+  wxStaticText* justif = new wxStaticText(this,-1,_("Alignment"),wxPoint(0,0));
   wxRect justifrect = justif->GetRect();
-  wxStaticText* space = new 
wxStaticText(this,-1,wxT("Espacement"),wxPoint(0,0));
+  wxStaticText* space = new wxStaticText(this,-1,_("Spacing"),wxPoint(0,0));
   wxRect spacerect = space->GetRect();
 
   // heading, first part
-// XXX:  bfontheader = new 
wxButton(this,Button_FontHeader,wxT("Caractères"),HFONT);
-  bfontheader = new wxButton(this,Button_FontHeader,wxT("Caracteres"),HFONT);
+  bfontheader = new wxButton(this,Button_FontHeader,_("Font..."),HFONT);
   wxRect bfontheadrect = bfontheader->GetRect();
   for(i=0; i<5; i++)
     {
       wxString txt;
-      txt << wxT("Titre colonne ") << (i+1);
+      txt << _("Title column ") << (i+1);
       Hcomment[i] = new wxStaticText(this,-1,txt,HCOMMENT(i));
       Hcommentrect[i] = Hcomment[i]->GetRect();
     }
 
   // text, first part
-// XXX:  bfonttext = new 
wxButton(this,Button_FontText,wxT("Caractères"),TFONT);
-  bfonttext = new wxButton(this,Button_FontText,wxT("Caracteres"),TFONT);
+  bfonttext = new wxButton(this,Button_FontText,_("Font..."),TFONT);
   wxRect bfonttextrect = bfonttext->GetRect();
   for(i=0; i<5; i++)
     {
       wxString txt;
-      txt << wxT("Texte colonne ") << (i+1);
+      txt << _("Text column ") << (i+1);
       Tcomment[i] = new wxStaticText(this,-1,txt,TCOMMENT(i),wxSize(-1,-1));
       Tcommentrect[i] = Tcomment[i]->GetRect();
     }
@@ -153,16 +147,15 @@
     {
       Htitle[i] = new wxTextCtrl(this,-1,wxT(""),HTITLE(i),wxSize(100,-1));
       Htitlerect[i] = Htitle[i]->GetRect();
-      Htitle[i]->SetToolTip(wxT("Texte du titre de la colonne"));
+      Htitle[i]->SetToolTip(_("Column heading"));
 
       Hjust[i] = new wxChoice(this,-1,HJUST(i),wxSize(-1,-1),3,choices);
       Hjustrect[i] = Hjust[i]->GetRect();
-      Hjust[i]->SetToolTip(wxT("Justification du titre de la colonne"));
+      Hjust[i]->SetToolTip(_("Alignment of the column heading"));
 
       Hspaces[i] = new wxTextCtrl(this,-1,wxT("00"),HSPACES(i),ESPSIZE);
       Hspacesrect[i] = Hspaces[i]->GetRect();
-// XXX:      Hspaces[i]->SetToolTip(wxT("Espacement des caractères du titre"));
-      Hspaces[i]->SetToolTip(wxT("Espacement des caracteres du titre"));
+      Hspaces[i]->SetToolTip(_("Spacing of the heading characters"));
     }
 
 
@@ -171,8 +164,7 @@
     {
       Tdim[i] = new wxTextCtrl(this,-1,wxT(""),TDIM(i),wxSize(50,-1));
       Tdimrect[i] = Tdim[i]->GetRect();
-// XXX:      Tdim[i]->SetToolTip(wxT("Dimension intérieure de la colonne (en 
mm)"));
-      Tdim[i]->SetToolTip(wxT("Dimension interieure de la colonne (en mm)"));
+      Tdim[i]->SetToolTip(_("Inner dimension of the column (in mm)"));
 
       Tunit[i] = new wxStaticText(this,-1,wxT("mm"),
                                  wxPoint(Tdimrect[i].GetRight()+
@@ -181,12 +173,11 @@
 
       Tjust[i] = new wxChoice(this,-1,TJUST(i),wxSize(-1,-1),3,choices);
       Tjustrect[i] = Tjust[i]->GetRect();
-      Tjust[i]->SetToolTip(wxT("Justification du texte de la colonne"));
+      Tjust[i]->SetToolTip(_("Alignment of the column text"));
 
       Tspaces[i] = new wxTextCtrl(this,-1,wxT(""),TSPACES(i),ESPSIZE);
       Tspacesrect[i] = Tspaces[i]->GetRect();
-// XXX:      Tspaces[i]->SetToolTip(wxT("Espacement des caractères"));
-      Tspaces[i]->SetToolTip(wxT("Espacement des caracteres"));
+      Tspaces[i]->SetToolTip(_("Characters spacing"));
     }
 
   justif->Move(wxPoint(Tjustrect[0].GetLeft(),bfontheadrect.GetBottom()
@@ -237,11 +228,11 @@
 #define DIM wxSize(30,-1)
 
   // Left part
-  wxStaticText* dyh1text = new wxStaticText(this,-1,wxT("Titre esp. 
sup."),DYH1COMMENT,wxSize(-1,-1));
+  wxStaticText* dyh1text = new wxStaticText(this,-1,_("Title spc. 
top"),DYH1COMMENT,wxSize(-1,-1));
   wxRect dyh1textrect = dyh1text->GetRect();
-  wxStaticText* dyt1text = new wxStaticText(this,-1,wxT("Texte esp. 
sup."),DYT1COMMENT,wxSize(-1,-1));
+  wxStaticText* dyt1text = new wxStaticText(this,-1,_("Text spc. 
top"),DYT1COMMENT,wxSize(-1,-1));
   wxRect dyt1textrect = dyt1text->GetRect();
-  wxStaticText* dxbegintext = new wxStaticText(this,-1,wxT("Texte esp. 
gauche."),DXBEGINCOMMENT,wxSize(-1,-1));
+  wxStaticText* dxbegintext = new wxStaticText(this,-1,_("Text spc. 
left"),DXBEGINCOMMENT,wxSize(-1,-1));
   wxRect dxbegintextrect = dxbegintext->GetRect();
 
   dyh1 = new wxTextCtrl(this,-1,wxT("00"),DYH1TEXT,DIM);
@@ -258,11 +249,11 @@
   wxRect dxbeginmmrect = dxbeginmm->GetRect();
 
   // Right part
-  wxStaticText* dyh2text = new wxStaticText(this,-1,wxT("Titre esp. 
inf."),DYH2COMMENT,wxSize(-1,-1));
+  wxStaticText* dyh2text = new wxStaticText(this,-1,_("Title spc. 
bot."),DYH2COMMENT,wxSize(-1,-1));
   wxRect dyh2textrect = dyh2text->GetRect();
-  wxStaticText* dyt2text = new wxStaticText(this,-1,wxT("Texte esp. 
inf."),DYT2COMMENT,wxSize(-1,-1));
+  wxStaticText* dyt2text = new wxStaticText(this,-1,_("Text spc. 
bot."),DYT2COMMENT,wxSize(-1,-1));
   wxRect dyt2textrect = dyt2text->GetRect();
-  wxStaticText* dxendtext = new wxStaticText(this,-1,wxT("Texte esp. 
droit."),DXENDCOMMENT,wxSize(-1,-1));
+  wxStaticText* dxendtext = new wxStaticText(this,-1,_("Text spc. 
right"),DXENDCOMMENT,wxSize(-1,-1));
   wxRect dxendtextrect = dxendtext->GetRect();
 
   dyh2 = new wxTextCtrl(this,-1,wxT("00"),DYH2TEXT,DIM);
@@ -292,25 +283,25 @@
 #define BCANCELPOINT wxPoint(Tspacesrect[0].GetRight() - CANCELWIDTH,BPOS)
   //#define BCANCELPOINT  wxPoint(dxendmmrect.GetRight() - CANCELWIDTH,BPOS)
 
-  bprinter = new wxButton(this,Button_Printer,wxT("Imprimante"),BPRINTERPOINT);
+  bprinter = new wxButton(this,Button_Printer,_("Printer"),BPRINTERPOINT);
   wxRect bprinterrect = bprinter->GetRect();
-  bprinter->SetToolTip(wxT("Configurer l'imprimante"));
+  bprinter->SetToolTip(_("Configure the printer"));
 
-  bpage = new wxButton(this,Button_Page,wxT("Page"),BPAGEPOINT);
+  bpage = new wxButton(this,Button_Page,_("Page"),BPAGEPOINT);
   //  wxRect bpagerect = bpage->GetRect();
-  bpage->SetToolTip(wxT("Configurer la taille de page"));
+  bpage->SetToolTip(_("Configure the dimensions of the page"));
 
-  bcancel = new wxButton(this,Button_Cancel,wxT("Annuler"));
+  bcancel = new wxButton(this,wxID_CANCEL);
   wxRect bcancelrect = bcancel->GetRect();
   bcancel->Move(BCANCELPOINT);
   bcancelrect = bcancel->GetRect();
-  bcancel->SetToolTip(wxT("Annuler les dernier changements et quitter"));
+  bcancel->SetToolTip(_("Cancel the last changes"));
 
-  bok = new wxButton(this,Button_Ok,wxT("OK"));
+  bok = new wxButton(this,wxID_OK);
   wxRect bokrect = bok->GetRect();
   bok->Move(BOKPOINT);
   bokrect = bok->GetRect();
-  bok->SetToolTip(wxT("Enregistrer les changements et quitter"));
+  bok->SetToolTip(_("Save the changes"));
 
 #define DLGWIDTH     (bcancelrect.GetRight() + HSPACE)
 #define DLGHEIGHT    (bokrect.GetBottom() + VSPACE)

Index: wxwin/configdb.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/configdb.cc,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- wxwin/configdb.cc   4 Aug 2007 20:01:27 -0000       1.8
+++ wxwin/configdb.cc   8 Jan 2008 13:52:43 -0000       1.9
@@ -25,6 +25,7 @@
  */
 
 #include <iostream>
+#include "wx/wx.h"
 #include "ewx.h"
 #include "configdb.h"
 #include "wx/colordlg.h"
@@ -199,7 +200,7 @@
 
 wxString ConfigDB::getDicName()
 {
-  return ReadStr(DICNAME,wxT("Aucun Dictionnaire"));
+  return ReadStr(DICNAME,_("No dictionary"));
 }
 
 wxString ConfigDB::getTilePath()
@@ -318,11 +319,11 @@
   wxString res;
   switch (i)
     {
-    case 0: res = ReadStr(wxString(HNAME) + wxT("1"), wxT("Num")); break;
-    case 1: res = ReadStr(wxString(HNAME) + wxT("2"), wxT("Tirage")); break;
-    case 2: res = ReadStr(wxString(HNAME) + wxT("3"), wxT("Solution")); break;
-    case 3: res = ReadStr(wxString(HNAME) + wxT("4"), wxT("Pos")); break;
-    case 4: res = ReadStr(wxString(HNAME) + wxT("5"), wxT("Pts")); break;
+    case 0: res = ReadStr(wxString(HNAME) + wxT("1"), _("Nb")); break;
+    case 1: res = ReadStr(wxString(HNAME) + wxT("2"), _("Rack")); break;
+    case 2: res = ReadStr(wxString(HNAME) + wxT("3"), _("Solution")); break;
+    case 3: res = ReadStr(wxString(HNAME) + wxT("4"), _("Pos")); break;
+    case 4: res = ReadStr(wxString(HNAME) + wxT("5"), _("Pts")); break;
     default: res = wxT(""); break;
   }
   return res;

Index: wxwin/confsearch.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/confsearch.cc,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- wxwin/confsearch.cc 5 Nov 2005 17:33:06 -0000       1.9
+++ wxwin/confsearch.cc 8 Jan 2008 13:52:43 -0000       1.10
@@ -17,20 +17,15 @@
 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
 
 #include "ewx.h"
+#include "wx/wx.h"
 #include "wx/sizer.h"
 #include "confsearch.h"
 
-enum {
-       Button_Ok,
-       Button_Cancel,
-       CheckBox_Joker,
-       CheckBox_Rack
-};
 
-BEGIN_EVENT_TABLE(ConfSearchDlg,wxDialog)
+BEGIN_EVENT_TABLE(ConfSearchDlg, wxDialog)
   EVT_CLOSE    (ConfSearchDlg::OnCloseWindow)
-  EVT_BUTTON   (Button_Ok,      ConfSearchDlg::OnButtonOk)
-  EVT_BUTTON   (Button_Cancel,  ConfSearchDlg::OnButtonCancel)
+  EVT_BUTTON   (wxID_OK,      ConfSearchDlg::OnButtonOk)
+  EVT_BUTTON   (wxID_CANCEL,  ConfSearchDlg::OnButtonCancel)
 END_EVENT_TABLE()
 
 
@@ -38,14 +33,13 @@
        : wxDialog(parent, -1, wxString(wxT("Configuration recherche")))
 {
 
-  joker_searching = new wxCheckBox(this,CheckBox_Joker,wxT("Recherche sur 
joker dans 7+1"));
-// XXX:  rack_checking = new wxCheckBox(this,CheckBox_Rack,wxT("Vérification 
de la validité des tirages"));
-  rack_checking = new wxCheckBox(this,CheckBox_Rack,wxT("Verification de la 
validite des tirages"));
-
-  bcancel = new wxButton(this,Button_Cancel,wxT("Annuler"),wxPoint(-1,-1));
-  bcancel->SetToolTip(wxT("Annuler les dernier changements et quitter"));
-  bok = new wxButton(this,Button_Ok,wxT("OK"),wxPoint(-1,-1));
-  bok->SetToolTip(wxT("Enregistrer les changements et quitter"));
+    joker_searching = new wxCheckBox(this, wxID_ANY, _("Search on joker in 7+1 
panel"));
+    rack_checking = new wxCheckBox(this, wxID_ANY, _("Check rack validity"));
+
+    bcancel = new wxButton(this, wxID_CANCEL);
+    bcancel->SetToolTip(_("Cancel last changes"));
+    bok = new wxButton(this, wxID_OK);
+    bok->SetToolTip(_("Save the changes"));
 
   wxBoxSizer *bsizer = new wxBoxSizer( wxHORIZONTAL);
   bsizer->Add(bok, 1, wxALL, 1);
@@ -63,21 +57,21 @@
   readconf();
 }
 
-void
+    void
 ConfSearchDlg::readconf()
 {
   joker_searching->SetValue(config.getJokerPlus1());
   rack_checking->SetValue(config.getRackChecking());
 }
 
-void
+    void
 ConfSearchDlg::writeconf()
 {
   config.setJokerPlus1(joker_searching->GetValue());
   config.setRackChecking(rack_checking->GetValue());
 }
 
-void
+    void
 ConfSearchDlg::OnCloseWindow(wxCloseEvent&)
 {
   if (IsModal() == TRUE)
@@ -86,7 +80,7 @@
     this->Destroy();
 }
 
-void
+    void
 ConfSearchDlg::OnButtonOk(wxCommandEvent&)
 {
   writeconf();
@@ -96,7 +90,7 @@
     this->Destroy();
 }
 
-void
+    void
 ConfSearchDlg::OnButtonCancel(wxCommandEvent&)
 {
   if (IsModal() == TRUE)

Index: wxwin/gfxresult.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/gfxresult.cc,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- wxwin/gfxresult.cc  4 Aug 2007 20:01:27 -0000       1.7
+++ wxwin/gfxresult.cc  8 Jan 2008 13:52:43 -0000       1.8
@@ -64,11 +64,11 @@
 #else
     results->SetSingleStyle(wxLC_REPORT | wxLC_SINGLE_SEL);
 #endif
-    results->InsertColumn(0, wxT("Sol"));
+    results->InsertColumn(0, _("Word"));
     results->InsertColumn(1, wxT("*"));
-    results->InsertColumn(2, wxT("Pos"));
-    results->InsertColumn(3, wxT("Pts"));
-    results->SetToolTip(wxT("Resultats de la recherche"));
+    results->InsertColumn(2, _("Pos"));
+    results->InsertColumn(3, _("Pts"));
+    results->SetToolTip(_("Results of the search"));
 
     wxBoxSizer *sizer_v = new wxBoxSizer(wxVERTICAL);
     wxBoxSizer *sizer_h = new wxBoxSizer(wxHORIZONTAL);
@@ -115,7 +115,7 @@
     debug("   GfxResult::Refresh : ");
     std::wstring rack = game->getCurrentPlayer().getCurrentRack().toString();
 
-    if (savedrack != rack || static_cast<Training*>(game)->getResults().size() 
!= results->GetItemCount())
+    if (savedrack != rack || 
(int)static_cast<Training*>(game)->getResults().size() != 
results->GetItemCount())
     {
         debug("changed (%ls -> %ls)",savedrack.c_str(),rack.c_str());
         savedrack = rack;
@@ -138,16 +138,16 @@
     if (game == NULL)
         return;
 
-    ((Training*)game)->search();
+    static_cast<Training*>(game)->search();
 
     results->DeleteAllItems();
     results->SetFont(config.getFont(LISTFONT));
 
-    const Results &res = ((Training*)game)->getResults();
+    const Results &res = static_cast<Training*>(game)->getResults();
     debug("   GfxResult::Search size = %d\n",res.size());
-    for (int i = 0; i < res.size(); i++)
+    for (unsigned int i = 0; i < res.size(); i++)
     {
-        Round r = res.get(i);
+        const Round &r = res.get(i);
         //debug("    adding %s\n",r.toString().c_str());
         wxString pts;
         wxString word   = wxU(r.getWord().c_str());
@@ -170,7 +170,7 @@
     if (res.size() > 0)
     {
         results->SetItemState(0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED 
| wxLIST_MASK_STATE);
-        ((Training*)game)->testPlay(0);
+        static_cast<Training*>(game)->testPlay(0);
     }
 }
 

Index: wxwin/main.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/main.cc,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- wxwin/main.cc       11 Aug 2006 22:18:33 -0000      1.10
+++ wxwin/main.cc       8 Jan 2008 13:52:43 -0000       1.11
@@ -67,19 +67,21 @@
     wxConfigBase* config = wxConfigBase::Get();
     config = NULL;
 #ifdef ENABLE_LOCALE
-    locale.Init(wxLocale::GetSystemLanguage(),
-                wxLOCALE_LOAD_DEFAULT | wxLOCALE_CONV_ENCODING);
+    locale.Init();
 
-    wxLocale::AddCatalogLookupPathPrefix(wxT("."));
-    wxLocale::AddCatalogLookupPathPrefix(wxT(".."));
+    // No need to search in the current directory, it is already done by 
default
+    // wxLocale::AddCatalogLookupPathPrefix(wxT("."));
+    // Search for translations in the installation directory
+    wxLocale::AddCatalogLookupPathPrefix(wxT(LOCALEDIR));
     locale.AddCatalog(wxT("eliot"));
 #ifdef __LINUX__
     {
         wxLogNull noLog;
-        locale.AddCatalog(_T("fileutils"));
+        locale.AddCatalog(wxT("fileutils"));
     }
 #endif
 #endif
+
     ConfigDB configdb;
     configdb.setFirstDefault();
     MainFrame *mainframe = new MainFrame(configdb.getFramePos(wxT(APPNAME)),
@@ -94,7 +96,7 @@
 EliotApp::OnExit()
 {
     GameFactory::Destroy();
-    delete wxConfigBase::Set((wxConfigBase *) NULL);
+    delete wxConfigBase::Set(NULL);
     return 0;
 }
 

Index: wxwin/mainframe.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/mainframe.cc,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- wxwin/mainframe.cc  4 Aug 2007 20:01:27 -0000       1.22
+++ wxwin/mainframe.cc  8 Jan 2008 13:52:43 -0000       1.23
@@ -24,10 +24,13 @@
  *  \date   2005
  */
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <iostream>
 #include <fstream>
+#include <exception>
 
 using namespace std;
 
@@ -42,6 +45,7 @@
 
 #include "dic.h"
 #include "game.h"
+#include "training.h"
 #include "game_factory.h"
 #include "player.h"
 
@@ -58,6 +62,7 @@
 enum
 {
     Menu_Game_New                             = 1000,
+    Menu_Game_NewJoker,
     Menu_Game_Open,
     Menu_Game_Save,
     Menu_Game_Print,
@@ -100,9 +105,6 @@
     Menu_ShowGame                             = (IDBASE + ID_Frame_Game),
     Menu_ShowResult                           = (IDBASE + ID_Frame_Result),
 
-    Menu_Quit_Apropos                         = 4000,
-    Menu_Quit_Confirm,
-
     Button_SetRack                            = 10000,
     Button_SetNew,
     Button_SetManual,
@@ -112,17 +114,19 @@
 
     ListCtrl_ID                               = 11000,
     Rack_ID,
-    Status_ID,
+    Status_ID
 };
 
 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
     //
     EVT_MENU(Menu_Game_New,          MainFrame::OnMenuGameNew)
+    EVT_MENU(Menu_Game_NewJoker,     MainFrame::OnMenuGameNew)
     EVT_MENU(Menu_Game_Open,         MainFrame::OnMenuGameOpen)
     EVT_MENU(Menu_Game_Save,         MainFrame::OnMenuGameSave)
     EVT_MENU(Menu_Game_Print,        MainFrame::OnMenuGamePrint)
     EVT_MENU(Menu_Game_PrintPreview, MainFrame::OnMenuGamePrintPreview)
     EVT_MENU(Menu_Game_PrintPS,      MainFrame::OnMenuGamePrintPS)
+    EVT_MENU(wxID_EXIT,              MainFrame::OnMenuGameQuit)
     //
     EVT_MENU(Menu_Conf_Game_Dic,     MainFrame::OnMenuConfGameDic)
     EVT_MENU(Menu_Conf_Game_Search,  MainFrame::OnMenuConfGameSearch)
@@ -133,8 +137,7 @@
     EVT_MENU_RANGE(Menu_Conf_Aspect_BoardColour_Lines, 
Menu_Conf_Aspect_BoardColour_Default, MainFrame::OnMenuConfAspectBoardColour)
     EVT_MENU_RANGE(Menu_ShowVerif, Menu_ShowResult, MainFrame::OnMenuShowFrame)
     //
-    EVT_MENU(Menu_Quit_Apropos, MainFrame::OnMenuQuitApropos)
-    EVT_MENU(Menu_Quit_Confirm, MainFrame::OnMenuQuitConfirm)
+    EVT_MENU(wxID_ABOUT, MainFrame::OnMenuHelpAbout)
     //
     EVT_BUTTON(Button_Play,     MainFrame::OnPlay)
     EVT_BUTTON(Button_SetRack,  MainFrame::OnSetRack)
@@ -153,39 +156,46 @@
 //
 // ******************************
     
-MainFrame::MainFrame(wxPoint __UNUSED__ pos_, wxSize size_) : 
-           wxFrame((wxFrame *) NULL, -1, wxT(APPNAME), wxPoint(-1, -1),
-                   size_, wxDEFAULT_FRAME_STYLE, wxT(APPNAME)), m_dic(NULL), 
m_game(NULL)
+MainFrame::MainFrame(wxPoint __UNUSED__ pos_, wxSize size_)
+    : wxFrame((wxFrame *) NULL, -1, wxT(APPNAME), wxPoint(-1, -1),
+              size_, wxDEFAULT_FRAME_STYLE, wxT(APPNAME)),
+    m_dic(NULL), m_game(NULL)
 {
 #if defined(ENABLE_RESLIST_IN_MAIN)
     reslist = NULL;
 #endif
     statusbar = NULL;
-    for(int i=0 ; i < MAX_FRAME_ID; i++)
+    for (int i = 0 ; i < MAX_FRAME_ID; i++)
       auxframes_ptr[i] = NULL;
 
-    wxString dicpath = config.getDicPath();
-    Dic_load(&m_dic, dicpath.mb_str());
-    if (m_dic == NULL)
-       {
-           wxCommandEvent event;
-           OnMenuConfGameDic(event);
-       }
-    m_game = GameFactory::Instance()->createTraining(m_dic);
-    if (m_game)
-       {
-           m_game->start();
-       }
-
     wxBoxSizer *listsizer = new wxBoxSizer(wxVERTICAL);
     rack = new wxTextCtrl(this, Rack_ID, wxU(""), wxPoint(-1, -1), wxSize(-1, 
-1), wxTE_PROCESS_ENTER);
-    listsizer->Add(rack    , 0 , wxEXPAND | wxALL, 1);
-    rack->SetToolTip(_("Tirage"));
+    listsizer->Add(rack, 0, wxEXPAND | wxALL, 1);
+    rack->SetToolTip(_("Rack"));
+    rack->Enable(false);
 #ifdef ENABLE_RESLIST_IN_MAIN
     reslist = new GfxResult(this,(MainFrame*)this,m_game);
     listsizer->Add(reslist, 1, wxEXPAND | wxLEFT | wxRIGHT, 1);
 #endif
 
+    wxString dicpath = config.getDicPath();
+    try
+    {
+        Dictionary *dic = new Dictionary(dicpath.mb_str().data());
+        m_dic = dic;
+        m_game = GameFactory::Instance()->createTraining(*m_dic);
+        if (m_game)
+        {
+            m_game->start();
+        }
+    }
+    catch (std::exception &e)
+    {
+        wxCommandEvent event;
+        // This will also start a new training game indirectly
+        OnMenuConfGameDic(event);
+    }
+
     InitMenu();
 
     statusbar = CreateStatusBar(2, 0, Status_ID);
@@ -193,17 +203,22 @@
     statusbar->SetStatusWidths(2, ww);
     UpdateStatusBar();
 
-    b_rackrandomset = new wxButton(this, Button_SetRack,  _(" Tirage "));
+    b_rackrandomset = new wxButton(this, Button_SetRack,  _(" Rack "));
     b_rackrandomnew = new wxButton(this, Button_SetNew,   _(" Complement "));
-    b_search        = new wxButton(this, Button_Search,   _(" Rechercher "));
-    b_back          = new wxButton(this, Button_PlayBack, _(" Arriere "));
-    b_play          = new wxButton(this, Button_Play,     _(" Jouer "));
-
-    b_rackrandomset->SetToolTip(_("Tirage aleatoire"));
-    b_rackrandomnew->SetToolTip(_("Complement aleatoire du tirage"));
-    b_search->SetToolTip(       _("Recherche sur le tirage courant"));
-    b_back->SetToolTip(         _("Revenir un coup en arriere"));
-    b_play->SetToolTip(         _("Jouer le mot selectionne"));
+    b_search        = new wxButton(this, Button_Search,   _(" Search "));
+    b_back          = new wxButton(this, Button_PlayBack, _(" Back "));
+    b_play          = new wxButton(this, Button_Play,     _(" Play "));
+
+    b_rackrandomset->SetToolTip(_("Random rack"));
+    b_rackrandomset->Enable(false);
+    b_rackrandomnew->SetToolTip(_("Random complement of the rack"));
+    b_rackrandomnew->Enable(false);
+    b_search->SetToolTip(       _("Search with the current rack"));
+    b_search->Enable(false);
+    b_back->SetToolTip(         _("Go back one turn"));
+    b_back->Enable(false);
+    b_play->SetToolTip(         _("Play the selected word"));
+    b_play->Enable(false);
 
     wxBoxSizer *buttonsizer = new wxBoxSizer(wxHORIZONTAL);
     buttonsizer->Add(b_rackrandomset, 1, wxEXPAND | wxTOP | wxBOTTOM | wxLEFT 
, 1);
@@ -242,10 +257,7 @@
        m_game = NULL;
       }
 
-    if (m_dic)
-      {
-       Dic_destroy(m_dic);
-      }
+    delete m_dic;
 }
 
 // ******************************
@@ -257,82 +269,72 @@
 {
     // menus
     wxMenu *menu_game = new wxMenu;
-    menu_game->Append(Menu_Game_New, _("Nouvelle"), _("Demarrer une nouvelle 
partie"));
-    menu_game->Append(Menu_Game_Open, _("Charger..."), _("Charger une 
partie"));
-    menu_game->Append(Menu_Game_Save, _("Sauver..."), _("Sauver cette 
partie"));
+    menu_game->Append(Menu_Game_New, _("&New game\tctrl+n"), _("Start a new 
game"));
+    menu_game->Append(Menu_Game_NewJoker, _("New &joker game\tctrl+j"), 
_("Start a new joker game"));
     menu_game->AppendSeparator();
-    menu_game->Append(Menu_Game_Print, _("Imprimer..."), _("Imprimer cette 
partie"));
-    menu_game->Append(Menu_Game_PrintPreview, _("Preimpression"), 
_("Preimpression de la partie"));
-#ifdef ENABLE_SAVE_POSTSCRIPT
+    menu_game->Append(Menu_Game_Open, _("&Load...\tctrl+l"), _("Load a game"));
+    menu_game->Append(Menu_Game_Save, _("&Save as...\tctrl+s"), _("Save the 
current game"));
     menu_game->AppendSeparator();
-    menu_game->Append(Menu_Game_PrintPS, _("Imprimer du PostScript"), 
_("Imprimer dans un fichier PostScript"));
+    menu_game->Append(Menu_Game_Print, _("&Print...\tctrl+p"), _("Print this 
game"));
+    menu_game->Append(Menu_Game_PrintPreview, _("Print pre&view..."), _("Print 
preview of the game"));
+#ifdef ENABLE_SAVE_POSTSCRIPT
+    menu_game->Append(Menu_Game_PrintPS, _("Print in PostS&cript..."), 
_("Print in a PostScript file"));
 #endif
+    menu_game->AppendSeparator();
+    menu_game->Append(wxID_EXIT, _("&Quit"), _("Quit Eliot"));
     //
     wxMenu *menu_conf_game = new wxMenu;
-    menu_conf_game->Append(Menu_Conf_Game_Dic, _("Dictionnaire"), _("Choix du 
dictionnaire"));
-    menu_conf_game->Append(Menu_Conf_Game_Search, _("Recherche"), _("Options 
de recherche"));
-    //
-    wxMenu *menu_tileback = new wxMenu;
-    menu_tileback->Append(Menu_Conf_Aspect_BoardColour_Letters     , 
_("Lettres jouees"), _("Lettres jouees sur la grille"));
-    menu_tileback->Append(Menu_Conf_Aspect_BoardColour_TestLetters , 
_("Lettres provisoires"), _("Lettres du mot a jouer"));
-    menu_tileback->AppendSeparator();
-    menu_tileback->Append(Menu_Conf_Aspect_BoardColour_TileBack    , _("Fonds 
lettres jouees"), _("Fonds des pions sur la grille"));
-    menu_tileback->Append(Menu_Conf_Aspect_BoardColour_TestTileBack, _("Fonds 
lettres provisoires"), _("Fonds des pions sur la grille"));
+    menu_conf_game->Append(Menu_Conf_Game_Dic, _("&Dictionary..."), _("Choose 
a dictionary"));
+    menu_conf_game->Append(Menu_Conf_Game_Search, _("&Search..."), _("Search 
options"));
     //
     wxMenu *menu_conf_board_colour = new wxMenu;
-    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Background, 
_("Fond"), _("Couleur du fond"));
-    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Lines, 
_("Lignes"), _("Couleur des lignes"));
-    menu_conf_board_colour->Append(Menu_Conf_Tile, _("Pions et lettres"), 
menu_tileback, _("Pions et lettres"));
+    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Background, 
_("&Background..."), _("Background color"));
+    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Lines, 
_("L&ines..."), _("Color of the lines"));
     menu_conf_board_colour->AppendSeparator();
-    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Letters, 
_("Lettres jouees"), _("Lettres jouees sur la grille"));
-    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_TestLetters, 
_("Lettres provisoires"), _("Lettres du mot a jouer"));
+    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Letters, 
_("&Played letters..."), _("Color of the letters played on the board"));
+    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_TestLetters, 
_("&Temporary letters..."), _("Color of the letters of the temporary word"));
+    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_TileBack    , 
_("B&ackground of played letters..."), _("Background color of the letters 
played on the board"));
+    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_TestTileBack, 
_("Ba&ckground of temporary letters..."), _("Background color of the temporary 
letters on the board"));
     menu_conf_board_colour->AppendSeparator();
-    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Wx2, _("Mot 
compte double"), _("Mot compte double"));
-    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Wx3, _("Mot 
compte triple"), _("Mot compte triple"));
-    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Lx2, _("Lettre 
compte double"), _("Lettre compte double"));
-    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Lx3, _("Lettre 
compte triple"), _("Lettre compte triple"));
+    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Wx2, _("Double 
&letter..."), _("Color of the \"double letter\" squares"));
+    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Wx3, _("Triple 
l&etter..."), _("Color of the \"triple letter\" squares"));
+    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Lx2, _("Double 
&word..."), _("Color of the \"double word\" squares"));
+    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Lx3, _("Triple 
w&ord..."), _("Color of the \"triple word\" squares"));
     menu_conf_board_colour->AppendSeparator();
-    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Default, 
_("Couleurs d'origine"), _("Retrouver les couleurs d'origine"));
+    menu_conf_board_colour->Append(Menu_Conf_Aspect_BoardColour_Default, 
_("&Default colors"), _("Restore the default colors"));
     //
     wxMenu *menu_conf_board_font = new wxMenu;
-// XXX:    menu_conf_board_font->Append(Menu_Conf_Aspect_Font_Search, 
_("Lettres de recherche"), _("Police de caractères pour les recherches"));
-    menu_conf_board_font->Append(Menu_Conf_Aspect_Font_Search, _("Lettres de 
recherche"), _("Police de caracteres pour les recherches"));
-// XXX:    menu_conf_board_font->Append(Menu_Conf_Aspect_Font_Board, 
_("Lettres de la grille"), _("Police de caractères de la grille"));
-    menu_conf_board_font->Append(Menu_Conf_Aspect_Font_Board, _("Lettres de la 
grille"), _("Police de caracteres de la grille"));
+    menu_conf_board_font->Append(Menu_Conf_Aspect_Font_Search, _("&Search 
letters..."), _("Font for the search"));
     //
     wxMenu *menu_conf = new wxMenu;
-    menu_conf->Append(Menu_Conf_Game, _("Jeu"), menu_conf_game, 
_("Configuration du jeu"));
-    menu_conf->Append(Menu_Conf_Aspect_Font, _("Fonte des lettres"), 
menu_conf_board_font, _("Modification des fontes"));
-    menu_conf->Append(Menu_Conf_Aspect_BoardColour, _("Couleurs de la 
grille"), menu_conf_board_colour, _("Modification des couleurs"));
-    menu_conf->Append(Menu_Conf_Print, _("Impression"), _("Dimensions de la 
partie"));
+    menu_conf->Append(Menu_Conf_Game, _("&Game"), menu_conf_game, 
_("Configuration of the game"));
+    menu_conf->Append(Menu_Conf_Aspect_Font, _("&Fonts"), 
menu_conf_board_font, _("Configuration of the fonts"));
+    menu_conf->Append(Menu_Conf_Aspect_BoardColour, _("&Colors"), 
menu_conf_board_colour, _("Configuration of the colors"));
+    menu_conf->Append(Menu_Conf_Print, _("&Printing..."), _("Configuration of 
the printing parameters"));
     //
     wxMenu *menu_frame = new wxMenu;
-    menu_frame->Append(Menu_ShowBoard, _("Grille"), _("Grille de jeu"));
-// XXX:    menu_frame->Append(Menu_ShowVerif, _("Vérification"), 
_("Vérification d'un mot dans le dictionnaire"));
-    menu_frame->Append(Menu_ShowVerif, _("Verification"), _("Verification d'un 
mot dans le dictionnaire"));
-    menu_frame->Append(Menu_ShowSearch, _("Recherche"), _("Recherche dans le 
dictionnaire"));
+    menu_frame->AppendCheckItem(Menu_ShowBoard, _("&Board"), _("Game board"));
+    menu_frame->AppendCheckItem(Menu_ShowBag, _("Ba&g"), _("Remaining letters 
in the bag"));
+    menu_frame->AppendCheckItem(Menu_ShowVerif, _("&Check"), _("Check a word 
in the dictionary"));
+    menu_frame->AppendCheckItem(Menu_ShowSearch, _("&Search"), _("Search in 
the dictionary"));
     menu_frame->AppendSeparator();
-    menu_frame->Append(Menu_ShowPlus1, _("Tirage + 1"), _("Lettres du tirage 
plus une"));
-    menu_frame->Append(Menu_ShowRacc, _("Raccords"), _("Raccords sur un mot de 
la recherche"));
-    menu_frame->Append(Menu_ShowBenj, _("Benjamins"), _("Benjamins sur un mot 
de la recherche"));
+    menu_frame->AppendCheckItem(Menu_ShowPlus1, _("&Rack + 1"), _("Letters of 
the rack plus one"));
+    menu_frame->AppendCheckItem(Menu_ShowRacc, _("R&accords"), _("Raccords on 
a word of the search"));
+    menu_frame->AppendCheckItem(Menu_ShowBenj, _("&Benjamins"), _("Benjamins 
on a word of the search"));
     menu_frame->AppendSeparator();
-    menu_frame->Append(Menu_ShowBag, _("Sac"), _("Lettres restantes dans le 
sac"));
-    menu_frame->AppendSeparator();
-    menu_frame->Append(Menu_ShowGame, _("Partie"), _("Partie"));
+    menu_frame->AppendCheckItem(Menu_ShowGame, _("Game &history"), _("Game 
history"));
 #ifndef ENABLE_RESLIST_IN_MAIN
-    menu_frame->Append(Menu_ShowResult, _("Resultats"), _("Resultats"));
+    menu_frame->Append(Menu_ShowResult, _("R&esults"), _("Results"));
 #endif
     //
-    wxMenu *menu_quit = new wxMenu;
-    menu_quit->Append(Menu_Quit_Apropos, _("A propos..."), _("A propos 
d'Eliot"));
-    menu_quit->Append(Menu_Quit_Confirm, _("Quitter"), _("Quitter"));
+    wxMenu *menu_help = new wxMenu;
+    menu_help->Append(wxID_ABOUT, _("&About..."), _("About Eliot"));
     //
     wxMenuBar *menu_bar = new wxMenuBar;
-    menu_bar->Append(menu_game, _("Partie"));
-    menu_bar->Append(menu_conf, _("Configuration"));
-// XXX:    menu_bar->Append(menu_frame, _("Fenêtres"));
-    menu_bar->Append(menu_frame, _("Fenetres"));
-    menu_bar->Append(menu_quit, _("Quitter"));
+    menu_bar->Append(menu_game, _("&Game"));
+    menu_bar->Append(menu_conf, _("&Settings"));
+    menu_bar->Append(menu_frame, _("&Windows"));
+    menu_bar->Append(menu_help, _("&Help"));
 
     SetMenuBar(menu_bar);
 }
@@ -352,11 +354,11 @@
 // *******************
 
 void
-MainFrame::OnMenuGameNew(wxCommandEvent&)
+MainFrame::OnMenuGameNew(wxCommandEvent& event)
 {
     if (m_dic == NULL)
       {
-        wxMessageBox(_("Il n'y a pas de dictionnaire selectionne"), _("Eliot: 
erreur"),
+        wxMessageBox(_("No dictionary selected"), _("Eliot: error"),
                      wxICON_INFORMATION | wxOK);
         return;
       }
@@ -369,13 +371,26 @@
        m_game = NULL;
       }
 
-    m_game = GameFactory::Instance()->createTraining(m_dic);
+    m_game = GameFactory::Instance()->createTraining(*m_dic);
+    // Joker game?
+    if (event.GetId() == Menu_Game_NewJoker)
+        m_game->setVariant(Game::kJOKER);
+
     m_game->start();
-    rack->SetValue(wxU(""));
+    rack->SetValue(wxT(""));
     InitFrames();
 #ifdef ENABLE_RESLIST_IN_MAIN
     reslist->SetGame(m_game);
 #endif
+    // Re-enable the main buttons
+    b_rackrandomset->Enable(true);
+    b_rackrandomnew->Enable(true);
+    b_search->Enable(true);
+    b_back->Enable(true);
+    b_play->Enable(true);
+    rack->Enable(true);
+
+
     UpdateStatusBar();
     UpdateFrames(AuxFrame::FORCE_REFRESH);
 }
@@ -387,11 +402,10 @@
 void
 MainFrame::OnMenuGameOpen(wxCommandEvent&)
 {
-    wxString txt;
-    wxFileDialog dialog(this, _("Ouvrir une partie"), wxT(""), wxT(""), 
wxT("*"), wxOPEN);
+    wxFileDialog dialog(this, _("Load a game"), wxT(""), wxT(""), wxT("*"), 
wxOPEN);
     if (m_dic == NULL)
     {
-        wxMessageBox(_("Il n'y a pas de dictionnaire selectionne"), _("Eliot: 
erreur"),
+        wxMessageBox(_("No dictionary selected"), _("Eliot: error"),
                      wxICON_INFORMATION | wxOK);
         return;
     }
@@ -410,20 +424,21 @@
 
     if ((fin = fopen(dialog.GetPath().mb_str(), "rb")) == NULL)
         {
-            txt << _("Impossible d'ouvrir") << dialog.GetPath();
-            wxMessageDialog msg(this, txt, _("Ouverture d'une partie"));
+        wxString txt;
+        txt << _("Cannot open ") << dialog.GetPath();
+        wxMessageDialog msg(this, txt, _("Load a game"));
             msg.ShowModal();
             return ;
         }
 
-    m_game = Game::load(fin, m_dic);
+    m_game = Game::load(fin, *m_dic);
     fclose(fin);
 
     if (m_game == NULL)
         {
             wxMessageDialog msg(this,
-                               _("Erreur pendant la lecture de la partie"),
-                               _("chargement de partie"));
+                            _("Error while loading the game"),
+                            _("Invalid game"));
             msg.ShowModal();
             return;
         }
@@ -431,18 +446,13 @@
     if (m_game->getHistory().getSize() == 0)
        {
             wxMessageDialog msg(this,
-                               _("Erreur pendant la lecture de la partie"),
-                               _("La partie est vide"));
+                            _("Error while loading the game"),
+                            _("The game is empty"));
             msg.ShowModal();
             return;
        }
 
-    std::wstring r;
-
-    if (m_game->getHistory().getSize() >= 0)
-    {
-        r = m_game->getCurrentPlayer().getCurrentRack().toString();
-    }
+    std::wstring r = m_game->getCurrentPlayer().getCurrentRack().toString();
 
     rack->SetValue(wxU(r.c_str()));
     // update gfxboard and all frames
@@ -462,16 +472,15 @@
 void
 MainFrame::OnMenuGameSave(wxCommandEvent& WXUNUSED(event))
 {
-    wxFileDialog dialog(this, _("Sauver une partie"), wxT(""), wxT(""), 
wxT("*"), wxSAVE|wxOVERWRITE_PROMPT);
+    wxFileDialog dialog(this, _("Save the game"), wxT(""), wxT(""), wxT("*"), 
wxSAVE|wxOVERWRITE_PROMPT);
     if (dialog.ShowModal() == wxID_OK)
     {
         ofstream fout(dialog.GetPath().mb_str());
         if (fout.rdstate() == ios::failbit)
         {
             wxString txt;
-// XXX:            txt << _("Impossible de créer ") << dialog.GetPath();
-            txt << _("Impossible de creer ") << dialog.GetPath();
-            wxMessageDialog msg(this, txt, _("Sauvegarde de la partie"));
+            txt << _("Cannot create ") << dialog.GetPath();
+            wxMessageDialog msg(this, txt, _("Save the game"));
             msg.ShowModal();
             return ;
         }
@@ -490,7 +499,7 @@
     // TODO: gray out the menu instead...
     if (m_game == NULL)
     {
-        wxMessageBox(_("Pas de partie en cours"), _("Eliot: erreur"),
+        wxMessageBox(_("No on going game"), _("Eliot: error"),
                      wxICON_INFORMATION | wxOK);
         return;
     }
@@ -498,8 +507,10 @@
     wxPrinter printer(&printDialogData);
     GamePrintout printout(*m_game);
     if (!printer.Print(this, &printout, TRUE))
-// XXX:        wxMessageBox(wxT("Impression non effectuée."));
-        wxMessageBox(_("Impression non effectuee."));
+    {
+        wxMessageBox(_("Printing not done"), _("Printing"),
+                     wxOK | wxICON_ERROR);
+    }
 }
 
 void
@@ -508,7 +519,7 @@
     // TODO: gray out the menu instead...
     if (m_game == NULL)
     {
-        wxMessageBox(_("Pas de partie en cours"), _("Eliot: erreur"),
+        wxMessageBox(_("No on going game"), _("Eliot: error"),
                      wxICON_INFORMATION | wxOK);
         return;
     }
@@ -520,15 +531,12 @@
     if (!preview->Ok())
     {
         delete preview;
-// XXX:        msg << _("Problème de prévisualisation.\n")
-        msg << _("Probleme de previsualisation.\n")
-// XXX:            << _("Il se peut que l'imprimante par défaut soit mal 
initialisée");
-            << _("Il se peut que l'imprimante par defaut soit mal 
initialisee");
-// XXX:        wxMessageBox(msg, _("Impression (prévisualisation)"), wxOK);
-        wxMessageBox(msg, _("Impression (previsualisation)"), wxOK);
+        msg << _("Print preview problem.\n")
+            << _("The printer may not be correctly initialized");
+        wxMessageBox(msg, _("Print preview"), wxOK);
         return;
     }
-    wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _("Impression"),
+    wxPreviewFrame *frame = new wxPreviewFrame(preview, this, _("Printing"),
                                                wxPoint(-1, -1), wxSize(600, 
550));
     frame->Centre(wxBOTH);
     frame->Initialize();
@@ -542,12 +550,11 @@
     // TODO: gray out the menu instead...
     if (m_game == NULL)
     {
-        wxMessageBox(_("Pas de partie en cours"), _("Eliot: erreur"),
+        wxMessageBox(_("No on going game"), _("Eliot: error"),
                      wxICON_INFORMATION | wxOK);
         return;
     }
-    wxString txt;
-    wxFileDialog dialog(this, _("Imprimer dans un fichier PostScript"), 
wxT(""), wxT(""), wxT("*.ps"), wxSAVE|wxOVERWRITE_PROMPT);
+    wxFileDialog dialog(this, _("Print to a PostScript file"), wxT(""), 
wxT(""), wxT("*.ps"), wxSAVE|wxOVERWRITE_PROMPT);
     if (dialog.ShowModal() == wxID_OK)
     {
         wxPrintData printdataPS;
@@ -565,76 +572,54 @@
             GamePrintout printout(*m_game);
             if (!printer.Print(this, &printout, FALSE))
             {
-// XXX:                wxMessageBox(_("Impression non effectuée."));
-                wxMessageBox(_("Impression non effectuee."));
-            }
-            else
-            {
-                wxString msg;
-// XXX:                msg << _("Dessin effectué dans ") << dialog.GetPath() 
<< _("\n");
-                msg << _("Dessin effectue dans ") << dialog.GetPath() << 
_("\n");
-                wxMessageBox(msg, _("Sauvegarde PostScript"), wxOK);
+                wxMessageBox(_("Printing not done"),
+                             _("PostScript printing"), wxOK | wxICON_ERROR);
             }
         }
         else
         {
-            wxString msg;
-            msg << _("impossible d'initialiser le traitement PostScript.\n");
-            wxMessageBox(msg, _("Sauvegarde PostScript"), wxOK);
+            wxMessageBox(_("Cannot initialize PostScript printer"),
+                         _("PostScript printing"), wxOK | wxICON_ERROR);
         }
     }
 #endif
 }
 
 
+void
+MainFrame::OnMenuGameQuit(wxCommandEvent& WXUNUSED(event))
+{
+    Close(TRUE);
+}
+
+
+
 // *******************
-// Dictionnary Loading
+// Dictionary Loading
 // *******************
 
 void
 MainFrame::OnMenuConfGameDic(wxCommandEvent& WXUNUSED(event))
 {
-    wxString txt, msg, dicpath;
-    wxFileDialog dialog(this, _("Choisir un dictionnaire"), wxT(""), 
wxT("*.dawg"), wxT("*.dawg"), wxOPEN);
+    wxFileDialog dialog(this, _("Choose a dictionary"), wxT(""), 
wxT("*.dawg"), wxT("*.dawg"), wxOPEN);
     if (dialog.ShowModal() == wxID_OK)
     {
         wxString dicpath = dialog.GetPath();
-        Dictionary dic;
-        int res = Dic_load(&dic, dicpath.mb_str());
-        if (res == 0)
-        {
-            if (m_dic)
+        try
              {
-                Dic_destroy(m_dic);
-             }
-
+            Dictionary *dic = new Dictionary(dicpath.mb_str().data());
+            delete m_dic;
             m_dic = dic;
             config.setDicPath(dialog.GetPath(), 
::wxFileNameFromPath(dialog.GetPath()));
+            wxCommandEvent event;
+            OnMenuGameNew(event);
         }
-        else
-        {
-            switch (res)
+        catch (std::exception &e)
             {
-                case 0: /* cas normal */ break;
-// XXX:                case 1: msg << _("chargement: problème d'ouverture de 
") << dicpath << _("\n"); break;
-                case 1: msg << _("chargement: probleme d'ouverture de ") << 
dicpath << _("\n"); break;
-// XXX:                case 2: msg << _("chargement: mauvais en-tête de 
dictionnaire\n"); break;
-                case 2: msg << _("chargement: mauvais en-tete de 
dictionnaire\n"); break;
-// XXX:                case 3: msg << _("chargement: problème 3 d'allocation 
mémoire\n"); break;
-                case 3: msg << _("chargement: probleme 3 d'allocation 
memoire\n"); break;
-// XXX:                case 4: msg << _("chargement: problème 4 d'allocation 
mémoire\n"); break;
-                case 4: msg << _("chargement: probleme 4 d'allocation 
memoire\n"); break;
-// XXX:                case 5: msg << _("chargement: problème de lecture des 
arcs du dictionnaire\n"); break;
-                case 5: msg << _("chargement: probleme de lecture des arcs du 
dictionnaire\n"); break;
-// XXX:                default: msg << _("chargement: problème 
non-répertorié\n"); break;
-                default: msg << _("chargement: probleme non-repertorie\n"); 
break;
-            }
-            wxMessageDialog dlg(NULL, msg, wxT(APPNAME));
+            wxMessageDialog dlg(NULL, wxU(e.what()), wxT(APPNAME));
             dlg.ShowModal();
         }
     }
-    UpdateStatusBar();
-    UpdateFrames();
 }
 
 // ****************
@@ -732,30 +717,22 @@
 }
 
 
//**************************************************************************************
-//   MENU QUIT
+//   MENU HELP
 
//**************************************************************************************
 
 void
-MainFrame::OnMenuQuitApropos(wxCommandEvent& WXUNUSED(event))
+MainFrame::OnMenuHelpAbout(wxCommandEvent& WXUNUSED(event))
 {
     wxString msg;
-    // XXX:    msg << wxT("Eliot\n© Antoine Fraboulet 1999-2004\n\n");
-    msg << wxT("Eliot\nCopyright Antoine Fraboulet 1999-2006\n\n");
-    msg << wxT("This program is free software; you can redistribute it and/or 
modify\n");
-    msg << wxT("it under the terms of the GNU General Public License as 
published by\n");
-    msg << wxT("the Free Software Foundation; either version 2 of the License, 
or\n");
-    msg << wxT("(at your option) any later version.\n\n");
-    msg << wxT("Version ") << wxT(VERSION) << wxT("\n");
-    wxMessageBox(msg, _("A propos d'Eliot"), wxICON_INFORMATION | wxOK);
+    msg.Printf(wxT("Eliot %s\n\n"), wxT(VERSION));
+    msg << wxT("Copyright (C) 1999-2007 - Antoine Fraboulet & Olivier 
Teuliere\n\n");
+    msg << _("This program is free software; you can redistribute it and/or 
modify " \
+             "it under the terms of the GNU General Public License as 
published by " \
+             "the Free Software Foundation; either version 2 of the License, 
or " \
+             "(at your option) any later version.");
+    wxMessageBox(msg, _("About Eliot"), wxICON_INFORMATION | wxOK);
 }
 
-void
-MainFrame::OnMenuQuitConfirm(wxCommandEvent& WXUNUSED(event))
-{
-    Close(TRUE);
-}
-
-
 
//**************************************************************************************
 // BUTTONS
 
//**************************************************************************************
@@ -837,33 +814,30 @@
            return;
        }
     
-    for(int i=0 ; i < MAX_FRAME_ID; i++)
-       {
-           if (auxframes_ptr[i] != NULL)
+    for (int i = 0 ; i < MAX_FRAME_ID; i++)
                {
                    debug("   delete frame %d\n",i);
                    delete auxframes_ptr[i];
                }
-       }
     
-    auxframes_ptr[ ID_Frame_Verif  ] = new VerifFrame (this, m_game->getDic());
+    auxframes_ptr[ID_Frame_Verif]  = new VerifFrame (this, m_game->getDic());
     debug("0 : Verif\n");
-    auxframes_ptr[ ID_Frame_Search ] = new SearchFrame(this, m_game->getDic());
+    auxframes_ptr[ID_Frame_Search] = new SearchFrame(this, m_game->getDic());
     debug("1 : Search\n");
-    auxframes_ptr[ ID_Frame_Plus1  ] = new Plus1Frame (this, m_game);
+    auxframes_ptr[ID_Frame_Plus1]  = new Plus1Frame (this, m_game);
     debug("2 : Plus1\n");
-    auxframes_ptr[ ID_Frame_Racc   ] = new RaccFrame  (this, m_game);
+    auxframes_ptr[ID_Frame_Racc]   = new RaccFrame  (this, m_game);
     debug("3 : Racc\n");
-    auxframes_ptr[ ID_Frame_Benj   ] = new BenjFrame  (this, m_game);
+    auxframes_ptr[ID_Frame_Benj]   = new BenjFrame  (this, m_game);
     debug("4 : Benj\n");
-    auxframes_ptr[ ID_Frame_Bag    ] = new BagFrame   (this, *m_game);
+    auxframes_ptr[ID_Frame_Bag]    = new BagFrame   (this, *m_game);
     debug("5 : Bag\n");
-    auxframes_ptr[ ID_Frame_Board  ] = new BoardFrame (this, *m_game);
+    auxframes_ptr[ID_Frame_Board]  = new BoardFrame (this, *m_game);
     debug("6 : Board\n");
-    auxframes_ptr[ ID_Frame_Game   ] = new GameFrame  (this, *m_game);
+    auxframes_ptr[ID_Frame_Game]   = new GameFrame  (this, *m_game);
     debug("7 : Game\n");
 #ifndef ENABLE_RESLIST_IN_MAIN
-    auxframes_ptr[ ID_Frame_Result ] = new ResultFrame(this, m_game);
+    auxframes_ptr[ID_Frame_Result] = new ResultFrame(this, m_game);
     debug("8 : Result\n");
 #endif
     
@@ -875,6 +849,19 @@
            debug("reload %d\n",i);
        }
     }
+
+    // Check the corresponding menu item if the window is visible
+    GetMenuBar()->Check(Menu_ShowVerif, 
auxframes_ptr[ID_Frame_Verif]->IsShown());
+    GetMenuBar()->Check(Menu_ShowSearch, 
auxframes_ptr[ID_Frame_Search]->IsShown());
+    GetMenuBar()->Check(Menu_ShowPlus1, 
auxframes_ptr[ID_Frame_Plus1]->IsShown());
+    GetMenuBar()->Check(Menu_ShowRacc, 
auxframes_ptr[ID_Frame_Racc]->IsShown());
+    GetMenuBar()->Check(Menu_ShowBenj, 
auxframes_ptr[ID_Frame_Benj]->IsShown());
+    GetMenuBar()->Check(Menu_ShowBag, auxframes_ptr[ID_Frame_Bag]->IsShown());
+    GetMenuBar()->Check(Menu_ShowBoard, 
auxframes_ptr[ID_Frame_Board]->IsShown());
+    GetMenuBar()->Check(Menu_ShowGame, 
auxframes_ptr[ID_Frame_Game]->IsShown());
+#ifndef ENABLE_RESLIST_IN_MAIN
+    GetMenuBar()->Check(Menu_ShowResult, 
auxframes_ptr[ID_Frame_Result]->IsShown());
+#endif
     debug("InitFrames end ok.\n");
 }
 
@@ -937,8 +924,8 @@
        if (m_game)
        {
            text = wxT("");
-           text << _("coup:") << (m_game->getHistory().getSize() + 1) << wxT(" 
");
-           text << _("points:") << (m_game->getCurrentPlayer().getPoints());
+            text << _("turn:") << wxT(" ") << (m_game->getHistory().getSize() 
+ 1) << wxT(" ");
+            text << _("points:") << wxT(" ") << 
(m_game->getCurrentPlayer().getPoints());
            statusbar->SetStatusText(text, 1);
        }
     }
@@ -957,13 +944,15 @@
 void
 MainFrame::SetRack(Game::set_rack_mode mode, wxString srack)
 {
-    int res = 0;
     wxString msg;
     bool check = config.getRackChecking();
 
+    if (m_game == NULL)
+    {
+        return;
+    }
     static_cast<Training*>(m_game)->removeTestPlay();
-    std::wstring str = srack.c_str();
-    res = static_cast<Training*>(m_game)->setRack(mode, check, str);
+    int res = static_cast<Training*>(m_game)->setRack(mode, check, 
srack.c_str());
 
     switch (res)
        {
@@ -971,20 +960,19 @@
            debug("SetRack Ok :: ");
            break;
         case 0x01:
-            msg = _("Le sac ne contient pas assez de lettres\npour assurer le 
tirage.");
-            wxMessageBox(msg, _("Correction du tirage"), wxICON_INFORMATION | 
wxOK);
+            msg = _("The bag doesn't contain enough letters\nfor a new rack.");
+            wxMessageBox(msg, _("Rack validation"), wxICON_ERROR | wxOK);
             return;
         case 0x02:
-            msg = _("Le tirage doit contenir au moins 2 consonnes et 2 
voyelles.\n");
-            wxMessageBox(msg, _("Correction du tirage"), wxICON_INFORMATION | 
wxOK);
+            msg = _("The rack must contain at least 2 consonants and 2 
vowels.");
+            wxMessageBox(msg, _("Rack validation"), wxICON_ERROR | wxOK);
             return;
         case 0x03:
-           msg  = _("Le tirage doit contenir au moins 2 consonnes et 2 
voyelles\n");
-           msg += _("mais le sac ne contient plus assez de lettres.\n\n");
-           wxMessageBox(msg, _("Correction du tirage"), wxICON_INFORMATION | 
wxOK);
+            msg = _("The rack contains invalid letters for the current 
dictionary");
+            wxMessageBox(msg, _("Rack validation"), wxICON_ERROR | wxOK);
             break;
        default:
-           statusbar->SetStatusText(_("Le tirage a ete modifie manuellement"), 
0);
+            statusbar->SetStatusText(_("The rack has been modified manually"), 
0);
            break;
        }
 
@@ -998,7 +986,7 @@
 void
 MainFrame::Search()
 {
-    if (m_game == NULL || m_game->getDic() == NULL)
+    if (m_game == NULL)
     {
         return;
     }
@@ -1030,7 +1018,7 @@
        }
     else
        {
-           int n=0;
+        int n = 0;
            debug("MainFrame::Play +%d\n",n);
 #ifdef ENABLE_RESLIST_IN_MAIN
            n = reslist->GetSelected();
@@ -1039,7 +1027,7 @@
 #endif
            if (n > -1)
                {
-                   ((Training*)m_game)->playResult(n);
+            static_cast<Training*>(m_game)->playResult(n);
                }
        }
     wxString r = 
wxU(m_game->getCurrentPlayer().getCurrentRack().toString().c_str());
@@ -1064,9 +1052,5 @@
 /****************************************************************/
 /****************************************************************/
 
-/// Local Variables:
-/// mode: c++
-/// mode: hs-minor
-/// c-basic-offset: 4
-/// indent-tabs-mode: nil
-/// End:
+/// Local Variables: / mode: c++ / mode: hs-minor / c-basic-offset: 4 /
+//indent-tabs-mode: nil / End:

Index: wxwin/mainframe.h
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/mainframe.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- wxwin/mainframe.h   1 Jan 2006 19:34:05 -0000       1.7
+++ wxwin/mainframe.h   8 Jan 2008 13:52:43 -0000       1.8
@@ -1,4 +1,4 @@
-/* Eliot                                                                     */
+// Joker game?* Eliot                                                          
           */
 /* Copyright (C) 1999  Antoine Fraboulet                                     */
 /* address@hidden                                                 */
 /*                                                                           */
@@ -34,7 +34,7 @@
 {
 private:
 
-    Dictionary  m_dic;
+    const Dictionary  *m_dic;
     Game        *m_game;
     ConfigDB    config;
     AuxFrame    *auxframes_ptr[MAX_FRAME_ID];
@@ -79,6 +79,7 @@
     void OnMenuGamePrint        (wxCommandEvent& event);
     void OnMenuGamePrintPreview (wxCommandEvent& event);
     void OnMenuGamePrintPS      (wxCommandEvent& event);
+    void OnMenuGameQuit         (wxCommandEvent& event);
 
     void OnMenuConfGameDic      (wxCommandEvent& event);
     void OnMenuConfGameSearch   (wxCommandEvent& event);
@@ -90,8 +91,7 @@
 
     void OnMenuShowFrame        (wxCommandEvent& event);
 
-    void OnMenuQuitApropos      (wxCommandEvent& event);
-    void OnMenuQuitConfirm      (wxCommandEvent& event);
+    void OnMenuHelpAbout        (wxCommandEvent& event);
 
     // *******
     // Buttons

Index: wxwin/printout.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/printout.cc,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- wxwin/printout.cc   4 Aug 2007 20:01:27 -0000       1.11
+++ wxwin/printout.cc   8 Jan 2008 13:52:43 -0000       1.12
@@ -176,14 +176,14 @@
     DIM(2);
     if ((numline > 0) && (numline <= NRounds))
     {
-        str = wxU(m_game.getHistory().getTurn(numline - 
1).getRound().getWord().c_str());
+        str = wxU(m_game.getHistory().getTurn(numline - 
1).getMove().getRound().getWord().c_str());
         DRW(2);
     }
     // pos
     DIM(3);
     if ((numline > 0) && (numline <= NRounds))
     {
-        str = wxU(m_game.getHistory().getTurn(numline - 
1).getRound().getCoord().toString().c_str());
+        str = wxU(m_game.getHistory().getTurn(numline - 
1).getMove().getRound().getCoord().toString().c_str());
         DRW(3);
     }
     // pts
@@ -191,7 +191,7 @@
     if ((numline > 0) && (numline <= NRounds))
     {
         str = wxT("");
-        str << m_game.getHistory().getTurn(numline - 1).getRound().getPoints();
+        str << m_game.getHistory().getTurn(numline - 
1).getMove().getRound().getPoints();
         DRW(4);
     }
     // total points

Index: wxwin/searchpanel.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/searchpanel.cc,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- wxwin/searchpanel.cc        22 Jan 2006 12:23:53 -0000      1.15
+++ wxwin/searchpanel.cc        8 Jan 2008 13:52:43 -0000       1.16
@@ -29,7 +29,6 @@
 
 #include "ewx.h"
 #include "dic.h"
-#include "dic_search.h"
 #include "regexp.h"
 #include "searchpanel.h"
 #include "tile.h"
@@ -55,7 +54,7 @@
 {
 protected:
   ConfigDB   config;
-  Dictionary dic;
+  const Dictionary *dic;
   wxTextCtrl *t;
   wxListBox  *l;
   wxBoxSizer *sizer;
@@ -65,9 +64,9 @@
   void panel_build();
   virtual void panel_options() = 0;
 public:
-  SimpleSearchPanel(wxWindow* parent, int id, Dictionary d) : 
wxPanel(parent,id) { dic = d; };
-  virtual void compute_char(wxCommandEvent&) {};
-  virtual void compute_enter(wxCommandEvent&) {};
+  SimpleSearchPanel(wxWindow* parent, int id, const Dictionary &d) : 
wxPanel(parent,id) { dic = &d; }
+  virtual void compute_char(wxCommandEvent&) {}
+  virtual void compute_enter(wxCommandEvent&) {}
   DECLARE_EVENT_TABLE()
 };
 
@@ -105,7 +104,7 @@
   if (dic == NULL)
     {
       l->Clear();
-      msg << wxT("Pas de dictionnaire");
+      msg << _("No dictionary");
       l->Append(msg);
       return 0;
     }
@@ -117,7 +116,7 @@
 {
   if (l->GetCount() == 0)
     {
-      l->Append(wxT("Aucun resultat"));
+      l->Append(_("No result"));
     }
 }
 
@@ -128,40 +127,40 @@
 class PCross : public SimpleSearchPanel
 {
 protected:
-  virtual void panel_options() {};
+  virtual void panel_options() {}
 public:
-  void compute_char(wxCommandEvent&) { };
+  void compute_char(wxCommandEvent&) {}
   void compute_enter(wxCommandEvent&);
-  PCross(wxWindow* parent, int id, Dictionary d) : 
SimpleSearchPanel(parent,id,d) { panel_build(); };
+  PCross(wxWindow* parent, int id, const Dictionary &d) : 
SimpleSearchPanel(parent,id,d) { panel_build(); }
 };
 
 void
 PCross::compute_enter(wxCommandEvent&)
 {
-  int  i;
-  wchar_t rack[DIC_WORD_MAX];
-  wchar_t buff[RES_CROS_MAX][DIC_WORD_MAX];
-
   if (!check_dic())
     return;
 
   if (t->GetValue().Len() >= DIC_WORD_MAX)
     {
-      wxString msg = wxT("");
-// XXX:      msg << wxT("La recherche est limitée à ") << DIC_WORD_MAX - 1 << 
wxT(" lettres");
-      msg << wxT("La recherche est limitee a ") << DIC_WORD_MAX - 1 << wxT(" 
lettres");
+        wxString msg;
+        msg.Printf(_("The search is limited to %d letters"), DIC_WORD_MAX - 1);
       l->Append(msg);
       return;
     }
 
+    wchar_t rack[DIC_WORD_MAX];
   wcsncpy(rack, t->GetValue().wc_str(), DIC_WORD_MAX);
-  Dic_search_Cros(dic,rack,buff);
+
+    list<wstring> wordList;
+    dic->searchCross(rack, wordList);
 
   int resnum = 0;
-  wxString res[RES_CROS_MAX];
-  for(i=0; i < RES_CROS_MAX && buff[i][0]; i++)
-    res[resnum++] =  wxU(buff[i]);
+    wxString *res = new wxString[wordList.size()];
+    list<wstring>::const_iterator it;
+    for (it = wordList.begin(); it != wordList.end(); it++)
+        res[resnum++] =  wxU(it->c_str());
   l->Set(resnum,res);
+    delete[] res;
   check_end();
 }
 
@@ -172,45 +171,55 @@
 class PPlus1 : public SimpleSearchPanel
 {
 protected:
-  virtual void panel_options() {};
+  virtual void panel_options() {}
 public:
-  void compute_char(wxCommandEvent&) { };
+  void compute_char(wxCommandEvent&) {}
   void compute_enter(wxCommandEvent&);
-  PPlus1(wxWindow* parent, int id, Dictionary dic) : 
SimpleSearchPanel(parent,id,dic) { panel_build(); };
+  PPlus1(wxWindow* parent, int id, const Dictionary &dic) : 
SimpleSearchPanel(parent,id,dic) { panel_build(); }
 };
 
 void
 PPlus1::compute_enter(wxCommandEvent&)
 {
-  int  i,j;
-  wchar_t rack[DIC_WORD_MAX];
-  wchar_t buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX];
-
   if (!check_dic())
     return;
 
   if (t->GetValue().Len() >= DIC_WORD_MAX)
     {
-      wxString msg = wxT("");
-// XXX:      msg << wxT("La recherche est limitée à ") << DIC_WORD_MAX - 1 << 
wxT(" lettres");
-      msg << wxT("La recherche est limitee a ") << DIC_WORD_MAX - 1 << wxT(" 
lettres");
+        wxString msg;
+        msg.Printf(_("The search is limited to %d letters"), DIC_WORD_MAX - 1);
       l->Append(msg);
       return;
     }
 
-  wcsncpy(rack, t->GetValue().wc_str(), DIC_WORD_MAX);
-  Dic_search_7pl1(dic,rack,buff,TRUE);
+    wstring rack = t->GetValue().wc_str();
+    map<wchar_t, list<wstring> > wordList;
+    dic->search7pl1(rack, wordList, true);
 
+    // Count the results
+    int sum = 0;
+    map<wchar_t, list<wstring> >::const_iterator it;
+    for (it = wordList.begin(); it != wordList.end(); it++)
+    {
+        if (it->first)
+            sum += 1;
+        sum += it->second.size();
+    }
+
+    wxString *res = new wxString[sum];
   int resnum = 0;
-  wxString res[DIC_LETTERS*(RES_7PL1_MAX+1)];
-  for(i=0; i < DIC_LETTERS; i++)
+    for (it = wordList.begin(); it != wordList.end(); it++)
+    {
+        if (it->first)
+            res[resnum++] = wxString(wxT("+")) + wxU((wxString)it->first);
+        list<wstring>::const_iterator itWord;
+        for (itWord = it->second.begin(); itWord != it->second.end(); itWord++)
     {
-      if (i && buff[i][0][0])
-          res[resnum++] = wxString(wxT("+")) + (wxChar)(i+'A'-1);
-      for(j=0; j < RES_7PL1_MAX && buff[i][j][0]; j++)
-          res[resnum++] = wxString(wxT("  ")) + wxU(buff[i][j]);
+            res[resnum++] = wxString(wxT("  ")) + wxU(itWord->c_str());
     }
-  l->Set(resnum,res);
+    }
+    l->Set(resnum, res);
+    delete[] res;
   check_end();
 }
 
@@ -228,9 +237,9 @@
   virtual void build_letter_lists();
   virtual void panel_options();
 public:
-  void compute_char(wxCommandEvent&) { };
+  void compute_char(wxCommandEvent&) {}
   void compute_enter(wxCommandEvent&);
-  PRegExp(wxWindow* parent, int id, Dictionary d) : 
SimpleSearchPanel(parent,id,d) { panel_build(); };
+  PRegExp(wxWindow* parent, int id, const Dictionary &d) : 
SimpleSearchPanel(parent,id,d) { panel_build(); }
 };
 
 void
@@ -261,8 +270,8 @@
       memset(llist.letters[i],0,sizeof(llist.letters[i]));
     }
 
-  const std::list<Tile>& allTiles = Tile::getAllTiles();
-  std::list<Tile>::const_iterator it;
+  const std::vector<Tile>& allTiles = dic->getAllTiles();
+  std::vector<Tile>::const_iterator it;
   for (it = allTiles.begin(); it != allTiles.end(); it++)
     {
       if (! it->isJoker() && ! it->isEmpty())
@@ -289,9 +298,9 @@
   wxStaticText *otmin;
   wxStaticText *otmax;
 
-  otmin = new wxStaticText(this,wxID_ANY,wxT("Longueur min."));
-  omin  = new wxTextCtrl(this,ID_OPTION1,wxT( 
"1"),wxDefaultPosition,wxDefaultSize,wxTE_PROCESS_ENTER);
-  otmax = new wxStaticText(this,wxID_ANY,wxT("max."));
+  otmin = new wxStaticText(this,wxID_ANY,_("Minimum length"));
+  omin  = new 
wxTextCtrl(this,ID_OPTION1,wxT("1"),wxDefaultPosition,wxDefaultSize,wxTE_PROCESS_ENTER);
+  otmax = new wxStaticText(this,wxID_ANY,_("Maximum length"));
   omax  = new 
wxTextCtrl(this,ID_OPTION2,wxT("15"),wxDefaultPosition,wxDefaultSize,wxTE_PROCESS_ENTER);
 
   wxBoxSizer *s = new wxBoxSizer( wxHORIZONTAL );
@@ -308,15 +317,13 @@
 void
 PRegExp::compute_enter(wxCommandEvent&)
 {
-  wchar_t re[DIC_RE_MAX];
-  wchar_t buff[RES_REGE_MAX][DIC_WORD_MAX];
-
   if (!check_dic())
     return;
 
   build_letter_lists();
-  wcsncpy(re, t->GetValue().wc_str(),DIC_RE_MAX);
-  debug("PRegExp::compute_enter for %ls",re);
+
+    wstring regexp = t->GetValue().wc_str();
+    debug("PRegExp::compute_enter for %ls", regexp.c_str());
 
   int lmin = atoi((const char*)omin->GetValue().mb_str());
   int lmax = atoi((const char*)omax->GetValue().mb_str());
@@ -334,14 +341,18 @@
     }
   debug("\n");
 
-  Dic_search_RegE(dic,re,buff,&llist);
+    list<wstring> wordList;
+    dic->searchRegExp(regexp, wordList, &llist);
 
+    wxString *res = new wxString[wordList.size()];
   int resnum = 0;
-  wxString res[RES_REGE_MAX];
-  for(int i=0; i < RES_REGE_MAX && buff[i][0]; i++)
-    res[resnum++] =  wxU(buff[i]);
-
+    list<wstring>::const_iterator it;
+    for (it = wordList.begin(); it != wordList.end(); it++)
+    {
+        res[resnum++] =  wxU(it->c_str());
+    }
   l->Set(resnum,res);
+    delete[] res;
   check_end();
 }
 
@@ -349,12 +360,12 @@
 // ************************************************************
 // ************************************************************
 
-SearchPanel::SearchPanel(wxFrame *parent, Dictionary dic) :
+SearchPanel::SearchPanel(wxFrame *parent, const Dictionary &dic) :
   wxNotebook(parent, -1)
 {
-  AddPage(new PCross (this,ID_PANEL_CROSS ,dic),wxT("Mots croises"));
-  AddPage(new PPlus1 (this,ID_PANEL_PLUS1 ,dic),wxT("Plus 1"));
-  AddPage(new PRegExp(this,ID_PANEL_REGEXP,dic),wxT("Exp. Rationnelle"));
+  AddPage(new PCross (this,ID_PANEL_CROSS ,dic), _("Cross words"));
+  AddPage(new PPlus1 (this,ID_PANEL_PLUS1 ,dic), _("Plus 1"));
+  AddPage(new PRegExp(this,ID_PANEL_REGEXP,dic), _("Regular expressions"));
   SetSelection(2);
 }
 

Index: wxwin/searchpanel.h
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/searchpanel.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- wxwin/searchpanel.h 26 Dec 2005 12:23:17 -0000      1.4
+++ wxwin/searchpanel.h 8 Jan 2008 13:52:43 -0000       1.5
@@ -33,7 +33,7 @@
 class SearchPanel : public wxNotebook
 {
  public:
-  SearchPanel(wxFrame*, Dictionary);
+  SearchPanel(wxFrame*, const Dictionary&);
   ~SearchPanel();
 };
 

Index: dic/automaton.cpp
===================================================================
RCS file: dic/automaton.cpp
diff -N dic/automaton.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/automaton.cpp   8 Jan 2008 13:52:33 -0000       1.2
@@ -0,0 +1,603 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+/**
+ *  \file   automaton.c
+ *  \brief  (Non)Deterministic Finite AutomatonHelper for Regexp
+ *  \author Antoine Fraboulet
+ *  \date   2005
+ */
+
+#include "config.h"
+
+#include <set>
+#include <list>
+#include <cassert>
+#include <cstring>
+#include <cstdlib>
+#include <cstdio>
+#include <sys/types.h>
+#ifdef HAVE_SYS_WAIT_H
+#   include <sys/wait.h>
+#endif
+#include <unistd.h>
+
+#include "dic.h"
+#include "regexp.h"
+#include "automaton.h"
+
+using namespace std;
+
+#ifdef DEBUG_AUTOMATON
+#   define DMSG(a) (a)
+#else
+#   define DMSG(a)
+#endif
+
+#define MAX_TRANSITION_LETTERS 256
+
+typedef struct automaton_state_t *astate;
+
+
+/* ************************************************** *
+   Helper class, allowing to build a NFA, then a DFA
+ * ************************************************** */
+
+class AutomatonHelper
+{
+public:
+    AutomatonHelper(astate iInitState);
+    ~AutomatonHelper();
+
+    astate getInitState() const { return m_initState; }
+#ifdef DEBUG_AUTOMATON
+    void dump(const string &iFileName) const;
+#endif
+
+    static AutomatonHelper *ps2nfa(int iInitState, int *ptl, int *PS);
+    static AutomatonHelper *nfa2dfa(const AutomatonHelper &iNfa,
+                                    struct search_RegE_list_t *iList);
+
+    /// List of states
+    list<astate> m_states;
+
+private:
+    /// Initial state of the automaton
+    astate m_initState;
+
+    void addState(astate s);
+    astate getState(const set<int> &iId) const;
+    void printNodes(FILE* f) const;
+    void printEdges(FILE* f) const;
+    void setAccept(astate s) const;
+    set<int> getSuccessor(const set<int> &S, int letter, struct 
search_RegE_list_t *iList) const;
+};
+
+
+/* ************************************************** *
+   State handling
+ * ************************************************** */
+
+static set<int> s_state_id_create(int id);
+static string   s_state_id_to_str(const set<int> &iId);
+static astate   s_state_create   (const set<int> &iId);
+
+struct automaton_state_t
+{
+    set<int> id;
+    int      accept;
+    int      id_static;
+    astate   next[MAX_TRANSITION_LETTERS];
+};
+
+
+/* ************************************************** *
+   Definition of the Automaton class
+ * ************************************************** */
+
+Automaton::Automaton(int iInitState, int *ptl, int *PS, struct 
search_RegE_list_t *iList)
+{
+    AutomatonHelper *nfa = AutomatonHelper::ps2nfa(iInitState, ptl, PS);
+    DMSG(printf("\n non deterministic automaton OK \n\n"));
+    DMSG(nfa->dump("auto_nfa"));
+
+    AutomatonHelper *dfa = AutomatonHelper::nfa2dfa(*nfa, iList);
+    DMSG(printf("\n deterministic automaton OK \n\n"));
+    DMSG(dfa->dump("auto_dfa"));
+
+    finalize(*dfa);
+    DMSG(printf("\n final automaton OK \n\n"));
+    DMSG(automaton_dump("auto_fin"));
+
+    delete nfa;
+    delete dfa;
+}
+
+
+Automaton::~Automaton()
+{
+    delete[] m_acceptors;
+    for (int i = 0; i <= m_nbStates; i++)
+    {
+        delete[] m_transitions[i];
+    }
+    delete[] m_transitions;
+}
+
+
+void Automaton::finalize(const AutomatonHelper &iHelper)
+{
+    /* Creation */
+    m_nbStates = iHelper.m_states.size();
+    m_acceptors = new bool[m_nbStates + 1];
+    memset(m_acceptors, 0, (m_nbStates + 1) * sizeof(bool));
+    m_transitions = new int*[m_nbStates + 1];
+    for (int i = 0; i <= m_nbStates; i++)
+    {
+        m_transitions[i] = new int[MAX_TRANSITION_LETTERS];
+        memset(m_transitions[i], 0, MAX_TRANSITION_LETTERS * sizeof(int));
+    }
+
+    /* Create new id for states */
+    list<astate>::const_iterator it;
+    int i;
+    for (i = 1, it = iHelper.m_states.begin();
+         it != iHelper.m_states.end(); it++, i++)
+    {
+        (*it)->id_static = i;
+    }
+
+    /* Build new automaton */
+    for (it = iHelper.m_states.begin(); it != iHelper.m_states.end(); it++)
+    {
+        astate s = *it;
+        int i = s->id_static;
+
+        if (s == iHelper.getInitState())
+            m_init = i;
+        if (s->accept == 1)
+            m_acceptors[i] = true;
+
+        for (int l = 0; l < MAX_TRANSITION_LETTERS; l++)
+        {
+            if (s->next[l])
+                m_transitions[i][l] = s->next[l]->id_static;
+        }
+    }
+}
+
+
+void Automaton::dump(const string &iFileName) const
+{
+    FILE *f = fopen(iFileName.c_str(), "w");
+    fprintf(f, "digraph automaton {\n");
+    for (int i = 1; i <= m_nbStates; i++)
+    {
+        fprintf(f, "\t%d [label = \"%d\"", i, i);
+        if (i == m_init)
+            fprintf(f, ", style = filled, color=lightgrey");
+        if (accept(i))
+            fprintf(f, ", shape = doublecircle");
+        fprintf(f, "];\n");
+    }
+    fprintf(f, "\n");
+    for (int i = 1; i <= m_nbStates; i++)
+    {
+        for (int l = 0; l < MAX_TRANSITION_LETTERS; l++)
+        {
+            if (m_transitions[i][l])
+            {
+                fprintf(f, "\t%d -> %d [label = \"", i, m_transitions[i][l]);
+                regexp_print_letter(f, l);
+                fprintf(f, "\"];\n");
+            }
+        }
+    }
+    fprintf(f, "fontsize=20;\n");
+    fprintf(f, "}\n");
+    fclose(f);
+
+#ifdef HAVE_SYS_WAIT_H
+    pid_t pid = fork ();
+    if (pid > 0)
+    {
+        wait(NULL);
+    }
+    else if (pid == 0)
+    {
+        execlp("dotty", "dotty", iFileName.c_str(), NULL);
+        printf("exec dotty failed\n");
+        exit(1);
+    }
+#endif
+}
+
+
+/* ************************************************** *
+   Definition of the state handling methods
+ * ************************************************** */
+
+static set<int> s_state_id_create(int id)
+{
+    set<int> l;
+    l.insert(id);
+    return l;
+}
+
+
+static string s_state_id_to_str(const set<int> &iId)
+{
+    string s;
+    set<int>::const_iterator it;
+    for (it = iId.begin(); it != iId.end(); it++)
+    {
+        char tmp[50];
+        sprintf(tmp, "%d ", *it);
+        s += tmp;
+    }
+    return s;
+}
+
+
+static astate s_state_create(const set<int> &iId)
+{
+    astate s = new automaton_state_t();
+    // TODO: use copy constructor
+    s->id      = iId;
+    s->accept  = 0;
+    memset(s->next, 0, sizeof(astate)*MAX_TRANSITION_LETTERS);
+    DMSG(printf("** state %s creation\n", s_state_id_to_str(iId).c_str()));
+    return s;
+}
+
+
+/* ************************************************** *
+   Definition of the AutomatonHelper class
+ * ************************************************** */
+
+AutomatonHelper::AutomatonHelper(astate iInitState)
+    : m_initState(iInitState)
+{
+}
+
+
+AutomatonHelper::~AutomatonHelper()
+{
+    list<astate>::const_iterator it;
+    for (it = m_states.begin(); it != m_states.end(); it++)
+    {
+        delete *it;
+    }
+}
+
+
+void AutomatonHelper::addState(astate s)
+{
+    m_states.push_front(s);
+    DMSG(printf("** state %s added to automaton\n", 
s_state_id_to_str(s->id).c_str()));
+}
+
+
+astate AutomatonHelper::getState(const set<int> &iId) const
+{
+    list<astate>::const_iterator it;
+    for (it = m_states.begin(); it != m_states.end(); it++)
+    {
+        astate s = *it;
+        if (s->id == iId)
+        {
+            //DMSG(printf("** get state %s ok\n", 
s_state_id_to_str(s->id).c_str()));
+            return s;
+        }
+    }
+    return NULL;
+}
+
+/* ************************************************** *
+ * ************************************************** *
+ * ************************************************** */
+
+AutomatonHelper *AutomatonHelper::ps2nfa(int init_state_id, int *ptl, int *PS)
+{
+    int maxpos = PS[0];
+    astate current_state;
+    char used_letter[MAX_TRANSITION_LETTERS];
+
+
+    /* 1: init_state = root->PP */
+    set<int> temp_id0 = s_state_id_create(init_state_id);
+    astate temp_state = s_state_create(temp_id0);
+    AutomatonHelper *nfa = new AutomatonHelper(temp_state);
+    nfa->addState(temp_state);
+    list<astate> L;
+    L.push_front(temp_state);
+    /* 2: while \exist state \in state_list */
+    while (! L.empty())
+    {
+        current_state = L.front();
+        L.pop_front();
+        DMSG(printf("** current state = %s\n", 
s_state_id_to_str(current_state->id).c_str()));
+        memset(used_letter, 0, sizeof(used_letter));
+        /* 3: \foreach l in \sigma | l \neq # */
+        for (int p = 1; p < maxpos; p++)
+        {
+            int current_letter = ptl[p];
+            if (used_letter[current_letter] == 0)
+            {
+                /* 4: int set = \cup { PS(pos) | pos \in state \wedge pos == l 
} */
+                int ens = 0;
+                for (int pos = 1; pos <= maxpos; pos++)
+                {
+                    if (ptl[pos] == current_letter &&
+                        (unsigned int)*(current_state->id.begin()) & (1 << 
(pos - 1)))
+                        ens |= PS[pos];
+                }
+                /* 5: transition from current_state to temp_state */
+                if (ens)
+                {
+                    set<int> temp_id = s_state_id_create(ens);
+                    temp_state = nfa->getState(temp_id);
+                    if (temp_state == NULL)
+                    {
+                        temp_state = s_state_create(temp_id);
+                        nfa->addState(temp_state);
+                        current_state->next[current_letter] = temp_state;
+                        L.push_front(temp_state);
+                    }
+                    else
+                    {
+                        current_state->next[current_letter] = temp_state;
+                    }
+                }
+                used_letter[current_letter] = 1;
+            }
+        }
+    }
+
+    list<astate>::const_iterator it;
+    for (it = nfa->m_states.begin(); it != nfa->m_states.end(); it++)
+    {
+        astate s = *it;
+        if (*(s->id.begin()) & (1 << (maxpos - 1)))
+            s->accept = 1;
+    }
+
+    return nfa;
+}
+
+/* ************************************************** *
+ * ************************************************** *
+ * ************************************************** */
+
+set<int> AutomatonHelper::getSuccessor(const set<int> &S,
+                                       int letter,
+                                       struct search_RegE_list_t *iList) const
+{
+    set<int> R, r;
+    set<int>::const_iterator it;
+    for (it = S.begin(); it != S.end(); it++)                /* \forall y \in 
S */
+    {
+        astate y, z;
+
+        set<int> t = s_state_id_create(*it);
+        assert(y = getState(t));
+
+        set<int> Ry;                                        /* Ry = \empty     
        */
+
+        if ((z = y->next[letter]) != NULL)                   /* \delta (y,z) = 
l        */
+        {
+            r = getSuccessor(z->id, RE_EPSILON, iList);
+            Ry.insert(r.begin(), r.end());
+            Ry.insert(z->id.begin(), z->id.end()); /* Ry = Ry \cup succ(z)    
*/
+        }
+
+        /* \epsilon transition from start node */
+        if ((z = y->next[RE_EPSILON]) != NULL)               /* \delta (y,z) = 
\epsilon */
+        {
+            r = getSuccessor(z->id, letter, iList);
+            Ry.insert(r.begin(), r.end());       /* Ry = Ry \cup succ(z)    */
+        }
+
+        if (letter < RE_FINAL_TOK)
+        {
+            for (int i = 0; i < DIC_SEARCH_REGE_LIST; i++)
+            {
+                if (iList->valid[i])
+                {
+                    if (iList->letters[i][letter] && (z = 
y->next[(int)iList->symbl[i]]) != NULL)
+                    {
+                        DMSG(printf("*** letter "));
+                        DMSG(regexp_print_letter(stdout, letter));
+                        DMSG(printf("is in "));
+                        DMSG(regexp_print_letter(stdout, i));
+
+                        r = getSuccessor(z->id, RE_EPSILON, iList);
+                        Ry.insert(r.begin(), r.end());
+                        Ry.insert(z->id.begin(), z->id.end());
+                    }
+                }
+            }
+        }
+
+#if 0
+        if (alist_is_empty(Ry))                              /* Ry = \empty    
         */
+            return Ry;
+#endif
+
+        R.insert(Ry.begin(), Ry.end());                      /* R = R \cup Ry  
         */
+    }
+
+    return R;
+}
+
+
+void AutomatonHelper::setAccept(astate s) const
+{
+    DMSG(printf("=== setting accept for node (%s) :", 
s_state_id_to_str(s->id).c_str()));
+    list<astate>::const_iterator it;
+    for (it = m_states.begin(); it != m_states.end(); it++)
+    {
+        astate ns = *it;
+        int idx = *(ns->id.begin());
+        DMSG(printf("%s ", s_state_id_to_str(ns->id).c_str()));
+        if (ns->accept && (find(s->id.begin(), s->id.end(), idx) != 
s->id.end()))
+        {
+            DMSG(printf("(ok) "));
+            s->accept = 1;
+        }
+    }
+    DMSG(printf("\n"));
+}
+
+
+AutomatonHelper *AutomatonHelper::nfa2dfa(const AutomatonHelper &iNfa,
+                                          struct search_RegE_list_t *iList)
+{
+    astate current_state;
+
+    list<astate> L;
+
+    // Clone the list
+    set<int> temp_id0 = iNfa.m_initState->id;
+    astate temp_state = s_state_create(temp_id0);
+    AutomatonHelper *dfa = new AutomatonHelper(temp_state);
+    dfa->addState(temp_state);
+    L.push_front(temp_state);
+    while (! L.empty())
+    {
+        current_state = L.front();
+        L.pop_front();
+        DMSG(printf("** current state = %s\n", 
s_state_id_to_str(current_state->id).c_str()));
+        for (int letter = 1; letter < DIC_LETTERS; letter++)
+        {
+            // DMSG(printf("*** start successor of %s\n", 
s_state_id_to_str(current_state->id).c_str()));
+
+            set<int> temp_id = iNfa.getSuccessor(current_state->id, letter, 
iList);
+
+            if (! temp_id.empty())
+            {
+
+                DMSG(printf("*** successor of %s for ", 
s_state_id_to_str(current_state->id).c_str()));
+                DMSG(regexp_print_letter(stdout, letter));
+                DMSG(printf(" = %s\n", s_state_id_to_str(temp_id).c_str()));
+
+                temp_state = dfa->getState(temp_id);
+
+                // DMSG(printf("*** automaton get state -%s- ok\n", 
s_state_id_to_str(temp_id).c_str()));
+
+                if (temp_state == NULL)
+                {
+                    temp_state = s_state_create(temp_id);
+                    dfa->addState(temp_state);
+                    current_state->next[letter] = temp_state;
+                    L.push_front(temp_state);
+                }
+                else
+                {
+                    current_state->next[letter] = temp_state;
+                }
+            }
+        }
+    }
+
+    list<astate>::const_iterator it;
+    for (it = dfa->m_states.begin(); it != dfa->m_states.end(); it++)
+    {
+        iNfa.setAccept(*it);
+    }
+
+    return dfa;
+}
+
+/* ************************************************** *
+ * ************************************************** *
+ * ************************************************** */
+
+void AutomatonHelper::printNodes(FILE* f) const
+{
+    list<astate>::const_iterator it;
+    for (it = m_states.begin(); it != m_states.end(); it++)
+    {
+        astate s = *it;
+        string sid = s_state_id_to_str(s->id);
+        fprintf(f, "\t\"%s\" [label = \"%s\"", sid.c_str(), sid.c_str());
+        if (s == m_initState)
+        {
+            fprintf(f, ", style = filled, color=lightgrey");
+        }
+        if (s->accept)
+        {
+            fprintf(f, ", shape = doublecircle");
+        }
+        fprintf(f, "];\n");
+    }
+    fprintf(f, "\n");
+}
+
+
+void AutomatonHelper::printEdges(FILE* f) const
+{
+    list<astate>::const_iterator it;
+    for (it = m_states.begin(); it != m_states.end(); it++)
+    {
+        astate s = *it;
+        for (int letter = 0; letter < 255; letter++)
+        {
+            if (s->next[letter])
+            {
+                string sid = s_state_id_to_str(s->id);
+                fprintf(f, "\t\"%s\" -> ", sid.c_str());
+                sid = s_state_id_to_str(s->next[letter]->id);
+                fprintf(f, "\"%s\" [label = \"", sid.c_str());
+                regexp_print_letter(f, letter);
+                fprintf(f, "\"];\n");
+            }
+        }
+    }
+}
+
+
+#ifdef DEBUG_AUTOMATON
+void AutomatonHelper::dump(const string &iFileName) const
+{
+    FILE *f = fopen(iFileName.c_str(), "w");
+    fprintf(f, "digraph automaton {\n");
+    printNodes(f);
+    printEdges(f);
+    fprintf(f, "fontsize=20;\n");
+    fprintf(f, "}\n");
+    fclose(f);
+
+#ifdef HAVE_SYS_WAIT_H
+    pid_t pid = fork();
+    if (pid > 0)
+    {
+        wait(NULL);
+    }
+    else if (pid == 0)
+    {
+        execlp("dotty", "dotty", iFileName.c_str(), NULL);
+        printf("exec dotty failed\n");
+        exit(1);
+    }
+#endif
+}
+#endif
+

Index: dic/compdic.cpp
===================================================================
RCS file: dic/compdic.cpp
diff -N dic/compdic.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/compdic.cpp     8 Jan 2008 13:52:33 -0000       1.2
@@ -0,0 +1,563 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+/**
+ *  \file   compdic.c
+ *  \brief  Program used to compress a dictionary
+ *  \author Antoine Fraboulet
+ *  \date   1999
+ */
+
+#include "config.h"
+
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <vector>
+#include <map>
+#include <boost/tokenizer.hpp>
+#include <getopt.h>
+#include <ctime>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <cwctype>
+#include <cstdlib>
+#include <cstdio>
+#include <cerrno>
+#include <cstring>
+
+// For ntohl & Co.
+#ifdef WIN32
+#   include <winsock2.h>
+#else
+#    if HAVE_NETINET_IN_H
+#       include <netinet/in.h>
+#    endif
+#    if HAVE_ARPA_INET_H
+#       include <arpa/inet.h>
+#    endif
+#endif
+
+#if ENABLE_NLS
+#   include <libintl.h>
+#   define _(String) gettext(String)
+#else
+#   define _(String) String
+#endif
+
+#include "hashtable.h"
+#include "encoding.h"
+#include "header.h"
+#include "dic_internals.h"
+#include "dic_exception.h"
+
+using namespace std;
+
+//#define DEBUG_LIST
+//#define DEBUG_OUTPUT
+//#define DEBUG_OUTPUT_L2
+#define CHECK_RECURSION
+
+
+const wchar_t* load_uncompressed(const string &iFileName, unsigned int 
&ioDicSize)
+{
+    ifstream file(iFileName.c_str());
+    if (!file.is_open())
+        throw DicException("Could not open file " + iFileName);
+
+    // Place the buffer in a vector to avoid worrying about memory handling
+    vector<char> buffer(ioDicSize);
+    // Load the file data, everything in one shot
+    file.read(&buffer.front(), ioDicSize);
+    file.close();
+
+    // Buffer for the wide characters (it will use at most as many characters
+    // as the utf-8 version)
+    wchar_t *wideBuf = new wchar_t[ioDicSize];
+    unsigned int number;
+
+    try
+    {
+        number = readFromUTF8(wideBuf, ioDicSize, &buffer.front(),
+                              ioDicSize, "load_uncompressed");
+        ioDicSize = number;
+        return wideBuf;
+    }
+    catch (...)
+    {
+        // Avoid leaks, and propagate the exception
+        delete[] wideBuf;
+        throw;
+    }
+}
+
+
+void readLetters(const char *iFileName, DictHeaderInfo &ioHeaderInfo)
+{
+    ifstream in(iFileName);
+    if (!in.is_open())
+        throw DicException("Could not open file " + string(iFileName));
+
+    // Use a more friendly type name
+    typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
+
+    int lineNb = 1;
+    string line;
+    while (getline(in, line))
+    {
+        // Split the lines on space characters
+        vector<string> tokens;
+        boost::char_separator<char> sep(" ");
+        Tokenizer tok(line, sep);
+        Tokenizer::iterator it;
+        for (it = tok.begin(); it != tok.end(); ++it)
+        {
+            tokens.push_back(*it);
+        }
+
+        // Ignore empty lines
+        if (tokens.empty())
+            continue;
+
+        // We expect 5 fields on the line, and the first one is a letter, so
+        // it cannot exceed 4 bytes
+        if (tokens.size() != 5 || tokens[0].size() > 4)
+        {
+            ostringstream ss;
+            ss << "readLetters: Invalid line in " << iFileName;
+            ss << " (line " << lineNb;
+            throw DicException(ss.str());
+        }
+
+#define MAX_SIZE 4
+        char buff[MAX_SIZE];
+        strncpy(buff, tokens[0].c_str(), MAX_SIZE);
+
+        wstring letter = readFromUTF8(buff, tokens[0].size(), "readLetters");
+
+        if (letter.size() != 1)
+        {
+            ostringstream ss;
+            ss << "readLetters: Invalid letter at line " << lineNb;
+            throw DicException(ss.str());
+        }
+#undef MAX_SIZE
+
+        ioHeaderInfo.letters += towupper(letter[0]);
+
+        ioHeaderInfo.points.push_back(atoi(tokens[1].c_str()));
+        ioHeaderInfo.frequency.push_back(atoi(tokens[2].c_str()));
+        ioHeaderInfo.vowels.push_back(atoi(tokens[3].c_str()));
+        ioHeaderInfo.consonants.push_back(atoi(tokens[4].c_str()));
+
+        ++lineNb;
+    }
+}
+
+
+Header skip_init_header(ostream &outfile, DictHeaderInfo &ioHeaderInfo)
+{
+    ioHeaderInfo.root       = 0;
+    ioHeaderInfo.nwords     = 0;
+    ioHeaderInfo.nodesused  = 1;
+    ioHeaderInfo.edgesused  = 1;
+    ioHeaderInfo.nodessaved = 0;
+    ioHeaderInfo.edgessaved = 0;
+
+    Header aHeader(ioHeaderInfo);
+    aHeader.write(outfile);
+    return aHeader;
+}
+
+
+void fix_header(ostream &outfile, DictHeaderInfo &ioHeaderInfo)
+{
+    ioHeaderInfo.root = ioHeaderInfo.edgesused;
+    // Go back to the beginning of the stream to overwrite the header
+    outfile.seekp(0, ios::beg);
+#if defined(WORDS_BIGENDIAN)
+#warning "**********************************************"
+#warning "compdic does not run yet on bigendian machines"
+#warning "**********************************************"
+#else
+    Header aHeader(ioHeaderInfo);
+    aHeader.write(outfile);
+#endif
+}
+
+
+// Change endianness of the pointes edges, and write them to the given ostream
+void write_node(uint32_t *ioEdges, unsigned int num, ostream &outfile)
+{
+    // Handle endianness
+    for (unsigned int i = 0; i < num; ++i)
+    {
+        ioEdges[i] = htonl(ioEdges[i]);
+    }
+
+#ifdef DEBUG_OUTPUT
+    printf("writing %d edges\n", num);
+    for (int i = 0; i < num; i++)
+    {
+#ifdef DEBUG_OUTPUT_L2
+        printf("ptr=%2d t=%d l=%d chr=%2d (%c)\n",
+               ioEdges[i].ptr, ioEdges[i].term, ioEdges[i].last,
+               ioEdges[i].chr, ioEdges[i].chr -1 +'a');
+#endif
+        outfile.write((char*)(ioEdges + i), sizeof(DicEdge));
+    }
+#else
+    outfile.write((char*)ioEdges, num * sizeof(DicEdge));
+#endif
+}
+
+#define MAX_STRING_LENGTH 200
+
+
+#define MAX_EDGES 2000
+/* ods3: ??   */
+/* ods4: 1746 */
+
+// Hashing function for a vector of DicEdge, based on the hashing function
+// of the HashTable
+struct HashVector
+{
+    unsigned int operator()(const vector<DicEdge> &iKey) const
+    {
+        if (iKey.empty())
+            return 0;
+        return HashPtr(&iKey.front(), iKey.size() * sizeof(DicEdge));
+    }
+};
+
+#ifdef CHECK_RECURSION
+class IncDec
+{
+    public:
+        IncDec(int &ioCounter)
+            : m_counter(ioCounter)
+        {
+            m_counter++;
+        }
+
+        ~IncDec()
+        {
+            m_counter--;
+        }
+    private:
+        int &m_counter;
+};
+
+int current_rec = 0;
+int max_rec = 0;
+#endif
+
+/* global variables */
+HashTable<vector<DicEdge>, unsigned int, HashVector> *global_hashtable;
+
+wchar_t  global_stringbuf[MAX_STRING_LENGTH]; /* Space for current string */
+wchar_t* global_endstring;                    /* Marks END of current string */
+const wchar_t* global_input;
+const wchar_t* global_endofinput;
+#ifdef CHECK_RECURSION
+map<int, vector<DicEdge> > global_mapfordepth;
+#endif
+
+/**
+ * Makenode takes a prefix (as position relative to stringbuf) and
+ * returns an index of the start node of a dawg that recognizes all
+ * words beginning with that prefix.  String is a pointer (relative
+ * to stringbuf) indicating how much of iPrefix is matched in the
+ * input.
+ * @param iPrefix: prefix to work on
+ * @param outfile: stream where to write the nodes
+ * @param ioHeaderInfo: information needed to build the final header, updated
+ *      during the processing
+ * @param iHeader: temporary header, used only to do the conversion between
+ *      the (wide) chars and their corresponding internal code
+ */
+unsigned int makenode(const wchar_t *iPrefix, ostream &outfile,
+                      DictHeaderInfo &ioHeaderInfo, const Header &iHeader)
+{
+#ifdef CHECK_RECURSION
+    IncDec inc(current_rec);
+    if (current_rec > max_rec)
+        max_rec = current_rec;
+#endif
+
+#ifdef CHECK_RECURSION
+    // Instead of creating a vector, try to reuse an existing one
+    vector<DicEdge> &edges = global_mapfordepth[current_rec];
+    edges.reserve(MAX_EDGES);
+    edges.clear();
+#else
+    vector<DicEdge> edges;
+    // Optimize allocation
+    edges.reserve(MAX_EDGES);
+#endif
+    DicEdge newEdge;
+
+    while (iPrefix == global_endstring)
+    {
+        // More edges out of node
+        newEdge.ptr  = 0;
+        newEdge.term = 0;
+        newEdge.last = 0;
+        newEdge.chr = iHeader.getCodeFromChar(*global_endstring++ = 
*global_input++);
+        edges.push_back(newEdge);
+
+        // End of a word?
+        if (*global_input == L'\n' || *global_input == L'\r')
+        {
+            ioHeaderInfo.nwords++;
+            *global_endstring = L'\0';
+            // Mark edge as word
+            edges.back().term = 1;
+
+            // Skip \r and/or \n
+            while (global_input != global_endofinput &&
+                   (*global_input == L'\n' || *global_input == L'\r'))
+            {
+                ++global_input;
+            }
+            // At the end of input?
+            if (global_input == global_endofinput)
+                break;
+
+            global_endstring = global_stringbuf;
+            while (*global_endstring == *global_input)
+            {
+                global_endstring++;
+                global_input++;
+            }
+        }
+        // Make dawg pointed to by this edge
+        edges.back().ptr =
+            makenode(iPrefix + 1, outfile, ioHeaderInfo, iHeader);
+    }
+
+    int numedges = edges.size();
+    if (numedges == 0)
+    {
+        // Special node zero - no edges
+        return 0;
+    }
+
+    // Mark the last edge
+    edges.back().last = 1;
+
+    const unsigned int *saved_position = global_hashtable->find(edges);
+    if (saved_position)
+    {
+        ioHeaderInfo.edgessaved += numedges;
+        ioHeaderInfo.nodessaved++;
+
+        return *saved_position;
+    }
+    else
+    {
+        unsigned int node_pos = ioHeaderInfo.edgesused;
+        global_hashtable->add(edges, ioHeaderInfo.edgesused);
+        ioHeaderInfo.edgesused += numedges;
+        ioHeaderInfo.nodesused++;
+        write_node(reinterpret_cast<uint32_t*>(&edges.front()),
+                   numedges, outfile);
+
+        return node_pos;
+    }
+}
+
+
+void printUsage(const string &iBinaryName)
+{
+    cout << "Usage: " << iBinaryName << " [options]" << endl
+         << _("Mandatory options:") << endl
+         << _("  -d, --dicname <string>  Set the dictionary name and version") 
<< endl
+         << _("  -l, --letters <string>  Path to the file containing the 
letters (see below)") << endl
+         << _("  -i, --input <string>    Path to the uncompressed dictionary 
file (encoded in UTF-8)") << endl
+         << _("  -o, --output <string    Path to the generated compressed 
dictionary file") << endl
+         << _("Other options:") << endl
+         << _("  -h, --help              Print this help and exit") << endl
+         << _("Example:") << endl
+         << "  " << iBinaryName << _(" -d 'ODS 5.0' -l letters.txt -i ods5.txt 
-o ods5.dawg") << endl
+         << endl
+         << _("The file containing the letters (--letters switch) must be 
UTF-8 encoded.") << endl
+         << _("Each line corresponds to one letter, and must contain 5 fields 
separated with ") << endl
+         << _("one or more space(s).") << endl
+         << _(" - 1st field: the letter itself") << endl
+         << _(" - 2nd field: the points of the letter") << endl
+         << _(" - 3rd field: the frequency of the letter (how many letters of 
this kind in the game)") << endl
+         << _(" - 4th field: 1 if the letter is considered as a vowel in 
Scrabble game, 0 otherwise") << endl
+         << _(" - 5th field: 1 if the letter is considered as a consonant in 
Scrabble game, 0 otherwise") << endl
+         << _("Example for french:") << endl
+         << _("A 1 9 1 0") << endl
+         << _("[...]") << endl
+         << _("Z 10 1 0 1") << endl
+         << _("? 0 2 1 1") << endl;
+}
+
+
+int main(int argc, char* argv[])
+{
+#if HAVE_SETLOCALE
+    // Set locale via LC_ALL
+    setlocale(LC_ALL, "");
+#endif
+
+#if ENABLE_NLS
+    // Set the message domain
+    bindtextdomain(PACKAGE, LOCALEDIR);
+    textdomain(PACKAGE);
+#endif
+
+    static const struct option long_options[] =
+    {
+        {"help", no_argument, NULL, 'h'},
+        {"dicname", required_argument, NULL, 'd'},
+        {"letters", required_argument, NULL, 'l'},
+        {"input", required_argument, NULL, 'i'},
+        {"output", required_argument, NULL, 'o'},
+        {0, 0, 0, 0}
+    };
+    static const char short_options[] = "hd:l:i:o:";
+
+    bool found_d = false;
+    bool found_l = false;
+    bool found_i = false;
+    bool found_o = false;
+    string inFileName;
+    string outFileName;
+    DictHeaderInfo headerInfo;
+
+    int res;
+    int option_index = 1;
+    try
+    {
+        while ((res = getopt_long(argc, argv, short_options,
+                                  long_options, &option_index)) != -1)
+        {
+            switch (res)
+            {
+                case 'h':
+                    printUsage(argv[0]);
+                    exit(0);
+                case 'd':
+                    found_d = true;
+                    headerInfo.dicName = convertToWc(optarg);
+                    break;
+                case 'l':
+                    found_l = true;
+                    readLetters(optarg, headerInfo);
+                    break;
+                case 'i':
+                    found_i = true;
+                    inFileName = optarg;
+                    break;
+                case 'o':
+                    found_o = true;
+                    outFileName = optarg;
+                    break;
+            }
+        }
+
+        // Check mandatory options
+        if (!found_d || !found_l || !found_i || !found_o)
+        {
+            cerr << _("A mandatory option is missing") << endl;
+            printUsage(argv[0]);
+            exit(1);
+        }
+
+        struct stat stat_buf;
+        if (stat(inFileName.c_str(), &stat_buf) < 0)
+        {
+            cerr << _("Cannot stat uncompressed dictionary ") << inFileName << 
endl;
+            exit(1);
+        }
+        unsigned int dicsize = (unsigned int)stat_buf.st_size;
+
+        ofstream outfile(outFileName.c_str(), ios::out | ios::binary | 
ios::trunc);
+        if (!outfile.is_open())
+        {
+            cerr << _("Cannot open output file ") << outFileName << endl;
+            exit(1);
+        }
+
+        clock_t startLoadTime = clock();
+        // FIXME: not exception safe
+        const wchar_t *uncompressed = load_uncompressed(inFileName, dicsize);
+        clock_t endLoadTime = clock();
+
+        global_input = uncompressed;
+        global_endofinput = global_input + dicsize;
+
+#define SCALE 0.6
+        global_hashtable = new HashTable<vector<DicEdge>, unsigned int, 
HashVector>((unsigned int)(dicsize * SCALE));
+#undef SCALE
+
+        headerInfo.dawg = true;
+        Header tempHeader = skip_init_header(outfile, headerInfo);
+
+        DicEdge specialnode = {0, 0, 0, 0};
+        specialnode.last = 1;
+        // Temporary variable to avoid a warning when compiling with -O2
+        // (there is no warning with -O0... g++ bug?)
+        DicEdge *tmpPtr = &specialnode;
+        write_node(reinterpret_cast<uint32_t*>(tmpPtr), 1, outfile);
+
+        /*
+         * Call makenode with null (relative to stringbuf) prefix;
+         * Initialize string to null; Put index of start node on output
+         */
+        DicEdge rootnode = {0, 0, 0, 0};
+        global_endstring = global_stringbuf;
+        clock_t startBuildTime = clock();
+        rootnode.ptr = makenode(global_endstring, outfile, headerInfo, 
tempHeader);
+        clock_t endBuildTime = clock();
+        // Reuse the temporary variable
+        tmpPtr = &rootnode;
+        write_node(reinterpret_cast<uint32_t*>(tmpPtr), 1, outfile);
+
+        fix_header(outfile, headerInfo);
+
+        Header aHeader(headerInfo);
+        aHeader.print();
+
+        delete global_hashtable;
+        delete[] uncompressed;
+        outfile.close();
+
+        printf(_(" Load time: %.3f s\n"), 1.0 * (endLoadTime - startLoadTime) 
/ CLOCKS_PER_SEC);
+        printf(_(" Compression time: %.3f s\n"), 1.0 * (endBuildTime - 
startBuildTime) / CLOCKS_PER_SEC);
+#ifdef CHECK_RECURSION
+        printf(_(" Maximum recursion level reached: %d\n"), max_rec);
+#endif
+        return 0;
+    }
+    catch (std::exception &e)
+    {
+        cerr << e.what() << endl;
+        return 1;
+    }
+
+}
+

Index: dic/dic.cpp
===================================================================
RCS file: dic/dic.cpp
diff -N dic/dic.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/dic.cpp 8 Jan 2008 13:52:34 -0000       1.2
@@ -0,0 +1,276 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2002-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+/**
+ *  \file   dic.c
+ *  \brief  Dawg dictionary
+ *  \author Antoine Fraboulet & Olivier Teuliere
+ *  \date   2002
+ */
+
+#include "config.h"
+
+#include <fstream>
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+#include <cctype>
+
+// For ntohl & Co.
+#ifdef WIN32
+#   include <winsock2.h>
+#else
+#    if HAVE_NETINET_IN_H
+#       include <netinet/in.h>
+#    endif
+#    if HAVE_ARPA_INET_H
+#       include <arpa/inet.h>
+#    endif
+#endif
+
+#include "dic.h"
+#include "header.h"
+#include "dic_exception.h"
+#include "dic_internals.h"
+#include "tile.h"
+
+
+const Dictionary *Dictionary::m_dic = NULL;
+
+
+// Note: duplicated in header.cpp
+#if defined(WORDS_BIGENDIAN)
+static uint32_t swap4(uint32_t v)
+{
+    uint32_t r;
+    uint8_t *pv = (uint8_t*)&v;
+    uint8_t *pr = (uint8_t*)&r;
+
+    pr[0] = pv[3];
+    pr[1] = pv[2];
+    pr[2] = pv[1];
+    pr[3] = pv[0];
+
+    return r;
+}
+#endif
+
+
+Dictionary::Dictionary(const string &iPath)
+    : m_dawg(NULL)
+{
+    ifstream file(iPath.c_str(), ios::in | ios::binary);
+
+    if (!file.is_open())
+        throw DicException("Cannot open " + iPath);
+
+    // XXX: we should protect these allocations with auto_ptr
+    m_header = new Header(file);
+    m_dawg = new uint32_t[m_header->getNbEdgesUsed() + 1];
+
+    streamsize toRead = (m_header->getNbEdgesUsed() + 1) * sizeof(uint32_t);
+    file.read((char*)m_dawg, toRead);
+    if (file.gcount() != toRead)
+    {
+        delete[] m_dawg;
+        delete m_header;
+        throw DicException("Problem reading dictionary arcs");
+    }
+
+    // Handle endianness
+    convertDataToArch();
+
+    initializeTiles();
+
+    // Concatenate the uppercase and lowercase letters
+    wstring lower = m_header->getLetters();
+    std::transform(lower.begin(), lower.end(), lower.begin(), towlower);
+    m_allLetters = m_header->getLetters() + lower;
+
+    m_dic = this;
+}
+
+
+Dictionary::~Dictionary()
+{
+    delete[] m_dawg;
+    delete m_header;
+}
+
+
+void Dictionary::convertDataToArch()
+{
+    if (m_header->getVersion() == 0)
+    {
+#if defined(WORDS_BIGENDIAN)
+        for (unsigned int i = 0; i < (m_header->getNbEdgesUsed() + 1); i++)
+        {
+            m_dawg[i] = swap4(m_dawg[i]);
+        }
+#endif
+    }
+    else
+    {
+        for (unsigned int i = 0; i < (m_header->getNbEdgesUsed() + 1); i++)
+        {
+            m_dawg[i] = ntohl(m_dawg[i]);
+        }
+    }
+}
+
+
+void Dictionary::initializeTiles()
+{
+    // "Activate" the dictionary by giving the header to the Tile class
+    Tile::SetHeader(*m_header);
+
+    // XXX: temp
+    Tile::m_TheJoker = Tile(Tile::kTILE_JOKER);
+
+    m_tilesVect.reserve(m_header->getLetters().size() + 1);
+    // Create a tile for each letter in the dictionary header
+    for (unsigned int i = 0; i < m_header->getLetters().size(); ++i)
+        m_tilesVect.push_back(Tile(m_header->getLetters()[i]));
+}
+
+
+bool Dictionary::validateLetters(const wstring &iLetters,
+                                 const wstring &iAccepted) const
+{
+    return iLetters.empty()
+        || iLetters.find_first_not_of(m_allLetters + iAccepted) == 
string::npos;
+}
+
+
+const dic_elt_t Dictionary::getNext(const dic_elt_t &e) const
+{
+     if (!isLast(e))
+         return e + 1;
+     return 0;
+}
+
+
+const dic_elt_t Dictionary::getSucc(const dic_elt_t &e) const
+{
+    if (m_header->getVersion() == 0)
+        return reinterpret_cast<const DicEdgeOld*>(m_dawg + e)->ptr;
+    else
+        return reinterpret_cast<const DicEdge*>(m_dawg + e)->ptr;
+}
+
+
+const dic_elt_t Dictionary::getRoot() const
+{
+    return m_header->getRoot();
+}
+
+
+const dic_code_t Dictionary::getCode(const dic_elt_t &e) const
+{
+    if (m_header->getVersion() == 0)
+        return reinterpret_cast<const DicEdgeOld*>(m_dawg + e)->chr;
+    else
+        return reinterpret_cast<const DicEdge*>(m_dawg + e)->chr;
+}
+
+
+wchar_t Dictionary::getChar(const dic_elt_t &e) const
+{
+    return m_header->getCharFromCode(getCode(e));
+}
+
+
+bool Dictionary::isLast(const dic_elt_t &e) const
+{
+    if (m_header->getVersion() == 0)
+        return reinterpret_cast<const DicEdgeOld*>(m_dawg + e)->last;
+    else
+        return reinterpret_cast<const DicEdge*>(m_dawg + e)->last;
+}
+
+
+bool Dictionary::isEndOfWord(const dic_elt_t &e) const
+{
+    if (m_header->getVersion() == 0)
+        return reinterpret_cast<const DicEdgeOld*>(m_dawg + e)->term;
+    else
+        return reinterpret_cast<const DicEdge*>(m_dawg + e)->term;
+}
+
+
+unsigned int Dictionary::lookup(const dic_elt_t &root, const dic_code_t *s) 
const
+{
+    unsigned int p;
+    dic_elt_t rootCopy = root;
+begin:
+    if (! *s)
+        return rootCopy;
+    if (! getSucc(rootCopy))
+        return 0;
+    p = getSucc(rootCopy);
+    do
+    {
+        if (getCode(p) == *s)
+        {
+            rootCopy = p;
+            s++;
+            goto begin;
+        }
+        else if (isLast( p))
+        {
+            return 0;
+        }
+        p = getNext(p);
+    } while (1);
+
+    return 0;
+}
+
+
+unsigned int Dictionary::charLookup(const dic_elt_t &iRoot, const wchar_t *s) 
const
+{
+    unsigned int p;
+    dic_elt_t rootCopy = iRoot;
+begin:
+    if (! *s)
+        return rootCopy;
+    if (! getSucc(rootCopy))
+        return 0;
+    p = getSucc(rootCopy);
+    do
+    {
+        if (getChar(p) == *s)
+        {
+            rootCopy = p;
+            s++;
+            goto begin;
+        }
+        else if (isLast(p))
+        {
+            return 0;
+        }
+        p = getNext(p);
+    } while (1);
+
+    return 0;
+}
+

Index: dic/dic_exception.cpp
===================================================================
RCS file: dic/dic_exception.cpp
diff -N dic/dic_exception.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/dic_exception.cpp       8 Jan 2008 13:52:34 -0000       1.2
@@ -0,0 +1,36 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#include "dic_exception.h"
+
+using namespace std;
+
+
+DicException::DicException(const string &iMessage)
+    : m_message(iMessage)
+{
+}
+
+
+const char *DicException::what() const throw()
+{
+    return m_message.c_str();
+}
+

Index: dic/dic_exception.h
===================================================================
RCS file: dic/dic_exception.h
diff -N dic/dic_exception.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/dic_exception.h 8 Jan 2008 13:52:34 -0000       1.2
@@ -0,0 +1,44 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#ifndef _DIC_EXCEPTION_H_
+#define _DIC_EXCEPTION_H_
+
+#include <exception>
+#include <string>
+
+
+/**
+ * Exception class for the dictionary.
+ * It simply inherits from the standard exception and overrides
+ * its what() method.
+ */
+class DicException: public std::exception
+{
+    public:
+        DicException(const std::string &iMessage);
+        ~DicException() throw() {}
+        virtual const char *what() const throw();
+
+    private:
+        std::string m_message;
+};
+
+#endif

Index: dic/dic_search.cpp
===================================================================
RCS file: dic/dic_search.cpp
diff -N dic/dic_search.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/dic_search.cpp  8 Jan 2008 13:52:34 -0000       1.2
@@ -0,0 +1,566 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2002-2007 Antoine Fraboulet
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+/**
+ *  \file   dic_search.c
+ *  \brief  Dictionary lookup functions
+ *  \author Antoine Fraboulet
+ *  \date   2002
+ */
+
+#include <cstdlib>
+#include <cstring>
+#include <cwchar>
+#include <cwctype>
+
+#include "dic_internals.h"
+#include "dic.h"
+#include "header.h"
+#include "encoding.h"
+#include "regexp.h"
+#include "libdic_a-ery.h"   /* generated by bison */
+#include "libdic_a-erl.h"   /* generated by flex  */
+#include "automaton.h"
+
+
+/**
+ * Function prototype for bison generated parser
+ */
+int regexpparse(yyscan_t scanner, NODE** root,
+                struct search_RegE_list_t *iList,
+                struct regexp_error_report_t *err);
+
+
+template <typename DAWG_EDGE>
+const DAWG_EDGE* Dictionary::seekEdgePtr(const wchar_t* s, const DAWG_EDGE 
*eptr) const
+{
+    if (*s)
+    {
+        const DAWG_EDGE *p = getEdgeAt<DAWG_EDGE>(eptr->ptr);
+        do
+        {
+            if (p->chr == getHeader().getCodeFromChar(*s))
+                return seekEdgePtr(s + 1, p);
+        } while (!(*p++).last);
+        return getEdgeAt<DAWG_EDGE>(0);
+    }
+    else
+        return eptr;
+}
+
+
+bool Dictionary::searchWord(const wstring &iWord) const
+{
+    if (!validateLetters(iWord))
+        return false;
+
+    if (getHeader().getVersion() == 0)
+    {
+        const DicEdgeOld *e =
+            seekEdgePtr(iWord.c_str(), getEdgeAt<DicEdgeOld>(getRoot()));
+        return e->term;
+    }
+    else
+    {
+        const DicEdge *e =
+            seekEdgePtr(iWord.c_str(), getEdgeAt<DicEdge>(getRoot()));
+        return e->term;
+    }
+}
+
+
+/**
+ * Global variables for searchWordByLen:
+ *
+ * A pointer to the structure is passed as a parameter
+ * so that all the search_* variables appear to the functions
+ * as global but the code remains re-entrant.
+ * Should be better to change the algorithm ...
+ */
+
+struct params_7plus1_t
+{
+    wchar_t added_char;
+    map<wchar_t, list<wstring> > *results;
+    int search_len;
+    wchar_t search_wordtst[DIC_WORD_MAX];
+    char search_letters[63];
+};
+
+template <typename DAWG_EDGE>
+void Dictionary::searchWordByLen(struct params_7plus1_t *params,
+                                 int i, const DAWG_EDGE *edgeptr) const
+{
+    /* depth first search in the dictionary */
+    do
+    {
+        /* the test is false only when reach the end-node */
+        if (edgeptr->chr)
+        {
+            /* is the letter available in search_letters */
+            if (params->search_letters[edgeptr->chr])
+            {
+                params->search_wordtst[i] = 
getHeader().getCharFromCode(edgeptr->chr);
+                params->search_letters[edgeptr->chr] --;
+                if (i == params->search_len)
+                {
+                    if (edgeptr->term)
+                    {
+                        
(*params->results)[params->added_char].push_back(params->search_wordtst);
+                    }
+                }
+                else
+                {
+                    searchWordByLen(params, i + 1, 
getEdgeAt<DAWG_EDGE>(edgeptr->ptr));
+                }
+                params->search_letters[edgeptr->chr] ++;
+                params->search_wordtst[i] = L'\0';
+            }
+
+            /* the letter is of course available if we have a joker available 
*/
+            if (params->search_letters[0])
+            {
+                params->search_wordtst[i] = 
getHeader().getCharFromCode(edgeptr->chr);
+                params->search_letters[0] --;
+                if (i == params->search_len)
+                {
+                    if (edgeptr->term)
+                    {
+                        
(*params->results)[params->added_char].push_back(params->search_wordtst);
+                    }
+                }
+                else
+                {
+                    searchWordByLen(params, i + 1, 
getEdgeAt<DAWG_EDGE>(edgeptr->ptr));
+                }
+                params->search_letters[0] ++;
+                params->search_wordtst[i] = L'\0';
+            }
+        }
+    } while (! (*edgeptr++).last);
+}
+
+
+template <typename DAWG_EDGE>
+void Dictionary::search7pl1Templ(const wstring &iRack,
+                                 map<wchar_t, list<wstring> > &oWordList,
+                                 bool joker) const
+{
+    if (iRack == L"" || iRack.size() > DIC_WORD_MAX)
+        return;
+
+    struct params_7plus1_t params;
+
+    for (unsigned int i = 0; i < sizeof(params.search_letters); i++)
+        params.search_letters[i] = 0;
+
+    /*
+     * the letters are verified and changed to the dic internal
+     * representation (using getCodeFromChar(*r))
+     */
+    int wordlen = 0;
+    for (const wchar_t* r = iRack.c_str(); *r; r++)
+    {
+        if (iswalpha(*r))
+        {
+            params.search_letters[getHeader().getCodeFromChar(*r)]++;
+            wordlen++;
+        }
+        else if (*r == L'?')
+        {
+            if (joker)
+            {
+                params.search_letters[0]++;
+                wordlen++;
+            }
+            else
+            {
+                oWordList[0].push_back(L"** joker **");
+                return;
+            }
+        }
+    }
+
+    if (wordlen < 1)
+        return;
+
+    const DAWG_EDGE *root_edge = getEdgeAt<DAWG_EDGE>(getRoot());
+    root_edge = getEdgeAt<DAWG_EDGE>(root_edge->ptr);
+
+    params.results = &oWordList;
+
+    /* search for all the words that can be done with the letters */
+    params.added_char = L'\0';
+    params.search_len = wordlen - 1;
+    params.search_wordtst[wordlen] = L'\0';
+    searchWordByLen(&params, 0, root_edge);
+
+    /* search for all the words that can be done with the letters +1 */
+    params.search_len = wordlen;
+    params.search_wordtst[wordlen + 1] = L'\0';
+    const wstring &letters = getHeader().getLetters();
+    for (unsigned int i = 0; i < letters.size(); i++)
+    {
+        params.added_char = letters[i];
+        unsigned int code = getHeader().getCodeFromChar(letters[i]);
+        params.search_letters[code]++;
+
+        searchWordByLen(&params, 0, root_edge);
+
+        params.search_letters[code]--;
+    }
+}
+
+
+void Dictionary::search7pl1(const wstring &iRack,
+                            map<wchar_t, list<wstring> > &oWordList,
+                            bool joker) const
+{
+    if (getHeader().getVersion() == 0)
+        search7pl1Templ<DicEdgeOld>(iRack, oWordList, joker);
+    else
+        search7pl1Templ<DicEdge>(iRack, oWordList, joker);
+}
+
+/****************************************/
+/****************************************/
+
+template <typename DAWG_EDGE>
+void Dictionary::searchRaccTempl(const wstring &iWord, list<wstring> 
&oWordList) const
+{
+    if (iWord == L"")
+        return;
+
+    /* search_racc will try to add a letter in front and at the end of a word 
*/
+
+    /* let's try for the front */
+    wchar_t wordtst[DIC_WORD_MAX];
+    wcscpy(wordtst + 1, iWord.c_str());
+    const wstring &letters = getHeader().getLetters();
+    for (unsigned int i = 0; i <= letters.size(); i++)
+    {
+        wordtst[0] = letters[i];
+        if (searchWord(wordtst))
+            oWordList.push_back(wordtst);
+    }
+
+    /* add a letter at the end */
+    int i;
+    for (i = 0; iWord[i]; i++)
+        wordtst[i] = iWord[i];
+
+    wordtst[i  ] = '\0';
+    wordtst[i+1] = '\0';
+
+    const DAWG_EDGE *edge_seek =
+        seekEdgePtr(iWord.c_str(), getEdgeAt<DAWG_EDGE>(getRoot()));
+
+    /* points to what the next letter can be */
+    const DAWG_EDGE *edge = getEdgeAt<DAWG_EDGE>(edge_seek->ptr);
+
+    if (edge != getEdgeAt<DAWG_EDGE>(0))
+    {
+        do
+        {
+            if (edge->term)
+            {
+                wordtst[i] = getHeader().getCharFromCode(edge->chr);
+                oWordList.push_back(wordtst);
+            }
+        } while (!(*edge++).last);
+    }
+}
+
+
+void Dictionary::searchRacc(const wstring &iWord, list<wstring> &oWordList) 
const
+{
+    if (getHeader().getVersion() == 0)
+        searchRaccTempl<DicEdgeOld>(iWord, oWordList);
+    else
+        searchRaccTempl<DicEdge>(iWord, oWordList);
+}
+
+/****************************************/
+/****************************************/
+
+template <typename DAWG_EDGE>
+void Dictionary::searchBenjTempl(const wstring &iWord, list<wstring> 
&oWordList) const
+{
+    if (iWord == L"")
+        return;
+
+    wchar_t wordtst[DIC_WORD_MAX];
+    wcscpy(wordtst + 3, iWord.c_str());
+    const DAWG_EDGE *edge0, *edge1, *edge2, *edgetst;
+    edge0 = getEdgeAt<DAWG_EDGE>(getRoot());
+    edge0 = getEdgeAt<DAWG_EDGE>(edge0->ptr);
+    do
+    {
+        wordtst[0] = getHeader().getCharFromCode(edge0->chr);
+        edge1 = getEdgeAt<DAWG_EDGE>(edge0->ptr);
+        do
+        {
+            wordtst[1] = getHeader().getCharFromCode(edge1->chr);
+            edge2 = getEdgeAt<DAWG_EDGE>(edge1->ptr);
+            do
+            {
+                edgetst = seekEdgePtr(iWord.c_str(), edge2);
+                if (edgetst->term)
+                {
+                    wordtst[2] = getHeader().getCharFromCode(edge2->chr);
+                    oWordList.push_back(wordtst);
+                }
+            } while (!(*edge2++).last);
+        } while (!(*edge1++).last);
+    } while (!(*edge0++).last);
+}
+
+
+void Dictionary::searchBenj(const wstring &iWord, list<wstring> &oWordList) 
const
+{
+    if (getHeader().getVersion() == 0)
+        searchBenjTempl<DicEdgeOld>(iWord, oWordList);
+    else
+        searchBenjTempl<DicEdge>(iWord, oWordList);
+}
+
+/****************************************/
+/****************************************/
+
+struct params_cross_t
+{
+    int wordlen;
+    wchar_t mask[DIC_WORD_MAX];
+};
+
+
+template <typename DAWG_EDGE>
+void Dictionary::searchCrossRecTempl(struct params_cross_t *params,
+                                     list<wstring> &oWordList,
+                                     const DAWG_EDGE *edgeptr) const
+{
+    const DAWG_EDGE *current = getEdgeAt<DAWG_EDGE>(edgeptr->ptr);
+
+    if (params->mask[params->wordlen] == '\0' && edgeptr->term)
+    {
+        oWordList.push_back(params->mask);
+    }
+    else if (params->mask[params->wordlen] == '.')
+    {
+        do
+        {
+            params->mask[params->wordlen] = 
getHeader().getCharFromCode(current->chr);
+            params->wordlen ++;
+            searchCrossRecTempl(params, oWordList, current);
+            params->wordlen --;
+            params->mask[params->wordlen] = '.';
+        }
+        while (!(*current++).last);
+    }
+    else
+    {
+        do
+        {
+            if (current->chr == 
getHeader().getCodeFromChar(params->mask[params->wordlen]))
+            {
+                params->wordlen ++;
+                searchCrossRecTempl(params, oWordList, current);
+                params->wordlen --;
+                break;
+            }
+        }
+        while (!(*current++).last);
+    }
+}
+
+
+void Dictionary::searchCross(const wstring &iMask, list<wstring> &oWordList) 
const
+{
+    if (iMask == L"")
+        return;
+
+    struct params_cross_t params;
+
+    int i;
+    for (i = 0; i < DIC_WORD_MAX && iMask[i]; i++)
+    {
+        if (iswalpha(iMask[i]))
+            params.mask[i] = towupper(iMask[i]);
+        else
+            params.mask[i] = '.';
+    }
+    params.mask[i] = '\0';
+
+    params.wordlen = 0;
+    if (getHeader().getVersion() == 0)
+    {
+        searchCrossRecTempl(&params, oWordList,
+                            getEdgeAt<DicEdgeOld>(getRoot()));
+    }
+    else
+    {
+        searchCrossRecTempl(&params, oWordList,
+                            getEdgeAt<DicEdge>(getRoot()));
+    }
+}
+
+/****************************************/
+/****************************************/
+
+struct params_regexp_t
+{
+    int minlength;
+    int maxlength;
+    Automaton *automaton_field;
+    struct search_RegE_list_t *charlist;
+    char word[DIC_WORD_MAX];
+    int  wordlen;
+};
+
+
+template <typename DAWG_EDGE>
+void Dictionary::searchRegexpRecTempl(struct params_regexp_t *params,
+                                      int state,
+                                      const DAWG_EDGE *edgeptr,
+                                      list<string> &oWordList) const
+{
+    int next_state;
+    /* if we have a valid word we store it */
+    if (params->automaton_field->accept(state) && edgeptr->term)
+    {
+        int l = strlen(params->word);
+        if (params->minlength <= l &&
+            params->maxlength >= l)
+        {
+            oWordList.push_back(params->word);
+        }
+    }
+    /* we now drive the search by exploring the dictionary */
+    const DAWG_EDGE *current = getEdgeAt<DAWG_EDGE>(edgeptr->ptr);
+    do
+    {
+        /* the current letter is current->chr */
+        next_state = params->automaton_field->getNextState(state, 
current->chr);
+        /* 1: the letter appears in the automaton as is */
+        if (next_state)
+        {
+            params->word[params->wordlen] = current->chr + 'a' - 1;
+            params->wordlen ++;
+            searchRegexpRecTempl(params, next_state, current, oWordList);
+            params->wordlen --;
+            params->word[params->wordlen] = '\0';
+        }
+    } while (!(*current++).last);
+}
+
+
+void Dictionary::searchRegExpInner(const string &iRegexp,
+                                   list<string> &oWordList,
+                                   struct search_RegE_list_t *iList) const
+{
+    int ptl[REGEXP_MAX+1];
+    int PS [REGEXP_MAX+1];
+
+    /* (expr)# */
+    char stringbuf[250];
+    sprintf(stringbuf, "(%s)#", iRegexp.c_str());
+    for (int i = 0; i < REGEXP_MAX; i++)
+    {
+        PS[i] = 0;
+        ptl[i] = 0;
+    }
+
+    struct regexp_error_report_t report;
+    report.pos1 = 0;
+    report.pos2 = 0;
+    report.msg[0] = '\0';
+
+    /* parsing */
+    yyscan_t scanner;
+    regexplex_init( &scanner );
+    YY_BUFFER_STATE buf = regexp_scan_string(stringbuf, scanner);
+    NODE *root  = NULL;
+    int value = regexpparse(scanner , &root, iList, &report);
+    regexp_delete_buffer(buf, scanner);
+    regexplex_destroy(scanner);
+
+    if (value)
+    {
+#ifdef DEBUG_FLEX_IS_BROKEN
+        fprintf(stderr, "parser error at pos %d - %d: %s\n",
+                report.pos1, report.pos2, report.msg);
+#endif
+        regexp_delete_tree(root);
+        return ;
+    }
+
+    int n = 1;
+    int p = 1;
+    regexp_parcours(root, &p, &n, ptl);
+    PS [0] = p - 1;
+    ptl[0] = p - 1;
+
+    regexp_possuivante(root, PS);
+
+    Automaton *a = new Automaton(root->PP, ptl, PS, iList);
+    if (a)
+    {
+        struct params_regexp_t params;
+        params.minlength      = iList->minlength;
+        params.maxlength      = iList->maxlength;
+        params.automaton_field = a;
+        params.charlist       = iList;
+        memset(params.word, '\0', sizeof(params.word));
+        params.wordlen        = 0;
+        if (getHeader().getVersion() == 0)
+        {
+            searchRegexpRecTempl(&params, a->getInitId(),
+                                 getEdgeAt<DicEdgeOld>(getRoot()), oWordList);
+        }
+        else
+        {
+            searchRegexpRecTempl(&params, a->getInitId(),
+                                 getEdgeAt<DicEdge>(getRoot()), oWordList);
+        }
+
+        delete a;
+    }
+    regexp_delete_tree(root);
+}
+
+
+void Dictionary::searchRegExp(const wstring &iRegexp,
+                              list<wstring> &oWordList,
+                              struct search_RegE_list_t *iList) const
+{
+    if (iRegexp == L"")
+        return;
+
+    list<string> tmpWordList;
+    // Do the actual work
+    searchRegExpInner(convertToMb(iRegexp), tmpWordList, iList);
+
+    list<string>::const_iterator it;
+    for (it = tmpWordList.begin(); it != tmpWordList.end(); it++)
+    {
+        oWordList.push_back(convertToWc(*it));
+    }
+}
+

Index: dic/encoding.cpp
===================================================================
RCS file: dic/encoding.cpp
diff -N dic/encoding.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/encoding.cpp    8 Jan 2008 13:52:34 -0000       1.2
@@ -0,0 +1,396 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+/**
+ *  \file   encoding.cpp
+ *  \brief  Utility functions to ease handling of wide-character strings
+ *  \author Olivier Teuliere
+ *  \date   2005
+ */
+
+#include "config.h"
+
+#include <iostream>
+#include <sstream>
+#include <cstdlib>
+#include <cstdarg>
+#include <cstring>
+#include <cwchar>
+#include <cwctype>
+#include <cerrno>
+#include <iconv.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include "encoding.h"
+#include "dic_exception.h"
+
+using namespace std;
+
+
+#ifdef WIN32
+// Utility function to get the last system error as a string
+static string GetWin32Error()
+{
+    char *lpMsgBuf;
+    DWORD dw = GetLastError();
+    cerr << dw << endl;
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                  FORMAT_MESSAGE_FROM_SYSTEM |
+                  FORMAT_MESSAGE_IGNORE_INSERTS,
+                  NULL, dw,
+                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                  (LPTSTR) &lpMsgBuf,
+                  0, NULL);
+    string msg = lpMsgBuf;
+    LocalFree(lpMsgBuf);
+    return msg;
+}
+#endif
+
+
+#if !HAVE_WCWIDTH
+// wcwidth replacement (for win32 in particular)
+// Inspired from the gnulib package, without some of the refinements
+static inline int wcwidth(wchar_t c)
+{
+    // Assume all the printable characters have width 1
+    return c == 0 ? 0 : (iswprint(c) ? 1 : -1);
+}
+#endif
+
+
+int _wtoi(const wchar_t *iWStr)
+{
+    return wcstol(iWStr, NULL, 10);
+}
+
+
+int _swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...)
+{
+    int res;
+    va_list argp;
+    va_start(argp, format);
+#ifdef WIN32
+    // Mingw32 does not take the maxlen argument
+    res = vswprintf(wcs, format, argp);
+#else
+    res = vswprintf(wcs, maxlen, format, argp);
+#endif
+    va_end(argp);
+    return res;
+}
+
+
+wchar_t *_wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **ptr)
+{
+#ifdef WIN32
+    // Mingw32 does not take the third argument
+    return wcstok(wcs, delim);
+#else
+    return wcstok(wcs, delim, ptr);
+#endif
+}
+
+
+#define _MAX_SIZE_FOR_STACK_ 30
+wstring convertToWc(const string& iStr)
+{
+#ifdef WIN32
+    // XXX: Assume the input is in UTF-8
+    return readFromUTF8(iStr.c_str(), iStr.size(), "convertToWc");
+#else
+    // Get the needed length (we _can't_ use string::size())
+    size_t len = mbstowcs(NULL, iStr.c_str(), 0);
+    if (len == (size_t)-1)
+        return L"";
+
+    // Change the allocation method depending on the length of the string
+    if (len < _MAX_SIZE_FOR_STACK_)
+    {
+        // Without multi-thread, we can use static storage
+        static wchar_t tmp[_MAX_SIZE_FOR_STACK_];
+        len = mbstowcs(tmp, iStr.c_str(), len + 1);
+        return tmp;
+    }
+    else
+    {
+        wchar_t *tmp = new wchar_t[len + 1];
+        len = mbstowcs(tmp, iStr.c_str(), len + 1);
+        wstring res = tmp;
+        delete[] tmp;
+        return res;
+    }
+#endif
+}
+
+
+string convertToMb(const wstring& iWStr)
+{
+#ifdef WIN32
+    const unsigned int size = iWStr.size() * 4;
+    char buf[size];
+    // XXX: Assume the output is in UTF-8
+    int nb = writeInUTF8(iWStr, buf, size, "convertToMb");
+    return string(buf, nb);
+#else
+    // Get the needed length (we _can't_ use wstring::size())
+    size_t len = wcstombs(NULL, iWStr.c_str(), 0);
+    if (len == (size_t)-1)
+        return "";
+
+    // Change the allocation method depending on the length of the string
+    if (len < _MAX_SIZE_FOR_STACK_)
+    {
+        // Without multi-thread, we can use static storage
+        static char tmp[_MAX_SIZE_FOR_STACK_];
+        len = wcstombs(tmp, iWStr.c_str(), len + 1);
+        return tmp;
+    }
+    else
+    {
+        char *tmp = new char[len + 1];
+        len = wcstombs(tmp, iWStr.c_str(), len + 1);
+        string res = tmp;
+        delete[] tmp;
+        return res;
+    }
+#endif
+}
+#undef _MAX_SIZE_FOR_STACK_
+
+
+string convertToMb(wchar_t iWChar)
+{
+#ifdef WIN32
+    return convertToMb(wstring(1, iWChar));
+#else
+    char res[MB_CUR_MAX + 1];
+    int len = wctomb(res, iWChar);
+    if (len == -1)
+        return "";
+    res[len] = '\0';
+
+    return res;
+#endif
+}
+
+
+string truncString(const string &iStr, unsigned int iMaxWidth)
+{
+    // Heuristic: the width of a character cannot exceed the number of
+    // bytes used to represent it (even in UTF-8)
+    if (iStr.size() <= iMaxWidth)
+        return iStr;
+    return truncAndConvert(convertToWc(iStr), iMaxWidth);
+}
+
+
+string truncAndConvert(const wstring &iWstr, unsigned int iMaxWidth)
+{
+    unsigned int width = 0;
+    unsigned int pos;
+    for (pos = 0; pos < iWstr.size(); ++pos)
+    {
+        int n = wcwidth(iWstr[pos]);
+        if (n == -1)
+        {
+            ostringstream ss;
+            ss << "truncAndConvert: non printable character: " << iWstr[pos];
+            // XXX: Should we throw an exception instead? Just ignore the 
problem?
+            cerr << ss.str() << endl;;
+            //throw DicException(ss.str());
+            return convertToMb(iWstr);
+        }
+        if (width + n > iMaxWidth)
+            break;
+        width += n;
+    }
+
+    return convertToMb(iWstr.substr(0, pos));
+}
+
+
+string truncOrPad(const string &iStr, unsigned int iWidth, char iChar)
+{
+    wstring wstr = convertToWc(iStr);
+    unsigned int width = 0;
+    unsigned int pos;
+    for (pos = 0; pos < wstr.size(); ++pos)
+    {
+        int n = wcwidth(wstr[pos]);
+        if (n == -1)
+        {
+            ostringstream ss;
+            ss << "truncAndConvert: non printable character: " << wstr[pos];
+            // XXX: Should we throw an exception instead? Just ignore the 
problem?
+            cerr << ss.str() << endl;;
+            //throw DicException(ss.str());
+            return convertToMb(wstr);
+        }
+        if (width + n > iWidth)
+            break;
+        width += n;
+    }
+
+    if (iWidth > width)
+        return convertToMb(wstr.substr(0, pos)) + string(iWidth - width, 
iChar);
+    else
+        return convertToMb(wstr.substr(0, pos));
+}
+
+
+string padAndConvert(const wstring &iWstr, unsigned int iLength,
+                     bool iLeftPad, char c)
+{
+    int width = 0;
+    for (unsigned int i = 0; i < iWstr.size(); ++i)
+    {
+        int n = wcwidth(iWstr[i]);
+        if (n == -1)
+        {
+            ostringstream ss;
+            ss << "padAndConvert: non printable character: " << iWstr[i];
+            // XXX: Should we throw an exception instead? Just ignore the 
problem?
+            cerr << ss.str() << endl;;
+            //throw DicException(ss.str());
+            return convertToMb(iWstr);
+        }
+        width += n;
+    }
+
+    if ((unsigned int)width >= iLength)
+        return convertToMb(iWstr);
+    else
+    {
+        // Padding is needed
+        string s(iLength - width, c);
+        if (iLeftPad)
+            return s + convertToMb(iWstr);
+        else
+            return convertToMb(iWstr) + s;
+    }
+}
+
+
+unsigned int readFromUTF8(wchar_t *oString, unsigned int iWideSize,
+                          const char *iBuffer, unsigned int iBufSize,
+                          const string &iContext)
+{
+#ifdef WIN32
+    int res = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, iBuffer,
+                                  iBufSize, oString, iWideSize);
+    if (res == 0)
+    {
+        // Retrieve the system error message for the last-error code
+        throw DicException("readFromUTF8: MultiByteToWideChar failed (" +
+                           iContext + "): " + GetWin32Error());
+    }
+    return res;
+#else
+    iconv_t handle = iconv_open("WCHAR_T", "UTF-8");
+    if (handle == (iconv_t)(-1))
+        throw DicException("readFromUTF8: iconv_open failed");
+    size_t inChars = iBufSize;
+    size_t outChars = iWideSize * sizeof(wchar_t);
+    // Use the ICONV_CONST trick because the declaration of iconv()
+    // differs depending on the implementations...
+    ICONV_CONST char *in = const_cast<ICONV_CONST char*>(iBuffer);
+    char *out = (char*)oString;
+    size_t res = iconv(handle, &in, &inChars, &out, &outChars);
+    iconv_close(handle);
+    // Problem during encoding conversion?
+    if (res == (size_t)(-1))
+    {
+        throw DicException("readFromUTF8: iconv failed (" +
+                           iContext + "): " + string(strerror(errno)));
+    }
+    return iWideSize - outChars / sizeof(wchar_t);
+#endif
+}
+
+
+wstring readFromUTF8(const char *iBuffer, unsigned int iBufSize,
+                     const string &iContext)
+{
+    // Temporary buffer for output
+    // We will have at most as many characters as in the UTF-8 string
+    wchar_t *wideBuf = new wchar_t[iBufSize];
+    unsigned int number;
+    try
+    {
+        number = readFromUTF8(wideBuf, iBufSize, iBuffer, iBufSize, iContext);
+    }
+    catch (...)
+    {
+        // Make sure not to leak
+        delete[] wideBuf;
+        throw;
+    }
+    // Copy the string
+    wstring res(wideBuf, number);
+    delete[] wideBuf;
+    return res;
+}
+
+
+unsigned int writeInUTF8(const wstring &iWString, char *oBuffer,
+                         unsigned int iBufSize, const string &iContext)
+{
+#ifdef WIN32
+    int res = WideCharToMultiByte(CP_UTF8, 0, iWString.c_str(), 
iWString.size(),
+                                  oBuffer, iBufSize, NULL, NULL);
+    if (res == 0)
+    {
+        DWORD dw = GetLastError();
+        cerr << dw << endl;
+        // Retrieve the system error message for the last-error code
+        throw DicException("writeInUTF8: WideCharToMultiByte failed (" +
+                           iContext + "): " + GetWin32Error());
+    }
+    return res;
+#else
+    iconv_t handle = iconv_open("UTF-8", "WCHAR_T");
+    if (handle == (iconv_t)(-1))
+        throw DicException("writeInUTF8: iconv_open failed");
+    size_t length = iWString.size();
+    size_t inChars = sizeof(wchar_t) * length;
+    size_t outChars = iBufSize;
+    // Use the ICONV_CONST trick because the declaration of iconv()
+    // differs depending on the implementations...
+    // FIXME: bonus ugliness for doing 2 casts at once, and accessing string
+    // internals...
+    ICONV_CONST char *in = (ICONV_CONST char*)(&iWString[0]);
+    char *out = oBuffer;
+    size_t res = iconv(handle, &in, &inChars, &out, &outChars);
+    iconv_close(handle);
+    // Problem during encoding conversion?
+    if (res == (size_t)(-1))
+    {
+        throw DicException("writeInUTF8: iconv failed (" +
+                           iContext + ")" + string(strerror(errno)));
+    }
+    // Return the number of written bytes
+    return iBufSize - outChars;
+#endif
+}
+

Index: dic/encoding.h
===================================================================
RCS file: dic/encoding.h
diff -N dic/encoding.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/encoding.h      8 Jan 2008 13:52:34 -0000       1.2
@@ -0,0 +1,122 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+/**
+ *  \file   encoding.h
+ *  \brief  Utility functions to ease manipulation of wide-character strings
+ *  \author Olivier Teuliere
+ *  \date   2005
+ */
+
+#ifndef _ENCODING_H_
+#define _ENCODING_H_
+
+#include <string>
+
+using std::string;
+using std::wstring;
+
+
+/// Equivalent of atoi for wide-caracter strings
+int _wtoi(const wchar_t *iWStr);
+
+/// Equivalent of swprintf, but working also with mingw32
+int _swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...);
+
+/// Equivalent of wcstok, but working also with mingw32
+wchar_t *_wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **ptr);
+
+/// Convert a multi-byte string into a wide-character string
+wstring convertToWc(const string &iStr);
+
+/// Convert a wide-character string into a multi-byte string
+string convertToMb(const wstring &iWStr);
+
+/// Convert a wide character into a multi-byte string
+string convertToMb(wchar_t iWChar);
+
+/**
+ * Truncate the given string to ensure that the number of columns needed
+ * to display it is at most iMaxWidth. If the string is already less wide,
+ * it is returned without truncation
+ */
+string truncString(const string &iStr, unsigned int iMaxWidth);
+
+/**
+ * Convert the given string into a multi-byte one. If the number of columns
+ * needed to display the resulting string is more than iMaxWidth, truncate it
+ * on the right before conversion
+ */
+string truncAndConvert(const wstring &iWStr, unsigned int iMaxWidth);
+
+/**
+ * Make sure the displayed version of iStr has a width of iWidth.
+ * If the string is too long, truncate it, if it is too short, pad it
+ * with iChar
+ */
+string truncOrPad(const string &iStr, unsigned int iWidth, char iChar = ' ');
+
+/**
+ * Convert the given string into a multi-byte one. If the number of columns
+ * needed to display the resulting string is less than iLength, pad it with
+ * the given character (defaulting to space)
+ */
+string padAndConvert(const wstring &iWstr, unsigned int iLength,
+                     bool iLeftPad = true, char c = ' ');
+
+/**
+ * Utility function to convert a char* buffer encoded in UTF-8 into a
+ * wchar_t* string
+ * @param oString: where to write the converted string
+ * @param iWideSize: size available in oString (number of wchar_t)
+ * @param iBuffer: UTF-8 string to convert
+ * @param iBufSize: available size in iBuffer
+ * @param iContext: free text used in case of exception
+ * @return: number of wide chars actually written
+ */
+unsigned int readFromUTF8(wchar_t *oString, unsigned int iWideSize,
+                          const char *iBuffer, unsigned int iBufSize,
+                          const string &iContext);
+
+/**
+ * Same as the other readFromUTF8 function, dealing with a wstring
+ * instead of a wchar_t*. Note that it performs an additional copy
+ * of the output string...
+ * @param iBuffer: UTF-8 string to convert
+ * @param iBufSize: available size in iBuffer
+ * @param iContext: free text used in case of exception
+ * @return: the converted wide string
+ */
+wstring readFromUTF8(const char *iBuffer, unsigned int iBufSize,
+                     const string &iContext);
+
+/**
+ * Utility function to convert a wstring into an UTF-8 char* buffer
+ * @param iWString: the wide string to encode
+ * @param oBuffer: where to write the encoded string
+ * @param iBufSize: available size in oBuffer
+ * @param iContext: free text used in case of exception
+ * @return: number of bytes actually written
+ */
+unsigned int writeInUTF8(const wstring &iWString, char *oBuffer,
+                         unsigned int iBufSize, const string &iContext);
+
+#endif
+

Index: dic/erl.lpp
===================================================================
RCS file: dic/erl.lpp
diff -N dic/erl.lpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/erl.lpp 8 Jan 2008 13:52:35 -0000       1.2
@@ -0,0 +1,59 @@
+%{
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet
+ * Authors: Antoine Fraboulet
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#include "dic.h"
+#include "regexp.h"
+#include "libdic_a-ery.h"
+
+#define MASK_TO_REMOVE    0x1F
+
+%}
+%option prefix="regexp"
+%option outfile="lex.yy.c"
+%option header-file="libdic_a-erl.h"
+%option reentrant bison-bridge
+%option bison-locations
+%option noyywrap nounput
+
+/* TODO : remove lexer translation */
+alphabet [a-zA-Z]
+%%
+
+{alphabet} {yylval_param->c=(yytext[0]&MASK_TO_REMOVE); return LEX_CHAR;}
+"["        {return LEX_L_SQBRACKET;}
+"]"        {return LEX_R_SQBRACKET;}
+"("        {return LEX_L_BRACKET;}
+")"        {return LEX_R_BRACKET;}
+"^"        {return LEX_HAT;}
+
+"."        {return LEX_ALL;}
+":v:"      {return LEX_VOWL;}
+":c:"      {return LEX_CONS;}
+":1:"      {return LEX_USER1;}
+":2:"      {return LEX_USER2;}
+
+"?"        {return LEX_QMARK;}
+"+"        {return LEX_PLUS;}
+"*"        {return LEX_STAR;}
+
+"#"        {return LEX_SHARP;}
+%%
+

Index: dic/ery.ypp
===================================================================
RCS file: dic/ery.ypp
diff -N dic/ery.ypp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/ery.ypp 8 Jan 2008 13:52:35 -0000       1.2
@@ -0,0 +1,295 @@
+%{
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet
+ * Authors: Antoine Fraboulet
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <malloc.h>
+
+#include "dic.h"
+#include "regexp.h"
+#include "libdic_a-ery.h"
+#include "libdic_a-erl.h"
+
+/* ************************************************** */
+/* ************************************************** */
+/* ************************************************** */
+
+    /**
+     * function prototype for parser generated by bison
+     */
+int  regexpparse(yyscan_t scanner, NODE** root,
+                struct search_RegE_list_t *list,
+                struct regexp_error_report_t *err);
+
+    /**
+     * function prototype for error reporting
+     */
+void regexperror(YYLTYPE *llocp, yyscan_t scanner, NODE** root,
+                struct search_RegE_list_t *list,
+                struct regexp_error_report_t *err,
+                char const *msg);
+
+/* ************************************************** */
+/* ************************************************** */
+/* ************************************************** */
+
+%}
+%union {
+  char c;
+  NODE *NODE_TYPE;
+  char letters[DIC_LETTERS];
+};
+
+%defines
+%name-prefix="regexp"
+%pure-parser
+%locations
+%parse-param {yyscan_t yyscanner}
+%parse-param {NODE **root}
+%parse-param {struct search_RegE_list_t *list}
+%parse-param {struct regexp_error_report_t *err}
+%lex-param   {yyscan_t yyscanner}
+
+%token  <c>  LEX_CHAR
+%token  LEX_ALL
+%token  LEX_VOWL
+%token  LEX_CONS
+%token  LEX_USER1
+%token  LEX_USER2
+
+%token  LEX_L_SQBRACKET LEX_R_SQBRACKET
+%token  LEX_L_BRACKET LEX_R_BRACKET
+%token  LEX_HAT
+
+%token  LEX_QMARK
+%token  LEX_PLUS
+%token  LEX_STAR
+%token  LEX_SHARP
+
+%type   <NODE_TYPE> var
+%type   <NODE_TYPE> expr
+%type   <letters>   vardis
+%type   <letters>   exprdis
+%type   <NODE_TYPE> exprdisnode
+%start  start
+%%
+
+start: LEX_L_BRACKET expr LEX_R_BRACKET LEX_SHARP
+       {
+        NODE* sharp = regexp_createNODE(NODE_VAR,RE_FINAL_TOK,NULL,NULL);
+        *root = regexp_createNODE(NODE_AND,'\0',$2,sharp);
+        YYACCEPT;
+       }
+     ;
+
+
+expr : var
+       {
+        $$=$1;
+       }
+     | expr expr
+       {
+        $$=regexp_createNODE(NODE_AND,'\0',$1,$2);
+       }
+     | var LEX_QMARK
+       {
+        NODE* epsilon=regexp_createNODE(NODE_VAR,RE_EPSILON,NULL,NULL);
+        $$=regexp_createNODE(NODE_OR,'\0',$1,epsilon);
+       }
+     | var LEX_PLUS
+       {
+        $$=regexp_createNODE(NODE_PLUS,'\0',$1,NULL);
+       }
+     | var LEX_STAR
+       {
+        $$=regexp_createNODE(NODE_STAR,'\0',$1,NULL);
+       }
+/* () */
+     | LEX_L_BRACKET expr LEX_R_BRACKET
+       {
+        $$=$2;
+       }
+     | LEX_L_BRACKET expr LEX_R_BRACKET LEX_QMARK
+       {
+        NODE* epsilon=regexp_createNODE(NODE_VAR,RE_EPSILON,NULL,NULL);
+        $$=regexp_createNODE(NODE_OR,'\0',$2,epsilon);
+       }
+     | LEX_L_BRACKET expr LEX_R_BRACKET LEX_PLUS
+       {
+        $$=regexp_createNODE(NODE_PLUS,'\0',$2,NULL);
+       }
+     | LEX_L_BRACKET expr LEX_R_BRACKET LEX_STAR
+       {
+        $$=regexp_createNODE(NODE_STAR,'\0',$2,NULL);
+       }
+/* [] */
+     | LEX_L_SQBRACKET exprdisnode LEX_R_SQBRACKET
+       {
+        $$=$2;
+       }
+     | LEX_L_SQBRACKET exprdisnode LEX_R_SQBRACKET LEX_QMARK
+       {
+        NODE* epsilon=regexp_createNODE(NODE_VAR,RE_EPSILON,NULL,NULL);
+        $$=regexp_createNODE(NODE_OR,'\0',$2,epsilon);
+       }
+     | LEX_L_SQBRACKET exprdisnode LEX_R_SQBRACKET LEX_PLUS
+       {
+        $$=regexp_createNODE(NODE_PLUS,'\0',$2,NULL);
+       }
+     | LEX_L_SQBRACKET exprdisnode LEX_R_SQBRACKET LEX_STAR
+       {
+        $$=regexp_createNODE(NODE_STAR,'\0',$2,NULL);
+       }
+     ;
+
+
+
+var : LEX_CHAR
+       {
+#ifdef DEBUG_RE_PARSE
+        printf("var : lecture %c\n",$1 + 'a' -1);
+#endif
+         $$=regexp_createNODE(NODE_VAR,$1,NULL,NULL);
+       }
+     | LEX_ALL
+       {
+         $$=regexp_createNODE(NODE_VAR,RE_ALL_MATCH,NULL,NULL);
+       }
+     | LEX_VOWL
+       {
+         $$=regexp_createNODE(NODE_VAR,RE_VOWL_MATCH,NULL,NULL);
+       }
+     | LEX_CONS
+       {
+         $$=regexp_createNODE(NODE_VAR,RE_CONS_MATCH,NULL,NULL);
+       }
+     | LEX_USER1
+       {
+         $$=regexp_createNODE(NODE_VAR,RE_USR1_MATCH,NULL,NULL);
+       }
+     | LEX_USER2
+       {
+         $$=regexp_createNODE(NODE_VAR,RE_USR2_MATCH,NULL,NULL);
+       }
+     ;
+
+
+exprdisnode : exprdis
+       {
+        int i,j;
+#ifdef DEBUG_RE_PARSE
+        printf("exprdisnode : exprdis : ");
+#endif
+        for(i=RE_LIST_USER_END + 1; i < DIC_SEARCH_REGE_LIST; i++)
+          {
+            if (list->valid[i] == 0)
+              {
+                list->valid[i] = 1;
+                list->symbl[i] = RE_ALL_MATCH + i;
+                list->letters[i][0] = 0;
+                for(j=1; j < DIC_LETTERS; j++)
+                  list->letters[i][j] = $1[j] ? 1 : 0;
+#ifdef DEBUG_RE_PARSE
+                printf("list %d symbl x%02x : ",i,list->symbl[i]);
+                for(j=0; j < DIC_LETTERS; j++)
+                  if (list->letters[i][j])
+                    printf("%c",j+'a'-1);
+                printf("\n");
+#endif
+                break;
+              }
+          }
+        $$=regexp_createNODE(NODE_VAR,list->symbl[i],NULL,NULL);
+       }
+     | LEX_HAT exprdis
+       {
+        int i,j;
+#ifdef DEBUG_RE_PARSE
+        printf("exprdisnode : HAT exprdis : ");
+#endif
+        for(i=RE_LIST_USER_END + 1; i < DIC_SEARCH_REGE_LIST; i++)
+          {
+            if (list->valid[i] == 0)
+              {
+                list->valid[i] = 1;
+                list->symbl[i] = RE_ALL_MATCH + i;
+                list->letters[i][0] = 0;
+                for(j=1; j < DIC_LETTERS; j++)
+                  list->letters[i][j] = $2[j] ? 0 : 1;
+#ifdef DEBUG_RE_PARSE
+                printf("list %d symbl x%02x : ",i,list->symbl[i]);
+                for(j=0; j < DIC_LETTERS; j++)
+                  if (list->letters[i][j])
+                    printf("%c",j+'a'-1);
+                printf("\n");
+#endif
+                break;
+              }
+          }
+        $$=regexp_createNODE(NODE_VAR,list->symbl[i],NULL,NULL);
+       }
+     ;
+
+
+exprdis: vardis
+       {
+        memcpy($$,$1,sizeof(char)*DIC_LETTERS);
+       }
+     | vardis exprdis
+       {
+        int i;
+        for(i=0; i < DIC_LETTERS; i++)
+          $$[i] = $1[i] | $2[i];
+       }
+     ;
+
+
+
+vardis: LEX_CHAR
+       {
+        int c = $1;
+        memset($$,0,sizeof(char)*DIC_LETTERS);
+#ifdef DEBUG_RE_PARSE
+        printf("vardis : lecture %c\n",c + 'a' -1);
+#endif
+        $$[c] = 1;
+       }
+     ;
+
+
+%%
+
+#define UNUSED __attribute__((unused))
+
+void regexperror(YYLTYPE *llocp, yyscan_t UNUSED yyscanner, NODE UNUSED **root,
+                struct search_RegE_list_t UNUSED *list,
+                struct regexp_error_report_t *err, char const *msg)
+{
+  err->pos1 = llocp->first_column;
+  err->pos2 = llocp->last_column;
+  strncpy(err->msg,msg,sizeof(err->msg));
+}
+
+/*
+ * shut down the compiler
+ */
+//int yy_init_globals (yyscan_t yyscanner);

Index: dic/hashtable.cpp
===================================================================
RCS file: dic/hashtable.cpp
diff -N dic/hashtable.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/hashtable.cpp   8 Jan 2008 13:52:35 -0000       1.2
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+/**
+ *  \file   hashtable.c
+ *  \brief  Simple hashtable type
+ *  \author Antoine Fraboulet
+ *  \date   1999
+ */
+
+#include "hashtable.h"
+
+
+unsigned int HashPtr(const void *iPtr, unsigned int iSize)
+{
+    unsigned int key = 0;
+
+    if (iSize % sizeof(unsigned int) == 0)
+    {
+        const unsigned int *ptr =
+            reinterpret_cast<const unsigned int*>(iPtr);
+        for (unsigned int i = 0; i < (iSize / sizeof(unsigned int)); ++i)
+            key ^= (key << 3) ^ (key >> 1) ^ ptr[i];
+    }
+    else
+    {
+        const unsigned char *ptr =
+            reinterpret_cast<const unsigned char*>(iPtr);
+        for (unsigned int i = 0; i < iSize; ++i)
+            key ^= (key << 3) ^ (key >> 1) ^ ptr[i];
+    }
+    return key;
+}
+

Index: dic/hashtable.i
===================================================================
RCS file: dic/hashtable.i
diff -N dic/hashtable.i
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/hashtable.i     8 Jan 2008 13:52:35 -0000       1.2
@@ -0,0 +1,88 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#include <cstdlib>
+
+#include "hashtable.h"
+
+
+template<typename KEY, typename VALUE, typename HASH_FCN>
+HashTable<KEY, VALUE, HASH_FCN>::HashTable(unsigned int iSize)
+    : m_size(iSize)
+{
+    m_nodes = new const Node*[m_size];
+    for (unsigned int i = 0; i < m_size; ++i)
+    {
+        m_nodes[i] = NULL;
+    }
+}
+
+
+template<typename KEY, typename VALUE, typename HASH_FCN>
+HashTable<KEY, VALUE, HASH_FCN>::~HashTable()
+{
+    for (unsigned int i = 0; i < m_size; ++i)
+        delete m_nodes[i];
+    delete[] m_nodes;
+}
+
+
+template<typename KEY, typename VALUE, typename HASH_FCN>
+HashTable<KEY, VALUE, HASH_FCN>::Node::Node(const KEY &iKey, const VALUE 
&iValue, const Node *iNext)
+    : m_key(iKey), m_value(iValue), m_next(iNext)
+{
+}
+
+
+template<typename KEY, typename VALUE, typename HASH_FCN>
+HashTable<KEY, VALUE, HASH_FCN>::Node::~Node()
+{
+    delete m_next;
+}
+
+
+template<typename KEY, typename VALUE, typename HASH_FCN>
+const VALUE *HashTable<KEY, VALUE, HASH_FCN>::find(const KEY &iKey) const
+{
+    HASH_FCN aHashFunc;
+    unsigned int h_key = aHashFunc(iKey) % m_size;
+    for (const Node *entry = m_nodes[h_key]; entry; entry = entry->m_next)
+    {
+        // Note: we need to be able to call == on a type KEY
+        if (entry->m_key == iKey)
+        {
+            return &entry->m_value;
+        }
+    }
+    return NULL;
+}
+
+
+template<typename KEY, typename VALUE, typename HASH_FCN>
+void HashTable<KEY, VALUE, HASH_FCN>::add(const KEY &iKey, const VALUE &iValue)
+{
+    HASH_FCN aHashFunc;
+    unsigned int h_key = aHashFunc(iKey) % m_size;
+    const Node *entry = new Node(iKey, iValue, m_nodes[h_key]);
+    m_nodes[h_key] = entry;
+}
+
+// vim: ft=cpp

Index: dic/header.cpp
===================================================================
RCS file: dic/header.cpp
diff -N dic/header.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/header.cpp      8 Jan 2008 13:52:35 -0000       1.2
@@ -0,0 +1,526 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#include "config.h"
+
+#include <string>
+#include <sstream>
+#include <iostream>
+
+// For ntohl & Co.
+#ifdef WIN32
+#   include <winsock2.h>
+#else
+#    if HAVE_NETINET_IN_H
+#       include <netinet/in.h>
+#    endif
+#    if HAVE_ARPA_INET_H
+#       include <arpa/inet.h>
+#    endif
+#endif
+
+#if ENABLE_NLS
+#   include <libintl.h>
+#   define _(String) gettext(String)
+#else
+#   define _(String) String
+#endif
+
+#include "header.h"
+#include "encoding.h"
+#include "dic_exception.h"
+
+
+// Note: swap4 is duplicated in dic.cpp
+#if defined(WORDS_BIGENDIAN)
+static uint32_t swap4(uint32_t v)
+{
+    uint32_t r;
+    uint8_t *pv = (uint8_t*)&v;
+    uint8_t *pr = (uint8_t*)&r;
+
+    pr[0] = pv[3];
+    pr[1] = pv[2];
+    pr[2] = pv[1];
+    pr[3] = pv[0];
+
+    return r;
+}
+
+// Nothing to do on big-endian machines
+#   define ntohll(x) (x)
+#   define htonll(x) (x)
+#else
+static inline uint64_t htonll(uint64_t host64)
+{
+    return (((uint64_t)htonl((host64 << 32) >> 32)) << 32) | htonl(host64 >> 
32);
+}
+
+static inline uint64_t ntohll(uint64_t net64)
+{
+    return htonll(net64);
+}
+#endif
+
+
+/**
+ * Keyword included in dictionary headers
+ * Implies little endian storage on words
+ */
+#define _COMPIL_KEYWORD_ "_COMPILED_DICTIONARY_"
+
+/** Old format of the header (i.e. version 0) */
+struct Dict_header_old
+{
+    /// Identification string
+    char ident[sizeof(_COMPIL_KEYWORD_)];
+    /// Version of the serialization format
+    uint8_t version;
+    /// Unused at the moment, reserved for further use
+    char unused;
+    uint32_t root;
+    uint32_t nwords;
+    /// Information about the compression
+    //@{
+    uint32_t edgesused;
+    uint32_t nodesused;
+    uint32_t nodessaved;
+    uint32_t edgessaved;
+    //@}
+};
+
+// Do not change these values, as they impact the size of the structure!
+// Note: they are chosen carefully to avoid alignment issues
+#define _MAX_USER_HOST_ 32
+#define _MAX_DIC_NAME_SIZE_ 30
+#define _MAX_LETTERS_NB_ 63
+#define _MAX_LETTERS_SIZE_ 80
+
+/** Extension of the old format (used in version 1)*/
+struct Dict_header_ext
+{
+    // Time when the dictionary was compressed
+    // (number of seconds since the Epoch)
+    uint64_t compressDate;
+    // Build information
+    char userHost[_MAX_USER_HOST_];
+    // Size taken by the build information
+    uint32_t userHostSize;
+
+    // --- we have a multiple of 64 bytes here
+
+    // Compression algorithm (1 = DAWG, 2 = GADDAG)
+    uint8_t algorithm;
+    // Variant used in the rules (XXX: currently unused)
+    uint8_t variant;
+
+    // --- we have a multiple of 64 bytes here
+
+    // Dictionary official name and version (e.g.: ODS 5.0)
+    char dicName[_MAX_DIC_NAME_SIZE_];
+    // Size taken by the dictionary name
+    uint32_t dicNameSize;
+
+    // --- we have a multiple of 64 bytes here
+
+    // Letters used in the dictionary
+    // We should have: nbLetters <= lettersSize <= _MAX_LETTERS_SIZE_
+    // and:            nbLetters <= _MAX_LETTERS_NB_
+    // The letters themselves, in UTF-8
+    char letters[_MAX_LETTERS_SIZE_];
+    // Size taken by the letters
+    uint32_t lettersSize;
+    // Number of letters (XXX: in theory useless, but allows a sanity check)
+    uint32_t nbLetters;
+
+    // --- we have a multiple of 64 bytes here
+
+    // Points of the letters (indexed by their code)
+    // The "+ 1" is there for struct alignment
+    uint8_t points[_MAX_LETTERS_NB_ + 1];
+    // Frequency of the letters (indexed by their code)
+    // The "+ 1" is there for struct alignment
+    uint8_t frequency[_MAX_LETTERS_NB_ + 1];
+    // Bitfield indicating whether letters are vowels
+    uint64_t vowels;
+    // Bitfield indicating whether letters are consonants
+    uint64_t consonants;
+
+    // --- we have a multiple of 64 bytes here
+};
+
+
+Header::Header(istream &iStream)
+    : m_root(0), m_nbWords(0), m_nodesUsed(0), m_edgesUsed(0),
+      m_nodesSaved(0), m_edgesSaved(0), m_type(kDAWG)
+{
+    // Simply delegate to the read() method
+    // The code is not moved here because I find it more natural to have a
+    // read() method symmetrical to the write() one
+    read(iStream);
+    buildMapCodeFromChar();
+}
+
+
+Header::Header(const DictHeaderInfo &iInfo)
+{
+    // Use the latest serialization format
+    m_version = 1;
+
+    // Sanity checks
+    if (iInfo.letters.size() > _MAX_LETTERS_NB_)
+    {
+        ostringstream ss;
+        ss << _MAX_LETTERS_NB_;
+        throw DicException("Header::Header: Too many different letters for "
+                           "the current format; only " + ss.str() +
+                           " are supported");
+    }
+    if (iInfo.points.size() != iInfo.letters.size())
+    {
+        throw DicException("Header::Header: Different sizes for "
+                           "iInfo.points and iInfo.letters");
+    }
+    if (iInfo.frequency.size() != iInfo.letters.size())
+    {
+        throw DicException("Header::Header: Different sizes for "
+                           "iInfo.frequency and iInfo.letters");
+    }
+    if (iInfo.vowels.size() != iInfo.letters.size())
+    {
+        throw DicException("Header::Header: Different sizes for "
+                           "iInfo.vowels and iInfo.letters");
+    }
+    if (iInfo.consonants.size() != iInfo.letters.size())
+    {
+        throw DicException("Header::Header: Different sizes for "
+                           "iInfo.consonants and iInfo.letters");
+    }
+
+    m_compressDate = time(NULL);
+    m_userHost = convertToWc(ELIOT_COMPILE_BY + string("@") + 
ELIOT_COMPILE_HOST);
+    m_root = iInfo.root;
+    m_nbWords = iInfo.nwords;
+    m_nodesUsed = iInfo.nodesused;
+    m_edgesUsed = iInfo.edgesused;
+    m_nodesSaved = iInfo.nodessaved;
+    m_edgesSaved = iInfo.edgessaved;
+    m_type = iInfo.dawg ? kDAWG : kGADDAG;
+    m_dicName = iInfo.dicName;
+    m_letters = iInfo.letters;
+    m_points = iInfo.points;
+    m_frequency = iInfo.frequency;
+    m_vowels = iInfo.vowels;
+    m_consonants = iInfo.consonants;
+
+    buildMapCodeFromChar();
+}
+
+
+void Header::buildMapCodeFromChar()
+{
+    for (unsigned int i = 0; i < m_letters.size(); ++i)
+    {
+        // We don't differentiate uppercase and lowercase letters
+        m_mapCodeFromChar[towlower(m_letters[i])] = i + 1;
+        m_mapCodeFromChar[towupper(m_letters[i])] = i + 1;
+    }
+}
+
+
+wchar_t Header::getCharFromCode(unsigned int iCode) const
+{
+    // Safety check
+    if (iCode == 0 || iCode > m_letters.size())
+    {
+        ostringstream ss;
+        ss << iCode;
+        throw DicException("Header::getCharFromCode: no letter for code " + 
ss.str());
+    }
+    return m_letters[iCode - 1];
+}
+
+
+unsigned int Header::getCodeFromChar(wchar_t iChar) const
+{
+    map<wchar_t, unsigned int>::const_iterator pair =
+        m_mapCodeFromChar.find(iChar);
+    if (pair == m_mapCodeFromChar.end())
+    {
+        throw DicException("Header::getCodeFromChar: No code for letter " +
+                           convertToMb(iChar));
+    }
+    return pair->second;
+}
+
+
+void Header::read(istream &iStream)
+{
+    Dict_header_old aHeader;
+    iStream.read((char*)&aHeader, sizeof(Dict_header_old));
+    if (iStream.gcount() != sizeof(Dict_header_old))
+        throw DicException("Header::read: expected to read more bytes");
+
+    // Check the identification string
+    if (string(aHeader.ident) != _COMPIL_KEYWORD_)
+        throw DicException("Header::read: incorrect header keyword; is it a 
dictionary file?");
+
+    m_version = aHeader.version;
+
+    // Handle endianness
+    if (m_version == 0)
+    {
+#if defined(WORDS_BIGENDIAN)
+        aHeader.root       = swap4(aHeader.root);
+        aHeader.nwords     = swap4(aHeader.nwords);
+        aHeader.nodesused  = swap4(aHeader.nodesused);
+        aHeader.edgesused  = swap4(aHeader.edgesused);
+        aHeader.nodessaved = swap4(aHeader.nodessaved);
+        aHeader.edgessaved = swap4(aHeader.edgessaved);
+#endif
+        m_root = aHeader.root;
+        m_nbWords = aHeader.nwords;
+        m_nodesUsed = aHeader.nodesused;
+        m_edgesUsed = aHeader.edgesused;
+        m_nodesSaved = aHeader.nodessaved;
+        m_edgesSaved = aHeader.edgessaved;
+    }
+    else
+    {
+        m_root = ntohl(aHeader.root);
+        m_nbWords = ntohl(aHeader.nwords);
+        m_nodesUsed = ntohl(aHeader.nodesused);
+        m_edgesUsed = ntohl(aHeader.edgesused);
+        m_nodesSaved = ntohl(aHeader.nodessaved);
+        m_edgesSaved = ntohl(aHeader.edgessaved);
+    }
+
+    if (m_version == 0)
+    {
+        m_compressDate = 0;
+        m_userHost = convertToWc(_("Unknown (old format)"));
+        m_dicName = convertToWc(_("Unknown (old format)"));
+
+        // In version 0, the letters, points, frequency,
+        // vowels and consonants were hard-coded...
+        m_letters = convertToWc("ABCDEFGHIJKLMNOPQRSTUVWXYZ?");
+
+        static const uint8_t Frenchpoints[] =
+        {
+            // A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ?
+               1,3,3,2, 1,4,2,4,1,8,10,1,2,1,1,3,8,1,1,1,1,4,10,10,10,10,0
+        };
+
+        static const uint8_t FrenchFrequency[] =
+        {
+            // A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ?
+               9,2,2,3,15,2,2,2,8,1, 1,5,3,6,6,2,1,6,6,6,6,2, 1, 1, 1, 1,2
+        };
+
+        // The jokers and the 'Y' can be considered both as vowels or 
consonants
+        static const uint8_t FrenchVowels[] =
+        {
+            // A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ?
+               1,0,0,0, 1,0,0,0,1,0, 0,0,0,0,1,0,0,0,0,0,1,0, 0, 0, 1, 0,1
+        };
+
+        static const uint8_t FrenchConsonants[] =
+        {
+            // A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ?
+               0,1,1,1, 0,1,1,1,0,1, 1,1,1,1,0,1,1,1,1,1,0,1, 1, 1, 1, 1,1
+        };
+
+        for (unsigned int i = 0; i < m_letters.size(); ++i)
+        {
+            m_points.push_back(Frenchpoints[i]);
+            m_frequency.push_back(FrenchFrequency[i]);
+            m_vowels.push_back(FrenchVowels[i]);
+            m_consonants.push_back(FrenchConsonants[i]);
+        }
+    }
+    else
+    {
+        // This header doesn't use the old serialization format, so read the
+        // extension as well
+        Dict_header_ext aHeaderExt;
+        iStream.read((char*)&aHeaderExt, sizeof(Dict_header_ext));
+        if (iStream.gcount() != sizeof(Dict_header_ext))
+            throw DicException("Header::read: expected to read more bytes");
+
+        // Handle endianness in the extension
+        aHeaderExt.compressDate = ntohll(aHeaderExt.compressDate);
+        aHeaderExt.userHostSize = ntohl(aHeaderExt.userHostSize);
+        aHeaderExt.dicNameSize = ntohl(aHeaderExt.dicNameSize);
+        aHeaderExt.lettersSize = ntohl(aHeaderExt.lettersSize);
+        aHeaderExt.nbLetters = ntohl(aHeaderExt.nbLetters);
+        aHeaderExt.vowels = ntohll(aHeaderExt.vowels);
+        aHeaderExt.consonants = ntohll(aHeaderExt.consonants);
+
+        m_compressDate = aHeaderExt.compressDate;
+
+        if (aHeaderExt.algorithm == kDAWG)
+            m_type = kDAWG;
+        else if (aHeaderExt.algorithm == kGADDAG)
+            m_type = kGADDAG;
+        else
+            throw DicException("Header::read: unrecognized algorithm type");
+
+        m_userHost = readFromUTF8(aHeaderExt.userHost, aHeaderExt.userHostSize,
+                                  "user and host information");
+
+        // Convert the dictionary letters from UTF-8 to wchar_t*
+        m_dicName = readFromUTF8(aHeaderExt.dicName, aHeaderExt.dicNameSize,
+                                 "dictionary name");
+
+        // Convert the dictionary letters from UTF-8 to wchar_t*
+        m_letters = readFromUTF8(aHeaderExt.letters, aHeaderExt.lettersSize,
+                                 "dictionary letters");
+        // Safety check: correct number of letters?
+        if (m_letters.size() != aHeaderExt.nbLetters)
+        {
+            throw DicException("Header::read: inconsistent header");
+        }
+
+        // Letters points and frequency
+        for (unsigned int i = 0; i < m_letters.size(); ++i)
+        {
+            m_points.push_back(aHeaderExt.points[i]);
+            m_frequency.push_back(aHeaderExt.frequency[i]);
+        }
+
+        // Vowels and consonants
+        for (unsigned int i = 0; i < m_letters.size(); ++i)
+        {
+            m_vowels.push_back(aHeaderExt.vowels & (1 << i));
+            m_consonants.push_back(aHeaderExt.consonants & (1 << i));
+        }
+
+    }
+}
+
+
+void Header::write(ostream &oStream) const
+{
+    Dict_header_old aHeader;
+    strcpy(aHeader.ident, _COMPIL_KEYWORD_);
+    aHeader.version = m_version;
+    aHeader.unused = 0;
+    aHeader.root = htonl(m_root);
+    aHeader.nwords = htonl(m_nbWords);
+    aHeader.nodesused = htonl(m_nodesUsed);
+    aHeader.edgesused = htonl(m_edgesUsed);
+    aHeader.nodessaved = htonl(m_nodesSaved);
+    aHeader.edgessaved = htonl(m_edgesSaved);
+
+    oStream.write((char*)&aHeader, sizeof(Dict_header_old));
+    if (!oStream.good())
+        throw DicException("Header::write: error when writing to file");
+
+    if (m_version != 0)
+    {
+        Dict_header_ext aHeaderExt;
+        aHeaderExt.compressDate = m_compressDate;
+        aHeaderExt.userHostSize =
+            writeInUTF8(m_userHost, aHeaderExt.userHost,
+                        _MAX_USER_HOST_, "user and host information");
+        aHeaderExt.algorithm = m_type;
+
+        // Convert the dictionary name to UTF-8
+        aHeaderExt.dicNameSize =
+            writeInUTF8(m_dicName, aHeaderExt.dicName,
+                        _MAX_DIC_NAME_SIZE_, "dictionary name");
+
+        // Convert the dictionary letters to UTF-8
+        aHeaderExt.lettersSize =
+            writeInUTF8(m_letters, aHeaderExt.letters,
+                        _MAX_LETTERS_SIZE_, "dictionary letters");
+        aHeaderExt.nbLetters = (uint32_t)m_letters.size();
+
+        // Letters points and frequency
+        for (unsigned int i = 0; i < m_letters.size(); ++i)
+        {
+            aHeaderExt.points[i] = m_points[i];
+            aHeaderExt.frequency[i] = m_frequency[i];
+        }
+
+        // Vowels and consonants
+        aHeaderExt.vowels = 0;
+        aHeaderExt.consonants = 0;
+        for (unsigned int i = 0; i < m_letters.size(); ++i)
+        {
+            if (m_vowels[i])
+                aHeaderExt.vowels |= 1 << i;
+            if (m_consonants[i])
+                aHeaderExt.consonants |= 1 << i;
+        }
+
+        // Handle endianness in the extension
+        aHeaderExt.userHostSize = htonl(aHeaderExt.userHostSize);
+        aHeaderExt.compressDate = htonll(aHeaderExt.compressDate);
+        aHeaderExt.dicNameSize = htonl(aHeaderExt.dicNameSize);
+        aHeaderExt.lettersSize = htonl(aHeaderExt.lettersSize);
+        aHeaderExt.nbLetters = htonl(aHeaderExt.nbLetters);
+        aHeaderExt.vowels = htonll(aHeaderExt.vowels);
+        aHeaderExt.consonants = htonll(aHeaderExt.consonants);
+
+        // Write the extension
+        oStream.write((char*)&aHeaderExt, sizeof(Dict_header_ext));
+        if (!oStream.good())
+            throw DicException("Header::write: error when writing to file");
+    }
+}
+
+
+void Header::print() const
+{
+    printf(_("dictionary name: %s\n"), convertToMb(m_dicName).c_str());
+    if (m_version)
+    {
+        char buf[50];
+        strftime(buf, sizeof(buf), "%c", gmtime(&m_compressDate));
+        printf(_("compressed on: %s\n"), buf);
+    }
+    else
+    {
+        printf(_("compressed on: Unknown date (old format)\n"));
+    }
+    printf(_("compressed using a binary compiled by: %s\n"), 
convertToMb(m_userHost).c_str());
+    printf(_("dictionary type: %s\n"), m_type == kDAWG ? "DAWG" : "GADDAG");
+    printf(_("letters: %s\n"), convertToMb(m_letters).c_str());
+    printf(_("number of letters: %lu\n"), (long unsigned int)m_letters.size());
+    printf(_("number of words: %d\n"), m_nbWords);
+    long unsigned int size =
+        sizeof(Dict_header_old) + (m_version ? sizeof(Dict_header_ext) : 0);
+    printf(_("header size: %lu bytes\n"), size);
+    printf(_("root: %d (edge)\n"), m_root);
+    printf(_("nodes: %d used + %d saved\n"), m_nodesUsed, m_nodesSaved);
+    printf(_("edges: %d used + %d saved\n"), m_edgesUsed, m_edgesSaved);
+    printf("===============================================\n");
+    printf(_("letter | points | frequency | vowel | consonant\n"));
+    printf("-------+--------+-----------+-------+----------\n");
+    for (unsigned int i = 0; i < m_letters.size(); ++i)
+    {
+        printf("  %s   |   %2d   |    %2d     |   %d   |    %d\n",
+               padAndConvert(wstring(1, m_letters[i]), 2).c_str(),
+               m_points[i], m_frequency[i], m_vowels[i], m_consonants[i]);
+    }
+    printf("===============================================\n");
+}
+

Index: dic/header.h
===================================================================
RCS file: dic/header.h
diff -N dic/header.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/header.h        8 Jan 2008 13:52:35 -0000       1.2
@@ -0,0 +1,191 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#ifndef _HEADER_H
+#define _HEADER_H
+
+#include <iosfwd>
+#include <map>
+#include <vector>
+#include <time.h>
+
+using namespace std;
+
+
+/**
+ * Structure used to create a Header object.
+ * Note: this structure doesn't pretend to map the way the data is stored in a
+ * file. For (de)serialization, always use a Header object
+ */
+struct DictHeaderInfo
+{
+    uint32_t root;
+    uint32_t nwords;
+    uint32_t edgesused;
+    uint32_t nodesused;
+    uint32_t nodessaved;
+    uint32_t edgessaved;
+    bool dawg;
+    wstring dicName;
+    wstring letters;
+    vector<uint8_t> points;
+    vector<uint8_t> frequency;
+    vector<bool> vowels;
+    vector<bool> consonants;
+};
+
+
+/**
+ * Dictionary header.
+ * There are 2 ways to create a Header object:
+ *  - fill a DictHeaderInfo structure and give it in the constructor of the
+ *    Header class (usually to call write() afterwards)
+ *  - give it an input stream on a compiled dictionary
+ *
+ * The class is immutable: a Header object cannot be modified after creation.
+ *
+ * Serialization:
+ * Several formats of headers will be handled by this class, even though only
+ * the first one is handled at the moment. You can use the write() method to
+ * write the latest version of the header into a given file.
+ * When using the constructor taking an input stream, all the header versions
+ * are supported.
+ */
+class Header
+{
+public:
+
+    /// Dictionary type
+    enum DictType
+    {
+        kDAWG = 1,
+        kGADDAG = 2
+    };
+
+    /**
+     * Constructor from an input stream
+     * @param iStream: Input stream where to read the header
+     */
+    Header(istream &iStream);
+
+    /**
+     * Constructor from a filled structure
+     * @param iInfo: info needed to build the header
+     */
+    Header(const DictHeaderInfo &iInfo);
+
+    /// Return the version of the dictionary format
+    uint8_t getVersion() const { return m_version; }
+
+    /// Getters
+    //@{
+    unsigned int getRoot()         const { return m_root; }
+    unsigned int getNbWords()      const { return m_nbWords; }
+    unsigned int getNbNodesUsed()  const { return m_nodesUsed; }
+    unsigned int getNbEdgesUsed()  const { return m_edgesUsed; }
+    unsigned int getNbNodesSaved() const { return m_nodesSaved; }
+    unsigned int getNbEdgesSaved() const { return m_edgesSaved; }
+    DictType     getType()         const { return m_type; }
+    wstring      getLetters()      const { return m_letters; }
+    uint8_t      getPoints(unsigned int iCode) const { return m_points[iCode - 
1]; }
+    uint8_t      getFrequency(unsigned int iCode) const { return 
m_frequency[iCode - 1]; }
+    bool         isVowel(unsigned int iCode) const { return m_vowels[iCode - 
1]; }
+    bool         isConsonant(unsigned int iCode) const { return 
m_consonants[iCode - 1]; }
+    //@}
+
+    /**
+     * Return the letter corresponding to the given code
+     */
+    wchar_t getCharFromCode(unsigned int iCode) const;
+
+    /**
+     * Return the code corresponding to the given letter
+     */
+    unsigned int getCodeFromChar(wchar_t iChar) const;
+
+    /**
+     * Print a readable summary of the header on standard output
+     */
+    void print() const;
+
+    /**
+     * Write the header to a file, using the latest format
+     * @param oStream: Output stream where to write the header
+     * @exception: Throw a DicException in case of problem
+     */
+    void write(ostream &oStream) const;
+
+private:
+    /// Version of the serialization
+    uint8_t m_version;
+
+    wstring m_userHost;
+    time_t m_compressDate;
+
+    uint32_t m_root;
+    uint32_t m_nbWords;
+    uint32_t m_nodesUsed;
+    uint32_t m_edgesUsed;
+    uint32_t m_nodesSaved;
+    uint32_t m_edgesSaved;
+
+    /// Specify whether the dictionary is a DAWG or a GADDAG
+    DictType m_type;
+
+    /// Dictionary name (e.g.: ODS 5.0)
+    wstring m_dicName;
+
+    /// The letters constituting the words of the dictionary
+    wstring m_letters;
+
+    /// Points of the letters
+    vector<uint8_t> m_points;
+
+    /// Frequency of the letters
+    vector<uint8_t> m_frequency;
+
+    /// Vowels
+    vector<bool> m_vowels;
+
+    /// Consonants
+    vector<bool> m_consonants;
+
+    map<wchar_t, unsigned int> m_mapCodeFromChar;
+
+    /**
+     * Load the header from a file
+     * @param iStream: Input stream where to read the header
+     * @exception: Throw a DicException in case of problem
+     */
+    void read(istream &iStream);
+
+    /** Build m_mapCodeFromChar */
+    void buildMapCodeFromChar();
+};
+
+
+#endif /* _HEADER_H */
+
+/// Local Variables:
+/// mode: c++
+/// mode: hs-minor
+/// c-basic-offset: 4
+/// indent-tabs-mode: nil
+/// End:

Index: dic/listdic.cpp
===================================================================
RCS file: dic/listdic.cpp
diff -N dic/listdic.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/listdic.cpp     8 Jan 2008 13:52:36 -0000       1.2
@@ -0,0 +1,187 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 1999-2007 Antoine Fraboulet & Olivier Teulière
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *          Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+/**
+ *  \file   listdic.c
+ *  \brief  Program used to list a dictionary
+ *  \author Antoine Fraboulet
+ *  \date   1999
+ */
+
+#include "config.h"
+
+#include <fstream>
+#include <iostream>
+#include <cstring>
+#include <cstdlib>
+#include <cstdio>
+#include <cstddef>
+
+#if ENABLE_NLS
+#   include <libintl.h>
+#   define _(String) gettext(String)
+#else
+#   define _(String) String
+#endif
+
+#include "header.h"
+#include "encoding.h"
+#include "dic_internals.h"
+#include "dic.h"
+
+using namespace std;
+
+
+template <typename DAWG_EDGE>
+static void print_dic_rec(ostream &out, const Dictionary &iDic, wchar_t *buf, 
wchar_t *s, DAWG_EDGE i)
+{
+    if (i.term)  /* edge points at a complete word */
+    {
+        *s = '\0';
+        out << convertToMb(buf) << endl;
+    }
+    if (i.ptr)
+    {           /* Compute index: is it non-zero ? */
+        const DAWG_EDGE *p = reinterpret_cast<const 
DAWG_EDGE*>(iDic.getEdgeAt(i.ptr));
+        do
+        {                         /* for each edge out of this node */
+            *s = iDic.getHeader().getCharFromCode(p->chr);
+            print_dic_rec(out, iDic, buf, s + 1, *p);
+        }
+        while (!(*p++).last);
+    }
+}
+
+
+template <typename DAWG_EDGE>
+void print_dic_list(const Dictionary &iDic)
+{
+    static wchar_t buf[80];
+    print_dic_rec(cout, iDic, buf, buf, *reinterpret_cast<const 
DAWG_EDGE*>(iDic.getEdgeAt(iDic.getRoot())));
+}
+
+
+template <typename DAWG_EDGE>
+static void print_node_hex(const Dictionary &dic, int i)
+{
+    union edge_t
+    {
+        DAWG_EDGE e;
+        uint32_t  s;
+    } ee;
+
+    ee.e = *reinterpret_cast<const DAWG_EDGE*>(dic.getEdgeAt(i));
+
+    printf("0x%04lx %08x |%4d ptr=%8d t=%d l=%d chr=%2d (%c)\n",
+           (unsigned long)i*sizeof(ee), (unsigned int)(ee.s),
+           i, ee.e.ptr, ee.e.term, ee.e.last, ee.e.chr, ee.e.chr +'a' -1);
+}
+
+
+template <typename DAWG_EDGE>
+void print_dic_hex(const Dictionary &iDic)
+{
+    printf(_("offset binary   | structure\n"));
+    printf("------ -------- | --------------------\n");
+    for (unsigned int i = 0; i < (iDic.getHeader().getNbEdgesUsed() + 1); i++)
+        print_node_hex<DAWG_EDGE>(iDic, i);
+}
+
+
+void usage(const string &iName)
+{
+    printf(_("usage: %s [-a|-h|-l|-x] dictionary\n"), iName.c_str());
+    printf(_("  -a: print all\n"));
+    printf(_("  -h: print header\n"));
+    printf(_("  -l: print dictionary word list\n"));
+    printf(_("  -x: print dictionary in hex\n"));
+}
+
+
+int main(int argc, char *argv[])
+{
+#if HAVE_SETLOCALE
+    // Set locale via LC_ALL
+    setlocale(LC_ALL, "");
+#endif
+
+#if ENABLE_NLS
+    // Set the message domain
+    bindtextdomain(PACKAGE, LOCALEDIR);
+    textdomain(PACKAGE);
+#endif
+
+    int arg_count;
+    int option_print_all      = 0;
+    int option_print_header   = 0;
+    int option_print_dic_hex  = 0;
+    int option_print_dic_list = 0;
+
+    if (argc < 3)
+    {
+        usage(argv[0]);
+        exit(1);
+    }
+
+    arg_count = 1;
+    while (argv[arg_count][0] == '-')
+    {
+        switch (argv[arg_count][1])
+        {
+            case 'a': option_print_all = 1; break;
+            case 'h': option_print_header = 1; break;
+            case 'l': option_print_dic_list = 1; break;
+            case 'x': option_print_dic_hex = 1; break;
+            default: usage(argv[0]); exit(2); break;
+        }
+        arg_count++;
+    }
+
+    try
+    {
+        Dictionary dic(argv[arg_count]);
+
+        if (option_print_header || option_print_all)
+        {
+            dic.getHeader().print();
+        }
+        if (option_print_dic_hex || option_print_all)
+        {
+            if (dic.getHeader().getVersion() == 0)
+                print_dic_hex<DicEdgeOld>(dic);
+            else
+                print_dic_hex<DicEdge>(dic);
+        }
+        if (option_print_dic_list || option_print_all)
+        {
+            if (dic.getHeader().getVersion() == 0)
+                print_dic_list<DicEdgeOld>(dic);
+            else
+                print_dic_list<DicEdge>(dic);
+        }
+        return 0;
+    }
+    catch (std::exception &e)
+    {
+        cerr << e.what() << endl;
+        return 1;
+    }
+}

Index: dic/regexp.cpp
===================================================================
RCS file: dic/regexp.cpp
diff -N dic/regexp.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/regexp.cpp      8 Jan 2008 13:52:36 -0000       1.2
@@ -0,0 +1,384 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 1999-2006 Antoine Fraboulet
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+/**
+ *  \file   regexp.c
+ *  \brief  Regular Expression functions
+ *  \author Antoine Fraboulet
+ *  \date   2005
+ */
+
+#include "config.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#ifdef HAVE_SYS_WAIT_H
+#   include <sys/wait.h>
+#endif
+#include <unistd.h>
+
+#include "dic.h"
+#include "regexp.h"
+#include "automaton.h"
+
+#ifndef PDBG
+#ifdef DEBUG_RE2
+#define PDBG(x) x
+#else
+#define PDBG(x)
+#endif
+#endif
+
+
+NODE* regexp_createNODE(int type, char v, NODE *fg, NODE *fd)
+{
+    NODE *x;
+    x=(NODE *)malloc(sizeof(NODE));
+    x->type      = type;
+    x->var       = v;
+    x->fd        = fd;
+    x->fg        = fg;
+    x->number    = 0;
+    x->position  = 0;
+    x->annulable = 0;
+    x->PP        = 0;
+    x->DP        = 0;
+    return x;
+}
+
+void regexp_delete_tree(NODE *root)
+{
+    if (root == NULL)
+        return;
+    regexp_delete_tree(root->fg);
+    regexp_delete_tree(root->fd);
+    free(root);
+}
+
+#ifdef DEBUG_RE
+static void print_node(FILE*, NODE *n, int detail);
+#endif
+
+/**
+ * computes position, annulable, PP, DP attributes
+ * @param r   = root
+ * @param p   = current leaf position
+ * @param n   = current node number
+ * @param ptl = position to letter
+ */
+
+void regexp_parcours(NODE* r, int *p, int *n, int ptl[])
+{
+    if (r == NULL)
+        return;
+
+    regexp_parcours(r->fg, p, n, ptl);
+    regexp_parcours(r->fd, p, n, ptl);
+
+    switch (r->type)
+    {
+        case NODE_VAR:
+            r->position = *p;
+            ptl[*p] = r->var;
+            *p = *p + 1;
+            r->annulable = 0;
+            r->PP = 1 << (r->position - 1);
+            r->DP = 1 << (r->position - 1);
+            break;
+        case NODE_OR:
+            r->position = 0;
+            r->annulable = r->fg->annulable || r->fd->annulable;
+            r->PP = r->fg->PP | r->fd->PP;
+            r->DP = r->fg->DP | r->fd->DP;
+            break;
+        case NODE_AND:
+            r->position = 0;
+            r->annulable = r->fg->annulable && r->fd->annulable;
+            r->PP = (r->fg->annulable) ? (r->fg->PP | r->fd->PP) : r->fg->PP;
+            r->DP = (r->fd->annulable) ? (r->fg->DP | r->fd->DP) : r->fd->DP;
+            break;
+        case NODE_PLUS:
+            r->position = 0;
+            r->annulable = 0;
+            r->PP = r->fg->PP;
+            r->DP = r->fg->DP;
+            break;
+        case NODE_STAR:
+            r->position = 0;
+            r->annulable = 1;
+            r->PP = r->fg->PP;
+            r->DP = r->fg->DP;
+            break;
+    }
+
+    r->number = *n;
+    *n = *n + 1;
+}
+
+/**
+ * computes possuivante
+ * @param r   = root
+ * @param PS  = next position
+ */
+
+void regexp_possuivante(NODE* r, int PS[])
+{
+    if (r == NULL)
+        return;
+
+    regexp_possuivante(r->fg, PS);
+    regexp_possuivante(r->fd, PS);
+
+    switch (r->type)
+    {
+        case NODE_AND:
+            /************************************/
+            /* \forall p \in DP(left)           */
+            /*     PS[p] = PS[p] \cup PP(right) */
+            /************************************/
+            for (int pos = 1; pos <= PS[0]; pos++)
+            {
+                if (r->fg->DP & (1 << (pos-1)))
+                    PS[pos] |= r->fd->PP;
+            }
+            break;
+        case NODE_PLUS:
+            /************************************/
+            /* == same as START                 */
+            /* \forall p \in DP(left)           */
+            /*     PS[p] = PS[p] \cup PP(left)  */
+            /************************************/
+            for (int pos = 1; pos <= PS[0]; pos++)
+            {
+                if (r->DP & (1 << (pos-1)))
+                    PS[pos] |= r->PP;
+            }
+            break;
+        case NODE_STAR:
+            /************************************/
+            /* \forall p \in DP(left)           */
+            /*     PS[p] = PS[p] \cup PP(left)  */
+            /************************************/
+            for (int pos = 1; pos <= PS[0]; pos++)
+            {
+                if (r->DP & (1 << (pos-1)))
+                    PS[pos] |= r->PP;
+            }
+            break;
+    }
+}
+
+/*////////////////////////////////////////////////
+// DEBUG only fonctions
+////////////////////////////////////////////////*/
+
+#ifdef DEBUG_RE
+void regexp_print_PS(int PS[])
+{
+    printf("** positions suivantes **\n");
+    for (int i = 1; i <= PS[0]; i++)
+    {
+        printf("%02d: 0x%08x\n", i, PS[i]);
+    }
+}
+#endif
+
+/*////////////////////////////////////////////////
+////////////////////////////////////////////////*/
+
+#ifdef DEBUG_RE
+void regexp_print_ptl(int ptl[])
+{
+    printf("** pos -> lettre: ");
+    for (int i = 1; i <= ptl[0]; i++)
+    {
+        printf("%d=%c ", i, ptl[i]);
+    }
+    printf("\n");
+}
+#endif
+
+/*////////////////////////////////////////////////
+////////////////////////////////////////////////*/
+
+void regexp_print_letter(FILE* f, char l)
+{
+    switch (l)
+    {
+        case RE_EPSILON:    fprintf(f, "( &  [%d])", l); break;
+        case RE_FINAL_TOK:  fprintf(f, "( #  [%d])", l);  break;
+        case RE_ALL_MATCH:  fprintf(f, "( .  [%d])", l);  break;
+        case RE_VOWL_MATCH: fprintf(f, "(:v: [%d])", l); break;
+        case RE_CONS_MATCH: fprintf(f, "(:c: [%d])", l); break;
+        case RE_USR1_MATCH: fprintf(f, "(:1: [%d])", l); break;
+        case RE_USR2_MATCH: fprintf(f, "(:2: [%d])", l); break;
+        default:
+            if (l < RE_FINAL_TOK)
+                fprintf(f, " (%c [%d]) ", l + 'a' - 1, l);
+            else
+                fprintf(f, " (liste %d)", l - RE_LIST_USER_END);
+            break;
+    }
+}
+
+/*////////////////////////////////////////////////
+////////////////////////////////////////////////*/
+
+void regexp_print_letter2(FILE* f, char l)
+{
+    switch (l)
+    {
+        case RE_EPSILON:    fprintf(f, "&"); break;
+        case RE_FINAL_TOK:  fprintf(f, "#");  break;
+        case RE_ALL_MATCH:  fprintf(f, ".");  break;
+        case RE_VOWL_MATCH: fprintf(f, ":v:"); break;
+        case RE_CONS_MATCH: fprintf(f, ":c:"); break;
+        case RE_USR1_MATCH: fprintf(f, ":1:"); break;
+        case RE_USR2_MATCH: fprintf(f, ":2:"); break;
+        default:
+            if (l < RE_FINAL_TOK)
+                fprintf(f, "%c", l + 'a' - 1);
+            else
+                fprintf(f, "l%d", l - RE_LIST_USER_END);
+            break;
+    }
+}
+
+/*////////////////////////////////////////////////
+////////////////////////////////////////////////*/
+
+#ifdef DEBUG_RE
+static void print_node(FILE* f, NODE *n, int detail)
+{
+    if (n == NULL)
+        return;
+
+    switch (n->type)
+    {
+        case NODE_VAR:
+            regexp_print_letter(f, n->var);
+            break;
+        case NODE_OR:
+            fprintf(f, "OR");
+            break;
+        case NODE_AND:
+            fprintf(f, "AND");
+            break;
+        case NODE_PLUS:
+            fprintf(f, "+");
+            break;
+        case NODE_STAR:
+            fprintf(f, "*");
+            break;
+    }
+    if (detail == 2)
+    {
+        fprintf(f, "\\n pos=%d\\n annul=%d\\n PP=0x%04x\\n DP=0x%04x",
+                n->position, n->annulable, n->PP, n->DP);
+    }
+}
+#endif
+
+/*////////////////////////////////////////////////
+////////////////////////////////////////////////*/
+
+#ifdef DEBUG_RE
+static void print_tree_nodes(FILE* f, NODE* n, int detail)
+{
+    if (n == NULL)
+        return;
+
+    print_tree_nodes(f, n->fg, detail);
+    print_tree_nodes(f, n->fd, detail);
+
+    fprintf(f, "%d [ label=\"", n->number);
+    print_node(f, n, detail);
+    fprintf(f, "\"];\n");
+}
+#endif
+
+/*////////////////////////////////////////////////
+////////////////////////////////////////////////*/
+
+#ifdef DEBUG_RE
+static void print_tree_edges(FILE *f, NODE *n)
+{
+    if (n == NULL)
+        return;
+
+    print_tree_edges(f, n->fg);
+    print_tree_edges(f, n->fd);
+
+    switch (n->type)
+    {
+        case NODE_OR:
+            fprintf(f, "%d -> %d;", n->number, n->fg->number);
+            fprintf(f, "%d -> %d;", n->number, n->fd->number);
+            break;
+        case NODE_AND:
+            fprintf(f, "%d -> %d;", n->number, n->fg->number);
+            fprintf(f, "%d -> %d;", n->number, n->fd->number);
+            break;
+        case NODE_PLUS:
+        case NODE_STAR:
+            fprintf(f, "%d -> %d;", n->number, n->fg->number);
+            break;
+    }
+}
+#endif
+
+/*////////////////////////////////////////////////
+////////////////////////////////////////////////*/
+
+#ifdef DEBUG_RE
+void regexp_print_tree(NODE* n, const string &iName, int detail)
+{
+    FILE *f = fopen(iName.c_str(), "w");
+    if (f == NULL)
+        return;
+    fprintf(f, "digraph %s {\n", iName.c_str());
+    print_tree_nodes(f, n, detail);
+    print_tree_edges(f, n);
+    fprintf(f, "fontsize=20;\n");
+    fprintf(f, "}\n");
+    fclose(f);
+
+#ifdef HAVE_SYS_WAIT_H
+    pid_t pid = fork();
+    if (pid > 0)
+    {
+        wait(NULL);
+    }
+    else if (pid == 0)
+    {
+        execlp("dotty", "dotty", iName.c_str(), NULL);
+        printf("exec dotty failed\n");
+        exit(1);
+    }
+#endif
+}
+#endif
+
+
+/// Local Variables:
+/// mode: hs-minor
+/// c-basic-offset: 2
+/// End:

Index: dic/regexpmain.cpp
===================================================================
RCS file: dic/regexpmain.cpp
diff -N dic/regexpmain.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/regexpmain.cpp  8 Jan 2008 13:52:36 -0000       1.2
@@ -0,0 +1,169 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Antoine Fraboulet
+ * Authors: Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+/**
+ *  \file   regexpmain.c
+ *  \brief  Program used to test regexp
+ *  \author Antoine Fraboulet
+ *  \date   2005
+ */
+
+#include "config.h"
+
+#include <exception>
+#include <iostream>
+#include <cstdlib>
+#include <cstring>
+
+#if ENABLE_NLS
+#   include <libintl.h>
+#   define _(String) gettext(String)
+#else
+#   define _(String) String
+#endif
+
+#include "dic.h"
+#include "regexp.h"
+#include "encoding.h"
+
+
+#define __UNUSED__ __attribute__((unused))
+
+/********************************************************/
+/********************************************************/
+/********************************************************/
+
+const unsigned int all_letter[DIC_LETTERS] =
+{
+    /*                      1  1 1 1 1 1 1 1 1 1 2 2 2  2  2  2  2 */
+    /* 0 1 2 3 4  5 6 7 8 9 0  1 2 3 4 5 6 7 8 9 0 1 2  3  4  5  6 */
+    /* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z */
+       0,1,1,1,1, 1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1, 1, 1, 1, 1
+};
+
+const unsigned int vowels[DIC_LETTERS] =
+{
+    /* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z */
+       0,1,0,0,0, 1,0,0,0,1,0, 0,0,0,0,1,0,0,0,0,0,1,0, 0, 0, 1, 0
+};
+
+const unsigned int consonants[DIC_LETTERS] =
+{
+    /* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z */
+       0,0,1,1,1, 0,1,1,1,0,1, 1,1,1,1,0,1,1,1,1,1,0,1, 1, 1, 1, 1
+};
+
+void init_letter_lists(struct search_RegE_list_t *iList)
+{
+    memset (iList, 0, sizeof(*iList));
+    iList->minlength = 1;
+    iList->maxlength = 15;
+    iList->valid[0] = 1; // all letters
+    iList->symbl[0] = RE_ALL_MATCH;
+    iList->valid[1] = 1; // vowels
+    iList->symbl[1] = RE_VOWL_MATCH;
+    iList->valid[2] = 1; // consonants
+    iList->symbl[2] = RE_CONS_MATCH;
+    for (int i = 0; i < DIC_LETTERS; i++)
+    {
+        iList->letters[0][i] = all_letter[i];
+        iList->letters[1][i] = vowels[i];
+        iList->letters[2][i] = consonants[i];
+    }
+    iList->valid[3] = 0; // user defined list 1
+    iList->symbl[3] = RE_USR1_MATCH;
+    iList->valid[4] = 0; // user defined list 2
+    iList->symbl[4] = RE_USR2_MATCH;
+}
+
+/********************************************************/
+/********************************************************/
+/********************************************************/
+void usage(const char *iBinaryName)
+{
+    cerr << _("usage: %s dictionary") << iBinaryName << endl;
+    cerr << _("   dictionary: path to eliot dawg dictionary") << endl;
+}
+
+
+int main(int argc, char* argv[])
+{
+#if HAVE_SETLOCALE
+    // Set locale via LC_ALL
+    setlocale(LC_ALL, "");
+#endif
+
+#if ENABLE_NLS
+    // Set the message domain
+    bindtextdomain(PACKAGE, LOCALEDIR);
+    textdomain(PACKAGE);
+#endif
+
+    if (argc != 2)
+    {
+        usage(argv[0]);
+        return 0;
+    }
+
+    try
+    {
+        Dictionary dic(argv[1]);
+
+        char er[200];
+        strcpy(er, ".");
+
+        struct search_RegE_list_t regList;
+        while (strcmp(er, ""))
+        {
+            cout << 
"**************************************************************" << endl;
+            cout << 
"**************************************************************" << endl;
+            cout << _("enter a regular expression:") << endl;
+            fgets(er, sizeof(er), stdin);
+            /* strip \n */
+            er[strlen(er) - 1] = '\0';
+            if (strcmp(er, "") == 0)
+                break;
+
+            /* automaton */
+            init_letter_lists(&regList);
+            list<wstring> wordList;
+            dic.searchRegExp(convertToWc(er), wordList, &regList);
+
+            cout << _("result:") << endl;
+            list<wstring>::const_iterator it;
+            for (it = wordList.begin(); it != wordList.end(); it++)
+            {
+                cerr << convertToMb(*it) << endl;
+            }
+        }
+
+        return 0;
+    }
+    catch (std::exception &e)
+    {
+        std::cerr << e.what() << endl;
+        return 1;
+    }
+    catch (...)
+    {
+        std::cerr << "Unkown exception taken" << endl;
+        return 1;
+    }
+}

Index: dic/tile.cpp
===================================================================
RCS file: dic/tile.cpp
diff -N dic/tile.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/tile.cpp        8 Jan 2008 13:52:36 -0000       1.2
@@ -0,0 +1,150 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière & Antoine Fraboulet
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *          Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#include <sstream>
+#include <string>
+#include <wctype.h>
+#include "tile.h"
+#include "header.h"
+#include "encoding.h"
+#include "dic_exception.h"
+
+
+const Header * Tile::m_header = NULL;
+Tile Tile::m_TheJoker;
+
+
+Tile::Tile(wchar_t c)
+{
+    if (iswalpha(c))
+    {
+        m_joker = iswlower(c);
+        m_char = towupper(c);
+        m_code = m_header->getCodeFromChar(m_char);
+    }
+    else if (c == kTILE_JOKER)
+    {
+        m_joker = true;
+        m_char = kTILE_JOKER;
+        m_code = m_header->getCodeFromChar(m_char);
+    }
+    else if (c == kTILE_DUMMY)
+    {
+        // The char and the code are chosen to be different from any possible
+        // real tile
+        m_joker = false;
+        m_char = kTILE_DUMMY;
+        m_code = 0;
+    }
+    else
+    {
+        ostringstream ss;
+        ss << "Tile::Tile: Unknown character: " << convertToMb(c);
+        throw DicException(ss.str());
+    }
+}
+
+
+bool Tile::isVowel() const
+{
+    if (m_code == 0)
+        throw DicException("Tile::isVowel: Invalid tile");
+    return m_header->isVowel(m_code);
+}
+
+
+bool Tile::isConsonant() const
+{
+    if (m_code == 0)
+        throw DicException("Tile::isConsonant: Invalid tile");
+    return m_header->isConsonant(m_code);
+}
+
+
+unsigned int Tile::maxNumber() const
+{
+    if (m_code == 0)
+        throw DicException("Tile::maxNumber: Invalid tile");
+    return m_header->getFrequency(m_code);
+}
+
+
+unsigned int Tile::getPoints() const
+{
+    if (m_code == 0)
+        throw DicException("Tile::getPoints: Invalid tile");
+    return m_header->getPoints(m_code);
+}
+
+
+wchar_t Tile::toChar() const
+{
+    if (m_joker)
+    {
+        if (iswalpha(m_char))
+            return towlower(m_char);
+        else
+            return kTILE_JOKER;
+    }
+    return m_char;
+}
+
+
+unsigned int Tile::toCode() const
+{
+    return m_code;
+}
+
+
+bool Tile::operator<(const Tile &iOther) const
+{
+    if (m_joker)
+        return false;
+    else if (iOther.m_joker)
+        return true;
+    else
+        return m_char < iOther.m_char;
+}
+
+
+bool Tile::operator==(const Tile &iOther) const
+{
+    if (m_joker || iOther.m_joker)
+    {
+        if (m_joker != iOther.m_joker)
+            return false;
+        return m_char == iOther.m_char;
+    }
+    return m_char == iOther.m_char;
+}
+
+
+bool Tile::operator!=(const Tile &iOther) const
+{
+    return !(*this == iOther);
+}
+
+/// Local Variables:
+/// mode: c++
+/// mode: hs-minor
+/// c-basic-offset: 4
+/// indent-tabs-mode: nil
+/// End:

Index: dic/tile.h
===================================================================
RCS file: dic/tile.h
diff -N dic/tile.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/tile.h  8 Jan 2008 13:52:36 -0000       1.2
@@ -0,0 +1,96 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2005-2007 Olivier Teulière & Antoine Fraboulet
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *          Antoine Fraboulet <antoine.fraboulet @@ free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#ifndef _TILE_H_
+#define _TILE_H_
+
+#include <list>
+#include <vector>
+
+using namespace std;
+
+class Header;
+
+
+/*************************
+ * A Tile is the internal representation
+ * used within the game library to
+ * handle letters
+ *************************/
+
+class Tile
+{
+    friend class Dictionary;
+public:
+
+    // a lowercase character is always a joker
+    // - this permits to detect joker in already played games
+    // - we need to pay attention when inserting characters taken
+    //   from user input
+
+    Tile(wchar_t c = kTILE_DUMMY);
+
+    bool isEmpty() const        { return m_char == kTILE_DUMMY; }
+    bool isJoker() const        { return m_joker; }
+    bool isVowel() const;
+    bool isConsonant() const;
+    unsigned int maxNumber() const;
+    unsigned int getPoints() const;
+    wchar_t toChar() const;
+    unsigned int toCode() const;
+
+    static const Tile &Joker()  { return m_TheJoker; }
+
+    bool operator <(const Tile &iOther) const;
+    bool operator ==(const Tile &iOther) const;
+    bool operator !=(const Tile &iOther) const;
+
+private:
+    wchar_t m_char;
+    bool m_joker;
+
+    /**
+     * Internal code, used in the dictionary to represent the letter.
+     * It is mainly used by the Cross class.
+     */
+    int m_code;
+
+    static const wchar_t kTILE_DUMMY = L'%';
+    static const wchar_t kTILE_JOKER = L'?';
+
+    // Special tiles are declared static
+    static Tile m_TheJoker;
+
+    /// Dictionary header
+    static const Header *m_header;
+
+    /// Update the dictionary header
+    static void SetHeader(const Header &iHeader) { m_header = &iHeader; }
+};
+
+#endif
+
+/// Local Variables:
+/// mode: c++
+/// mode: hs-minor
+/// c-basic-offset: 4
+/// indent-tabs-mode: nil
+/// End:

Index: game/move.cpp
===================================================================
RCS file: game/move.cpp
diff -N game/move.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ game/move.cpp       8 Jan 2008 13:52:38 -0000       1.2
@@ -0,0 +1,107 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#include <algorithm>
+#include <wctype.h>
+
+#include "move.h"
+
+
+Move::Move(const Round &iRound)
+    : m_score(0), m_round(iRound)
+{
+    m_type = VALID_ROUND;
+    m_score = m_round.getPoints();
+}
+
+
+Move::Move(const wstring &iWord, const wstring &iCoord)
+    : m_word(iWord), m_coord(iCoord)
+{
+    m_type = INVALID_WORD;
+    m_score = 0;
+}
+
+
+Move::Move(const wstring &iLetters)
+    : m_score(0), m_letters(iLetters)
+{
+    // Make the letters uppercase
+    std::transform(m_letters.begin(), m_letters.end(),
+                   m_letters.begin(), towupper);
+
+    if (m_letters.empty())
+        m_type = PASS;
+    else
+        m_type = CHANGE_LETTERS;
+}
+
+
+const Round & Move::getRound() const
+{
+    if (m_type != VALID_ROUND)
+    {
+        // FIXME: throw an exception object instead
+        throw 1;
+    }
+    return m_round;
+}
+
+
+const wstring & Move::getBadWord() const
+{
+    if (m_type != INVALID_WORD)
+    {
+        // FIXME: throw an exception object instead
+        throw 1;
+    }
+    return m_word;
+}
+
+
+const wstring & Move::getBadCoord() const
+{
+    if (m_type != INVALID_WORD)
+    {
+        // FIXME: throw an exception object instead
+        throw 1;
+    }
+    return m_coord;
+}
+
+
+const wstring & Move::getChangedLetters() const
+{
+    if (m_type != CHANGE_LETTERS &&
+        m_type != PASS)
+    {
+        // FIXME: throw an exception object instead
+        throw 1;
+    }
+    return m_letters;
+}
+
+
+wstring Move::toString() const
+{
+    // TODO
+    return L"";
+}
+

Index: game/move.h
===================================================================
RCS file: game/move.h
diff -N game/move.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ game/move.h 8 Jan 2008 13:52:38 -0000       1.2
@@ -0,0 +1,134 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#ifndef _MOVE_H
+#define _MOVE_H
+
+#include <string>
+
+#include "round.h"
+
+using std::wstring;
+
+
+/**
+ * A Move is what a player can do during the game:
+ *  - play a valid word
+ *  - play an invalid or misplaced word
+ *  - pass the turn (freegame only)
+ *  - change letters (freegame only)
+ *  - play nothing (timeout) (not supported yet)
+ *
+ * Moves are useful to record what happened, even if the board doesn't keep
+ * a trace of the move (e.g.: an invalid move which was rejected will still
+ * be remembered in the player history).
+ *
+ * Currently, moves are not used by the interfaces (they are only used
+ * internally), but this could change in the future.
+ */
+class Move
+{
+    public:
+        /**
+         * Constructor taking a (valid) round
+         */
+        explicit Move(const Round &iRound);
+
+        /**
+         * Constructor taking a word and its coordinates, corresponding
+         * to an invalid move by the player (invalid word, invalid coordinates,
+         * letters not corresponding to the rack, ...)
+         */
+        explicit Move(const wstring &iWord, const wstring &iCoord);
+
+        /**
+         * Constructor taking letters to change.
+         * An empty string means that the player simply passes without
+         * changing any letter.
+         * The given letters must have been already validated for correctness.
+         */
+        explicit Move(const wstring &iLetters);
+
+        enum Type
+        {
+            VALID_ROUND,
+            INVALID_WORD,
+            PASS,
+            CHANGE_LETTERS
+        };
+
+        /// Return the type of move
+        Type getType() const { return m_type; }
+
+        /// Get the score of this move (0 unless the round is valid)
+        int getScore() const { return m_score; };
+
+        /**
+         * Return the round associated with the move, or throw an exception
+         * if this move was not constructed from a valid round
+         */
+        const Round & getRound() const;
+
+        /**
+         * Return the word played at this move associated with the move, or
+         * throw an exception if this move was not constructed from an invalid
+         * pair (word, coord)
+         */
+        const wstring & getBadWord() const;
+
+        /**
+         * Return the coordinates of the (incorrect) word played at this move,
+         * or throw an exception if this move was not constructed from an
+         * invalid pair (cord, coord)
+         */
+        const wstring & getBadCoord() const;
+
+        /**
+         * Return the changed letters (possibly an empty string if the player
+         * simply wanted to pass the turn), or throw an exception if this move
+         * does not correspond to a passed turn
+         */
+        const wstring & getChangedLetters() const;
+
+        /// To help debugging
+        wstring toString() const;
+
+    private:
+        /// Type of move
+        Type m_type;
+
+        /// Score associated with this move
+        int m_score;
+
+        /// Round played at this turn
+        Round m_round;
+
+        /// Word played (incorrectly)
+        wstring m_word;
+
+        /// Coordinates of the word played (incorrectly)
+        wstring m_coord;
+
+        /// Changed letters (or empty string for passed turn)
+        wstring m_letters;
+};
+
+#endif
+

Index: game/settings.cpp
===================================================================
RCS file: game/settings.cpp
diff -N game/settings.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ game/settings.cpp   8 Jan 2008 13:52:39 -0000       1.2
@@ -0,0 +1,134 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#include <cstdlib>
+
+#include "settings.h"
+
+
+Settings *Settings::m_instance = NULL;
+
+
+Settings & Settings::Instance()
+{
+    if (m_instance == NULL)
+    {
+        m_instance = new Settings;
+    }
+    return *m_instance;
+}
+
+
+void Settings::Destroy()
+{
+    delete m_instance;
+    m_instance = NULL;
+}
+
+
+Settings::Settings()
+{
+    // ============== General options ==============
+
+
+    // ============== Training mode options ==============
+
+
+    // ============== Duplicate mode options ==============
+
+    // Minimum number of players in a duplicate game needed to apply a "solo" 
bonus
+    // (16 is the ODS value)
+    m_intHandler.addOption("duplicate-solo-players", 16);
+    // Number of points granted for a solo (10 is the ODS value)
+    m_intHandler.addOption("duplicate-solo-value", 10);
+
+    // If true, Eliot complains when the player does something illegal
+    // If false, the word is accepted (with a score of 0) and the player does
+    // not get a second chance
+    m_boolHandler.addOption("duplicate-reject-invalid", false);
+
+
+    // ============== Freegame mode options ==============
+
+    // If true, Eliot complains when the player does something illegal
+    // If false, the word is accepted (with a score of 0) and the player does
+    // not get a second chance.
+    // Trying to change letters or to pass the turn in an incorrect way will
+    // be rejected in any case.
+    m_boolHandler.addOption("freegame-reject-invalid", false);
+}
+
+
+void Settings::setBool(const string &iName, bool iValue)
+{
+    m_boolHandler.setOption(iName, iValue);
+}
+
+
+bool Settings::getBool(const string &iName) const
+{
+    return m_boolHandler.getOption(iName);
+}
+
+
+void Settings::setInt(const string &iName, int iValue)
+{
+    m_intHandler.setOption(iName, iValue);
+}
+
+
+int Settings::getInt(const string &iName) const
+{
+    return m_intHandler.getOption(iName);
+}
+
+
+template <typename T>
+void Settings::OptionsHandler<T>::addOption(const string &iName, const T 
&iValue)
+{
+    m_options[iName] = iValue;
+}
+
+
+template <typename T>
+void Settings::OptionsHandler<T>::setOption(const string &iName, const T 
&iValue)
+{
+    typename map<string, T>::iterator it = m_options.find(iName);
+    if (it == m_options.end())
+    {
+        // FIXME: throw an exception object instead
+        throw 1;
+    }
+    it->second = iValue;
+}
+
+
+template <typename T>
+const T& Settings::OptionsHandler<T>::getOption(const string &iName) const
+{
+    typename map<string, T>::const_iterator it = m_options.find(iName);
+    if (it == m_options.end())
+    {
+        // FIXME: throw an exception object instead
+        throw 1;
+    }
+    return it->second;
+}
+

Index: game/settings.h
===================================================================
RCS file: game/settings.h
diff -N game/settings.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ game/settings.h     8 Jan 2008 13:52:39 -0000       1.2
@@ -0,0 +1,109 @@
+/*****************************************************************************
+ * Eliot
+ * Copyright (C) 2007 Olivier Teulière
+ * Authors: Olivier Teulière <ipkiss @@ gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#ifndef _SETTINGS_H_
+#define _SETTINGS_H_
+
+#include <string>
+#include <map>
+
+using std::string;
+using std::map;
+
+
+/**
+ * This class centralizes the various configuration options of Eliot.
+ * It implements the Singleton pattern.
+ *
+ * Currently, there are few settings, and their initial value is hard-coded.
+ * In a later phase, this class will be able to export/import settings
+ * to/from a configuration file, and it should be possible to override
+ * configuration settings with settings given on the command-line (TODO).
+ * The boost::program_options library could be useful for this.
+ *
+ * This class will also be helpful for the "Settings" dialog box of the GUI.
+ */
+class Settings
+{
+public:
+    /// Access to the singleton
+    static Settings& Instance();
+    /// Destroy the singleton cleanly
+    static void Destroy();
+
+    void setBool(const string &iName, bool iValue);
+    bool getBool(const string &iName) const;
+
+    void setInt(const string &iName, int iValue);
+    int getInt(const string &iName) const;
+
+private:
+
+    /**
+     * This nested class is simply there to handle storage and retrieval
+     * for options of a particular type (and factorize code)
+     */
+    template <typename T>
+    class OptionsHandler
+    {
+        public:
+            /// Set the value of an option
+            /**
+             * If the option already exists, its value is replaced,
+             * otherwise the option is created
+             */
+            void addOption(const string &iName, const T &iValue);
+
+            /**
+             * Change the value of an existing option.
+             * An exception is thrown if the option doesn't exist yet
+             */
+            void setOption(const string &iName, const T &iValue);
+
+            /**
+             * Query the value of an option.
+             * An exception is thrown if the option doesn't exist
+             */
+            const T& getOption(const string &iName) const;
+
+        private:
+            map<string, T> m_options;
+    };
+
+
+    /// Singleton instance
+    static Settings *m_instance;
+    Settings();
+
+    /// The settings can be of various types
+    OptionsHandler<bool> m_boolHandler;
+    OptionsHandler<int> m_intHandler;
+    // Add types as needed...
+
+};
+
+#endif
+
+/// Local Variables:
+/// mode: c++
+/// mode: hs-minor
+/// c-basic-offset: 4
+/// indent-tabs-mode: nil
+/// End:

Index: m4/ax_boost_base.m4
===================================================================
RCS file: m4/ax_boost_base.m4
diff -N m4/ax_boost_base.m4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ m4/ax_boost_base.m4 8 Jan 2008 13:52:40 -0000       1.2
@@ -0,0 +1,198 @@
+##### http://autoconf-archive.cryp.to/ax_boost_base.html
+#
+# SYNOPSIS
+#
+#   AX_BOOST_BASE([MINIMUM-VERSION])
+#
+# DESCRIPTION
+#
+#   Test for the Boost C++ libraries of a particular version (or newer)
+#
+#   If no path to the installed boost library is given the macro
+#   searchs under /usr, /usr/local, and /opt, and evaluates the
+#   $BOOST_ROOT environment variable. Further documentation is
+#   available at <http://randspringer.de/boost/index.html>.
+#
+#   This macro calls:
+#
+#     AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
+#
+#   And sets:
+#
+#     HAVE_BOOST
+#
+# LAST MODIFICATION
+#
+#   2007-03-15
+#
+# COPYLEFT
+#
+#   Copyright (c) 2007 Thomas Porschberg <address@hidden>
+#
+#   Copying and distribution of this file, with or without
+#   modification, are permitted in any medium without royalty provided
+#   the copyright notice and this notice are preserved.
+
+AC_DEFUN([AX_BOOST_BASE],
+[
+AC_ARG_WITH([boost],
+       AS_HELP_STRING([--with-boost@<:@=DIR@:>@], [use boost (default is yes) 
- it is possible to specify the root directory for boost (optional)]),
+       [
+    if test "$withval" = "no"; then
+               want_boost="no"
+    elif test "$withval" = "yes"; then
+        want_boost="yes"
+        ac_boost_path=""
+    else
+           want_boost="yes"
+        ac_boost_path="$withval"
+       fi
+    ],
+    [want_boost="yes"])
+
+if test "x$want_boost" = "xyes"; then
+       boost_lib_version_req=ifelse([$1], ,1.20.0,$1)
+       boost_lib_version_req_shorten=`expr $boost_lib_version_req : 
'\([[0-9]]*\.[[0-9]]*\)'`
+       boost_lib_version_req_major=`expr $boost_lib_version_req : 
'\([[0-9]]*\)'`
+       boost_lib_version_req_minor=`expr $boost_lib_version_req : 
'[[0-9]]*\.\([[0-9]]*\)'`
+       boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : 
'[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+       if test "x$boost_lib_version_req_sub_minor" = "x" ; then
+               boost_lib_version_req_sub_minor="0"
+       fi
+       WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+  
$boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor`
+       AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req)
+       succeeded=no
+
+       dnl first we check the system location for boost libraries
+       dnl this location ist chosen if boost libraries are installed with the 
--layout=system option
+       dnl or if you install boost with RPM
+       if test "$ac_boost_path" != ""; then
+               BOOST_LDFLAGS="-L$ac_boost_path/lib"
+               BOOST_CPPFLAGS="-I$ac_boost_path/include"
+       else
+               for ac_boost_path_tmp in /usr /usr/local /opt ; do
+                       if test -d "$ac_boost_path_tmp/include/boost" && test 
-r "$ac_boost_path_tmp/include/boost"; then
+                               BOOST_LDFLAGS="-L$ac_boost_path_tmp/lib"
+                               BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
+                               break;
+                       fi
+               done
+       fi
+
+       CPPFLAGS_SAVED="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+       export CPPFLAGS
+
+       LDFLAGS_SAVED="$LDFLAGS"
+       LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+       export LDFLAGS
+
+       AC_LANG_PUSH(C++)
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+       @%:@include <boost/version.hpp>
+       ]], [[
+       #if BOOST_VERSION >= $WANT_BOOST_VERSION
+       // Everything is okay
+       #else
+       #  error Boost version is too old
+       #endif
+       ]])],[
+        AC_MSG_RESULT(yes)
+       succeeded=yes
+       found_system=yes
+               ],[
+               ])
+       AC_LANG_POP([C++])
+
+
+
+       dnl if we found no boost with system layout we search for boost 
libraries
+       dnl built and installed without the --layout=system option or for a 
staged(not installed) version
+       if test "x$succeeded" != "xyes"; then
+               _version=0
+               if test "$ac_boost_path" != ""; then
+                               BOOST_LDFLAGS="-L$ac_boost_path/lib"
+                       if test -d "$ac_boost_path" && test -r 
"$ac_boost_path"; then
+                               for i in `ls -d $ac_boost_path/include/boost-* 
2>/dev/null`; do
+                                       _version_tmp=`echo $i | sed 
"s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
+                                       V_CHECK=`expr $_version_tmp \> 
$_version`
+                                       if test "$V_CHECK" = "1" ; then
+                                               _version=$_version_tmp
+                                       fi
+                                       VERSION_UNDERSCORE=`echo $_version | 
sed 's/\./_/'`
+                                       
BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
+                               done
+                       fi
+               else
+                       for ac_boost_path in /usr /usr/local /opt ; do
+                               if test -d "$ac_boost_path" && test -r 
"$ac_boost_path"; then
+                                       for i in `ls -d 
$ac_boost_path/include/boost-* 2>/dev/null`; do
+                                               _version_tmp=`echo $i | sed 
"s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
+                                               V_CHECK=`expr $_version_tmp \> 
$_version`
+                                               if test "$V_CHECK" = "1" ; then
+                                                       _version=$_version_tmp
+                                                       best_path=$ac_boost_path
+                                               fi
+                                       done
+                               fi
+                       done
+
+                       VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
+                       
BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
+                       BOOST_LDFLAGS="-L$best_path/lib"
+
+                       if test "x$BOOST_ROOT" != "x"; then
+                               if test -d "$BOOST_ROOT" && test -r 
"$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/lib" && test -r 
"$BOOST_ROOT/stage/lib"; then
+                                       version_dir=`expr //$BOOST_ROOT : 
'.*/\(.*\)'`
+                                       stage_version=`echo $version_dir | sed 
's/boost_//' | sed 's/_/./g'`
+                                       stage_version_shorten=`expr 
$stage_version : '\([[0-9]]*\.[[0-9]]*\)'`
+                                       V_CHECK=`expr $stage_version_shorten 
\>\= $_version`
+                                       if test "$V_CHECK" = "1" ; then
+                                               AC_MSG_NOTICE(We will use a 
staged boost library from $BOOST_ROOT)
+                                               BOOST_CPPFLAGS="-I$BOOST_ROOT"
+                                               
BOOST_LDFLAGS="-L$BOOST_ROOT/stage/lib"
+                                       fi
+                               fi
+                       fi
+               fi
+
+               CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+               export CPPFLAGS
+               LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+               export LDFLAGS
+
+               AC_LANG_PUSH(C++)
+               AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+               @%:@include <boost/version.hpp>
+               ]], [[
+               #if BOOST_VERSION >= $WANT_BOOST_VERSION
+               // Everything is okay
+               #else
+               #  error Boost version is too old
+               #endif
+               ]])],[
+               AC_MSG_RESULT(yes)
+               succeeded=yes
+               found_system=yes
+                       ],[
+               ])
+               AC_LANG_POP([C++])
+       fi
+
+       if test "$succeeded" != "yes" ; then
+               if test "$_version" = "0" ; then
+                       AC_MSG_ERROR([[We could not detect the boost libraries 
(version $boost_lib_version_req_shorten or higher). If you have a staged boost 
library (still not installed) please specify \$BOOST_ROOT in your environment 
and do not give a PATH to --with-boost option.  If you are sure you have boost 
installed, then check your version number looking in <boost/version.hpp>. See 
http://randspringer.de/boost for more documentation.]])
+               else
+                       AC_MSG_NOTICE([Your boost libraries seems to old 
(version $_version).])
+               fi
+       else
+               AC_SUBST(BOOST_CPPFLAGS)
+               AC_SUBST(BOOST_LDFLAGS)
+               AC_DEFINE(HAVE_BOOST,,[define if the Boost library is 
available])
+       fi
+
+        CPPFLAGS="$CPPFLAGS_SAVED"
+               LDFLAGS="$LDFLAGS_SAVED"
+fi
+
+])

Index: test/duplicate_humans_ai.input
===================================================================
RCS file: test/duplicate_humans_ai.input
diff -N test/duplicate_humans_ai.input
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ test/duplicate_humans_ai.input      8 Jan 2008 13:52:41 -0000       1.2
@@ -0,0 +1,20 @@
+d 2 1
+a T
+j DOSAIT H4
+j DOSAIT h5
+a S
+a T
+n 1
+j DISAIENT 11A
+a S
+j DESTINAI 11E
+a S
+a t
+j FRiPE 10K
+j sERF M11
+a S
+a t
+a g
+a p
+q
+q

Index: test/duplicate_humans_ai.ref
===================================================================
RCS file: test/duplicate_humans_ai.ref
diff -N test/duplicate_humans_ai.ref
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ test/duplicate_humans_ai.ref        8 Jan 2008 13:52:41 -0000       1.2
@@ -0,0 +1,78 @@
+[?] pour l'aide
+commande> d 2 1
+mode duplicate
+[?] pour l'aide
+commande> a T
+Joueur 0: ATOYDSI
+Joueur 1: ATOYDSI
+Joueur 2: ATOYDSI
+commande> j DOSAIT H4
+commande> j DOSAIT h5
+commande> a S
+Joueur 0:   18
+Joueur 1:   14
+Joueur 2:   30
+commande> a T
+Joueur 0: DIAEINS
+Joueur 1: DIAEINS
+Joueur 2: DIAEINS
+commande> n 1
+commande> j DISAIENT 11A
+commande> a S
+Joueur 0:   18
+Joueur 1:   82
+Joueur 2:   30
+commande> j DESTINAI 11E
+commande> a S
+Joueur 0:  104
+Joueur 1:   82
+Joueur 2:  116
+commande> a t
+P?RBFEG
+commande> j FRiPE 10K
+commande> j sERF M11
+commande> a S
+Joueur 0:  126
+Joueur 1:  103
+Joueur 2:  145
+commande> a t
+BGEEMTB
+commande> a g
+     1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+ A   -  -  -  -  -  -  -  -  -  -  -  F  -  -  -
+ B   -  -  -  -  -  -  -  -  -  -  -  R  -  -  -
+ C   -  -  -  -  -  -  -  -  -  -  -  i  -  -  -
+ D   -  -  -  -  -  -  -  -  -  -  -  P  -  -  -
+ E   -  -  -  -  -  -  -  -  -  -  D  E  -  -  -
+ F   -  -  -  -  -  -  -  -  -  -  E  -  -  -  -
+ G   -  -  -  -  -  -  -  -  -  -  S  -  -  -  -
+ H   -  -  -  -  -  -  -  O  Y  A  T  S  -  -  -
+ I   -  -  -  -  -  -  -  -  -  -  I  -  -  -  -
+ J   -  -  -  -  -  -  -  -  -  -  N  -  -  -  -
+ K   -  -  -  -  -  -  -  -  -  -  A  -  -  -  -
+ L   -  -  -  -  -  -  -  -  -  -  I  -  -  -  -
+ M   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ N   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+ O   -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+commande> a p
+Eliot 1.5
+
+Game type: Duplicate
+Player 0: Human
+Player 1: Human
+Player 2: Computer
+
+    N |   RACK   |    SOLUTION     | REF | PTS | P | BONUS
+   ===|==========|=================|=====|=====|===|======
+    1 |  ATOYDSI | OYATS           |  H8 |  30 | 2 |  
+    2 | DI+AEINS | DESTINAI        | 11E |  86 | 0 | *
+    3 |  P?RBFEG | FRiPE           | 12A |  29 | 2 |  
+
+   Total: 145
+
+Rack 0: BG+EEMTB
+Rack 1: BG+EEMTB
+Rack 2: BG+EEMTB
+commande> q
+fin du mode duplicate
+commande> q

Index: test/training_7pl1.input
===================================================================
RCS file: test/training_7pl1.input
diff -N test/training_7pl1.input
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ test/training_7pl1.input    8 Jan 2008 13:52:41 -0000       1.2
@@ -0,0 +1,6 @@
+e
+b p maison
+b p noword
+b p zeuer
+q
+q

Index: test/training_7pl1.ref
===================================================================
RCS file: test/training_7pl1.ref
diff -N test/training_7pl1.ref
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ test/training_7pl1.ref      8 Jan 2008 13:52:41 -0000       1.2
@@ -0,0 +1,84 @@
+[?] pour l'aide
+commande> e
+mode entraînement
+[?] pour l'aide
+commande> b p maison
+  AIMONS
+  AMNIOS
+  MAISON
++A
+  OMANAIS
++B
+  ABIMONS
++C
+  CAMIONS
+  MANIOCS
++D
+  AMIDONS
+  DAMIONS
+  DOMINAS
+  MADISON
+  MONDAIS
++E
+  ANOMIES
+  ANOSMIE
++G
+  GOMINAS
++I
+  AIMIONS
++L
+  LAMIONS
+  OSMANLI
++M
+  NOMMAIS
++N
+  ANIMONS
+  MANIONS
+  MANNOIS
+  MANSION
+  NOMINAS
++P
+  PAMIONS
++R
+  ARMIONS
+  MANOIRS
+  MARIONS
+  MINORAS
+  NORMAIS
+  RAMIONS
+  ROMAINS
+  ROMANIS
++S
+  MAISONS
++T
+  MATIONS
+  MOISANT
+  MONTAIS
++Z
+  MAZIONS
+commande> b p noword
+commande> b p zeuer
++A
+  AZUREE
++C
+  ECUREZ
++H
+  HUEREZ
++M
+  MUEREZ
+  REMUEZ
++N
+  NUEREZ
++P
+  EPUREZ
+  PUEREZ
++R
+  RUEREZ
++S
+  SUEREZ
+  USEREZ
++T
+  TUEREZ
+commande> q
+fin du mode entraînement
+commande> q

Index: test/training_benj.input
===================================================================
RCS file: test/training_benj.input
diff -N test/training_benj.input
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ test/training_benj.input    8 Jan 2008 13:52:42 -0000       1.2
@@ -0,0 +1,6 @@
+e
+b b maison
+b b animal
+b b jures
+q
+q

Index: test/training_benj.ref
===================================================================
RCS file: test/training_benj.ref
diff -N test/training_benj.ref
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ test/training_benj.ref      8 Jan 2008 13:52:42 -0000       1.2
@@ -0,0 +1,14 @@
+[?] pour l'aide
+commande> e
+mode entraînement
+[?] pour l'aide
+commande> b b maison
+PLUmaison
+commande> b b animal
+commande> b b jures
+CONjures
+GOUjures
+PARjures
+commande> q
+fin du mode entraînement
+commande> q

Index: test/training_racc.input
===================================================================
RCS file: test/training_racc.input
diff -N test/training_racc.input
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ test/training_racc.input    8 Jan 2008 13:52:42 -0000       1.2
@@ -0,0 +1,6 @@
+e
+b r ave
+b r yeux
+b r ka
+q
+q

Index: test/training_racc.ref
===================================================================
RCS file: test/training_racc.ref
diff -N test/training_racc.ref
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ test/training_racc.ref      8 Jan 2008 13:52:42 -0000       1.2
@@ -0,0 +1,26 @@
+[?] pour l'aide
+commande> e
+mode entraînement
+[?] pour l'aide
+commande> b r ave
+Bave
+Cave
+Gave
+Have
+Lave
+Nave
+Pave
+Rave
+aveC
+aveN
+aveU
+aveZ
+commande> b r yeux
+commande> b r ka
+Oka
+Ska
+kaN
+kaS
+commande> q
+fin du mode entraînement
+commande> q

Index: dic/alist.c
===================================================================
RCS file: dic/alist.c
diff -N dic/alist.c
--- dic/alist.c 4 Aug 2007 20:01:28 -0000       1.5
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,201 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 2005  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   alist.c
- *  \brief  List type used by automaton
- *  \author Antoine Fraboulet
- *  \date   2005
- */
-
-#include <stdlib.h>
-#include "alist.h"
-
-#define __UNUSED__ __attribute__((unused))
-
-struct alist_elt_t {
-  void* info;
-  alist_elt next;
-};
-
-struct alist_t {
-  int size;
-  void (*delete_function)(void*);
-  alist_elt start;
-};
-
-
-void*
-alist_elt_get_value(alist_elt e)
-{
-  return e->info;
-}
-
-alist_elt
-alist_elt_create(void* info)
-{
-  alist_elt e;
-  e = (alist_elt)malloc(sizeof(struct alist_elt_t));
-  e->info = info;
-  e->next = NULL;
-  return e;
-}
-
-/* ************************************************** */
-/* ************************************************** */
-/* ************************************************** */
-
-alist
-alist_create()
-{
-  alist l;
-  l                  = (alist)malloc(sizeof(struct alist_t));
-  l->size            = 0;
-  l->start           = NULL;
-  l->delete_function = NULL;
-  return l;
-}
-
-alist
-alist_clone(alist l)
-{
-  alist t;
-  alist_elt ptr;
-  t = alist_create();
-  for(ptr = alist_get_first(l); ptr ; ptr = alist_get_next(l,ptr))
-    {
-      alist_add(t,alist_elt_get_value(ptr));
-    }
-  return t;
-}
-
-void
-alist_set_delete (alist l, void (*f)(void*))
-{
-  l->delete_function = f;
-}
-
-static void
-alist_delete_rec(alist_elt e, void (*delete_function)(void*))
-{
-  if (e != NULL)
-    {
-      alist_delete_rec(e->next, delete_function);
-      if (delete_function)
-       delete_function(e->info);
-      e->info = NULL;
-      free(e);
-    }
-}
-
-void
-alist_delete(alist l)
-{
-  alist_delete_rec(l->start,l->delete_function);
-  free(l);
-}
-
-void
-alist_add(alist l, void* value)
-{
-  alist_elt e;
-  e = alist_elt_create(value);
-  e->next = l->start;
-  l->start = e;
-  l->size ++;
-}
-
-int
-alist_is_in(alist l, void* e)
-{
-  alist_elt ptr;
-  for(ptr = alist_get_first(l); ptr; ptr = alist_get_next(l,ptr))
-    if (alist_elt_get_value(ptr) == e)
-      return 1;
-  return 0;
-}
-
-int
-alist_equal(alist id1, alist id2)
-{
-  alist_elt e1;
-
-  if (alist_get_size(id1) != alist_get_size(id2))
-    return 0;
-
-  for(e1 = alist_get_first(id1) ; e1 ; e1 = alist_get_next(id1,e1))
-    {
-      if (! alist_is_in(id2, alist_elt_get_value(e1)))
-       return 0;
-    }
-
-  return 1;
-}
-
-void
-alist_insert(alist dst, alist src)
-{
-  alist_elt ptr;
-  for(ptr = alist_get_first(src); ptr ; ptr = alist_get_next(src,ptr))
-    {
-      void *e = alist_elt_get_value(ptr);
-      if (! alist_is_in(dst,e))
-       alist_add(dst,e);
-    }
-}
-
-alist_elt
-alist_get_first(alist l)
-{
-  return l->start;
-}
-
-alist_elt
-alist_get_next(alist __UNUSED__ l, alist_elt e)
-{
-  return e->next;
-}
-
-void*
-alist_pop_first_value(alist l)
-{
-  void* p = NULL;
-  alist_elt e = l->start;
-  if (e)
-    {
-      l->start = e->next;
-      e->next  = NULL;
-      p = e->info;
-      l->size --;
-      alist_delete_rec(e,l->delete_function);
-    }
-  return p;
-}
-
-int
-alist_get_size(alist l)
-{
-  return l->size;
-}
-
-int
-alist_is_empty(alist l)
-{
-  return l->size == 0;
-}

Index: dic/alist.h
===================================================================
RCS file: dic/alist.h
diff -N dic/alist.h
--- dic/alist.h 1 Jan 2006 19:51:00 -0000       1.4
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,98 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 2005  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   alist.h
- *  \brief  List type used by automaton
- *  \author Antoine Fraboulet
- *  \date   2005
- */
-
-#ifndef _ALIST_H_
-#define _ALIST_H_
-#if defined(__cplusplus)
-extern "C"
-  {
-#endif
-
-    /**
-     * untyped list type element
-     */
-    typedef struct alist_elt_t* alist_elt;
-
-    /**
-     * extract the value from an alist element
-     * result is untyped si the user should know
-     * what the value type is
-     */
-    void* alist_elt_get_value(alist_elt);
-
-    /**
-     * untyped list type
-     */
-    typedef struct alist_t* alist;
-
-    /**
-     * list creation
-     * @returns list
-     */
-    alist     alist_create     ();
-    alist     alist_clone      (alist);
-
-    /**
-     * funtion to use on data during list deletion.
-     */
-    void      alist_set_delete (alist,void (*f)(void*));
-
-    /**
-     * delete a complete list.
-     */
-    void      alist_delete     (alist);
-
-    /**
-     * add a element to the list
-     */
-    void      alist_add        (alist, void*);
-    void      alist_insert     (alist, alist);
-    /**
-     * get first element
-     */
-    int       alist_is_in      (alist l, void* e);
-    int       alist_equal      (alist , alist);
-
-    alist_elt alist_get_first  (alist);
-
-    /**
-     * get next element from current
-     */
-    alist_elt alist_get_next   (alist,alist_elt);
-
-    /**
-     * @returns 0 or 1
-     */
-    int       alist_is_empty   (alist);
-
-    int       alist_get_size   (alist);
-
-    void*     alist_pop_first_value  (alist);
-
-#if defined(__cplusplus)
-  }
-#endif
-#endif /* _ALIST_H_ */

Index: dic/automaton.c
===================================================================
RCS file: dic/automaton.c
diff -N dic/automaton.c
--- dic/automaton.c     4 Aug 2007 20:01:28 -0000       1.13
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,679 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 2005  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   automaton.c
- *  \brief  (Non)Deterministic Finite Automaton for Regexp
- *  \author Antoine Fraboulet
- *  \date   2005
- */
-
-#include "config.h"
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_WAIT_H
-#   include <sys/wait.h>
-#endif
-#include <unistd.h>
-
-#include "dic.h"
-#include "regexp.h"
-#include "alist.h"
-#include "automaton.h"
-
-#ifdef DEBUG_AUTOMATON
-#define DMSG(a) a
-#else
-#define DMSG(a)
-#endif
-
-#define MAX_TRANSITION_LETTERS 256
-
-typedef struct automaton_state_t *astate;
-typedef struct Automaton_t       *Automaton;
-
-/* ************************************************** *
-   exported functions for static automata
- * ************************************************** */
-
-automaton automaton_build          (int init_state, int *ptl, int *PS, struct 
search_RegE_list_t *list);
-void      automaton_delete         (automaton a);
-int       automaton_get_nstate     (automaton a);
-int       automaton_get_init       (automaton a);
-int       automaton_get_accept     (automaton a, int state);
-int       automaton_get_next_state (automaton a, int start, char l);
-void      automaton_dump           (automaton a, char* filename);
-
-
-/* ************************************************** *
-   static functions for dynamic automata
- * ************************************************** */
-
-static Automaton s_automaton_create         ();
-static void      s_automaton_delete         (Automaton a);
-
-static alist     s_automaton_id_create      (int id);
-static astate    s_automaton_state_create   (alist id);
-
-static void      s_automaton_add_state      (Automaton a, astate s);
-static astate    s_automaton_get_state      (Automaton a, alist id);
-
-static Automaton s_automaton_PS_to_NFA      (int init_state, int *ptl, int 
*PS);
-static Automaton s_automaton_NFA_to_DFA     (Automaton a, struct 
search_RegE_list_t *list);
-static automaton s_automaton_finalize       (Automaton a);
-
-#ifdef DEBUG_AUTOMATON
-static char*     s_automaton_id_to_str      (alist id);
-static void      s_automaton_dump           (Automaton a, char* filename);
-#endif
-
-/* ************************************************** *
-   data types
- * ************************************************** */
-
-struct automaton_state_t {
-  alist    id;                     // alist of int
-  int      accept;
-  int      id_static;
-  astate   next[MAX_TRANSITION_LETTERS];
-};
-
-struct Automaton_t {
-  int      nstates;
-  astate   init_state;
-  alist    states;                 // alist of alist of int
-};
-
-struct automaton_t {
-  int   nstates;
-  int   init;
-  int  *accept;
-  int **trans;
-};
-
-/* ************************************************** *
-   exported functions for static automata
- * ************************************************** */
-
-automaton automaton_build(int init_state, int *ptl, int *PS, struct 
search_RegE_list_t *list)
-{
-  Automaton nfa,dfa;
-  automaton final;
-
-  nfa = s_automaton_PS_to_NFA(init_state,ptl,PS);
-  DMSG(printf("\n non deterministic automaton OK \n\n"));
-  DMSG(s_automaton_dump(nfa,"auto_nfa"));
-
-  dfa = s_automaton_NFA_to_DFA(nfa, list);
-  DMSG(printf("\n deterministic automaton OK \n\n"));
-  DMSG(s_automaton_dump(dfa,"auto_dfa"));
-
-  final = s_automaton_finalize(dfa);
-  DMSG(printf("\n final automaton OK \n\n"));
-  DMSG(automaton_dump(final,"auto_fin"));
-
-  s_automaton_delete(nfa);
-  s_automaton_delete(dfa);
-  return final;
-}
-
-void automaton_delete(automaton a)
-{
-  int i;
-  free(a->accept);
-  for(i=0; i <= a->nstates; i++)
-    free(a->trans[i]);
-  free(a->trans);
-  free(a);
-}
-
-inline int automaton_get_nstates(automaton a)
-{
-  return a->nstates;
-}
-
-inline int automaton_get_init(automaton a)
-{
-  return a->init;
-}
-
-inline int automaton_get_accept(automaton a, int state)
-{
-  return a->accept[state];
-}
-
-inline int automaton_get_next_state(automaton a, int state, char l)
-{
-  return a->trans[state][(int)l];
-}
-
-void automaton_dump(automaton a, char* filename)
-{
-  int i,l;
-  FILE* f;
-#ifdef HAVE_SYS_WAIT_H
-  pid_t   pid;
-#endif
-
-  if (a == NULL)
-    return ;
-  f=fopen(filename,"w");
-  fprintf(f,"digraph automaton {\n");
-  for(i=1; i<=a->nstates; i++)
-    {
-      fprintf(f,"\t%d [label = \"%d\"",i,i);
-      if (i == a->init)
-       fprintf(f,", style = filled, color=lightgrey");
-      if (a->accept[i])
-       fprintf(f,", shape = doublecircle");
-      fprintf(f,"];\n");
-    }
-  fprintf(f,"\n");
-  for(i=1; i<=a->nstates; i++)
-    for(l=0; l < MAX_TRANSITION_LETTERS; l++)
-      if (a->trans[i][l])
-       {
-         fprintf(f,"\t%d -> %d [label = \"",i,a->trans[i][l]);
-         regexp_print_letter(f,l);
-         fprintf(f,"\"];\n");
-       }
-  fprintf(f,"fontsize=20;\n");
-  fprintf(f,"}\n");
-  fclose(f);
-
-#ifdef HAVE_SYS_WAIT_H
-  pid = fork ();
-  if (pid > 0) {
-    wait(NULL);
-  } else if (pid == 0) {
-    execlp("dotty","dotty",filename,NULL);
-    printf("exec dotty failed\n");
-    exit(1);
-  }
-#endif
-}
-
-/* ************************************************** *
- * ************************************************** *
- * ************************************************** */
-
-void state_delete_fun(void* ps)
-{
-  astate s = ps;
-  alist_delete(s->id);
-  free(s);
-}
-
-static Automaton s_automaton_create()
-{
-  Automaton a;
-  a = (Automaton)malloc(sizeof(struct Automaton_t));
-  a->nstates      = 0;
-  a->init_state   = NULL;
-  a->states       = alist_create();
-  alist_set_delete(a->states,state_delete_fun);
-  return a;
-}
-
-
-static void s_automaton_delete(Automaton a)
-{
-  alist_delete(a->states);
-  free(a);
-}
-
-static alist s_automaton_id_create(int id)
-{
-  alist a = alist_create();
-  alist_add(a,(void*)((unsigned long)id));
-  return a;
-}
-
-static astate s_automaton_state_create(alist id)
-{
-  astate s;
-  s = (astate)malloc(sizeof(struct automaton_state_t));
-  s->id      = id;
-  s->accept  = 0;
-  memset(s->next,0,sizeof(astate)*MAX_TRANSITION_LETTERS);
-  DMSG(printf("** state %s creation\n",s_automaton_id_to_str(id)));
-  return s;
-}
-
-static void s_automaton_add_state(Automaton a, astate s)
-{
-  a->nstates ++;
-  alist_add(a->states,(void*)s);
-  DMSG(printf("** state %s added to 
automaton\n",s_automaton_id_to_str(s->id)));
-}
-
-static astate s_automaton_get_state(Automaton a, alist id)
-{
-  astate s;
-  alist_elt ptr;
-  for(ptr = alist_get_first(a->states) ;  ptr ; ptr = 
alist_get_next(a->states,ptr))
-    {
-      s = alist_elt_get_value(ptr);
-      if (alist_equal(s->id,id))
-       {
-         //DMSG(printf("** get state %s ok\n",s_automaton_id_to_str(s->id)));
-         return s;
-       }
-    }
-  return NULL;
-}
-
-/* ************************************************** *
- * ************************************************** *
- * ************************************************** */
-
-Automaton s_automaton_PS_to_NFA(int init_state_id, int *ptl, int *PS)
-{
-  int p;
-  int maxpos = PS[0];
-  Automaton nfa = NULL;
-  alist temp_id;
-  alist_elt ptr;
-  astate temp_state,current_state;
-  alist L;
-  char used_letter[MAX_TRANSITION_LETTERS];
-
-  nfa = s_automaton_create();
-  L   = alist_create();
-
-  /* 1: init_state = root->PP */
-  temp_id          = s_automaton_id_create(init_state_id);
-  temp_state       = s_automaton_state_create(temp_id);
-  nfa->init_state  = temp_state;
-  s_automaton_add_state(nfa,temp_state);
-  alist_add(L,temp_state);
-  /* 2: while \exist state \in state_list */
-  while (! alist_is_empty(L))
-    {
-      current_state = (astate)alist_pop_first_value(L);
-      DMSG(printf("** current state = 
%s\n",s_automaton_id_to_str(current_state->id)));
-      memset(used_letter,0,sizeof(used_letter));
-      /* 3: \foreach l in \sigma | l \neq # */
-      for(p=1; p < maxpos; p++)
-       {
-         int current_letter = ptl[p];
-         if (used_letter[current_letter] == 0)
-           {
-             /* 4: int set = \cup { PS(pos) | pos \in state \wedge pos == l } 
*/
-             int pos, ens = 0;
-             for(pos = 1; pos <= maxpos; pos++)
-               {
-                 if (ptl[pos] == current_letter &&
-                     (unsigned 
long)alist_elt_get_value(alist_get_first(current_state->id)) & (1 << (pos - 1)))
-                   ens |= PS[pos];
-               }
-             /* 5: transition from current_state to temp_state */
-             if (ens)
-               {
-                 temp_id    = s_automaton_id_create(ens);
-                 temp_state = s_automaton_get_state(nfa,temp_id);
-                 if (temp_state == NULL)
-                   {
-                     temp_state = s_automaton_state_create(temp_id);
-                     s_automaton_add_state     (nfa,temp_state);
-                     current_state->next[current_letter] = temp_state;
-                     alist_add(L,temp_state);
-                   }
-                 else
-                   {
-                     alist_delete(temp_id);
-                     current_state->next[current_letter] = temp_state;
-                   }
-               }
-             used_letter[current_letter] = 1;
-           }
-       }
-    }
-
-  alist_delete(L);
-
-  for(ptr = alist_get_first(nfa->states); ptr ; ptr = 
alist_get_next(nfa->states,ptr))
-    {
-      astate s = (astate)alist_elt_get_value(ptr);
-      if ((unsigned long)alist_elt_get_value(alist_get_first(s->id)) & (1 << 
(maxpos - 1)))
-       s->accept = 1;
-    }
-
-  return nfa;
-}
-
-/* ************************************************** *
- * ************************************************** *
- * ************************************************** */
-
-static alist s_automaton_successor(alist S, int letter, Automaton nfa, struct 
search_RegE_list_t *list)
-{
-  alist R,r;
-  alist_elt ptr;
-  R = alist_create();                                       /* R = \empty */
-                                                            /* \forall y \in S 
*/
-  for(ptr = alist_get_first(S); ptr ; ptr = alist_get_next(S,ptr))
-    {
-      int i;
-      alist t, Ry; astate y,z;
-
-      i = (unsigned long)alist_elt_get_value(ptr);
-      t = s_automaton_id_create(i);
-      assert(y = s_automaton_get_state(nfa,t));
-      alist_delete(t);
-
-      Ry = alist_create();                                 /* Ry = \empty      
       */
-
-      if ((z = y->next[letter]) != NULL)                   /* \delta (y,z) = l 
       */
-       {
-         r = s_automaton_successor(z->id,RE_EPSILON,nfa, list);
-         alist_insert(Ry,r);
-         alist_delete(r);
-         alist_insert(Ry,z->id);                          /* Ry = Ry \cup 
succ(z)    */
-       }
-
-      /* \epsilon transition from start node */
-      if ((z = y->next[RE_EPSILON]) != NULL)               /* \delta (y,z) = 
\epsilon */
-       {
-         r = s_automaton_successor(z->id,letter,nfa, list);
-         alist_insert(Ry,r);                              /* Ry = Ry \cup 
succ(z)    */
-         alist_delete(r);
-       }
-
-      if (letter < RE_FINAL_TOK)
-       {
-         for(i = 0 ; i < DIC_SEARCH_REGE_LIST ; i++)
-           if (list->valid[i])
-             {
-               if (list->letters[i][letter] && (z = 
y->next[(int)list->symbl[i]]) != NULL)
-                 {
-                   DMSG(printf("*** letter "));
-                   DMSG(regexp_print_letter(stdout,letter));
-                   DMSG(printf("is in "));
-                   DMSG(regexp_print_letter(stdout,i));
-
-                   r = s_automaton_successor(z->id,RE_EPSILON,nfa, list);
-                   alist_insert(Ry,r);
-                   alist_delete(r);
-                   alist_insert(Ry,z->id);
-                 }
-             }
-       }
-
-#if 0
-      if (alist_is_empty(Ry))                              /* Ry = \empty      
       */
-       return Ry;
-#endif
-
-      alist_insert(R,Ry);                                  /* R = R \cup Ry    
       */
-      alist_delete(Ry);
-    }
-
-  return R;
-}
-
-static void s_automaton_node_set_accept(astate s, Automaton nfa)
-{
-  void* idx;
-  alist_elt ptr;
-
-  DMSG(printf("=== setting accept for node (%s) 
:",s_automaton_id_to_str(s->id)));
-  for(ptr = alist_get_first(nfa->states) ; ptr ; ptr = 
alist_get_next(nfa->states,ptr))
-    {
-      astate ns = (astate)alist_elt_get_value(ptr);
-      idx = alist_elt_get_value(alist_get_first(ns->id));
-      DMSG(printf("%s ",s_automaton_id_to_str(ns->id)));
-      if (ns->accept && alist_is_in(s->id,idx))
-       {
-         DMSG(printf("(ok) "));
-         s->accept = 1;
-       }
-    }
-  DMSG(printf("\n"));
-}
-
-static Automaton s_automaton_NFA_to_DFA(Automaton nfa, struct 
search_RegE_list_t *list)
-{
-  Automaton dfa = NULL;
-  alist temp_id;
-  alist_elt ptr;
-  astate temp_state, current_state;
-  alist L;
-  int letter;
-
-  dfa = s_automaton_create();
-  L   = alist_create();
-
-  temp_id         = alist_clone(nfa->init_state->id);
-  temp_state      = s_automaton_state_create(temp_id);
-  dfa->init_state = temp_state;
-  s_automaton_add_state(dfa,temp_state);
-  alist_add(L,temp_state);
-  while (! alist_is_empty(L))
-    {
-      current_state = (astate)alist_pop_first_value(L);
-      DMSG(printf("** current state = 
%s\n",s_automaton_id_to_str(current_state->id)));
-      for(letter = 1; letter < DIC_LETTERS; letter++)
-       {
-         //      DMSG(printf("*** start successor of 
%s\n",s_automaton_id_to_str(current_state->id)));
-
-         temp_id = s_automaton_successor(current_state->id,letter,nfa,list);
-
-         if (! alist_is_empty(temp_id))
-           {
-
-             DMSG(printf("*** successor of %s for 
",s_automaton_id_to_str(current_state->id)));
-             DMSG(regexp_print_letter(stdout,letter));
-             DMSG(printf(" = %s\n", s_automaton_id_to_str(temp_id)));
-
-             temp_state = s_automaton_get_state(dfa,temp_id);
-
-             //          DMSG(printf("*** automaton get state -%s- 
ok\n",s_automaton_id_to_str(temp_id)));
-
-             if (temp_state == NULL)
-               {
-                 temp_state = s_automaton_state_create(temp_id);
-                 s_automaton_add_state(dfa,temp_state);
-                 current_state->next[letter] = temp_state;
-                 alist_add(L,temp_state);
-               }
-             else
-               {
-                 alist_delete(temp_id);
-                 current_state->next[letter] = temp_state;
-               }
-           }
-         else
-           {
-             alist_delete(temp_id);
-           }
-       }
-    }
-
-  for(ptr = alist_get_first(dfa->states) ; ptr ; ptr = 
alist_get_next(dfa->states,ptr))
-    {
-      astate s = (astate)alist_elt_get_value(ptr);
-      s_automaton_node_set_accept(s,nfa);
-    }
-
-  alist_delete(L);
-  return dfa;
-}
-
-/* ************************************************** *
- * ************************************************** *
- * ************************************************** */
-
-static automaton s_automaton_finalize(Automaton a)
-{
-  int i,l;
-  automaton fa = NULL;
-  alist_elt ptr;
-  astate s;
-
-  if (a == NULL)
-    return NULL;
-
-  /* creation */
-  fa = (automaton)malloc(sizeof(struct automaton_t));
-  fa->nstates = a->nstates;
-  fa->accept  = (int*) malloc((fa->nstates + 1)*sizeof(int));
-  memset(fa->accept,0,(fa->nstates + 1)*sizeof(int));
-  fa->trans   = (int**)malloc((fa->nstates + 1)*sizeof(int*));
-  for(i=0; i <= fa->nstates; i++)
-    {
-      fa->trans[i] = (int*)malloc(MAX_TRANSITION_LETTERS * sizeof(int));
-      memset(fa->trans[i],0,MAX_TRANSITION_LETTERS * sizeof(int));
-    }
-
-  /* create new id for states */
-  for(i = 1 , ptr = alist_get_first(a->states); ptr ; ptr = 
alist_get_next(a->states,ptr), i++)
-    {
-      s = (astate)alist_elt_get_value(ptr);
-      s->id_static = i;
-    }
-
-  /* build new automaton */
-  for(ptr = alist_get_first(a->states); ptr ; ptr = 
alist_get_next(a->states,ptr))
-    {
-      s = (astate)alist_elt_get_value(ptr);
-      i = s->id_static;
-
-      if (s == a->init_state)
-       fa->init = i;
-      if (s->accept == 1)
-       fa->accept[i] = 1;
-
-      for(l=0; l < MAX_TRANSITION_LETTERS; l++)
-       if (s->next[l])
-         fa->trans[i][l] = s->next[l]->id_static;
-    }
-
-  return fa;
-}
-
-
-/* ************************************************** *
- * ************************************************** *
- * ************************************************** */
-
-#ifdef DEBUG_AUTOMATON
-static char* s_automaton_id_to_str(alist id)
-{
-  static char s[250];
-  memset(s,0,sizeof(s));
-  alist_elt ptr;
-  for(ptr = alist_get_first(id); ptr ; ptr = alist_get_next(id,ptr))
-    {
-      char tmp[50];
-      sprintf(tmp,"%d ",(int)alist_elt_get_value(ptr));
-      strcat(s,tmp);
-    }
-  return s;
-}
-#endif // DEBUG_AUTOMATON
-
-#ifdef DEBUG_AUTOMATON
-static void s_automaton_print_nodes(FILE* f, Automaton a)
-{
-  char * sid;
-  astate s;
-  alist_elt ptr;
-  for(ptr = alist_get_first(a->states) ; ptr != NULL ; ptr = 
alist_get_next(a->states,ptr))
-    {
-      s = alist_elt_get_value(ptr);
-      sid = s_automaton_id_to_str(s->id);
-      fprintf(f,"\t\"%s\" [label = \"%s\"",sid,sid);
-      if (s == a->init_state)
-           {
-             fprintf(f,", style = filled, color=lightgrey");
-           }
-      if (s->accept)
-       {
-         fprintf(f,", shape = doublecircle");
-       }
-      fprintf(f,"];\n");
-    }
-  fprintf(f,"\n");
-}
-#endif // DEBUG_AUTOMATON
-
-#ifdef DEBUG_AUTOMATON
-static void s_automaton_print_edges(FILE* f, Automaton a)
-{
-  int letter;
-  char * sid;
-  astate s;
-  alist_elt ptr;
-  for(ptr = alist_get_first(a->states) ; ptr != NULL ; ptr = 
alist_get_next(a->states,ptr))
-    {
-      s = (astate)alist_elt_get_value(ptr);
-      for(letter=0; letter < 255; letter++)
-       {
-         if (s->next[letter])
-           {
-             sid = s_automaton_id_to_str(s->id);
-             fprintf(f,"\t\"%s\" -> ",sid);
-             sid = s_automaton_id_to_str(s->next[letter]->id);
-             fprintf(f,"\"%s\" [label = \"",sid);
-             regexp_print_letter(f,letter);
-             fprintf(f,"\"];\n");
-           }
-       }
-    }
-}
-#endif // DEBUG_AUTOMATON
-
-#ifdef DEBUG_AUTOMATON
-static void s_automaton_dump(Automaton a, char* filename)
-{
-  FILE* f;
-#ifdef HAVE_SYS_WAIT_H
-  pid_t   pid;
-#endif
-  if (a == NULL)
-    return;
-  f=fopen(filename,"w");
-  fprintf(f,"digraph automaton {\n");
-  s_automaton_print_nodes(f,a);
-  s_automaton_print_edges(f,a);
-  fprintf(f,"fontsize=20;\n");
-  fprintf(f,"}\n");
-  fclose(f);
-
-#ifdef HAVE_SYS_WAIT_H
-  pid = fork ();
-  if (pid > 0) {
-    wait(NULL);
-  } else if (pid == 0) {
-    execlp("dotty","dotty",filename,NULL);
-    printf("exec dotty failed\n");
-    exit(1);
-  }
-#endif
-}
-#endif // DEBUG_AUTOMATON
-
-/* ************************************************** *
- * ************************************************** *
- * ************************************************** */
-

Index: dic/compdic.c
===================================================================
RCS file: dic/compdic.c
diff -N dic/compdic.c
--- dic/compdic.c       4 Aug 2007 20:01:28 -0000       1.10
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,350 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   compdic.c
- *  \brief  Program used to compress a dictionary
- *  \author Antoine Fraboulet
- *  \date   1999
- */
-
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "hashtable.h"
-#include "dic_internals.h"
-#include "dic.h"
-
-//#define DEBUG_LIST
-//#define DEBUG_OUTPUT
-//#define DEBUG_OUTPUT_L2
-#define CHECK_RECURSION
-
-char*
-load_uncompressed(const char* file_name, unsigned int *dic_size)
-{
-  unsigned r;
-  char *uncompressed;
-  FILE* file_desc;
-
-  if ((file_desc = fopen (file_name, "r")) == NULL)
-    return NULL;
-
-  if ((uncompressed = (char*)malloc (sizeof(char)*(*dic_size))) == NULL)
-    return NULL;
-
-  r = fread (uncompressed, 1, *dic_size, file_desc);
-  if (r < *dic_size)
-    {
-      /* \n is 2 chars under MS OS */
-      printf("\n");
-      printf("** The number of bytes read is less than the size of the file 
**\n");
-      printf("** this may be OK if you run a Microsoft OS but not on Unix   
**\n");
-      printf("** please check the results.                                  
**\n");
-      printf("\n");
-      *dic_size = r;
-    }
-
-  fclose(file_desc);
-  return uncompressed;
-}
-
-
-int
-file_length(const char* file_name)
-{
-  struct stat stat_buf;
-  if (stat (file_name, &stat_buf) < 0)
-    return - 1;
-  return (int) stat_buf.st_size;
-}
-
-
-void
-skip_init_header(FILE* outfile, Dict_header *header)
-{
-  header->unused_1   = 0;
-  header->unused_2   = 0;
-  header->root       = 0;
-  header->nwords     = 0;
-  header->nodesused  = 1;
-  header->edgesused  = 1;
-  header->nodessaved = 0;
-  header->edgessaved = 0;
-
-  fwrite (header, sizeof(Dict_header), 1, outfile);
-}
-
-
-void
-fix_header(FILE* outfile, Dict_header* header)
-{
-  strcpy(header->ident,_COMPIL_KEYWORD_);
-  header->root = header->edgesused;
-  rewind (outfile);
-#if defined(WORDS_BIGENDIAN)
-  #warning "**********************************************"
-  #warning "compdic does not run yet on bigendian machines"
-  #warning "**********************************************"
-#else
-  fwrite (header, sizeof(Dict_header), 1, outfile);
-#endif
-}
-
-
-void
-print_header_info(Dict_header *header)
-{
-  printf("============================\n");
-  printf("keyword length %lu bytes\n", (unsigned 
long)strlen(_COMPIL_KEYWORD_));
-  printf("keyword size   %lu bytes\n", (unsigned 
long)sizeof(_COMPIL_KEYWORD_));
-  printf("header size    %lu bytes\n", (unsigned long)sizeof(Dict_header));
-  printf("\n");
-  printf("%d words\n",header->nwords);
-  printf("\n");
-  printf("root : %7d (edge)\n",header->root);
-  printf("root : %7lu (byte)\n",(unsigned long) header->root * 
sizeof(Dawg_edge));
-  printf("\n");
-  printf("nodes : %d+%d\n",header->nodesused, header->nodessaved);
-  printf("edges : %d+%d\n",header->edgesused, header->edgessaved);
-  printf("============================\n");
-}
-
-
-void
-write_node(Dawg_edge *edges, int size, int num, FILE* outfile)
-{
-#ifdef DEBUG_OUTPUT
-  int i;
-  printf("writing %d edges\n",num);
-  for(i=0; i<num; i++)
-    {
-#ifdef DEBUG_OUTPUT_L2
-      printf("ptr=%2d t=%d l=%d f=%d chr=%2d (%c)\n",
-            edges[i].ptr, edges[i].term, edges[i].last,
-            edges[i].fill, edges[i].chr, edges[i].chr -1 +'a');
-#endif
-      fwrite (edges+i, sizeof(Dawg_edge), 1, outfile);
-    }
-#else
-  fwrite (edges, size, num, outfile);
-#endif
-}
-
-#define MAX_STRING_LENGTH 200
-
-
-#define MAX_EDGES 2000
-/* ods3: ??   */
-/* ods4: 1746 */
-
-/* global variables */
-FILE*       global_outfile;
-Dict_header global_header;
-Hash_table  global_hashtable;
-
-char        global_stringbuf[MAX_STRING_LENGTH]; /* Space for current string */
-char*       global_endstring;                    /* Marks END of current 
string */
-char*       global_input;
-char*       global_endofinput;
-
-/*
- * Makenode takes a prefix (as position relative to stringbuf) and
- * returns an index of the start node of a dawg that recognizes all
- * words beginning with that prefix.  String is a pointer (relative
- * to stringbuf) indicating how much of prefix is matched in the
- * input.
- */
-#ifdef CHECK_RECURSION
-int current_rec =0;
-int max_rec = 0;
-#endif
-
-unsigned int
-makenode(char *prefix)
-{
-  int    numedges;
-  Dawg_edge  edges[MAX_EDGES];
-  Dawg_edge *edgeptr = edges;
-  unsigned  *saved_position;
-
-#ifdef CHECK_RECURSION
-  current_rec++;
-  if (current_rec > max_rec)
-    max_rec = current_rec;
-#endif
-
-  while (prefix == global_endstring)
-    {
-      /* More edges out of node */
-      edgeptr->ptr  = 0;
-      edgeptr->term = 0;
-      edgeptr->last = 0;
-      edgeptr->fill = 0;
-      edgeptr->chr  = 0;
-
-      (*(edgeptr++)).chr = (*global_endstring++ = *global_input++) & 
DIC_CHAR_MASK;
-      if (*global_input == '\n')                 /* End of a word */
-        {
-          global_header.nwords++;
-          edgeptr[-1].term = 1;                  /* Mark edge as word */
-          *global_endstring++ = *global_input++; /* Skip \n */
-          if (global_input == global_endofinput) /* At end of input? */
-            break;
-
-         global_endstring = global_stringbuf;
-         while(*global_endstring == *global_input)
-           {
-              global_endstring++;
-              global_input++;
-           }
-        }
-      /* make dawg pointed to by this edge */
-      edgeptr[-1].ptr = makenode(prefix + 1);
-    }
-
-  numedges = edgeptr - edges;
-  if (numedges == 0)
-    {
-#ifdef CHECK_RECURSION
-      current_rec --;
-#endif
-      return 0;             /* Special node zero - no edges */
-    }
-
-  edgeptr[-1].last = 1;     /* Mark the last edge */
-
-  saved_position = (unsigned int*) hash_find (global_hashtable,
-                                             (void*)edges,
-                                             numedges*sizeof(Dawg_edge));
-  if (saved_position)
-    {
-      global_header.edgessaved += numedges;
-      global_header.nodessaved++;
-
-#ifdef CHECK_RECURSION
-      current_rec --;
-#endif
-      return *saved_position;
-    }
-  else
-    {
-      unsigned int node_pos;
-
-      node_pos = global_header.edgesused;
-      hash_add(global_hashtable,
-              (void*)edges,numedges*sizeof(Dawg_edge),
-              
(void*)(&global_header.edgesused),sizeof(global_header.edgesused));
-      global_header.edgesused += numedges;
-      global_header.nodesused++;
-      write_node (edges, sizeof(Dawg_edge), numedges, global_outfile);
-
-#ifdef CHECK_RECURSION
-      current_rec --;
-#endif
-      return node_pos;
-    }
-}
-
-
-
-
-int
-main(int argc, char* argv[])
-{
-  unsigned int dicsize;
-  char *uncompressed;
-  Dawg_edge rootnode = {0,0,0,0,0};
-  Dawg_edge specialnode = {0,0,0,0,0};
-
-  int size;
-  char* outfilename;
-  char outfilenamedefault[] = "dict.daw";
-  clock_t starttime, endtime;
-
-  if (argc < 2)
-    {
-      fprintf(stderr,"usage: %s uncompressed_dic [compressed_dic]\n",argv[0]);
-      exit(1);
-    }
-
-  size = file_length (argv[1]);
-  if (size < 0)
-    {
-      fprintf(stderr,"Cannot stat uncompressed dictionary %s\n",argv[1]);
-      exit(1);
-    }
-
-  dicsize = size;
-  outfilename = (argc == 3) ? argv[2] : outfilenamedefault;
-
-  if ((global_outfile = fopen (outfilename,"wb")) == NULL)
-    {
-      fprintf(stderr,"Cannot open output file %s\n",outfilename);
-      exit(1);
-    }
-
-  if ((uncompressed = load_uncompressed(argv[1], &dicsize)) == NULL)
-    {
-      fprintf(stderr,"Cannot load uncompressed dictionary into memory\n");
-      exit(1);
-    }
-
-  global_input = uncompressed;
-  global_endofinput = global_input + dicsize;
-
-#define SCALE 0.6
-  global_hashtable = hash_init((unsigned int)(dicsize * SCALE));
-#undef SCALE
-
-  skip_init_header(global_outfile,&global_header);
-
-  specialnode.last = 1;
-  write_node(&specialnode,sizeof(specialnode),1,global_outfile);
-  /*
-   * Call makenode with null (relative to stringbuf) prefix;
-   * Initialize string to null; Put index of start node on output
-   */
-  starttime=clock();
-  rootnode.ptr = makenode(global_endstring = global_stringbuf);
-  endtime=clock();
-  write_node(&rootnode,sizeof(rootnode),1,global_outfile);
-
-  fix_header(global_outfile,&global_header);
-
-  print_header_info(&global_header);
-  hash_destroy(global_hashtable);
-  free(uncompressed);
-  fclose(global_outfile);
-
-  printf(" Elapsed time is                 : %f s\n", 1.0*(endtime-starttime) 
/ CLOCKS_PER_SEC);
-#ifdef CHECK_RECURSION
-  printf(" Maximum recursion level reached : %d\n",max_rec);
-#endif
-  return 0;
-}
-
-

Index: dic/dic.c
===================================================================
RCS file: dic/dic.c
diff -N dic/dic.c
--- dic/dic.c   4 Aug 2007 20:01:28 -0000       1.12
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,282 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   dic.c
- *  \brief  Dawg dictionary
- *  \author Antoine Fraboulet
- *  \date   2002
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-
-#include "config.h"
-#include "dic_internals.h"
-#include "dic.h"
-
-#define __UNUSED__ __attribute__((unused))
-
-#if defined(WORDS_BIGENDIAN)
-static uint32_t swap4(uint32_t v)
-{
-  uint32_t   r;
-  uint8_t  *pv,*pr;
-
-  pv = (uint8_t*)&v;
-  pr = (uint8_t*)&r;
-  
-  pr[0] = pv[3];
-  pr[1] = pv[2];
-  pr[2] = pv[1];
-  pr[3] = pv[0];
-
-  return r;
-}
-#endif
-
-static int
-Dic_read_convert_header(Dict_header *header, FILE* file)
-{
-
-  if (fread(header,sizeof(Dict_header),1,file) != 1)
-    return 1;
-
-#if defined(WORDS_BIGENDIAN)
-  header->root       = swap4(header->root);
-  header->nwords     = swap4(header->nwords);
-  header->nodesused  = swap4(header->nodesused);
-  header->edgesused  = swap4(header->edgesused);
-  header->nodessaved = swap4(header->nodessaved);
-  header->edgessaved = swap4(header->edgessaved);
-#else
-
-#endif
-  return 0;
-}
-
-int
-Dic_check_header(Dict_header *header, const char *path)
-{
-  int r;
-  FILE* file;
-  if ((file = fopen(path,"rb")) == NULL)
-    return 1;
-  
-  r = Dic_read_convert_header(header,file);
-  fclose(file);
-
-  return r || strcmp(header->ident,_COMPIL_KEYWORD_);
-}
-
-static void
-Dic_convert_data_to_arch(Dictionary __UNUSED__ dic)
-{
-#if defined(WORDS_BIGENDIAN)
-  int i;
-  uint32_t* p;
-  p = (uint32_t*)dic->dawg;
-  for(i=0; i < (dic->nedges + 1); i++)
-    {
-      p[i] = swap4(p[i]);
-    }
-#endif
-}
-
-int
-Dic_load(Dictionary *dic, const char* path)
-{
-  FILE* file;
-  Dict_header header;
-
-
-  *dic = NULL;
-  if ((file = fopen(path,"rb")) == NULL)
-    return 1;
-
-  Dic_read_convert_header(&header,file);
-
-  if ((*dic = (Dictionary) malloc(sizeof(struct _Dictionary))) == NULL)
-    return 3;
-
-  if (((*dic)->dawg = (Dawg_edge*)malloc((header.edgesused + 
1)*sizeof(Dawg_edge))) == NULL)
-    {
-      free(*dic);
-      *dic = NULL;
-      return 4;
-    }
-
-  if (fread((*dic)->dawg,sizeof(Dawg_edge),header.edgesused + 1,file) !=
-      (header.edgesused + 1))
-    {
-      free((*dic)->dawg);
-      free(*dic);
-      *dic = NULL;
-      return 5;
-    }
-
-  (*dic)->root   = header.root;
-  (*dic)->nwords = header.nwords;
-  (*dic)->nnodes = header.nodesused;
-  (*dic)->nedges = header.edgesused;
-
-  Dic_convert_data_to_arch(*dic);
-
-  fclose(file);
-  return 0;
-}
-
-
-int
-Dic_destroy(Dictionary dic)
-{
-  if (dic != NULL)
-    {
-      if (dic->dawg != NULL)
-        free(dic->dawg);
-      else
-        {
-          free(dic);
-          return 2;
-        }
-      free(dic);
-    }
-  else
-    return 1;
-
-  return 0;
-}
-
-
-dic_elt_t
-Dic_next(Dictionary d, dic_elt_t e)
-{
-     if (! Dic_last(d,e))
-          return e+1;
-     return 0;
-}
-
-
-dic_elt_t
-Dic_succ(Dictionary d, dic_elt_t e)
-{
-  return (d->dawg[e]).ptr;
-}
-
-
-dic_elt_t
-Dic_root(Dictionary d)
-{
-  return d->root;
-}
-
-
-dic_code_t
-Dic_chr(Dictionary d, dic_elt_t e)
-{
-  return (dic_code_t)(d->dawg[e]).chr;
-}
-
-
-int
-Dic_last(Dictionary d, dic_elt_t e)
-{
-  return (d->dawg[e]).last;
-}
-
-
-int
-Dic_word(Dictionary d, dic_elt_t e)
-{
-  return (d->dawg[e]).term;
-}
-
-unsigned int
-Dic_lookup(Dictionary d, dic_elt_t root, dic_code_t* s)
-{
-    unsigned int p;
-begin:
-    if (! *s)
-        return root;
-    if (! Dic_succ(d, root))
-        return 0;
-    p = Dic_succ(d, root);
-    do
-    {
-        if (Dic_chr(d, p) == *s)
-        {
-            root = p;
-            s++;
-            goto begin;
-        }
-        else if (Dic_last(d, p))
-        {
-            return 0;
-        }
-        p = Dic_next(d, p);
-    } while (1);
-
-    return 0;
-}
-
-/* 
**************************************************************************** */
-/* 
**************************************************************************** */
-/* 
**************************************************************************** */
-/* 
**************************************************************************** */
-
-char
-Dic_char(Dictionary d, dic_elt_t e)
-{
-  char c = (d->dawg[e]).chr;
-  if (c)
-    return c + 'A' - 1;
-  else
-    return 0;
-}
-
-unsigned int
-Dic_char_lookup(Dictionary d, dic_elt_t root, char* s)
-{
-    unsigned int p;
-begin:
-    if (! *s)
-        return root;
-    if (! Dic_succ(d, root))
-        return 0;
-    p = Dic_succ(d, root);
-    do
-    {
-        if (Dic_char(d, p) == *s)
-        {
-            root = p;
-            s++;
-            goto begin;
-        }
-        else if (Dic_last(d, p))
-        {
-            return 0;
-        }
-        p = Dic_next(d, p);
-    } while (1);
-
-    return 0;
-}

Index: dic/dic_search.c
===================================================================
RCS file: dic/dic_search.c
diff -N dic/dic_search.c
--- dic/dic_search.c    4 Aug 2007 20:01:28 -0000       1.21
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,690 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   dic_search.c
- *  \brief  Dictionary lookup functions
- *  \author Antoine Fraboulet
- *  \date   2002
- */
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wchar.h>
-
-#include "dic_internals.h"
-#include "dic.h"
-#include "regexp.h"
-#include "dic_search.h"
-#include "libdic_a-ery.h"    /* generated by bison */
-#include "libdic_a-erl.h"    /* generated by flex  */
-#include "automaton.h"
-
-/**
- * function prototype for bison generated parser 
- */
-int  regexpparse(yyscan_t scanner, NODE** root,
-                 struct search_RegE_list_t *list,
-                 struct regexp_error_report_t *err);
- 
-/**
- * Dic_seel_edgeptr
- * walk the dictionary until the end of the word
- * @param dic : dictionnary
- * @param s : current pointer to letters
- * @param eptr : current edge in the dawg
- */
-static Dawg_edge*
-Dic_seek_edgeptr(const Dictionary dic, const char* s, Dawg_edge *eptr)
-{
-  if (*s)
-    {
-      Dawg_edge *p = dic->dawg + eptr->ptr;
-      do {
-        if (p->chr == (unsigned)(*s & DIC_CHAR_MASK))
-          return Dic_seek_edgeptr (dic,s + 1, p);
-      } while (!(*p++).last);
-      return dic->dawg;
-    }
-  else
-    return eptr;
-}
-
-
-/**
- * Dic_search_word_inner : direct application of Dic_seek_edgeptr
- * @param dic : dictionary
- * @param word : word to lookup
- * @result 0 not a valid word, 1 ok
- */
-static int Dic_search_word_inner(const Dictionary dic, const char* word)
-{
-    Dawg_edge *e;
-    e = Dic_seek_edgeptr(dic, word, dic->dawg + dic->root);
-    return e->term;
-}
-
-
-/**
- * Wrapper around Dic_search_word_inner, until we have multibyte support in
- * the dictionary
- */
-int Dic_search_word(const Dictionary dic, const wchar_t* word)
-{
-    int res;
-    char *tmp_word = malloc(wcslen(word) + 1);
-    sprintf(tmp_word, "%ls", word);
-
-    // Do the actual work
-    res = Dic_search_word_inner(dic, tmp_word);
-
-    // Release memory
-    free(tmp_word);
-    return res;
-}
-
-
-/**
- * global variables for Dic_search_word_by_len :
- *
- * a pointer to the structure is passed as a parameter
- * so that all the search_* variables appear to the functions
- * as global but the code remains re-entrant.
- * Should be better to change the algorithm ...
- */
-
-struct params_7plus1_t {
- Dictionary search_dic;
- int search_len;
- int search_wordlistlen;
- int search_wordlistlenmax;
- char search_wordtst[DIC_WORD_MAX];
- char search_letters[DIC_LETTERS];
- char (*search_wordlist)[RES_7PL1_MAX][DIC_WORD_MAX];
-};
-
-static void
-Dic_search_word_by_len(struct params_7plus1_t *params, int i, Dawg_edge 
*edgeptr)
-{
-  /* depth first search in the dictionary */
-  do {
-    /* we use a static array and not a real list so we have to stop if
-     * the array is full */
-    if (params->search_wordlistlen >= params->search_wordlistlenmax)
-      break;
-
-    /* the test is false only when reach the end-node */
-    if (edgeptr->chr)
-      {
-
-       /* is the letter available in search_letters */
-       if (params->search_letters[edgeptr->chr])
-         {
-           params->search_wordtst[i] = edgeptr->chr + 'A' - 1;
-           params->search_letters[edgeptr->chr] --;
-           if (i == params->search_len)
-             {
-               if ((edgeptr->term)
-                 /* && (params->search_wordlistlen < 
params->search_wordlistlenmax) */)
-                 
strcpy((*params->search_wordlist)[params->search_wordlistlen++],params->search_wordtst);
-             }
-           else /* if (params->search_wordlistlen < 
params->search_wordlistlenmax) */
-             {
-               Dic_search_word_by_len(params,i + 1, params->search_dic->dawg + 
edgeptr->ptr);
-             }
-           params->search_letters[edgeptr->chr] ++;
-           params->search_wordtst[i] = '\0';
-         }
-
-       /* the letter is of course available if we have a joker available */
-       if (params->search_letters[0])
-         {
-           params->search_wordtst[i] = edgeptr->chr + 'a' - 1;
-           params->search_letters[0] --;
-           if (i == params->search_len)
-             {
-               if ((edgeptr->term)
-                    /* && (params->search_wordlistlen < 
params->search_wordlistlenmax) */)
-                 
strcpy((*(params->search_wordlist))[params->search_wordlistlen++],params->search_wordtst);
-             }
-           else /* if (params->search_wordlistlen < 
params->search_wordlistlenmax) */
-             {
-               Dic_search_word_by_len(params,i + 1,params->search_dic->dawg + 
edgeptr->ptr);
-             }
-           params->search_letters[0] ++;
-           params->search_wordtst[i] = '\0';
-         }
-      }
-  } while (! (*edgeptr++).last);
-}
-
-static void
-Dic_search_7pl1_inner(const Dictionary dic, const char* rack,
-                      char buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX],
-                      int joker)
-{
-  int i,j,wordlen;
-  const char* r = rack;
-  struct params_7plus1_t params;
-  Dawg_edge *root_edge;
-
-  for(i=0; i < DIC_LETTERS; i++)
-    for(j=0; j < RES_7PL1_MAX; j++)
-      buff[i][j][0] = '\0';
-
-  for(i=0; i<DIC_LETTERS; i++)
-    params.search_letters[i] = 0;
-
-  if (dic == NULL || rack == NULL || *rack == '\0')
-    return;
-
-  /*
-   * the letters are verified and changed to the dic internal
-   * representation (*r & DIC_CHAR_MASK)
-   */
-  for(wordlen=0; wordlen < DIC_WORD_MAX && *r; r++)
-    {
-      if (isalpha(*r))
-       {
-         params.search_letters[(int)*r & DIC_CHAR_MASK]++;
-          wordlen++;
-       }
-      else if (*r == '?')
-       {
-         if (joker)
-           {
-             params.search_letters[0]++;
-             wordlen++;
-           }
-         else
-           {
-             strncpy(buff[0][0],"** joker **",DIC_WORD_MAX);
-             return;
-           }
-       }
-    }
-
-  if (wordlen < 1)
-    return;
-
-  root_edge = dic->dawg + (dic->dawg[dic->root].ptr);
-
-  params.search_dic = dic;
-  params.search_wordlistlenmax = RES_7PL1_MAX;
-
-  /* search for all the words that can be done with the letters */
-  params.search_len = wordlen - 1;
-  params.search_wordtst[wordlen]='\0';
-  params.search_wordlist = & buff[0];
-  params.search_wordlistlen = 0;
-  Dic_search_word_by_len(&params,0,root_edge);
-
-  /* search for all the words that can be done with the letters +1 */
-  params.search_len = wordlen;
-  params.search_wordtst[wordlen + 1]='\0';
-  for(i='a'; i <= 'z'; i++)
-    {
-      params.search_letters[i & DIC_CHAR_MASK]++;
-
-      params.search_wordlist = & buff[i & DIC_CHAR_MASK];
-      params.search_wordlistlen = 0;
-      Dic_search_word_by_len(&params,0,root_edge);
-
-      params.search_letters[i & DIC_CHAR_MASK]--;
-    }
-}
-
-
-/**
- * Wrapper around Dic_search_7pl1_inner, until we have multibyte support in
- * the dictionary
- */
-void
-Dic_search_7pl1(const Dictionary dic, const wchar_t* rack,
-                wchar_t buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX],
-                int joker)
-{
-    int i, j, k;
-    char tmp_buff[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX];
-    char *tmp_rack = malloc(wcslen(rack) + 1);
-    sprintf(tmp_rack, "%ls", rack);
-    // Do the actual work
-    Dic_search_7pl1_inner(dic, tmp_rack, tmp_buff, joker);
-
-    for (i = 0; i < DIC_LETTERS; i++)
-    {
-        for (j = 0; j < RES_7PL1_MAX; j++)
-        {
-            for (k = 0; k < DIC_WORD_MAX; k++)
-            {
-                buff[i][j][k] = tmp_buff[i][j][k];
-            }
-        }
-    }
-    free(tmp_rack);
-}
-
-/****************************************/
-/****************************************/
-
-static void
-Dic_search_Racc_inner(const Dictionary dic, const char* word,
-                      char wordlist[RES_RACC_MAX][DIC_WORD_MAX])
-{
-  /* search_racc will try to add a letter in front and at the end of a word */
-
-  int i,wordlistlen;
-  Dawg_edge *edge;
-  char wordtst[DIC_WORD_MAX];
-
-  for(i=0; i < RES_RACC_MAX; i++)
-    wordlist[i][0] = 0;
-
-  if (dic == NULL || wordlist == NULL || *wordlist == '\0')
-    return;
-
-  /* let's try for the front */
-  wordlistlen = 0;
-  strcpy(wordtst+1,word);
-  for(i='a'; i <= 'z'; i++)
-    {
-      wordtst[0] = i;
-      if (Dic_search_word_inner(dic,wordtst) && wordlistlen < RES_RACC_MAX)
-       strcpy(wordlist[wordlistlen++],wordtst);
-    }
-
-  /* add a letter at the end */
-  for(i=0; word[i]; i++)
-    wordtst[i] = word[i];
-
-  wordtst[i  ] = '\0';
-  wordtst[i+1] = '\0';
-
-  edge = Dic_seek_edgeptr(dic,word,dic->dawg + dic->root);
-
-  /* points to what the next letter can be */
-  edge = dic->dawg + edge->ptr;
-
-  if (edge != dic->dawg)
-    {
-      do {
-         if (edge->term && wordlistlen < RES_RACC_MAX)
-           {
-             wordtst[i] = edge->chr + 'a' - 1;
-             strcpy(wordlist[wordlistlen++],wordtst);
-           }
-      } while (!(*edge++).last);
-    }
-}
-
-/**
- * Wrapper around Dic_search_Racc_inner, until we have multibyte support in
- * the dictionary
- */
-void
-Dic_search_Racc(const Dictionary dic, const wchar_t* word,
-                wchar_t wordlist[RES_RACC_MAX][DIC_WORD_MAX])
-{
-    int i, j;
-    char tmp_buff[RES_RACC_MAX][DIC_WORD_MAX];
-    char *tmp_word = malloc(wcslen(word) + 1);
-    sprintf(tmp_word, "%ls", word);
-    // Do the actual work
-    Dic_search_Racc_inner(dic, tmp_word, tmp_buff);
-
-    for (i = 0; i < RES_RACC_MAX; i++)
-    {
-        for (j = 0; j < DIC_WORD_MAX; j++)
-        {
-            wordlist[i][j] = tmp_buff[i][j];
-        }
-    }
-    free(tmp_word);
-}
-
-/****************************************/
-/****************************************/
-
-
-static void
-Dic_search_Benj_inner(const Dictionary dic, const char* word,
-                      char wordlist[RES_BENJ_MAX][DIC_WORD_MAX])
-{
-  int i,wordlistlen;
-  char wordtst[DIC_WORD_MAX];
-  Dawg_edge *edge0,*edge1,*edge2,*edgetst;
-
-  for(i=0; i < RES_BENJ_MAX; i++)
-    wordlist[i][0] = 0;
-
-  if (dic == NULL || word == NULL || *word == '\0')
-    return;
-
-  wordlistlen = 0;
-
-  strcpy(wordtst+3,word);
-  edge0 = dic->dawg + (dic->dawg[dic->root].ptr);
-  do {
-    wordtst[0] = edge0->chr + 'a' - 1;
-    edge1 = dic->dawg + edge0->ptr;
-    do {
-      wordtst[1] = edge1->chr + 'a' - 1;
-      edge2  = dic->dawg + edge1->ptr;
-      do {
-       wordtst[2] = edge2->chr + 'a' - 1;
-       edgetst = Dic_seek_edgeptr(dic,word,edge2);
-       if (edgetst->term && wordlistlen < RES_BENJ_MAX)
-         strcpy(wordlist[wordlistlen++],wordtst);
-      } while (!(*edge2++).last);
-    } while (!(*edge1++).last);
-  } while (!(*edge0++).last);
-}
-
-/**
- * Wrapper around Dic_search_Benj_inner, until we have multibyte support in
- * the dictionary
- */
-void
-Dic_search_Benj(const Dictionary dic, const wchar_t* word,
-                wchar_t wordlist[RES_BENJ_MAX][DIC_WORD_MAX])
-{
-    int i, j;
-    char tmp_buff[RES_BENJ_MAX][DIC_WORD_MAX];
-    char *tmp_word = malloc(wcslen(word) + 1);
-    sprintf(tmp_word, "%ls", word);
-    // Do the actual work
-    Dic_search_Benj_inner(dic, tmp_word, tmp_buff);
-
-    for (i = 0; i < RES_BENJ_MAX; i++)
-    {
-        for (j = 0; j < DIC_WORD_MAX; j++)
-        {
-            wordlist[i][j] = tmp_buff[i][j];
-        }
-    }
-    free(tmp_word);
-}
-
-
-/****************************************/
-/****************************************/
-
-struct params_cross_t {
- Dictionary dic;
- int wordlen;
- int wordlistlen;
- int wordlistlenmax;
- char mask[DIC_WORD_MAX];
-};
-
-
-void
-Dic_search_cross_rec(struct params_cross_t *params,
-                     char wordlist[RES_CROS_MAX][DIC_WORD_MAX],
-                     Dawg_edge *edgeptr)
-{
-  Dawg_edge *current = params->dic->dawg + edgeptr->ptr;
-
-  if (params->mask[params->wordlen] == '\0' && edgeptr->term)
-    {
-      if (params->wordlistlen < params->wordlistlenmax)
-       strcpy(wordlist[params->wordlistlen++],params->mask);
-    }
-  else if (params->mask[params->wordlen] == '.')
-    {
-      do
-       {
-         params->mask[params->wordlen] = current->chr + 'a' - 1;
-         params->wordlen ++;
-         Dic_search_cross_rec(params,wordlist,current);
-         params->wordlen --;
-         params->mask[params->wordlen] = '.';
-       }
-      while (!(*current++).last);
-    }
-  else
-    {
-      do
-       {
-         if (current->chr == (unsigned int)(params->mask[params->wordlen] & 
DIC_CHAR_MASK))
-           {
-             params->wordlen ++;
-             Dic_search_cross_rec(params,wordlist,current);
-             params->wordlen --;
-             break;
-           }
-       }
-      while (!(*current++).last);
-    }
-}
-
-
-static void
-Dic_search_Cros_inner(const Dictionary dic, const char* mask,
-                      char wordlist[RES_CROS_MAX][DIC_WORD_MAX])
-{
-  int  i;
-  struct params_cross_t params;
-
-  for(i=0; i < RES_CROS_MAX; i++)
-    wordlist[i][0] = 0;
-
-  if (dic == NULL || mask == NULL || *mask == '\0')
-    return;
-
-  for(i=0; i < DIC_WORD_MAX && mask[i]; i++)
-    {
-      if (isalpha(mask[i]))
-       params.mask[i] = (mask[i] & DIC_CHAR_MASK) + 'A' - 1;
-      else
-       params.mask[i] = '.';
-    }
-  params.mask[i] = '\0';
-
-  params.dic            = dic;
-  params.wordlen        = 0;
-  params.wordlistlen    = 0;
-  params.wordlistlenmax = RES_CROS_MAX;
-  Dic_search_cross_rec(&params, wordlist, dic->dawg + dic->root);
-}
-
-
-/**
- * Wrapper around Dic_search_Cros_inner, until we have multibyte support in
- * the dictionary
- */
-void
-Dic_search_Cros(const Dictionary dic, const wchar_t* mask,
-                wchar_t wordlist[RES_CROS_MAX][DIC_WORD_MAX])
-{
-    int i, j;
-    char tmp_buff[RES_CROS_MAX][DIC_WORD_MAX];
-    char *tmp_mask = malloc(wcslen(mask) + 1);
-    sprintf(tmp_mask, "%ls", mask);
-    // Do the actual work
-    Dic_search_Cros_inner(dic, tmp_mask, tmp_buff);
-
-    for (i = 0; i < RES_CROS_MAX; i++)
-    {
-        for (j = 0; j < DIC_WORD_MAX; j++)
-        {
-            wordlist[i][j] = tmp_buff[i][j];
-        }
-    }
-    free(tmp_mask);
-}
-
-/****************************************/
-/****************************************/
-
-struct params_regexp_t {
-  Dictionary dic;
-  int minlength;
-  int maxlength;
-  automaton automaton;
-  struct search_RegE_list_t *charlist;
-  char word[DIC_WORD_MAX];
-  int  wordlen;
-  int  wordlistlen;
-  int  wordlistlenmax;
-};
-
-void
-Dic_search_regexp_rec(struct params_regexp_t *params,
-                     int state,
-                     Dawg_edge *edgeptr,
-                     char wordlist[RES_REGE_MAX][DIC_WORD_MAX])
-{
-  int next_state;
-  Dawg_edge *current;
-  /* if we have a valid word we store it */
-  if (automaton_get_accept(params->automaton,state) && edgeptr->term)
-    {
-      int l = strlen(params->word);
-      if (params->wordlistlen < params->wordlistlenmax &&
-         params->minlength <= l                        &&
-         params->maxlength >= l)
-       {
-         strcpy(wordlist[params->wordlistlen++],params->word);
-       }
-    }
-  /* we now drive the search by exploring the dictionary */
-  current = params->dic->dawg + edgeptr->ptr;
-  do {
-    /* the current letter is current->chr */
-    next_state = 
automaton_get_next_state(params->automaton,state,current->chr);
-    /* 1 : the letter appears in the automaton as is */
-    if (next_state)
-      {
-       params->word[params->wordlen] = current->chr + 'a' - 1;
-       params->wordlen ++;
-       Dic_search_regexp_rec(params,next_state,current,wordlist);
-       params->wordlen --;
-       params->word[params->wordlen] = '\0';
-      }
-  } while (!(*current++).last);
-}
-
-
-void
-Dic_search_RegE_inner(const Dictionary dic, const char* re,
-                      char wordlist[RES_REGE_MAX][DIC_WORD_MAX],
-                      struct search_RegE_list_t *list)
-{
-  int i,p,n,value;
-  int ptl[REGEXP_MAX+1];
-  int PS [REGEXP_MAX+1];
-  NODE* root;
-  yyscan_t scanner;
-  YY_BUFFER_STATE buf;
-  automaton a;
-  char stringbuf[250];
-  struct params_regexp_t params;
-  struct regexp_error_report_t report;
-
-  /* init */
-  for(i=0; i < RES_REGE_MAX; i++)
-    wordlist[i][0] = 0;
-
-  if (dic == NULL || re == NULL || *re == '\0')
-    return;
-
-  /* (expr)# */
-  sprintf(stringbuf,"(%s)#",re);
-  for(i=0; i < REGEXP_MAX; i++)
-    {
-      PS[i] = 0;
-      ptl[i] = 0;
-    }
-
-  report.pos1 = 0;
-  report.pos2 = 0;
-  report.msg[0] = '\0';
-
-  /* parsing */
-  regexplex_init( &scanner );
-  buf   = regexp_scan_string( stringbuf, scanner );
-  root  = NULL;
-  value = regexpparse( scanner , &root, list, &report);
-  regexp_delete_buffer(buf,scanner);
-  regexplex_destroy( scanner );
-
-  if (value)
-    {
-#ifdef DEBUG_FLEX_IS_BROKEN
-      fprintf(stderr,"parser error at pos %d - %d : %s\n",
-             report.pos1, report.pos2, report.msg);
-#endif
-      regexp_delete_tree(root);
-      return ;
-    }
-
-  n = 1;
-  p = 1;
-  regexp_parcours(root, &p, &n, ptl);
-  PS [0] = p - 1;
-  ptl[0] = p - 1;
-
-  regexp_possuivante(root,PS);
-
-  if ((a = automaton_build(root->PP,ptl,PS,list)) != NULL)
-    {
-      params.dic            = dic;
-      params.minlength      = list->minlength;
-      params.maxlength      = list->maxlength;
-      params.automaton      = a;
-      params.charlist       = list;
-      memset(params.word,'\0',sizeof(params.word));
-      params.wordlen        = 0;
-      params.wordlistlen    = 0;
-      params.wordlistlenmax = RES_REGE_MAX;
-      Dic_search_regexp_rec(&params, automaton_get_init(a), dic->dawg + 
dic->root, wordlist);
-
-      automaton_delete(a);
-    }
-  regexp_delete_tree(root);
-}
-
-/**
- * Wrapper around Dic_search_RegE_inner, until we have multibyte support in
- * the dictionary
- */
-void
-Dic_search_RegE(const Dictionary dic, const wchar_t* re,
-                wchar_t wordlist[RES_REGE_MAX][DIC_WORD_MAX],
-                struct search_RegE_list_t *list)
-{
-    int i;
-    char tmp_buff[RES_REGE_MAX][DIC_WORD_MAX];
-    char *tmp_re = malloc(wcslen(re) + 1);
-    sprintf(tmp_re, "%ls", re);
-    // Do the actual work
-    Dic_search_RegE_inner(dic, tmp_re, tmp_buff, list);
-
-    for (i = 0; i < RES_REGE_MAX; i++)
-    {
-        mbstowcs(wordlist[i], tmp_buff[i], DIC_WORD_MAX);
-    }
-    free(tmp_re);
-}
-
-/****************************************/
-/****************************************/
-

Index: dic/dic_search.h
===================================================================
RCS file: dic/dic_search.h
diff -N dic/dic_search.h
--- dic/dic_search.h    22 Jan 2006 12:23:53 -0000      1.12
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,131 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   dic_search.h
- *  \brief  Dictionary lookup functions
- *  \author Antoine Fraboulet
- *  \date   2002
- */
-
-#ifndef _DIC_SEARCH_H_
-#define _DIC_SEARCH_H_
-#if defined(__cplusplus)
-extern "C"
-  {
-#endif
-
-    /**
-     * number of results for Rack+1 search (Dic_search_7pl1)
-     */
-#define RES_7PL1_MAX 200
-
-    /**
-     * number of results for Extensions search (Dic_search_Racc)
-     */
-#define RES_RACC_MAX 100
-
-    /**
-     * number of results for Benjamin search (Dic_search_Benj)
-     */
-#define RES_BENJ_MAX 100
-
-    /**
-     * number of results for CrossWords search (Dic_search_Cros)
-     */
-#define RES_CROS_MAX 200
-
-    /**
-     * number of results for Regular Expression search (Dic_search_RegE)
-     */
-#define RES_REGE_MAX 200
-
-    /**
-     * Search for a word in the dictionnary
-     * @param dic : dictionary
-     * @param path : lookup word
-     * @return 1 present, 0 error
-     */
-int  Dic_search_word(Dictionary dic,
-                     const wchar_t* path);
-
-    /**
-     * Search for all feasible word with "rack" plus one letter
-     * @param dic : dictionary
-     * @param rack : letters
-     * @param wordlist : results
-     */
-void Dic_search_7pl1(Dictionary dic,
-                     const wchar_t* rack,
-                     wchar_t wordlist[DIC_LETTERS][RES_7PL1_MAX][DIC_WORD_MAX],
-                     int joker);
-
-    /**
-     * Search for all feasible word adding a letter in front or at the end
-     * @param dic : dictionary
-     * @param word : word
-     * @param wordlist : results
-     */
-void Dic_search_Racc(Dictionary dic,
-                     const wchar_t* word,
-                     wchar_t wordlist[RES_RACC_MAX][DIC_WORD_MAX]);
-
-    /**
-     * Search for benjamins
-     * @param dic : dictionary
-     * @param rack : letters
-     * @param wordlist : results
-     */
-void Dic_search_Benj(Dictionary dic,
-                     const wchar_t* word,
-                     wchar_t wordlist[RES_BENJ_MAX][DIC_WORD_MAX]);
-
-    /**
-     * Search for crosswords
-     * @param dic : dictionary
-     * @param rack : letters
-     * @param wordlist : results
-     */
-void Dic_search_Cros(Dictionary dic,
-                     const wchar_t* mask,
-                     wchar_t wordlist[RES_CROS_MAX][DIC_WORD_MAX]);
-
-    /**
-     * Search for words matching a regular expression
-     * @param dic : dictionary
-     * @param re : regular expression
-     * @param wordlist : results
-     */
-void Dic_search_RegE(Dictionary dic,
-                     const wchar_t* re,
-                     wchar_t wordlist[RES_REGE_MAX][DIC_WORD_MAX],
-                     struct search_RegE_list_t *list);
-
-    /**
-     * Internal version of Dic_search_RegE, used inside the dictionary.
-     * Please use Dic_search_RegE instead from outside the dic library.
-     */
-void Dic_search_RegE_inner(const Dictionary dic, const char* re,
-                           char wordlist[RES_REGE_MAX][DIC_WORD_MAX],
-                           struct search_RegE_list_t *list);
-
-#if defined(__cplusplus)
-  }
-#endif
-#endif /* _DIC_SEARCH_H_ */

Index: dic/erl.l
===================================================================
RCS file: dic/erl.l
diff -N dic/erl.l
--- dic/erl.l   4 Aug 2007 19:57:46 -0000       1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,58 +0,0 @@
-%{
-/* Eliot                                                                     */
-/* Copyright (C) 2005  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Elit is distributed in the hope that it will be useful,                   */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-#include "dic.h"
-#include "regexp.h"
-#include "libdic_a-ery.h"
-
-#define MASK_TO_REMOVE    0x1F
-
-%}
-%option prefix="regexp"
-%option outfile="lex.yy.c"
-%option header-file="libdic_a-erl.h"
-%option reentrant bison-bridge
-%option bison-locations
-%option noyywrap nounput
-
-/* TODO : remove lexer translation */
-alphabet [a-zA-Z]
-%%
-
-{alphabet} {yylval_param->c=(yytext[0]&MASK_TO_REMOVE); return LEX_CHAR;}
-"["        {return LEX_L_SQBRACKET;}
-"]"        {return LEX_R_SQBRACKET;}
-"("        {return LEX_L_BRACKET;}
-")"        {return LEX_R_BRACKET;}
-"^"        {return LEX_HAT;}
-
-"."        {return LEX_ALL;}
-":v:"      {return LEX_VOWL;}
-":c:"      {return LEX_CONS;}
-":1:"      {return LEX_USER1;}
-":2:"      {return LEX_USER2;}
-
-"?"        {return LEX_QMARK;}
-"+"        {return LEX_PLUS;}
-"*"        {return LEX_STAR;}
-
-"#"        {return LEX_SHARP;}
-%%
-

Index: dic/ery.y
===================================================================
RCS file: dic/ery.y
diff -N dic/ery.y
--- dic/ery.y   4 Aug 2007 19:57:45 -0000       1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,294 +0,0 @@
-%{
-/* Eliot                                                                     */
-/* Copyright (C) 2005  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Elit is distributed in the hope that it will be useful,                   */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-#include <stdio.h>
-#include <malloc.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "dic.h"
-#include "regexp.h"
-#include "libdic_a-ery.h"
-#include "libdic_a-erl.h"
-
-/* ************************************************** */
-/* ************************************************** */
-/* ************************************************** */
-
-    /**
-     * function prototype for parser generated by bison
-     */
-int  regexpparse(yyscan_t scanner, NODE** root,
-                struct search_RegE_list_t *list,
-                struct regexp_error_report_t *err);
-
-    /**
-     * function prototype for error reporting
-     */
-void regexperror(YYLTYPE *llocp, yyscan_t scanner, NODE** root,
-                struct search_RegE_list_t *list,
-                struct regexp_error_report_t *err,
-                char const *msg);
-
-/* ************************************************** */
-/* ************************************************** */
-/* ************************************************** */
-
-%}
-%union {
-  char c;
-  NODE *NODE_TYPE;
-  char letters[DIC_LETTERS];
-};
-
-%defines
-%name-prefix="regexp"
-%pure-parser
-%locations
-%parse-param {yyscan_t yyscanner}
-%parse-param {NODE **root}
-%parse-param {struct search_RegE_list_t *list}
-%parse-param {struct regexp_error_report_t *err}
-%lex-param   {yyscan_t yyscanner}
-
-%token  <c>  LEX_CHAR
-%token  LEX_ALL
-%token  LEX_VOWL
-%token  LEX_CONS
-%token  LEX_USER1
-%token  LEX_USER2
-
-%token  LEX_L_SQBRACKET LEX_R_SQBRACKET
-%token  LEX_L_BRACKET LEX_R_BRACKET
-%token  LEX_HAT
-
-%token  LEX_QMARK
-%token  LEX_PLUS
-%token  LEX_STAR
-%token  LEX_SHARP
-
-%type   <NODE_TYPE> var
-%type   <NODE_TYPE> expr
-%type   <letters>   vardis
-%type   <letters>   exprdis
-%type   <NODE_TYPE> exprdisnode
-%start  start
-%%
-
-start: LEX_L_BRACKET expr LEX_R_BRACKET LEX_SHARP
-       {
-        NODE* sharp = regexp_createNODE(NODE_VAR,RE_FINAL_TOK,NULL,NULL);
-        *root = regexp_createNODE(NODE_AND,'\0',$2,sharp);
-        YYACCEPT;
-       }
-     ;
-
-
-expr : var
-       {
-        $$=$1;
-       }
-     | expr expr
-       {
-        $$=regexp_createNODE(NODE_AND,'\0',$1,$2);
-       }
-     | var LEX_QMARK
-       {
-        NODE* epsilon=regexp_createNODE(NODE_VAR,RE_EPSILON,NULL,NULL);
-        $$=regexp_createNODE(NODE_OR,'\0',$1,epsilon);
-       }
-     | var LEX_PLUS
-       {
-        $$=regexp_createNODE(NODE_PLUS,'\0',$1,NULL);
-       }
-     | var LEX_STAR
-       {
-        $$=regexp_createNODE(NODE_STAR,'\0',$1,NULL);
-       }
-/* () */
-     | LEX_L_BRACKET expr LEX_R_BRACKET
-       {
-        $$=$2;
-       }
-     | LEX_L_BRACKET expr LEX_R_BRACKET LEX_QMARK
-       {
-        NODE* epsilon=regexp_createNODE(NODE_VAR,RE_EPSILON,NULL,NULL);
-        $$=regexp_createNODE(NODE_OR,'\0',$2,epsilon);
-       }
-     | LEX_L_BRACKET expr LEX_R_BRACKET LEX_PLUS
-       {
-        $$=regexp_createNODE(NODE_PLUS,'\0',$2,NULL);
-       }
-     | LEX_L_BRACKET expr LEX_R_BRACKET LEX_STAR
-       {
-        $$=regexp_createNODE(NODE_STAR,'\0',$2,NULL);
-       }
-/* [] */
-     | LEX_L_SQBRACKET exprdisnode LEX_R_SQBRACKET
-       {
-        $$=$2;
-       }
-     | LEX_L_SQBRACKET exprdisnode LEX_R_SQBRACKET LEX_QMARK
-       {
-        NODE* epsilon=regexp_createNODE(NODE_VAR,RE_EPSILON,NULL,NULL);
-        $$=regexp_createNODE(NODE_OR,'\0',$2,epsilon);
-       }
-     | LEX_L_SQBRACKET exprdisnode LEX_R_SQBRACKET LEX_PLUS
-       {
-        $$=regexp_createNODE(NODE_PLUS,'\0',$2,NULL);
-       }
-     | LEX_L_SQBRACKET exprdisnode LEX_R_SQBRACKET LEX_STAR
-       {
-        $$=regexp_createNODE(NODE_STAR,'\0',$2,NULL);
-       }
-     ;
-
-
-
-var : LEX_CHAR
-       {
-#ifdef DEBUG_RE_PARSE
-        printf("var : lecture %c\n",$1 + 'a' -1);
-#endif
-         $$=regexp_createNODE(NODE_VAR,$1,NULL,NULL);
-       }
-     | LEX_ALL
-       {
-         $$=regexp_createNODE(NODE_VAR,RE_ALL_MATCH,NULL,NULL);
-       }
-     | LEX_VOWL
-       {
-         $$=regexp_createNODE(NODE_VAR,RE_VOWL_MATCH,NULL,NULL);
-       }
-     | LEX_CONS
-       {
-         $$=regexp_createNODE(NODE_VAR,RE_CONS_MATCH,NULL,NULL);
-       }
-     | LEX_USER1
-       {
-         $$=regexp_createNODE(NODE_VAR,RE_USR1_MATCH,NULL,NULL);
-       }
-     | LEX_USER2
-       {
-         $$=regexp_createNODE(NODE_VAR,RE_USR2_MATCH,NULL,NULL);
-       }
-     ;
-
-
-exprdisnode : exprdis
-       {
-        int i,j;
-#ifdef DEBUG_RE_PARSE
-        printf("exprdisnode : exprdis : ");
-#endif
-        for(i=RE_LIST_USER_END + 1; i < DIC_SEARCH_REGE_LIST; i++)
-          {
-            if (list->valid[i] == 0)
-              {
-                list->valid[i] = 1;
-                list->symbl[i] = RE_ALL_MATCH + i;
-                list->letters[i][0] = 0;
-                for(j=1; j < DIC_LETTERS; j++)
-                  list->letters[i][j] = $1[j] ? 1 : 0;
-#ifdef DEBUG_RE_PARSE
-                printf("list %d symbl x%02x : ",i,list->symbl[i]);
-                for(j=0; j < DIC_LETTERS; j++)
-                  if (list->letters[i][j])
-                    printf("%c",j+'a'-1);
-                printf("\n");
-#endif
-                break;
-              }
-          }
-        $$=regexp_createNODE(NODE_VAR,list->symbl[i],NULL,NULL);
-       }
-     | LEX_HAT exprdis
-       {
-        int i,j;
-#ifdef DEBUG_RE_PARSE
-        printf("exprdisnode : HAT exprdis : ");
-#endif
-        for(i=RE_LIST_USER_END + 1; i < DIC_SEARCH_REGE_LIST; i++)
-          {
-            if (list->valid[i] == 0)
-              {
-                list->valid[i] = 1;
-                list->symbl[i] = RE_ALL_MATCH + i;
-                list->letters[i][0] = 0;
-                for(j=1; j < DIC_LETTERS; j++)
-                  list->letters[i][j] = $2[j] ? 0 : 1;
-#ifdef DEBUG_RE_PARSE
-                printf("list %d symbl x%02x : ",i,list->symbl[i]);
-                for(j=0; j < DIC_LETTERS; j++)
-                  if (list->letters[i][j])
-                    printf("%c",j+'a'-1);
-                printf("\n");
-#endif
-                break;
-              }
-          }
-        $$=regexp_createNODE(NODE_VAR,list->symbl[i],NULL,NULL);
-       }
-     ;
-
-
-exprdis: vardis
-       {
-        memcpy($$,$1,sizeof(char)*DIC_LETTERS);
-       }
-     | vardis exprdis
-       {
-        int i;
-        for(i=0; i < DIC_LETTERS; i++)
-          $$[i] = $1[i] | $2[i];
-       }
-     ;
-
-
-
-vardis: LEX_CHAR
-       {
-        int c = $1;
-        memset($$,0,sizeof(char)*DIC_LETTERS);
-#ifdef DEBUG_RE_PARSE
-        printf("vardis : lecture %c\n",c + 'a' -1);
-#endif
-        $$[c] = 1;
-       }
-     ;
-
-
-%%
-
-#define UNUSED __attribute__((unused))
-
-void regexperror(YYLTYPE *llocp, yyscan_t UNUSED yyscanner, NODE UNUSED **root,
-                struct search_RegE_list_t UNUSED *list,
-                struct regexp_error_report_t *err, char const *msg)
-{
-  err->pos1 = llocp->first_column;
-  err->pos2 = llocp->last_column;
-  strncpy(err->msg,msg,sizeof(err->msg));
-}
-
-/*
- * shut down the compiler
- */
-//int yy_init_globals (yyscan_t yyscanner);

Index: dic/hashtable.c
===================================================================
RCS file: dic/hashtable.c
diff -N dic/hashtable.c
--- dic/hashtable.c     1 Jan 2006 19:51:00 -0000       1.5
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,163 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   hashtable.c
- *  \brief  Simple hashtable type
- *  \author Antoine Fraboulet
- *  \date   1999
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "hashtable.h"
-
-typedef struct _Hash_node {
-  struct _Hash_node *next;
-  void* key;
-  unsigned int keysize;
-  void* value;
-  unsigned int valuesize;
-} Hash_node;
-
-struct _Hash_table {
-  unsigned int size;
-  Hash_node** nodes;
-};
-
-
-Hash_table
-hash_init(unsigned int size)
-{
-  Hash_table ht;
-
-  ht = (Hash_table) calloc(1,sizeof(struct _Hash_table));
-  ht->size = size;
-  ht->nodes = (Hash_node  **) calloc (size, sizeof (Hash_node*));
-  return ht;
-}
-
-void
-hash_rec_free(Hash_node* node)
-{
-  if (node)
-    {
-      if (node->next)
-       hash_rec_free(node->next);
-      if (node->key)
-       free(node->key);
-      if (node->value)
-       free(node->value);
-      free(node);
-    }
-}
-
-int
-hash_destroy(Hash_table hashtable)
-{
-  unsigned int i;
-  if (hashtable)
-    {
-      for(i=0; i<hashtable->size; i++)
-       if (hashtable->nodes[i])
-         hash_rec_free(hashtable->nodes[i]);
-      if (hashtable->nodes)
-       free(hashtable->nodes);
-      free(hashtable);
-    }
-  return 0;
-}
-
-
-static unsigned int
-hash_key(Hash_table hashtable, void* ptr, unsigned int size)
-{
-  unsigned int i;
-  unsigned int key = 0;
-
-  if (size % 4 == 0)
-    {
-      unsigned int *v = (unsigned int*)ptr;
-      for (i = 0; i < (size / 4); i++)
-       key ^= (key << 3) ^ (key >> 1) ^ v[i];
-    }
-  else
-    {
-      unsigned char *v = (unsigned char*)ptr;
-      for (i = 0; i < size; i++)
-       key ^= (key << 3) ^ (key >> 1) ^ v[i];
-    }
-  key %= hashtable->size;
-  return key;
-}
-
-
-void*
-hash_find(Hash_table hashtable, void* key, unsigned int keysize)
-{
-  Hash_node *entry;
-  unsigned int h_key;
-
-  h_key = hash_key(hashtable,key,keysize);
-  for (entry = hashtable->nodes[h_key]; entry; entry = entry -> next)
-    {
-      if ((entry -> keysize == keysize) &&
-         (memcmp(entry->key,key,keysize) == 0))
-       {
-         return entry->value;
-       }
-    }
-  return NULL;
-}
-
-
-static Hash_node*
-new_entry(void* key, unsigned int keysize, void* value, unsigned int
-         valuesize)
-{
-  Hash_node *n;
-  n = (Hash_node*)calloc(1,sizeof(Hash_node));
-  n->key = (void*)malloc(keysize);
-  n->value = (void*)malloc(valuesize);
-  n->keysize = keysize;
-  n->valuesize = valuesize;
-  memcpy(n->key,key,keysize);
-  memcpy(n->value,value,valuesize);
-  return n;
-}
-
-
-int
-hash_add(Hash_table hashtable,
-        void* key, unsigned int keysize,
-        void* value, unsigned int valuesize)
-{
-  Hash_node *entry;
-  unsigned int h_key;
-
-  h_key = hash_key(hashtable,key,keysize);
-  entry = new_entry(key,keysize,value,valuesize);
-  entry->next = hashtable->nodes[h_key];
-  hashtable->nodes[h_key] = entry;
-
-  return 0;
-}
-
-

Index: dic/listdic.c
===================================================================
RCS file: dic/listdic.c
diff -N dic/listdic.c
--- dic/listdic.c       4 Aug 2007 20:01:28 -0000       1.10
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,207 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   listdic.c
- *  \brief  Program used to list a dictionary
- *  \author Antoine Fraboulet
- *  \date   1999
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stddef.h>
-#include "dic_internals.h"
-#include "dic.h"
-
-
-static void
-print_dic_rec(FILE* out, Dictionary dic, char *buf, char* s, Dawg_edge i)
-{
-  if (i.term)  /* edge points at a complete word */
-    {
-      *s = '\0';
-      fprintf (out,"%s\n", buf);
-    }
-  if (i.ptr)
-    {           /* Compute index: is it non-zero ? */
-      Dawg_edge *p = dic->dawg + i.ptr;
-      do {                         /* for each edge out of this node */
-        *s = p->chr + 'a' - 1;
-        print_dic_rec (out,dic,buf,s + 1, *p);
-      }
-      while (!(*p++).last);
-    }
-}
-
-
-void
-dic_load(Dictionary* dic, char* filename)
-{
-  int res;
-  if ((res = Dic_load(dic, filename)) != 0)
-    {
-      switch (res) {
-      case 1: printf("chargement: problème d'ouverture de %s\n",filename); 
break;
-      case 2: printf("chargement: mauvais en-tete de dictionnaire\n"); break;
-      case 3: printf("chargement: problème 3 d'allocation mémoire\n"); break;
-      case 4: printf("chargement: problème 4 d'alocation mémoire\n"); break;
-      case 5: printf("chargement: problème de lecture des arcs du 
dictionnaire\n"); break;
-      default: printf("chargement: problème non-repertorié\n"); break;
-      }
-      exit(res);
-    }
-}
-
-
-void
-print_dic_list(char* filename, char* out)
-{
-  FILE* fout;
-  Dictionary dic;
-  static char buf[80];
-
-  dic_load(&dic,filename);
-
-  if (strcmp(out,"stdout") == 0)
-    print_dic_rec(stdout,dic,buf,buf,dic->dawg[dic->root]);
-  else if (strcmp(out,"stderr") == 0)
-    print_dic_rec(stderr,dic,buf,buf,dic->dawg[dic->root]);
-  else
-    {
-      if ((fout = fopen(out,"w")) == NULL)
-       return;
-      print_dic_rec(fout,dic,buf,buf,dic->dawg[dic->root]);
-      fclose(fout);
-    }
-  Dic_destroy(dic);
-}
-
-
-void
-print_header(char* filename)
-{
-  Dict_header header;
-
-  Dic_check_header(&header,filename);
-
-#define OO(IDENT) (unsigned long)offsetof(Dict_header,IDENT)
-
-  printf("Dictionary header information\n");
-  printf("0x%02lx ident       : %s\n",      OO(ident)     ,header.ident);
-  printf("0x%02lx unused 1    : %6d %06x\n",OO(unused_1)  ,header.unused_1  
,header.unused_1);
-  printf("0x%02lx unused 2    : %6d %06x\n",OO(unused_2)  ,header.unused_2  
,header.unused_2);
-  printf("0x%02lx root        : %6d %06x\n",OO(root)      ,header.root      
,header.root);
-  printf("0x%02lx words       : %6d %06x\n",OO(nwords)    ,header.nwords    
,header.nwords);
-  printf("0x%02lx edges used  : %6d %06x\n",OO(edgesused) ,header.edgesused 
,header.edgesused);
-  printf("0x%02lx nodes used  : %6d %06x\n",OO(nodesused) ,header.nodesused 
,header.nodesused);
-  printf("0x%02lx nodes saved : %6d 
%06x\n",OO(nodessaved),header.nodessaved,header.nodessaved);
-  printf("0x%02lx edges saved : %6d 
%06x\n",OO(edgessaved),header.edgessaved,header.edgessaved);
-  printf("\n");
-  printf("sizeof(header) = 0x%lx (%lu)\n", (unsigned long)sizeof(header), 
(unsigned long)sizeof(header));
-}
-
-
-static void
-print_node_hex(Dictionary dic, int i)
-{
-  union edge_t {
-    Dawg_edge e;
-    uint32_t  s;
-  } ee;
-
-  ee.e = dic->dawg[i];
-
-  printf("0x%04lx %08x |%4d ptr=%8d t=%d l=%d f=%d chr=%2d (%c)\n",
-        (unsigned long)i*sizeof(ee), (unsigned int)(ee.s), 
-        i, ee.e.ptr, ee.e.term, ee.e.last, ee.e.fill, ee.e.chr, ee.e.chr +'a' 
-1);
-}
-
-
-void
-print_dic_hex(char* filename)
-{
-  int i;
-  Dictionary dic;
-  dic_load(&dic,filename);
-
-  printf("offs binary       structure         \n");
-  printf("---- -------- |   ------------------\n");
-  for(i=0; i < (dic->nedges + 1); i++)
-    print_node_hex(dic,i);
-  Dic_destroy(dic);
-}
-
-
-void
-usage(char* name)
-{
-  printf("usage: %s [-a|-d|-h|-l] dictionnaire\n", name);
-  printf("  -a : print all\n");
-  printf("  -h : print header\n");
-  printf("  -d : print dic in hex\n");
-  printf("  -l : print dic word list\n");
-}
-
-
-int
-main(int argc, char *argv[])
-{
-  int arg_count;
-  int option_print_all      = 0;
-  int option_print_header   = 0;
-  int option_print_dic_hex  = 0;
-  int option_print_dic_list = 0;
-
-  if (argc < 3)
-    {
-      usage(argv[0]);
-      exit(1);
-    }
-
-  arg_count = 1;
-  while(argv[arg_count][0] == '-')
-    {
-      switch (argv[arg_count][1])
-       {
-       case 'a': option_print_all = 1; break;
-       case 'h': option_print_header = 1; break;
-       case 'd': option_print_dic_hex = 1; break;
-       case 'l': option_print_dic_list = 1; break;
-       default: usage(argv[0]); exit(2);
-         break;
-       }
-      arg_count++;
-    }
-
-  if (option_print_header || option_print_all)
-    {
-      print_header(argv[arg_count]);
-    }
-  if (option_print_dic_hex || option_print_all)
-    {
-      print_dic_hex(argv[arg_count]);
-    }
-  if (option_print_dic_list || option_print_all)
-    {
-      print_dic_list(argv[arg_count],"stdout");
-    }
-  return 0;
-}

Index: dic/regexp.c
===================================================================
RCS file: dic/regexp.c
diff -N dic/regexp.c
--- dic/regexp.c        1 Jan 2006 19:51:00 -0000       1.12
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,382 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   regexp.c
- *  \brief  Regular Expression functions
- *  \author Antoine Fraboulet
- *  \date   2005
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_WAIT_H
-#   include <sys/wait.h>
-#endif
-#include <unistd.h>
-
-#include "dic.h"
-#include "regexp.h"
-#include "automaton.h"
-
-#ifndef PDBG
-#ifdef DEBUG_RE2
-#define PDBG(x) x
-#else
-#define PDBG(x)
-#endif
-#endif
-
-NODE* regexp_createNODE(int type,char v,NODE *fg,NODE *fd)
-{
-  NODE *x;
-  x=(NODE *)malloc(sizeof(NODE));
-  x->type      = type;
-  x->var       = v;
-  x->fd        = fd;
-  x->fg        = fg;
-  x->numero    = 0;
-  x->position  = 0;
-  x->annulable = 0;
-  x->PP        = 0;
-  x->DP        = 0;
-  return x;
-}
-
-void regexp_delete_tree(NODE *root)
-{
-  if (root == NULL)
-    return;
-  regexp_delete_tree(root->fg);
-  regexp_delete_tree(root->fd);
-  free(root);
-}
-
-#ifdef DEBUG_RE
-static void print_node(FILE*, NODE *n, int detail);
-#endif
-
-/**
- * computes position, annulable, PP, DP attributes
- * @param r   = root
- * @param p   = current leaf position
- * @param n   = current node number
- * @param ptl = position to letter
- */
-
-void regexp_parcours(NODE* r, int *p, int *n, int ptl[])
-{
-  if (r == NULL)
-    return;
-
-  regexp_parcours(r->fg,p,n,ptl);
-  regexp_parcours(r->fd,p,n,ptl);
-
-  switch (r->type)
-    {
-    case NODE_VAR:
-      r->position = *p;
-      ptl[*p] = r->var;
-      *p = *p + 1;
-      r->annulable = 0;
-      r->PP = 1 << (r->position - 1);
-      r->DP = 1 << (r->position - 1);
-      break;
-    case NODE_OR:
-      r->position = 0;
-      r->annulable = r->fg->annulable || r->fd->annulable;
-      r->PP = r->fg->PP | r->fd->PP;
-      r->DP = r->fg->DP | r->fd->DP;
-      break;
-    case NODE_AND:
-      r->position = 0;
-      r->annulable = r->fg->annulable && r->fd->annulable;
-      r->PP = (r->fg->annulable) ? (r->fg->PP | r->fd->PP) : r->fg->PP;
-      r->DP = (r->fd->annulable) ? (r->fg->DP | r->fd->DP) : r->fd->DP;
-      break;
-    case NODE_PLUS:
-      r->position = 0;
-      r->annulable = 0;
-      r->PP = r->fg->PP;
-      r->DP = r->fg->DP;
-      break;
-    case NODE_STAR:
-      r->position = 0;
-      r->annulable = 1;
-      r->PP = r->fg->PP;
-      r->DP = r->fg->DP;
-      break;
-    }
-
-  r->numero = *n;
-  *n = *n + 1;
-}
-
-/**
- * computes possuivante
- * @param r   = root
- * @param PS  = next position
- */
-
-void regexp_possuivante(NODE* r, int PS[])
-{
-  int pos;
-  if (r == NULL)
-    return;
-
-  regexp_possuivante(r->fg,PS);
-  regexp_possuivante(r->fd,PS);
-
-  switch (r->type)
-    {
-    case NODE_AND:
-      /************************************/
-      /* \forall p \in DP(left)           */
-      /*     PS[p] = PS[p] \cup PP(right) */
-      /************************************/
-      for(pos=1; pos <= PS[0]; pos++)
-       {
-         if (r->fg->DP & (1 << (pos-1)))
-           PS[pos] |= r->fd->PP;
-       }
-      break;
-    case NODE_PLUS:
-      /************************************/
-      /* == same as START                 */
-      /* \forall p \in DP(left)           */
-      /*     PS[p] = PS[p] \cup PP(left)  */
-      /************************************/
-      for(pos=1; pos <= PS[0]; pos++)
-       {
-         if (r->DP & (1 << (pos-1)))
-           PS[pos] |= r->PP;
-       }
-      break;
-    case NODE_STAR:
-      /************************************/
-      /* \forall p \in DP(left)           */
-      /*     PS[p] = PS[p] \cup PP(left)  */
-      /************************************/
-      for(pos=1; pos <= PS[0]; pos++)
-       {
-         if (r->DP & (1 << (pos-1)))
-           PS[pos] |= r->PP;
-       }
-      break;
-    }
-}
-
-/*////////////////////////////////////////////////
-// DEBUG only fonctions
-////////////////////////////////////////////////*/
-
-#ifdef DEBUG_RE
-void regexp_print_PS(int PS[])
-{
-  int i;
-  printf("** positions suivantes **\n");
-  for(i=1; i <= PS[0]; i++)
-    {
-      printf("%02d: 0x%08x\n", i, PS[i]);
-    }
-}
-#endif
-
-/*////////////////////////////////////////////////
-////////////////////////////////////////////////*/
-
-#ifdef DEBUG_RE
-void regexp_print_ptl(int ptl[])
-{
-  int i;
-  printf("** pos -> lettre: ");
-  for(i=1; i <= ptl[0]; i++)
-    {
-      printf("%d=%c ",i,ptl[i]);
-    }
-  printf("\n");
-}
-#endif
-
-/*////////////////////////////////////////////////
-////////////////////////////////////////////////*/
-
-void regexp_print_letter(FILE* f, char l)
-{
-  switch (l)
-    {
-    case RE_EPSILON:    fprintf(f,"( &  [%d])",l); break;
-    case RE_FINAL_TOK:  fprintf(f,"( #  [%d])",l);  break;
-    case RE_ALL_MATCH:  fprintf(f,"( .  [%d])",l);  break;
-    case RE_VOWL_MATCH: fprintf(f,"(:v: [%d])",l); break;
-    case RE_CONS_MATCH: fprintf(f,"(:c: [%d])",l); break;
-    case RE_USR1_MATCH: fprintf(f,"(:1: [%d])",l); break;
-    case RE_USR2_MATCH: fprintf(f,"(:2: [%d])",l); break;
-    default:
-      if (l < RE_FINAL_TOK)
-       fprintf(f," (%c [%d]) ",l + 'a' - 1, l);
-      else
-       fprintf(f," (liste %d)",l - RE_LIST_USER_END);
-       break;
-    }
-}
-
-/*////////////////////////////////////////////////
-////////////////////////////////////////////////*/
-
-void regexp_print_letter2(FILE* f, char l)
-{
-  switch (l)
-    {
-    case RE_EPSILON:    fprintf(f,"&"); break;
-    case RE_FINAL_TOK:  fprintf(f,"#");  break;
-    case RE_ALL_MATCH:  fprintf(f,".");  break;
-    case RE_VOWL_MATCH: fprintf(f,":v:"); break;
-    case RE_CONS_MATCH: fprintf(f,":c:"); break;
-    case RE_USR1_MATCH: fprintf(f,":1:"); break;
-    case RE_USR2_MATCH: fprintf(f,":2:"); break;
-    default:
-      if (l < RE_FINAL_TOK)
-       fprintf(f,"%c",l + 'a' - 1);
-      else
-       fprintf(f,"l%d",l - RE_LIST_USER_END);
-       break;
-    }
-}
-
-/*////////////////////////////////////////////////
-////////////////////////////////////////////////*/
-
-#ifdef DEBUG_RE
-static void print_node(FILE* f, NODE *n, int detail)
-{
-  if (n == NULL)
-    return;
-
-  switch (n->type)
-    {
-    case NODE_VAR:
-      regexp_print_letter(f,n->var);
-      break;
-    case NODE_OR:
-      fprintf(f,"OR");
-      break;
-    case NODE_AND:
-      fprintf(f,"AND");
-      break;
-    case NODE_PLUS:
-      fprintf(f,"+");
-      break;
-    case NODE_STAR:
-      fprintf(f,"*");
-      break;
-    }
-  if (detail == 2)
-    {
-      fprintf(f,"\\n pos=%d\\n annul=%d\\n PP=0x%04x\\n DP=0x%04x",
-             n->position,n->annulable,n->PP,n->DP);
-    }
-}
-#endif
-
-/*////////////////////////////////////////////////
-////////////////////////////////////////////////*/
-
-#ifdef DEBUG_RE
-static void print_tree_nodes(FILE* f, NODE* n, int detail)
-{
-  if (n == NULL)
-    return;
-
-  print_tree_nodes(f,n->fg,detail);
-  print_tree_nodes(f,n->fd,detail);
-
-  fprintf(f,"%d [ label=\"",n->numero);
-  print_node(f,n,detail);
-  fprintf(f,"\"];\n");
-}
-#endif
-
-/*////////////////////////////////////////////////
-////////////////////////////////////////////////*/
-
-#ifdef DEBUG_RE
-static void print_tree_edges(FILE* f, NODE* n)
-{
-  if (n == NULL)
-    return;
-
-  print_tree_edges(f,n->fg);
-  print_tree_edges(f,n->fd);
-
-  switch (n->type)
-    {
-    case NODE_OR:
-      fprintf(f,"%d -> %d;",n->numero,n->fg->numero);
-      fprintf(f,"%d -> %d;",n->numero,n->fd->numero);
-      break;
-    case NODE_AND:
-      fprintf(f,"%d -> %d;",n->numero,n->fg->numero);
-      fprintf(f,"%d -> %d;",n->numero,n->fd->numero);
-      break;
-    case NODE_PLUS:
-    case NODE_STAR:
-      fprintf(f,"%d -> %d;",n->numero,n->fg->numero);
-      break;
-    }
-}
-#endif
-
-/*////////////////////////////////////////////////
-////////////////////////////////////////////////*/
-
-#ifdef DEBUG_RE
-void regexp_print_tree(NODE* n, char* name, int detail)
-{
-  FILE* f;
-  pid_t   pid;
-
-  f=fopen(name,"w");
-  fprintf(f,"digraph %s {\n",name);
-  print_tree_nodes(f,n,detail);
-  print_tree_edges(f,n);
-  fprintf(f,"fontsize=20;\n");
-  fprintf(f,"}\n");
-  fclose(f);
-
-#ifdef HAVE_SYS_WAIT_H
-  pid = fork ();
-  if (pid > 0) {
-    wait(NULL);
-  } else if (pid == 0) {
-    execlp("dotty","dotty",name,NULL);
-    printf("exec dotty failed\n");
-    exit(1);
-  }
-#endif
-}
-#endif
-
-
-/// Local Variables:
-/// mode: hs-minor
-/// c-basic-offset: 2
-/// End:

Index: dic/regexpmain.c
===================================================================
RCS file: dic/regexpmain.c
diff -N dic/regexpmain.c
--- dic/regexpmain.c    4 Aug 2007 20:01:28 -0000       1.13
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,140 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   regexpmain.c
- *  \brief  Program used to test regexp
- *  \author Antoine Fraboulet
- *  \date   2005
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "dic.h"
-#include "regexp.h"
-#include "dic_search.h"
-
-#define __UNUSED__ __attribute__((unused))
-
-/********************************************************/
-/********************************************************/
-/********************************************************/
-
-const unsigned int all_letter[DIC_LETTERS] =
-  {
-    /*                      1  1 1 1 1 1 1 1 1 1 2 2 2  2  2  2  2 */
-    /* 0 1 2 3 4  5 6 7 8 9 0  1 2 3 4 5 6 7 8 9 0 1 2  3  4  5  6 */
-    /* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z */
-       0,1,1,1,1, 1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1, 1, 1, 1, 1
-  };
-
-const unsigned int vowels[DIC_LETTERS] =
-  {
-    /* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z */
-       0,1,0,0,0, 1,0,0,0,1,0, 0,0,0,0,1,0,0,0,0,0,1,0, 0, 0, 1, 0
-  };
-
-const unsigned int consonants[DIC_LETTERS] =
-  {
-    /* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z */
-       0,0,1,1,1, 0,1,1,1,0,1, 1,1,1,1,0,1,1,1,1,1,0,1, 1, 1, 1, 1
-  };
-
-void init_letter_lists(struct search_RegE_list_t *list)
-{
-  int i;
-  memset (list,0,sizeof(*list));
-  list->minlength = 1;
-  list->maxlength = 15;
-  list->valid[0] = 1; // all letters
-  list->symbl[0] = RE_ALL_MATCH;
-  list->valid[1] = 1; // vowels
-  list->symbl[1] = RE_VOWL_MATCH;
-  list->valid[2] = 1; // consonants
-  list->symbl[2] = RE_CONS_MATCH;
-  for(i=0; i < DIC_LETTERS; i++)
-    {
-      list->letters[0][i] = all_letter[i];
-      list->letters[1][i] = vowels[i];
-      list->letters[2][i] = consonants[i];
-    }
-  list->valid[3] = 0; // user defined list 1
-  list->symbl[3] = RE_USR1_MATCH;
-  list->valid[4] = 0; // user defined list 2
-  list->symbl[4] = RE_USR2_MATCH;
-}
-
-/********************************************************/
-/********************************************************/
-/********************************************************/
-void
-usage(int __UNUSED__ argc, char* argv[])
-{
-  fprintf(stderr,"usage: %s dictionary\n",argv[0]);
-  fprintf(stderr,"   dictionary : path to dawg eliot dictionary\n");
-}
-
-int main(int argc, char* argv[])
-{
-  int i;
-  Dictionary dic;
-  char wordlist[RES_REGE_MAX][DIC_WORD_MAX];
-  char er[200];
-  strcpy(er,".");
-  struct search_RegE_list_t list;
-
-  if (argc < 2)
-    {
-      usage(argc,argv);
-    }
-
-  if (Dic_load(&dic,argv[1]))
-    {
-      fprintf(stdout,"impossible de lire le dictionnaire\n");
-      return 1;
-    }
-
-  while (strcmp(er,""))
-    {
-      
fprintf(stdout,"**************************************************************\n");
-      
fprintf(stdout,"**************************************************************\n");
-      fprintf(stdout,"entrer une ER:\n");
-      fgets(er,sizeof(er),stdin);
-      /* strip \n */
-      er[strlen(er) - 1] = '\0';
-      if (strcmp(er,"") == 0)
-       break;
-
-      /* automaton */
-      init_letter_lists(&list);
-      Dic_search_RegE_inner(dic,er,wordlist,&list);
-
-      fprintf(stdout,"résultat:\n");
-      for(i=0; i<RES_REGE_MAX && wordlist[i][0]; i++)
-       {
-         fprintf(stderr,"%s\n",wordlist[i]);
-       }
-    }
-
-  Dic_destroy(dic);
-  return 0;
-}

Index: game/encoding.cpp
===================================================================
RCS file: game/encoding.cpp
diff -N game/encoding.cpp
--- game/encoding.cpp   5 Nov 2006 13:30:54 -0000       1.3
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,98 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   encoding.cpp
- *  \brief  Utility functions to ease manipulation of wide-character strings
- *  \author Olivier Teuliere
- *  \date   2005
- */
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <wchar.h>
-#include <wctype.h>
-#include "encoding.h"
-
-
-int _wtoi(const wchar_t *iWStr)
-{
-    return wcstol(iWStr,NULL,10);
-}
-
-
-int _swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...)
-{
-    int res;
-    va_list argp;
-    va_start(argp, format);
-#ifdef WIN32
-    // Mingw32 does not take the maxlen argument
-    res = vswprintf(wcs, format, argp);
-#else
-    res = vswprintf(wcs, maxlen, format, argp);
-#endif
-    va_end(argp);
-    return res;
-}
-
-
-wstring convertToWc(const string& iStr)
-{
-    // Get the needed length (we _can't_ use string::size())
-    size_t len = mbstowcs(NULL, iStr.c_str(), 0);
-    if (len == (size_t)-1)
-        return L"";
-
-    wchar_t *tmp = new wchar_t[len + 1];
-    len = mbstowcs(tmp, iStr.c_str(), len + 1);
-    wstring res = tmp;
-    delete[] tmp;
-
-    return res;
-}
-
-
-string convertToMb(const wstring& iWStr)
-{
-    // Get the needed length (we _can't_ use wstring::size())
-    size_t len = wcstombs(NULL, iWStr.c_str(), 0);
-    if (len == (size_t)-1)
-        return "";
-
-    char *tmp = new char[len + 1];
-    len = wcstombs(tmp, iWStr.c_str(), len + 1);
-    string res = tmp;
-    delete[] tmp;
-
-    return res;
-}
-
-
-string convertToMb(wchar_t iWChar)
-{
-    char res[MB_CUR_MAX + 1];
-    int len = wctomb(res, iWChar);
-    if (len == -1)
-        return "";
-    res[len] = '\0';
-
-    return res;
-}
-

Index: game/encoding.h
===================================================================
RCS file: game/encoding.h
diff -N game/encoding.h
--- game/encoding.h     22 Jan 2006 12:23:53 -0000      1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,52 +0,0 @@
-/* Eliot                                                                     */
-/* Copyright (C) 1999  Antoine Fraboulet                                     */
-/*                                                                           */
-/* This file is part of Eliot.                                               */
-/*                                                                           */
-/* Eliot is free software; you can redistribute it and/or modify             */
-/* it under the terms of the GNU General Public License as published by      */
-/* the Free Software Foundation; either version 2 of the License, or         */
-/* (at your option) any later version.                                       */
-/*                                                                           */
-/* Eliot is distributed in the hope that it will be useful,                  */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
-/* GNU General Public License for more details.                              */
-/*                                                                           */
-/* You should have received a copy of the GNU General Public License         */
-/* along with this program; if not, write to the Free Software               */
-/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
-
-/**
- *  \file   encoding.h
- *  \brief  Utility functions to ease manipulation of wide-character strings
- *  \author Olivier Teuliere
- *  \date   2005
- */
-
-#ifndef _ENCODING_H_
-#define _ENCODING_H_
-
-#include <string>
-
-using std::string;
-using std::wstring;
-
-
-/// Equivalent of atoi for wide-caracter strings
-int _wtoi(const wchar_t *iWStr);
-
-/// Equivalent of swprintf, but working also with mingw32
-int _swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...);
-
-/// Convert a multi-byte string into a wide-character string
-wstring convertToWc(const string& iStr);
-
-/// Convert a wide-character string into a multi-byte string
-string convertToMb(const wstring& iWStr);
-
-/// Convert a wide character into a multi-byte string
-string convertToMb(wchar_t iWChar);
-
-#endif
-

Index: game/tile.cpp
===================================================================
RCS file: game/tile.cpp
diff -N game/tile.cpp
--- game/tile.cpp       22 Jan 2006 12:23:53 -0000      1.7
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,233 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 1999-2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *****************************************************************************/
-
-#include "tile.h"
-#include <wctype.h>
-
-
-/*************************
- * French tiles
- * Zero + 26 letters + joker
- * tiles ares supposed to be contiguous and joker is separated
- *************************/
-
-#define TILE_START     'A'
-#define TILE_END       'Z'
-#define TILE_JOKER     '?'
-#define TILE_DUMMY     '%'
-
-#define TILE_IDX_DUMMY   0
-#define TILE_IDX_START   1
-#define TILE_IDX_END    26
-#define TILE_IDX_JOKER  27
-
-#define TILES_NUMBER    28
-
-/* The jokers and the 'Y' can be considered both as vowels or consonants */
-const unsigned int Tiles_vowels[TILES_NUMBER] =
-{
-/* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ? */
-   0,1,0,0,0, 1,0,0,0,1,0, 0,0,0,0,1,0,0,0,0,0,1,0, 0, 0, 1, 0,1
-};
-
-const unsigned int Tiles_consonants[TILES_NUMBER] =
-{
-/* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ? */
-   0,0,1,1,1, 0,1,1,1,0,1, 1,1,1,1,0,1,1,1,1,1,0,1, 1, 1, 1, 1,1
-};
-
-const unsigned int Tiles_numbers[TILES_NUMBER] =
-{
-/* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ? */
-   0,9,2,2,3,15,2,2,2,8,1, 1,5,3,6,6,2,1,6,6,6,6,2, 1, 1, 1, 1,2
-};
-
-const unsigned int Tiles_points[TILES_NUMBER] =
-{
-/* x A B C D  E F G H I J  K L M N O P Q R S T U V  W  X  Y  Z ? */
-   0,1,3,3,2, 1,4,2,4,1,8,10,1,2,1,1,3,8,1,1,1,1,4,10,10,10,10,0
-};
-
-/***************************
- ***************************/
-
-const Tile Tile::m_TheJoker(TILE_JOKER);
-const Tile Tile::m_TheDummy(0);
-list<Tile> Tile::m_tilesList;
-vector<Tile> Tile::m_tilesVect(TILES_NUMBER, Tile::dummy());
-bool Tile::m_vectInitialized(false);
-
-
-Tile::Tile(wchar_t c)
-{
-    if (c == TILE_JOKER)
-    {
-        m_joker = true;
-        m_dummy = false;
-        m_char = TILE_JOKER;
-        m_code = 27;
-    }
-    else if (isalpha(c))
-    {
-        m_joker = islower(c);
-        m_dummy = false;
-        m_char = towupper(c);
-        m_code = m_char - 'A' + 1;
-    }
-    else
-    {
-        m_joker = false;
-        m_dummy = true;
-        m_char = 0;
-        m_code = 0;
-    }
-}
-
-
-bool Tile::isVowel() const
-{
-    if (m_dummy)
-        return false;
-    if (m_joker)
-        return Tiles_vowels[TILE_IDX_JOKER];
-    return Tiles_vowels[TILE_IDX_START + m_char - TILE_START];
-}
-
-
-bool Tile::isConsonant() const
-{
-    if (m_dummy)
-        return false;
-    if (m_joker)
-        return Tiles_consonants[TILE_IDX_JOKER];
-    return Tiles_consonants[TILE_IDX_START + m_char - TILE_START];
-}
-
-
-unsigned int Tile::maxNumber() const
-{
-    if (m_dummy)
-        return false;
-    if (m_joker)
-        return Tiles_numbers[TILE_IDX_JOKER];
-    return Tiles_numbers[TILE_IDX_START + m_char - TILE_START];
-}
-
-
-unsigned int Tile::getPoints() const
-{
-    if (m_dummy)
-        return false;
-    if (m_joker)
-        return Tiles_points[TILE_IDX_JOKER];
-    return Tiles_points[TILE_IDX_START + m_char - TILE_START];
-}
-
-
-const list<Tile>& Tile::getAllTiles()
-{
-    if (Tile::m_tilesList.size() == 0)
-    {
-        // XXX: this should be filled from a "language file" instead
-        for (char i = TILE_START; i <= TILE_END; i++)
-            Tile::m_tilesList.push_back(Tile(i));
-        m_tilesList.push_back(Tile(TILE_JOKER));
-    }
-    return Tile::m_tilesList;
-}
-
-
-const Tile& Tile::GetTileFromCode(unsigned int iCode)
-{
-    if (!m_vectInitialized)
-    {
-        // XXX: this should be filled from a "language file" instead
-        for (char i = TILE_IDX_START; i <= TILE_IDX_END; i++)
-            Tile::m_tilesVect[i] = Tile(i + 'A' - TILE_IDX_START);
-        m_tilesVect[TILE_IDX_JOKER] = Tile::Joker();
-        m_vectInitialized = true;
-    }
-    return Tile::m_tilesVect[iCode];
-}
-
-
-wchar_t Tile::toChar() const
-{
-    if (m_dummy)
-        return TILE_DUMMY;
-    if (m_joker)
-    {
-        if (iswalpha(m_char))
-            return towlower(m_char);
-        else
-            return TILE_JOKER;
-    }
-    return m_char;
-}
-
-unsigned int Tile::toCode() const
-{
-    return m_code;
-}
-
-bool Tile::operator <(const Tile &iOther) const
-{
-    if (iOther.m_dummy)
-        return false;
-    else if (m_dummy)
-        return true;
-    else if (m_joker)
-        return false;
-    else if (iOther.m_joker)
-        return true;
-    else
-        return m_char < iOther.m_char;
-}
-
-
-bool Tile::operator ==(const Tile &iOther) const
-{
-    if (m_dummy || iOther.m_dummy)
-        return m_dummy == iOther.m_dummy;
-    if (m_joker || iOther.m_joker)
-    {
-        if (m_joker != iOther.m_joker)
-            return false;
-        return m_char == iOther.m_char;
-    }
-    return m_char == iOther.m_char;
-//     return (m_joker && iOther.m_joker && m_char == iOther.m_char) ||
-//            (m_dummy && iOther.m_dummy) ||
-//            (!m_dummy && !iOther.m_dummy
-//             && !m_joker && !iOther.m_joker
-//             && m_char == iOther.m_char);
-}
-
-
-bool Tile::operator !=(const Tile &iOther) const
-{
-    return !(*this == iOther);
-}
-
-/// Local Variables:
-/// mode: c++
-/// mode: hs-minor
-/// c-basic-offset: 4
-/// indent-tabs-mode: nil
-/// End:

Index: game/tile.h
===================================================================
RCS file: game/tile.h
diff -N game/tile.h
--- game/tile.h 22 Jan 2006 12:23:53 -0000      1.8
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,95 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2005 Eliot
- * Authors: Olivier Teuliere  <address@hidden>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *****************************************************************************/
-
-#ifndef _TILE_H_
-#define _TILE_H_
-
-#include <list>
-#include <vector>
-
-using namespace std;
-
-
-/*************************
- * A Tile is the internal representation
- * used within the game library to
- * handle letters
- *************************/
-
-class Tile
-{
-public:
-
-  // a lowercase character always a joker
-  // - this permits to detect joker in already played games
-  // - we need to pay attention when inserting character taken
-  //   from user input
-
-    Tile(wchar_t c = 0);
-    virtual ~Tile() {}
-
-    bool isEmpty() const        { return m_dummy; }
-    bool isJoker() const        { return m_joker; }
-    bool isVowel() const;
-    bool isConsonant() const;
-    unsigned int maxNumber() const;
-    unsigned int getPoints() const;
-    wchar_t toChar() const;
-    unsigned int toCode() const;
-
-    static const Tile &dummy()  { return m_TheDummy; }
-    static const Tile &Joker()  { return m_TheJoker; }
-    static const list<Tile>& getAllTiles();
-    static const Tile &GetTileFromCode(unsigned int iCode);
-
-    bool operator <(const Tile &iOther) const;
-    bool operator ==(const Tile &iOther) const;
-    bool operator !=(const Tile &iOther) const;
-
-private:
-    wchar_t m_char;
-    bool m_joker;
-    bool m_dummy;
-
-    /**
-     * Internal code, used in the dictionary to represent the letter.
-     * It is mainly used by the Cross class.
-     */
-    int m_code;
-
-    // Special tiles are declared static
-    static const Tile m_TheJoker;
-    static const Tile m_TheDummy;
-
-    /// List of available tiles
-    static list<Tile> m_tilesList;
-    /// Vector of tiles indexed by their code, for fast look-up
-    static vector<Tile> m_tilesVect;
-    /// True when m_tilesVect is correctly initialized
-    static bool m_vectInitialized;
-};
-
-#endif
-
-/// Local Variables:
-/// mode: c++
-/// mode: hs-minor
-/// c-basic-offset: 4
-/// indent-tabs-mode: nil
-/// End:




reply via email to

[Prev in Thread] Current Thread [Next in Thread]