The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 450
MANIFEST 248
META.yml 100
Makefile 0694
Makefile.PL 27
README 1135
bin/rtf2html 660
bin/rtf2text 660
docs/Overview.pod 580
docs/rtf2html.txt 1350
lib/RTF/Control.pm 1791795
lib/RTF/HTML/Converter/ansi.pm 490
lib/RTF/HTML/Converter/charmap.pm 1970
lib/RTF/HTML/Converter.pm 1117
lib/RTF/HTML/ansi 035
lib/RTF/HTML/char_map 0183
lib/RTF/Parser.pm 603282
lib/RTF/TEXT/Converter/ansi.pm 490
lib/RTF/TEXT/Converter/charmap.pm 1970
lib/RTF/TEXT/Converter.pm 12719
lib/RTF/TEXT/ansi 035
lib/RTF/TEXT/char_map 0183
rtf2html 066
rtf2text 066
t/01_parser_01_new.t 200
t/01_parser_02_api.t 1270
t/01_parser_03_parse_string.t 160
t/01_parser_04_parse_file.t 260
t/01_parser_05_control_definition.t 220
t/01_parser_06_skip_destinations.t 260
t/02_control_01_new.t 120
t/02_control_02_configure.t 540
t/02_control_03_application_dir.t 180
t/02_control_04_charmap_reader.t 330
t/02_control_05_strip_dead_content.t --
t/03_html_01_handling_ulnone.t 260
t/05_charmaps_01_loading.t 190
t/05_charmaps_02_html_sample.t 170
t/99_old_test.t 730
t/t1.t 073
40 files changed (This is a version diff) 40302488
@@ -1,48 +1,3 @@
-1.09 Tue 30 March 2004, 13:00pm BST
-
-+ Decided to release a 'production' version. It works, it works
-  well, it just lacks some documentation. This way, people will 
-	find it. That's good.
-
-+ Fixed a bug that'd allow trailing data after the last }
-
-1.8_7 Wed 17 March 2004, 15:00pm GBT
-
-+ Actually fixed ansi/charmap problem actually for real :-/
-
-1.8_6 Sun 14 March 2004, 22:00pm GBT
-
-+ 'ansi' and 'char_map' files put into modules, to make
-  packing the module into an executable easier, and to
-  make some really nasty code redundant
-+ RTF::TEXT::Converter does The Right Thing with entities
-  and blank lines, even on non \ansi files...
-+ Little files now get converted properly
-- \ulnone treated like \ul0 in RTF::Control
-
-1.8_5 Sat 24 January 2004, 10:45pm GBT
-
-+ Documentation is almost done
-+ RTF::Parser is fully tested
-+ Final beta release?
-
-1.8_3 Jan 22 January 2004, 12:55pm GBT
-
-+ Added documentation for the HTML and TEXT converting
-  modules
-
-1.8_2 Mon 12 January 2004, 07:10pm GBT
-
-+ Added RTF::Control tests and documentation
-+ Added more RTF::Parser docs
-+ Moved executables into their own directory
-
-1.8_1 Thu 28 August 2003, 10:00pm GBT
-
-+ Rewrote all of RTF::Parser
-+ Documented RTF::Parser's interface
-+ Added a nice big sample in the docs 
-
 1.7 mercredi, 28 juillet 1999, 12:10:54 MET DST
 
 - Corrected problem with the loading of the char_map file
@@ -1,35 +1,19 @@
 Changes
 MANIFEST
-META.yml
+Makefile
 Makefile.PL
 README
-bin/rtf2html
-bin/rtf2text
-docs/Overview.pod		How the distribution fits together
-docs/rtf2html.txt
 examples/tests.pl
 lib/RTF/Charsets.pm
 lib/RTF/Config.pm
 lib/RTF/Control.pm
-lib/RTF/HTML/Converter/ansi.pm
-lib/RTF/HTML/Converter/charmap.pm
 lib/RTF/HTML/Converter.pm
+lib/RTF/HTML/ansi
+lib/RTF/HTML/char_map
 lib/RTF/Parser.pm
-lib/RTF/TEXT/Converter/ansi.pm
-lib/RTF/TEXT/Converter/charmap.pm
 lib/RTF/TEXT/Converter.pm
-t/01_parser_01_new.t
-t/01_parser_02_api.t
-t/01_parser_03_parse_string.t
-t/01_parser_04_parse_file.t
-t/01_parser_05_control_definition.t
-t/01_parser_06_skip_destinations.t
-t/02_control_01_new.t
-t/02_control_02_configure.t
-t/02_control_03_application_dir.t
-t/02_control_04_charmap_reader.t
-t/02_control_05_strip_dead_content.t
-t/03_html_01_handling_ulnone.t
-t/05_charmaps_01_loading.t
-t/05_charmaps_02_html_sample.t
-t/99_old_test.t
+lib/RTF/TEXT/ansi
+lib/RTF/TEXT/char_map
+rtf2html
+rtf2text
+t/t1.t
@@ -1,10 +0,0 @@
-#XXXXXXX This is a prototype!!!  It will change in the future!!! XXXXX#
-name:         RTF-Parser
-version:      1.08_6
-version_from: lib/RTF/Parser.pm
-installdirs:  site
-requires:
-    RTF::Tokenizer:                1.04
-
-distribution_type: module
-generated_by: ExtUtils::MakeMaker version 6.12
@@ -0,0 +1,694 @@
+# This Makefile is for the RTF::Parser extension to perl.
+#
+# It was generated automatically by MakeMaker version
+# 5.4301 (Revision: 1.222) from the contents of
+# Makefile.PL. Don't edit this file, edit Makefile.PL instead.
+#
+#	ANY CHANGES MADE HERE WILL BE LOST!
+#
+#   MakeMaker Parameters:
+
+#	DISTNAME => q[RTF-Parser]
+#	EXE_FILES => [q[rtf2html], q[rtf2text]]
+#	NAME => q[RTF::Parser]
+#	VERSION_FROM => q[lib/RTF/Parser.pm]
+#	dist => { COMPRESS=>q[gzip], SUFFIX=>q[gz] }
+
+# --- MakeMaker post_initialize section:
+
+
+# --- MakeMaker const_config section:
+
+# These definitions are from config.sh (via /usr/local/lib/perl5/5.00502/sun4-solaris/Config.pm)
+
+# They may have been overridden via Makefile.PL or on the command line
+AR = ar
+CC = gcc
+CCCDLFLAGS = -fPIC
+CCDLFLAGS =  
+DLEXT = so
+DLSRC = dl_dlopen.xs
+LD = gcc
+LDDLFLAGS = -G -L/usr/local/lib
+LDFLAGS =  -L/usr/local/lib
+LIBC = /lib/libc.so
+LIB_EXT = .a
+OBJ_EXT = .o
+OSNAME = solaris
+OSVERS = 2.5.1
+RANLIB = :
+SO = so
+EXE_EXT = 
+
+
+# --- MakeMaker constants section:
+AR_STATIC_ARGS = cr
+NAME = RTF::Parser
+DISTNAME = RTF-Parser
+NAME_SYM = RTF_Parser
+VERSION = 1.07
+VERSION_SYM = 1_07
+XS_VERSION = 1.07
+INST_BIN = blib/bin
+INST_EXE = blib/script
+INST_LIB = blib/lib
+INST_ARCHLIB = blib/arch
+INST_SCRIPT = blib/script
+PREFIX = /usr/local
+INSTALLDIRS = site
+INSTALLPRIVLIB = $(PREFIX)/lib/perl5/5.00502
+INSTALLARCHLIB = $(PREFIX)/lib/perl5/5.00502/sun4-solaris
+INSTALLSITELIB = $(PREFIX)/lib/perl5/site_perl/5.005
+INSTALLSITEARCH = $(PREFIX)/lib/perl5/site_perl/5.005/sun4-solaris
+INSTALLBIN = $(PREFIX)/bin
+INSTALLSCRIPT = $(PREFIX)/bin
+PERL_LIB = /usr/local/lib/perl5/5.00502
+PERL_ARCHLIB = /usr/local/lib/perl5/5.00502/sun4-solaris
+SITELIBEXP = /usr/local/lib/perl5/site_perl/5.005
+SITEARCHEXP = /usr/local/lib/perl5/site_perl/5.005/sun4-solaris
+LIBPERL_A = libperl.a
+FIRST_MAKEFILE = Makefile
+MAKE_APERL_FILE = Makefile.aperl
+PERLMAINCC = $(CC)
+PERL_INC = /usr/local/lib/perl5/5.00502/sun4-solaris/CORE
+PERL = /usr/local/bin/perl
+FULLPERL = /usr/local/bin/perl
+
+VERSION_MACRO = VERSION
+DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\"
+XS_VERSION_MACRO = XS_VERSION
+XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\"
+
+MAKEMAKER = /usr/local/lib/perl5/5.00502/ExtUtils/MakeMaker.pm
+MM_VERSION = 5.4301
+
+# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle).
+# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle)
+# ROOTEXT = Directory part of FULLEXT with leading slash (eg /DBD)  !!! Deprecated from MM 5.32  !!!
+# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar)
+# DLBASE  = Basename part of dynamic library. May be just equal BASEEXT.
+FULLEXT = RTF/Parser
+BASEEXT = Parser
+PARENT_NAME = RTF
+DLBASE = $(BASEEXT)
+VERSION_FROM = lib/RTF/Parser.pm
+OBJECT = 
+LDFROM = $(OBJECT)
+LINKTYPE = dynamic
+
+# Handy lists of source code files:
+XS_FILES= 
+C_FILES = 
+O_FILES = 
+H_FILES = 
+MAN1PODS = 
+MAN3PODS = 
+INST_MAN1DIR = blib/man1
+INSTALLMAN1DIR = /usr/local/man/man1
+MAN1EXT = 1
+INST_MAN3DIR = blib/man3
+INSTALLMAN3DIR = /usr/local/lib/perl5/5.00502/man/man3
+MAN3EXT = 3
+PERM_RW = 644
+PERM_RWX = 755
+
+# work around a famous dec-osf make(1) feature(?):
+makemakerdflt: all
+
+.SUFFIXES: .xs .c .C .cpp .cxx .cc $(OBJ_EXT)
+
+# Nick wanted to get rid of .PRECIOUS. I don't remember why. I seem to recall, that
+# some make implementations will delete the Makefile when we rebuild it. Because
+# we call false(1) when we rebuild it. So make(1) is not completely wrong when it
+# does so. Our milage may vary.
+# .PRECIOUS: Makefile    # seems to be not necessary anymore
+
+.PHONY: all config static dynamic test linkext manifest
+
+# Where is the Config information that we are using/depend on
+CONFIGDEP = $(PERL_ARCHLIB)/Config.pm $(PERL_INC)/config.h
+
+# Where to put things:
+INST_LIBDIR      = $(INST_LIB)/RTF
+INST_ARCHLIBDIR  = $(INST_ARCHLIB)/RTF
+
+INST_AUTODIR     = $(INST_LIB)/auto/$(FULLEXT)
+INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT)
+
+INST_STATIC  =
+INST_DYNAMIC =
+INST_BOOT    =
+
+EXPORT_LIST = 
+
+PERL_ARCHIVE = 
+
+TO_INST_PM = lib/RTF/Charsets.pm \
+	lib/RTF/Config.pm \
+	lib/RTF/Control.pm \
+	lib/RTF/HTML/Converter.pm \
+	lib/RTF/HTML/ansi \
+	lib/RTF/HTML/char_map \
+	lib/RTF/Parser.pm \
+	lib/RTF/TEXT/Converter.pm \
+	lib/RTF/TEXT/ansi \
+	lib/RTF/TEXT/char_map
+
+PM_TO_BLIB = lib/RTF/TEXT/char_map \
+	$(INST_LIB)/RTF/TEXT/char_map \
+	lib/RTF/TEXT/ansi \
+	$(INST_LIB)/RTF/TEXT/ansi \
+	lib/RTF/TEXT/Converter.pm \
+	$(INST_LIB)/RTF/TEXT/Converter.pm \
+	lib/RTF/HTML/Converter.pm \
+	$(INST_LIB)/RTF/HTML/Converter.pm \
+	lib/RTF/HTML/char_map \
+	$(INST_LIB)/RTF/HTML/char_map \
+	lib/RTF/HTML/ansi \
+	$(INST_LIB)/RTF/HTML/ansi \
+	lib/RTF/Charsets.pm \
+	$(INST_LIB)/RTF/Charsets.pm \
+	lib/RTF/Parser.pm \
+	$(INST_LIB)/RTF/Parser.pm \
+	lib/RTF/Config.pm \
+	$(INST_LIB)/RTF/Config.pm \
+	lib/RTF/Control.pm \
+	$(INST_LIB)/RTF/Control.pm
+
+
+# --- MakeMaker tool_autosplit section:
+
+# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
+AUTOSPLITFILE = $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e 'use AutoSplit;autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1) ;'
+
+
+# --- MakeMaker tool_xsubpp section:
+
+
+# --- MakeMaker tools_other section:
+
+SHELL = /bin/sh
+CHMOD = chmod
+CP = cp
+LD = gcc
+MV = mv
+NOOP = $(SHELL) -c true
+RM_F = rm -f
+RM_RF = rm -rf
+TEST_F = test -f
+TOUCH = touch
+UMASK_NULL = umask 0
+DEV_NULL = > /dev/null 2>&1
+
+# The following is a portable way to say mkdir -p
+# To see which directories are created, change the if 0 to if 1
+MKPATH = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e mkpath
+
+# This helps us to minimize the effect of the .exists files A yet
+# better solution would be to have a stable file in the perl
+# distribution with a timestamp of zero. But this solution doesn't
+# need any changes to the core distribution and works with older perls
+EQUALIZE_TIMESTAMP = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Command -e eqtime
+
+# Here we warn users that an old packlist file was found somewhere,
+# and that they should call some uninstall routine
+WARN_IF_OLD_PACKLIST = $(PERL) -we 'exit unless -f $$ARGV[0];' \
+-e 'print "WARNING: I have found an old package in\n";' \
+-e 'print "\t$$ARGV[0].\n";' \
+-e 'print "Please make sure the two installations are not conflicting\n";'
+
+UNINST=0
+VERBINST=1
+
+MOD_INSTALL = $(PERL) -I$(INST_LIB) -I$(PERL_LIB) -MExtUtils::Install \
+-e "install({@ARGV},'$(VERBINST)',0,'$(UNINST)');"
+
+DOC_INSTALL = $(PERL) -e '$$\="\n\n";' \
+-e 'print "=head2 ", scalar(localtime), ": C<", shift, ">", " L<", shift, ">";' \
+-e 'print "=over 4";' \
+-e 'while (defined($$key = shift) and defined($$val = shift)){print "=item *";print "C<$$key: $$val>";}' \
+-e 'print "=back";'
+
+UNINSTALL =   $(PERL) -MExtUtils::Install \
+-e 'uninstall($$ARGV[0],1,1); print "\nUninstall is deprecated. Please check the";' \
+-e 'print " packlist above carefully.\n  There may be errors. Remove the";' \
+-e 'print " appropriate files manually.\n  Sorry for the inconveniences.\n"'
+
+
+# --- MakeMaker dist section:
+
+DISTVNAME = $(DISTNAME)-$(VERSION)
+TAR  = tar
+TARFLAGS = cvf
+ZIP  = zip
+ZIPFLAGS = -r
+COMPRESS = gzip
+SUFFIX = gz
+SHAR = shar
+PREOP = @$(NOOP)
+POSTOP = @$(NOOP)
+TO_UNIX = @$(NOOP)
+CI = ci -u
+RCS_LABEL = rcs -Nv$(VERSION_SYM): -q
+DIST_CP = best
+DIST_DEFAULT = tardist
+
+
+# --- MakeMaker macro section:
+
+
+# --- MakeMaker depend section:
+
+
+# --- MakeMaker cflags section:
+
+
+# --- MakeMaker const_loadlibs section:
+
+
+# --- MakeMaker const_cccmd section:
+
+
+# --- MakeMaker post_constants section:
+
+
+# --- MakeMaker pasthru section:
+
+PASTHRU = LIB="$(LIB)"\
+	LIBPERL_A="$(LIBPERL_A)"\
+	LINKTYPE="$(LINKTYPE)"\
+	PREFIX="$(PREFIX)"\
+	OPTIMIZE="$(OPTIMIZE)"
+
+
+# --- MakeMaker c_o section:
+
+
+# --- MakeMaker xs_c section:
+
+
+# --- MakeMaker xs_o section:
+
+
+# --- MakeMaker top_targets section:
+
+#all ::	config $(INST_PM) subdirs linkext manifypods
+
+all :: pure_all manifypods
+	@$(NOOP)
+
+pure_all :: config pm_to_blib subdirs linkext
+	@$(NOOP)
+
+subdirs :: $(MYEXTLIB)
+	@$(NOOP)
+
+config :: Makefile $(INST_LIBDIR)/.exists
+	@$(NOOP)
+
+config :: $(INST_ARCHAUTODIR)/.exists
+	@$(NOOP)
+
+config :: $(INST_AUTODIR)/.exists
+	@$(NOOP)
+
+config :: Version_check
+	@$(NOOP)
+
+
+$(INST_AUTODIR)/.exists :: /usr/local/lib/perl5/5.00502/sun4-solaris/CORE/perl.h
+	@$(MKPATH) $(INST_AUTODIR)
+	@$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00502/sun4-solaris/CORE/perl.h $(INST_AUTODIR)/.exists
+
+	-@$(CHMOD) $(PERM_RWX) $(INST_AUTODIR)
+
+$(INST_LIBDIR)/.exists :: /usr/local/lib/perl5/5.00502/sun4-solaris/CORE/perl.h
+	@$(MKPATH) $(INST_LIBDIR)
+	@$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00502/sun4-solaris/CORE/perl.h $(INST_LIBDIR)/.exists
+
+	-@$(CHMOD) $(PERM_RWX) $(INST_LIBDIR)
+
+$(INST_ARCHAUTODIR)/.exists :: /usr/local/lib/perl5/5.00502/sun4-solaris/CORE/perl.h
+	@$(MKPATH) $(INST_ARCHAUTODIR)
+	@$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00502/sun4-solaris/CORE/perl.h $(INST_ARCHAUTODIR)/.exists
+
+	-@$(CHMOD) $(PERM_RWX) $(INST_ARCHAUTODIR)
+
+help:
+	perldoc ExtUtils::MakeMaker
+
+Version_check:
+	@$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) \
+		-MExtUtils::MakeMaker=Version_check \
+		-e "Version_check('$(MM_VERSION)')"
+
+
+# --- MakeMaker linkext section:
+
+linkext :: $(LINKTYPE)
+	@$(NOOP)
+
+
+# --- MakeMaker dlsyms section:
+
+
+# --- MakeMaker dynamic section:
+
+## $(INST_PM) has been moved to the all: target.
+## It remains here for awhile to allow for old usage: "make dynamic"
+#dynamic :: Makefile $(INST_DYNAMIC) $(INST_BOOT) $(INST_PM)
+dynamic :: Makefile $(INST_DYNAMIC) $(INST_BOOT)
+	@$(NOOP)
+
+
+# --- MakeMaker dynamic_bs section:
+
+BOOTSTRAP =
+
+
+# --- MakeMaker dynamic_lib section:
+
+
+# --- MakeMaker static section:
+
+## $(INST_PM) has been moved to the all: target.
+## It remains here for awhile to allow for old usage: "make static"
+#static :: Makefile $(INST_STATIC) $(INST_PM)
+static :: Makefile $(INST_STATIC)
+	@$(NOOP)
+
+
+# --- MakeMaker static_lib section:
+
+
+# --- MakeMaker manifypods section:
+
+manifypods : pure_all
+	@$(NOOP)
+
+
+# --- MakeMaker processPL section:
+
+
+# --- MakeMaker installbin section:
+
+$(INST_SCRIPT)/.exists :: /usr/local/lib/perl5/5.00502/sun4-solaris/CORE/perl.h
+	@$(MKPATH) $(INST_SCRIPT)
+	@$(EQUALIZE_TIMESTAMP) /usr/local/lib/perl5/5.00502/sun4-solaris/CORE/perl.h $(INST_SCRIPT)/.exists
+
+	-@$(CHMOD) $(PERM_RWX) $(INST_SCRIPT)
+
+EXE_FILES = rtf2html rtf2text
+
+FIXIN = $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::MakeMaker \
+    -e "MY->fixin(shift)"
+
+all :: $(INST_SCRIPT)/rtf2text $(INST_SCRIPT)/rtf2html
+	@$(NOOP)
+
+realclean ::
+	rm -f $(INST_SCRIPT)/rtf2text $(INST_SCRIPT)/rtf2html
+
+$(INST_SCRIPT)/rtf2text: rtf2text Makefile $(INST_SCRIPT)/.exists
+	@rm -f $(INST_SCRIPT)/rtf2text
+	cp rtf2text $(INST_SCRIPT)/rtf2text
+	$(FIXIN) $(INST_SCRIPT)/rtf2text
+	-@$(CHMOD) $(PERM_RWX) $(INST_SCRIPT)/rtf2text
+
+$(INST_SCRIPT)/rtf2html: rtf2html Makefile $(INST_SCRIPT)/.exists
+	@rm -f $(INST_SCRIPT)/rtf2html
+	cp rtf2html $(INST_SCRIPT)/rtf2html
+	$(FIXIN) $(INST_SCRIPT)/rtf2html
+	-@$(CHMOD) $(PERM_RWX) $(INST_SCRIPT)/rtf2html
+
+
+# --- MakeMaker subdirs section:
+
+# none
+
+# --- MakeMaker clean section:
+
+# Delete temporary files but do not touch installed files. We don't delete
+# the Makefile here so a later make realclean still has a makefile to use.
+
+clean ::
+	-rm -rf ./blib $(MAKE_APERL_FILE) $(INST_ARCHAUTODIR)/extralibs.all perlmain.c mon.out core so_locations pm_to_blib *~ */*~ */*/*~ *$(OBJ_EXT) *$(LIB_EXT) perl.exe $(BOOTSTRAP) $(BASEEXT).bso $(BASEEXT).def $(BASEEXT).exp
+	-mv Makefile Makefile.old $(DEV_NULL)
+
+
+# --- MakeMaker realclean section:
+
+# Delete temporary files (via clean) and also delete installed files
+realclean purge ::  clean
+	rm -rf $(INST_AUTODIR) $(INST_ARCHAUTODIR)
+	rm -f $(INST_LIB)/RTF/TEXT/char_map $(INST_LIB)/RTF/TEXT/ansi $(INST_LIB)/RTF/TEXT/Converter.pm $(INST_LIB)/RTF/HTML/Converter.pm $(INST_LIB)/RTF/HTML/char_map $(INST_LIB)/RTF/HTML/ansi $(INST_LIB)/RTF/Charsets.pm $(INST_LIB)/RTF/Parser.pm $(INST_LIB)/RTF/Config.pm $(INST_LIB)/RTF/Control.pm
+	rm -rf Makefile Makefile.old
+
+
+# --- MakeMaker dist_basics section:
+
+distclean :: realclean distcheck
+
+distcheck :
+	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=fullcheck \
+		-e fullcheck
+
+skipcheck :
+	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=skipcheck \
+		-e skipcheck
+
+manifest :
+	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=mkmanifest \
+		-e mkmanifest
+
+
+# --- MakeMaker dist_core section:
+
+dist : $(DIST_DEFAULT)
+	@$(PERL) -le 'print "Warning: Makefile possibly out of date with $$vf" if ' \
+	    -e '-e ($$vf="$(VERSION_FROM)") and -M $$vf < -M "Makefile";'
+
+tardist : $(DISTVNAME).tar$(SUFFIX)
+
+zipdist : $(DISTVNAME).zip
+
+$(DISTVNAME).tar$(SUFFIX) : distdir
+	$(PREOP)
+	$(TO_UNIX)
+	$(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME)
+	$(RM_RF) $(DISTVNAME)
+	$(COMPRESS) $(DISTVNAME).tar
+	$(POSTOP)
+
+$(DISTVNAME).zip : distdir
+	$(PREOP)
+	$(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME)
+	$(RM_RF) $(DISTVNAME)
+	$(POSTOP)
+
+uutardist : $(DISTVNAME).tar$(SUFFIX)
+	uuencode $(DISTVNAME).tar$(SUFFIX) \
+		$(DISTVNAME).tar$(SUFFIX) > \
+		$(DISTVNAME).tar$(SUFFIX)_uu
+
+shdist : distdir
+	$(PREOP)
+	$(SHAR) $(DISTVNAME) > $(DISTVNAME).shar
+	$(RM_RF) $(DISTVNAME)
+	$(POSTOP)
+
+
+# --- MakeMaker dist_dir section:
+
+distdir :
+	$(RM_RF) $(DISTVNAME)
+	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=manicopy,maniread \
+		-e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');"
+
+
+# --- MakeMaker dist_test section:
+
+disttest : distdir
+	cd $(DISTVNAME) && $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) Makefile.PL
+	cd $(DISTVNAME) && $(MAKE)
+	cd $(DISTVNAME) && $(MAKE) test
+
+
+# --- MakeMaker dist_ci section:
+
+ci :
+	$(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -MExtUtils::Manifest=maniread \
+		-e "@all = keys %{ maniread() };" \
+		-e 'print("Executing $(CI) @all\n"); system("$(CI) @all");' \
+		-e 'print("Executing $(RCS_LABEL) ...\n"); system("$(RCS_LABEL) @all");'
+
+
+# --- MakeMaker install section:
+
+install :: all pure_install doc_install
+
+install_perl :: all pure_perl_install doc_perl_install
+
+install_site :: all pure_site_install doc_site_install
+
+install_ :: install_site
+	@echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
+
+pure_install :: pure_$(INSTALLDIRS)_install
+
+doc_install :: doc_$(INSTALLDIRS)_install
+	@echo Appending installation info to $(INSTALLARCHLIB)/perllocal.pod
+
+pure__install : pure_site_install
+	@echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
+
+doc__install : doc_site_install
+	@echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
+
+pure_perl_install ::
+	@$(MOD_INSTALL) \
+		read $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist \
+		write $(INSTALLARCHLIB)/auto/$(FULLEXT)/.packlist \
+		$(INST_LIB) $(INSTALLPRIVLIB) \
+		$(INST_ARCHLIB) $(INSTALLARCHLIB) \
+		$(INST_BIN) $(INSTALLBIN) \
+		$(INST_SCRIPT) $(INSTALLSCRIPT) \
+		$(INST_MAN1DIR) $(INSTALLMAN1DIR) \
+		$(INST_MAN3DIR) $(INSTALLMAN3DIR)
+	@$(WARN_IF_OLD_PACKLIST) \
+		$(SITEARCHEXP)/auto/$(FULLEXT)
+
+
+pure_site_install ::
+	@$(MOD_INSTALL) \
+		read $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist \
+		write $(INSTALLSITEARCH)/auto/$(FULLEXT)/.packlist \
+		$(INST_LIB) $(INSTALLSITELIB) \
+		$(INST_ARCHLIB) $(INSTALLSITEARCH) \
+		$(INST_BIN) $(INSTALLBIN) \
+		$(INST_SCRIPT) $(INSTALLSCRIPT) \
+		$(INST_MAN1DIR) $(INSTALLMAN1DIR) \
+		$(INST_MAN3DIR) $(INSTALLMAN3DIR)
+	@$(WARN_IF_OLD_PACKLIST) \
+		$(PERL_ARCHLIB)/auto/$(FULLEXT)
+
+doc_perl_install ::
+	-@$(DOC_INSTALL) \
+		"Module" "$(NAME)" \
+		"installed into" "$(INSTALLPRIVLIB)" \
+		LINKTYPE "$(LINKTYPE)" \
+		VERSION "$(VERSION)" \
+		EXE_FILES "$(EXE_FILES)" \
+		>> $(INSTALLARCHLIB)/perllocal.pod
+
+doc_site_install ::
+	-@$(DOC_INSTALL) \
+		"Module" "$(NAME)" \
+		"installed into" "$(INSTALLSITELIB)" \
+		LINKTYPE "$(LINKTYPE)" \
+		VERSION "$(VERSION)" \
+		EXE_FILES "$(EXE_FILES)" \
+		>> $(INSTALLARCHLIB)/perllocal.pod
+
+
+uninstall :: uninstall_from_$(INSTALLDIRS)dirs
+
+uninstall_from_perldirs ::
+	@$(UNINSTALL) $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist
+
+uninstall_from_sitedirs ::
+	@$(UNINSTALL) $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist
+
+
+# --- MakeMaker force section:
+# Phony target to force checking subdirectories.
+FORCE:
+	@$(NOOP)
+
+
+# --- MakeMaker perldepend section:
+
+
+# --- MakeMaker makefile section:
+
+# We take a very conservative approach here, but it\'s worth it.
+# We move Makefile to Makefile.old here to avoid gnu make looping.
+Makefile : Makefile.PL $(CONFIGDEP)
+	@echo "Makefile out-of-date with respect to $?"
+	@echo "Cleaning current config before rebuilding Makefile..."
+	-@$(RM_F) Makefile.old
+	-@$(MV) Makefile Makefile.old
+	-$(MAKE) -f Makefile.old clean $(DEV_NULL) || $(NOOP)
+	$(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" Makefile.PL 
+	@echo "==> Your Makefile has been rebuilt. <=="
+	@echo "==> Please rerun the make command.  <=="
+	false
+
+# To change behavior to :: would be nice, but would break Tk b9.02
+# so you find such a warning below the dist target.
+#Makefile :: $(VERSION_FROM)
+#	@echo "Warning: Makefile possibly out of date with $(VERSION_FROM)"
+
+
+# --- MakeMaker staticmake section:
+
+# --- MakeMaker makeaperl section ---
+MAP_TARGET    = perl
+FULLPERL      = /usr/local/bin/perl
+
+$(MAP_TARGET) :: static $(MAKE_APERL_FILE)
+	$(MAKE) -f $(MAKE_APERL_FILE) $@
+
+$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE)
+	@echo Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET)
+	@$(PERL) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) \
+		Makefile.PL DIR= \
+		MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
+		MAKEAPERL=1 NORECURS=1 CCCDLFLAGS=
+
+
+# --- MakeMaker test section:
+
+TEST_VERBOSE=0
+TEST_TYPE=test_$(LINKTYPE)
+TEST_FILE = test.pl
+TEST_FILES = t/*.t
+TESTDB_SW = -d
+
+testdb :: testdb_$(LINKTYPE)
+
+test :: $(TEST_TYPE)
+
+test_dynamic :: pure_all
+	PERL_DL_NONLAZY=1 $(FULLPERL) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) -e 'use Test::Harness qw(&runtests $$verbose); $$verbose=$(TEST_VERBOSE); runtests @ARGV;' $(TEST_FILES)
+
+testdb_dynamic :: pure_all
+	PERL_DL_NONLAZY=1 $(FULLPERL) $(TESTDB_SW) -I$(INST_ARCHLIB) -I$(INST_LIB) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(TEST_FILE)
+
+test_ : test_dynamic
+
+test_static :: test_dynamic
+testdb_static :: testdb_dynamic
+
+
+# --- MakeMaker ppd section:
+# Creates a PPD (Perl Package Description) for a binary distribution.
+ppd:
+	@$(PERL) -e "print qq{<SOFTPKG NAME=\"RTF-Parser\" VERSION=\"1,07,0,0\">\n}. qq{\t<TITLE>RTF-Parser</TITLE>\n}. qq{\t<ABSTRACT></ABSTRACT>\n}. qq{\t<AUTHOR></AUTHOR>\n}. qq{\t<IMPLEMENTATION>\n}. qq{\t\t<OS NAME=\"$(OSNAME)\" />\n}. qq{\t\t<CODEBASE HREF=\"\" />\n}. qq{\t</IMPLEMENTATION>\n}. qq{</SOFTPKG>\n}" > RTF-Parser.ppd
+
+# --- MakeMaker pm_to_blib section:
+
+pm_to_blib: $(TO_INST_PM)
+	@$(PERL) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" \
+	"-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -MExtUtils::Install \
+        -e "pm_to_blib({qw{$(PM_TO_BLIB)}},'$(INST_LIB)/auto')"
+	@$(TOUCH) $@
+
+
+# --- MakeMaker selfdocument section:
+
+
+# --- MakeMaker postamble section:
+
+
+# End.
@@ -1,12 +1,17 @@
+#
+# Makefile.PL for RTF::Parser distribution
+#
+# Filename:     Makefile.PL
+# Created:      21 October 1998
+#
 
 use ExtUtils::MakeMaker;
 
 &WriteMakefile(
                NAME          => 'RTF::Parser',
-               EXE_FILES     => [ 'bin/rtf2html', 'bin/rtf2text' ],
+               EXE_FILES     => [ 'rtf2html', 'rtf2text' ],
                DISTNAME      => 'RTF-Parser',
                VERSION_FROM  => 'lib/RTF/Parser.pm', 
-	       PREREQ_PM     => { 'RTF::Tokenizer' => '1.04' },
                dist          => {COMPRESS => 'gzip', SUFFIX => 'gz', },
               );
 
@@ -1,16 +1,40 @@
-RTF::Parser
------------
 
-  Please note this is a beta release from a new maintainer. The original
-release had no documentation or tests - I hope to get around to writing
-those in time.
+                     RTF Processor V 1.07 - ALPHA
 
-  The rtf2html program, as the original author states, is just a an
-example, not a fully-fledged application.
 
-  +Pete Sergeant
+The RTF package set is a minimal RTF processor.  This set is provided
+with an RTF to HTML converter.  This converter is just an example, not
+a full-fledged application.
 
-   rtf-parser@clueball.com
+You can try this converter the RTF specification (see the "Ressources"
+section).  For example:
+
+	% rtf2html RTF-Spec-1_5.rtf > RTF-Spec-1_5.htm
+
+Philippe Verdret
+pverdret@sonovision-itep.fr
+
+__________________
+Module description
+
+Name           DSLI  Description                                  Info
+
+-------------  ----  -------------------------------------------- -----
+
+RTF::Parser    adpO  Base class for parsing RTF files             PVERD
+
+
+____
+TODO
+
+- write a documentation 
+
+__________
+Ressources
+
+Specification for RTF and filters are available at:
+- <ftp://ftp.primate.wisc.edu/pub/RTF>
+
+General information on converters:
+- <http://www.kfa-juelich.de/isr/1/texconv.html>
 
-  Work on RTF processing modules is being carried out under a grant from
-The Perl Foundation.
@@ -1,66 +0,0 @@
-#!/usr/local/bin/perl 
-# Sonovision-Itep, Verdret 1995-1999
-
-require 5.004;
-use strict;
-
-my $VERSION = "1.07";
-
-use Getopt::Long;
-use File::Basename;
-
-use vars qw/$BASENAME $DIRNAME/;
-BEGIN {
-  ($BASENAME, $DIRNAME) = fileparse($0); 
-}
-use lib "$DIRNAME/lib";
-
-my $usage = "usage: 
- -h                    print this help
- -l log_file RTF_file  process RTF_file and generate a log file
- -V                    print version number
-";
-my $help = "";
-
-use vars qw($EOM $trace);
-$trace = 0;
-$EOM = "\n";			# end of message
-
-use RTF::Config;
-
-die "$usage" unless @ARGV;
-use vars qw($trace $opt_d $opt_h $opt_t $opt_v $opt_V);
-{ local $SIG{__WARN__} = sub {};
-  GetOptions('h',		# Help
-	     't=s',		# name of the target document
-	     'r=s',		# name of the report file
-	     'd',		# debugging mode
-	     'v',		# verbose
-	     'V',		# print version number
-	     'l=s' => \$LOG_FILE, # -l logfile
-	    ) or die "$usage$EOM";
-}
-
-if ($opt_h) {
-  print STDOUT "$help\n";
-  exit 0;
-}
-if ($opt_V) {
-  print STDOUT "$VERSION\n";
-  exit 0;
-}
-if ($opt_d) {
-  $| = 1;
-  $EOM = "";
-}
-
-select(STDOUT);
-
-require RTF::HTML::Converter;
-my $self = new RTF::HTML::Converter(Output => \*STDOUT);	# actually the default
-
-foreach my $filename (@ARGV) {
-  $self->parse_stream($filename);
-}
-
-1;
@@ -1,66 +0,0 @@
-#!/usr/local/bin/perl
-# Sonovision-Itep, Verdret 1995-1999
-
-require 5.004;
-use strict;
-
-my $VERSION = "1.03";
-
-use Getopt::Long;
-use File::Basename;
-
-use vars qw/$BASENAME $DIRNAME/;
-BEGIN {
-  ($BASENAME, $DIRNAME) = fileparse($0); 
-}
-use lib "$DIRNAME/lib";
-
-my $usage = "usage: 
- -h                    print this help
- -l log_file RTF_file  process RTF_file and generate a log file
- -V                    print version number
-";
-my $help = "";
-
-use vars qw($EOM $trace);
-$trace = 0;
-$EOM = "\n";			# end of message
-
-use RTF::Config;
-
-die "$usage" unless @ARGV;
-use vars qw($trace $opt_d $opt_h $opt_t $opt_v $opt_V);
-{ local $SIG{__WARN__} = sub {};
-  GetOptions('h',		# Help
-	     't=s',		# name of the target document
-	     'r=s',		# name of the report file
-	     'd',		# debugging mode
-	     'v',		# verbose
-	     'V',		# print version number
-	     'l=s' => \$LOG_FILE, # -l logfile
-	    ) or die "$usage$EOM";
-}
-
-if ($opt_h) {
-  print STDOUT "$help\n";
-  exit 0;
-}
-if ($opt_V) {
-  print STDOUT "$VERSION\n";
-  exit 0;
-}
-if ($opt_d) {
-  $| = 1;
-  $EOM = "";
-}
-
-select(STDOUT);
-
-require RTF::TEXT::Converter;
-my $self = new RTF::TEXT::Converter(Output => \*STDOUT);	# actually the default
-
-foreach my $filename (@ARGV) {
-  $self->parse_stream($filename);
-}
-
-1;
@@ -1,58 +0,0 @@
-
-=head1 RTF Overview
-
-RTF is a format that can express complex formatted documents in ASCII.
-This document expects that you have some familiarity with it, and are
-familiar with the terms 'text field', 'control word', and 'group' as
-they apply to RTF.
-
-Sean Burke has very usefully written:
-
-An online introduction to RTF
-
-L<http://search.cpan.org/~sburke/RTF-Writer/lib/RTF/Cookbook.pod>
-
-The RTF Pocket Guide
-
-L<http://www.oreilly.com/catalog/rtfpg/>
-
-=head1 What the different modules do
-
-=head2 RTF::Parser
-
-L<RTF::Parser> is the foundation class. It's essentially a wrapper
-for <RTF::Tokenizer> that executes events that you define as it comes
-across different parts of the RTF document - it has handlers for
-when groups open, when they close, when we come across a control word,
-and so on. 
-
-=head2 RTF::Control
-
-L<RTF::Control> sub-classes L<RTF::Parser>. It defines a number of events
-for which you can write handlers that are specifically geared towards 
-people who want to write converters - where RTF::Parser things in terms
-of control words and groups, RTF::Control thinks in terms of paragraphs,
-and formatting properties for text.
-
-=head2 RTF::TEXT::Converter, RTF::HTML::Converter
-
-L<RTF::TEXT::Converter> and L<RTF::HTML::Converter> sub-class L<RTF::Control>,
-and are essentially documents that specify how to react to RTF::Control's
-events to spit RTF out as text and HTML respectively. You can also use them
-to inline RTF conversion to text or HTML in your documents.
-
-=head1 AUTHOR
-
-Peter Sergeant C<rtf.parser@clueball.com>
-
-=head1 COPYRIGHT
-
-Copyright 2004 B<Pete Sergeant>.
-
-This documentation is free documentation; you can redistribute it and/or modify it under
-the same terms as Perl itself.
-
-=head1 CREDITS
-
-This work was carried out under a grant generously provided by The Perl Foundation -
-give them money!
@@ -1,135 +0,0 @@
-
-*************** IMPORTANT ******************
-
-These are rough notes of mine on what happens
-when you run rtf2html. They're not yet ready
-for human consumption. Please ignore lack of
-continuity and sanity.
-
-*************** IMPORTANT ******************
-
-
-
-rtf2html - takes the options and the filenames, and then
-loads RTF::HTML::Convertor. It sets the output channel to
-STDOUT (which it claims to default to anyway), and then
-loops over the filenames it was given and invokes
-the 'parse_stream( $filename )' method on each file...
-
-RTF::HTML::Convertor is a subclass of RTF::Control which
-is a subclass of RTF::Parser, which is a wrapper around
-RTF::Tokenizer. :-)
-
-RTF::HTML::Convertor sets definitions for the basic RTF::Parser
-API - overriding some subs. Specifically, it over-rides:
-
-	text()
-	
-	symbol()
-	
-	%symbol -- defines a lot of this
-	
-	%do_on_control{'ansi'}
-	
-	%do_on_event -- lots of this
-	
-RTF::Control, as previously mentioned, is a subclass of
-RTF::Parser, and as such, provides a number of default
-over-rides for RTF::Parser's API, specifically to help
-people building modules like RTF::HTML::Convertor.
-
-It exports:
-
-	new() - a wrapper of RTF::Parser's new, with some extra option handling
-	output - a function to output text to the right place
-	%symbol - a symbol transliteration hash: e.g. $symbol{'~'} = '&nbsp;';
-	%info - meta-data about the document that it parses out for you
-	%do_on_event - things to do when certain abstract things happen (we encounter a table)
-	%do_on_control - what to do when we encounter a specific control word
-	%par_props - properties set for the current paragraph
-	$style - the style we're currently using
-	$newstyle - the style we're changing into, if we're about to change
-	$event - current event
-	$text - pending text to print
-	
-as well as all the things that RTF::Parser exports, so,
-essentially:
-
-	parse_start()
-	parse_end()
-	group_end()
-	group_start()
-	text()
-	char()
-	symbol()
-	
-So now we're going to follow exactly what happens when we
-step through a really simple RTF document and convert it to
-HTML using the rtf2html tool.
-
-rtf2html reads in the filename, selects STDOUT as the default
-output mode, and creates a new RTF::HTML::Converter object.
-
-RTF::HTML::Converter doesn't define a new() method, so RTF::Control's
-one is used. RTF::Control's constructor method is simple - it invokes
-RTF::Parser's constructor method, and then invokes the _configure method
-(in RTF::Control) on this object. RTF::Parser::new() is also pretty
-simple - it sets some options depending on if RTF::Control is being
-used, and returns an object.
-
-It's on this object then that RTF::Parser::_configure() is called. 
-_configure() reads in options the user passed to the constructor -
-at the moment, the only one recognised is 'output', which, if set,
-passes the value of 'output' to RTF::Control::set_top_output_to().
-
-RTF::Control::set_top_output_to() checks to see if it's been passed
-a filehandle or a reference to a scalar. Depending on which it's been passed, it
-over-rides the behaviour of the sub RTF::Control::flush_top_output
-to either print the top item of @RTF::Control::output_stack to said
-filehandle, or add it to the scalar referenced.
-
-rtf2html then runs the parse_stream method on our RTF::HTML::Converter
-object.
-
-This creates an RTF::Tokenizer object from our filehandle, and executes
-RTF::Parser::_parse(). parse_start() is called, which, in this case,
-is RTF::Control::parse_start(). This executes RTF::Control::push_output(),
-which adds a new and empty element to our output stack. This in turn 
-executes the code reference in $RTF::HTML::Converter::do_on_event{'document'},
-which, as we've passed a 'start' event to it, calls RTF::Control::output() with
-a doctype to print. This adds that doctype to the current element at the end
-of our output stack. RTF::Control::flush_top_output() is then called, which
-prints the doctype to STDOUT. We call push_output again to add another blank
-element to our output stack, and return to RTF::Parser::_parse().
-
-We then enter the loop around all the tokens. The first token we come across
-opens a group, so $self->group_start is called, which in this case is
-RTF::Control::group_start(). Here we add paragraph properties, and character
-properties currently in force (although because we're just starting, there
-are none) to their respective stacks, and add a holder to @control to keep
-track of any controls we're going to open.
-
-The next token is a control word, 'rtf', with the argument 1. There's a
-%do_on_control entry defined in RTF::Control for 'rtf', so we execute that.
-It calls RTF::Control::push_output with 'nul', which over-rides our output()
-function to not do anything. It then sets 'rtf' to be an open control in
-@control (so that when we leave this group, it executes the %do_on_control
-entry for 'rtf', only with 'end' rather than 'start').
-
-	\ansi
-	
-	This is defined in do_on_control in RTF::HTML::Converter. It does a lot
-	of scary character-set stuff. Wibble.
-	
-	\deff0
-	
-	Ignored, because we don't have a handler
-	
-	\fonttbl
-	
-	
-
-
-
-
-
@@ -1,529 +1,190 @@
 # Sonovision-Itep, Philippe Verdret 1998-1999
-# TPF - Pete Sergeant 2003 - 2004
-
-
-
-
-
-=head1 NAME
-
-RTF::Control - Application of RTF::Parser for document conversion
-
-=head1 DESCRIPTION
-
-Application of RTF::Parser for document conversion
-
-=head1 OVERVIEW
-
-L<RTF::Control> is a sublass of L<RTF::Parser>. L<RTF::Control> can be seen as
-a helper module for people wanting to write their own document convertors -
-L<RTF::HTML::Convertor> and L<RTF::TEXT::Convertor> both subclass it.
-
-I am the new maintainer of this module. My aim is to keep the interface
-identical to the old interface while cleaning up, documenting, and testing
-the internals. There are things in the interface I'm unhappy with, and things
-I like - however, I'm maintaining rather than developing the module, so, the
-interface is mostly frozen.
-
-=head1 HOW IT ALL WORKS
-
-For starters, go and look at the source of M<RTF::TEXT::Convertor>
-
-
-Except for B<RTF::Parser subs>, the following is a list of variables
-exported by RTF::Control that you're expected to tinker with in your
-own subclass.
-
-=head2 RTF::Parser subs
-
-If you read the docs of RTF::Parser you'll see that you can redefine some
-subs there - RTF::Control has its own definitions for all of these, but you
-might want to over-ride C<symbol()>, C<text()>, and C<char()>. We'll look
-at what the defaults of each of these do, and what you need to do if you
-want to override any of them a little further down.
-
-=head2 %symbol
-
-This hash is actually merged into %do_on_control, with the value wrapped in
-a subroutine that effectively says C<print shift>. You can put any control
-words that should map directly to a certain output in here - C<\tab>, for
-example could be C<$symbol{'tab'} = "\t">.
-
-=head2 %info
-
-This hash gets filled with document meta-data, as per the RTF specification.
-
-=head2 %par_props
-
-Not really sure, but paragraph properties
-
-=head2 %do_on_event %do_on_control
-
-%do_on_control tells us what to do when we meet a specific control word.
-The values are coderefs. %do_on_event also holds coderefs, but these are
-more abstract things to do, say when the stylesheet changes. %do_on_event
-thingies tend to be called by %do_on_control thingies, as far as I can tell.
-
-=head2 $style $newstyle
-
-Style is the current style, $newstyle is the one we're about to
-change to if we're about to change...
-
-=head2 $event
-
-Current event
-
-=head2 $text
-
-Pending text
-
-=cut
-
-# Define all our dependencies and other fluff
-
-	use strict;
-
-	require 5.003;
-	package RTF::Control;
-
-	use RTF::Parser;
-	use RTF::Config;
-	use RTF::Charsets;		# define names of chars
-
-	use File::Basename;
-	use Exporter;
-	
-# I'm an RTF::Parser! I'm an Exporter! I'm a class! 
-# "When I grow up, I'm going to bovine university!" 
-
-	@RTF::Control::ISA = qw(Exporter RTF::Parser);
-
-# Define the symbols we'll be exporting - these are 
-# documented in the API part of the POD and a little
-# further down
-	
-	use vars qw(
-	
-		%symbol %info %par_props %do_on_event %do_on_control
-		$style $newstyle $event $text
-	
-	);
-
-# There are used to that we have named arguments for callbacks
-# I don't like this, but hey, I didn't design it, and I'm meant
-# to be maintaining the interface :-)
-   
-	use constant SELF    => 0;  # rtf processor instance 
-	use constant CONTROL => 1;  # control word
-	use constant ARG     => 2;  # associated argument
-	use constant EVENT   => 3;  # start/end event
-	use constant TOP     => -1; # access to the TOP element of a stack
-	
-
-# Actually export stuff...
-
-	@RTF::Control::EXPORT = qw(
-
-		output 
-	
-		%symbol
-		%info
-		%do_on_event
-		%do_on_control
-		%par_props
-		
-		$style
-		$newstyle
-		$event
-		$text
-	
-		SELF
-		CONTROL
-		ARG
-		EVENT
-		TOP
-	
-	);
-
-# Flags to specify where we are... Because this is all undocumented
-# I feel justified putting these into a hash at some point in the
-# near future... They also shouldn't be package variables, they
-# should be class variables, but, to be honest, trying to rid this
-# module of package variables seems an exercise in futility if I'm
-# actually trying to maintain the interface... I could internalise
-# everything that isn't part of the API though
-
-	my $IN_STYLESHEET = 0;		# inside or outside style table
-	my $IN_FONTTBL = 0;			# inside or outside font table
-	my $IN_TABLE = 0;
-
-# Declare where we're going to be holding meta-data etc
-	my %fonttbl;
-	my %stylesheet;
-	my %colortbl;
-
-# Property stacks
-	my @par_props_stack = ();	# stack of paragraph properties
-	my @char_props_stack = ();	# stack of character properties
-	my @control = ();			# stack of control instructions, rename control_stack
-
-# Some other stuff
-	my $stylename = '';
-	my $cstylename = '';		# previous encountered style
-	my $cli = 0;				# current line indent value
-	my $styledef = '';
-
+# 
+# Stack machine - must be application independant!
+# 
+# defined some interesting events for your application
+# an application can redefine its own control callbacks if %do_on_control is exported
+
+# todo:
+# - output well-formed HTML
+# - better list processing
+# - process fields and bookmarks
+
+use strict;
+require 5.003;
+package RTF::Control;
+use RTF::Parser;
+use RTF::Config;
+use RTF::Charsets;		# define names of chars
+
+use File::Basename;
+use Exporter;
+@RTF::Control::ISA = qw(Exporter RTF::Parser);
+
+				# here is what you can use in your application
+use vars qw(%symbol %info  %do_on_event %par_props
+	    %do_on_control
+	    $style $newstyle $event $text
+	   );
+###########################################################################
+				# Specification of the callback interface
+				# so you can easily reorder sub arguments
+use constant SELF => 0;		# rtf processor instance 
+use constant CONTROL => 1;	# control word
+use constant ARG => 2;		# associated argument
+use constant EVENT => 3;	# start/end event
+use constant TOP => -1;		# access to the TOP element of a stack
+###########################################################################
+				# symbols to export in the application layer
+@RTF::Control::EXPORT = qw(output 
+			   %symbol %info %do_on_event
+			   %do_on_control
+			   %par_props
+			   $style $newstyle $event $text
+			   SELF CONTROL ARG EVENT TOP
+			  );
+###########################################################################
 
-=head2 new
- 
-Returns an RTF::Control object. RTF::Control is a subclass of RTF::Parser.
-Internally, we call RTF::Parser's new() method, and then we call an internal
-method called _configure(), which takes care of options we were passed.
+%do_on_event = ();		# output routines
+$style = '';			# current style
+$newstyle = '';			# new style if style changing
+$event = '';			# start or end
+$text = '';			# pending text
+%symbol = ();			# symbol translations
+%info = ();			# info part of the document
+%par_props = ();		# paragraph properties
+###########################################################################
+				# Automata states, control modes
+my $IN_STYLESHEET = 0;		# inside or outside style table
+my $IN_FONTTBL = 0;		# inside or outside font table
+my $IN_TABLE = 0;
+
+my %fonttbl;
+my %stylesheet;
+my %colortbl;
+my @par_props_stack = ();	# stack of paragraph properties
+my @char_props_stack = ();	# stack of character properties
+my @control = ();		# stack of control instructions, rename control_stack
+my $stylename = '';
+my $cstylename = '';		# previous encountered style
+my $cli = 0;			# current line indent value
+my $styledef = '';
 
-ADD STUFF ON -output AND -confdir
- 
-=cut
- 
+###########################################################################
+				# Added methods
 sub new {
-
-        my $proto = shift;
-        my $class = ref( $proto ) || $proto;
-       
-        my $self = $class->SUPER::new(@_);
-
-        $self->_configure(@_);
-
-		return $self;
-		
-} 
-
-# This is a private method. It accepts a hash (well, a list) 
-#      of values, and stores them. If one of them is 'output',
-#      it calls a function I'm yet to examine. This was done
-#      in a horrendous way - it's now a lot tidier. :-)
-
-sub _configure {
-
-        my $self = shift;
-
-        my %options = @_;
-       
-        # Sanitize the options
-        my %clean_options;
-        for my $key ( keys %options ) {
-        
-                my $oldkey = $key;
-                
-                $key =~ s/^-//;
-                $key = lc($key);
-                
-                $clean_options{ $key } = $options{ $oldkey }
-        
-        }
-        
-        $self->{'_RTF_Control_Options'} = \%clean_options;
-        
-        $self->set_top_output_to( $clean_options{'output'} )
-               if $clean_options{'output'};
- 
-        return $self;
-
-} 
+  my $receiver = shift;
+  my $self = $receiver->SUPER::new(@_);
+  $self->configure(@_);
+}
+sub configure { 
+  my $self = shift;
+  unless (@_ >= 2) { }
+  my ($key, $value);
+  while (@_ >= 2) {
+    ($key, $value) = (shift, shift);
+    if ($key =~ /^-?[Oo]utput$/) {
+      set_top_output_to($value);
+      $self->{$key} = $value;
+    } else {
+      last;
+    }
+  }
+  $self;
+}
 
 use constant APPLICATION_DIR => 0;
-
-=head2 application_dir
-
-I'm leaving this method in because removing it will cause a backward-compatability
-nightmare. This method returns the ( wait for it ) path that the .pm file corresponding
-to the class that the object is contained, without a trailing semi-colon. Obviously
-this is nasty in several ways. If you've set C<-confdir> in C<new()> that will be
-returned instead. You should definitely take that route if you're on an OS on which 
-Perl can't use / as a directory seperator.
-
-=cut
-
 sub application_dir {
-
-	# Grab our object
-	my $self = shift;
-	
-	# Return -confdir if set
-	return $self->{'_RTF_Control_Options'}->{'confdir'}
-		if $self->{'_RTF_Control_Options'}->{'confdir'};
-
-	# Grab the class name
-	my $class = ref $self;
-
-	# Clean it up and look it up in %INC
-  	$class =~ s|::|/|g;
-  	$class = $INC{"$class.pm"};
-	
-	return dirname $class;
-			
-}
-
-=head2 charmap_reader
-
-This nicely abstracts away using application_dir and so on. It's a method
-call. It'll take the name of the class, and an argument for the module/file
-it's looking for. This is likely to be 'ansi' or 'charmap'. This argument,
-for historical reasons (ho ho ho) will have any _'s removed in the check for
-a module name ... C< $self->charmap_reader('char_map') > will thus look for, for
-example, C< RTF::TEXT::charmap > to load. It'll return the data in the file as
-an array of lines. This description sucks.
-
-=cut
-
-sub charmap_reader {
-
-	my $self = shift;
-	my $file = shift;
-	
-	my @char_map_data;
-
-	# Try and work out what our character set module would be called...
-		my $module_file = $file;
-		$module_file =~ s/_//g;
-		my $module_name = ref( $self ) . '::' . $module_file;
-	
-	# Can we load it?
-		eval "use $module_name";
-
-	# That would be a no...
-		if ($@) {
-			
-		# Create a path for the charset file using the old method...
-			my $charset_file = $_[SELF]->application_dir(__FILE__) . "/$file";
-			
-		# Try and open it...
-			open( CHAR_MAP, "< $charset_file" ) or die
-				"Unable to open the charset file '$charset_file': $!";
-		
-		# Read in the data...
-			@char_map_data = (<CHAR_MAP>);
-	
-	# Why yes, yes we can...
-		} else {
-		
-			my $sub_name = $module_name . '::' . 'data';
-			@char_map_data = main->$sub_name();
-		
-		}
-		
-	return @char_map_data;
-
+  my $class = ref $_[SELF];
+  my $file;
+  ($file = $class) =~ s|::|/|g;
+  $file = $INC{"$file.pm"};
+  my $dirname;
+  if (-f $file) {		
+    $dirname = dirname $file; 
+  } else {
+    $dirname = dirname '.' . $file; 
+  }
+  "$dirname"; 				
 }
-
 ###########################################################################
-
-# This stuff is all to do with the stack, and I'm not really sure how it
-#   works. I'm hoping it'll become more obvious as I go. The routines themselves
-#   are now all documented, but who knows what the stack is or why? hrm?
-
-				
-# This hurts my little brane.		
-
-# Holds the output stack		
+				# Utils
+				# output stack management
 my @output_stack;
-
-# Defines how large the output stack can be
-use constant MAX_OUTPUT_STACK_SIZE => 0; # PV: 8 seems a good value
-                                         # PS: Then why not default it to that?
-
-=head1 Stack manipulation
-
-=head2 dump_stack
-
-Serializes and prints the stack to STDERR
-
-=cut
-
-# Serializes the stack, and prints it to STDERR.
+use constant MAX_OUTPUT_STACK_SIZE => 0; # 8 seems a good value
 sub dump_stack {
-
-  my $stack_size = @output_stack;
-  
-  print STDERR "Stack size: $stack_size\n";
-  
-  print STDERR $stack_size-- . " |$_|\n" for reverse @output_stack;
-
-}
-
-=head2 output
-
-Holder routine for the current thing to do with output text we're given.
-It starts off as the same as C<$string_output_sub>, which adds the string
-to the element at the C<TOP> of the output stack. However, the idea, I 
-believe, is to allow that to be changed at will, using C<push_output>.
-
-=cut
-
-sub output {
-
-	$output_stack[TOP] .= $_[0]
-
+  local($", $\) = ("\n") x 2;
+  my $i = @output_stack;
+  print STDERR "Stack size: $i";
+  print STDERR map { $i-- . " |$_|\n" } reverse @output_stack;
 }
-
-# I'm guessing (because I'm generous ;-) that this is done because
-#	subclasses might want to modifiy the values of these. These are
-#	obviously the two different ways to spit out ... something. We
-#	start with the string_output_sub being what &output does tho.
-
-my $nul_output_sub = sub {
-	#print STDERR "** $_[0] **\n";
-};
-
-my $string_output_sub = sub {
-
-	$output_stack[TOP] .= $_[0] if $_[0];
-	
-};
-
-=head2 push_output
-
-Adds a blank element to the end of the stack. It will change (or
-maintain) the function of C<output> to be C<$string_output_sub>,
-unless you pass it the argument C< 'nul' >, in which case it will
-set C<output> to be C<$nul_output_sub>.
-
-=cut
-
+my $nul_output_sub = sub {};
+my $string_output_sub = sub { $output_stack[TOP] .= $_[0] };
+sub output { $output_stack[TOP] .= $_[0] }
 sub push_output {  
+  if (MAX_OUTPUT_STACK_SIZE) {
+    die "max size of output stack exceeded" if @output_stack == MAX_OUTPUT_STACK_SIZE;
+  }
 
-	# If we've set a maximum output stack and then exceeded it, complain.
-		if (MAX_OUTPUT_STACK_SIZE) {
-			die "max size of output stack exceeded" if @output_stack == MAX_OUTPUT_STACK_SIZE;
-		}
-	
-	# If we didn't get an argument, output becomes string...
-		unless (defined($_[0])) {
-  
-			local $^W = 0;
-			*output = $string_output_sub; 
-
-	# If we were given 'nul', set output to $nul_output_sub
-		} elsif ($_[0] eq 'nul') {
-
-			local $^W = 0;
-			*output = $nul_output_sub;
-		
-		}
-
-	# Add an empty element to the end of the ouput stack
-		push @output_stack, '';
-
-}
-
-=head2 pop_output
-
-Removes and returns the last element of the ouput stack
-
-=cut
-
-# Remove and return an element of the output stack, which
-# should basically be the in-scope text... See how &do_on_info
-# uses this
-
-sub pop_output {
+  unless (defined($_[0])) {
+    local $^W = 0;
+    *output = $string_output_sub; 
+  } elsif ($_[0] eq 'nul') {
+    local $^W = 0;
+    *output = $nul_output_sub;
+  }
 
-	pop @output_stack;
-	
+  push @output_stack, '';
 }
-
+sub pop_output {  pop @output_stack; }
 use constant SET_TOP_OUTPUT_TO_TRACE => 0;
-
-=head2 set_top_output_to
-
-Only called at init time, is a method call not a function.
-Sets the action of C<flush_top_output>, depending on whether
-you pass it a filehandle or string reference.
-
-=cut
-
-# Sets flush_top_output to print to the appropriate thingy
 sub set_top_output_to {
-
-	my $self = shift;
-  
-	# Are we being passed a filehandle?
-	
-		local *X = $_[0];
-		
-		if (fileno X) {		
-							
-			my $stream = *X;
-    	
-		# Debugging info if asked for
-			print STDERR "stream: ", fileno X, "\n" if SET_TOP_OUTPUT_TO_TRACE;
-    
-    	# Turn off warnings
-			local $^W = 0;
-    
-    	# Overwrite &flush_top_output
-			*flush_top_output = sub {
-				print $stream $output_stack[TOP];
-				$output_stack[TOP] = ''; 
-			};
-    
-	# We've been passed a reference to a scalar...
-	
-		} elsif (ref $_[0] eq 'SCALAR') {
-    
-			print STDERR "output to string\n" if SET_TOP_OUTPUT_TO_TRACE;
-    
-			my $content_ref = $_[0];
-    
-			local $^W = 0;
-    
-			*flush_top_output = sub {
-				$$content_ref .= $output_stack[TOP]; 
-				$output_stack[TOP] = ''; 
-			};
-			
-	# Someone's done something weird
-
-		} else {
-		
-			warn "unknown output specification: $_[0]\n";
-		
-		}
+  local *X = $_[0];
+  if (fileno X) {		# set_top_output_to(\*FH)
+				# is there a better way to do this?
+    my $stream = *X;
+    print STDERR "stream: ", fileno X, "\n" if SET_TOP_OUTPUT_TO_TRACE;
+    local $^W = 0;
+    *flush_top_output = sub {
+      print $stream $output_stack[TOP];
+      $output_stack[TOP] = ''; 
+    };
+  } elsif (ref $_[0] eq 'SCALAR') { # set_top_output_to(\$string)
+    print STDERR "output to string\n" if SET_TOP_OUTPUT_TO_TRACE;
+    my $content_ref = $_[0];
+    local $^W = 0;
+    *flush_top_output = sub {
+      $$content_ref .= $output_stack[TOP]; 
+      $output_stack[TOP] = ''; 
+    };
+  } else {
+    warn "unknown output specification: $_[0]\n";
+  }
 
 }
-
 # the default prints on the selected output filehandle
-
-=head2 flush_top_output
-
-Output the top element of the stack in the way specified by the call
-to C<set_top_output_to>
-
-=cut
-
 sub flush_top_output {		
-
   print $output_stack[TOP]; 
   $output_stack[TOP] = ''; 
-
 }
-
-
+#sub print_output_stack {
+#  if (@output_stack) {
+#    print @output_stack;
+#    @output_stack = ();
+#  } else {
+#    warn "empty \@output_stack\n";
+#  }
+#}
 ###########################################################################
 				# Trace management
-use constant RTF_DEBUG => 0;
+use constant DEBUG => 0;
 use constant TRACE => 0;	
 use constant STACK_TRACE => 0;	# 
 use constant STYLESHEET_TRACE => 0; # If you want to see the stylesheet of the document
 use constant STYLE_TRACE => 0; # 
 use constant LIST_TRACE => 0;
 
-$| = 1 if TRACE or STACK_TRACE or RTF_DEBUG;
-
-# Debugging function - prints the number of _'s matching
-# the number of controls in our current control stack,
-# and anything else we were passed, and the $. - input
-# line number.
-
+$| = 1 if TRACE or STACK_TRACE or DEBUG;
 sub trace {
   #my(@caller) = (caller(1));
   #my $sub = (@caller)[3];
@@ -535,90 +196,45 @@ sub trace {
 $SIG{__DIE__} = sub {
   require Carp;
   Carp::confess;
-} if RTF_DEBUG;
+} if DEBUG;
 
 ###########################################################################
 				# Some generic routines
 use constant DISCARD_CONTENT => 0;
-
-# This seems to be what we do when we hit a control word
-#   we're not going to parse. He seems to be manually
-#	implementing this some times - I wonder why?
-
-sub discard_content {
-
-	# Read in information about the control word we hit
-		my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
-
-		trace "($_[CONTROL], $_[ARG], $_[EVENT])" if DISCARD_CONTENT;
-
-	# This I don't understand. Presumably if we've hit 0, then it's
-	# the close of a part of the document being dictated by a char
-	# property, like, say, \b1I'm bold\b0 I'm not. 
-	
-	if ($_[ARG] eq "0") { 
-
-		# Remove the last element on the output stack
-	  pop_output();
-	
-		# Set the property as on(?) on the control stack
-		# This should probably be a 0. Something to test
-		# later.
-	  $control[TOP]->{"$_[CONTROL]1"} = 1;
-
-	# Add a blank element to the end of the output stack
-	} elsif ($_[EVENT] eq 'start') { 
-  		
-  		push_output();
-  		$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-
-	} elsif ($_[ARG] eq "1") {
-  		$cevent = 'start';
-  		push_output();
-
-	} elsif ($_[EVENT] eq 'end') { # End of discard
-
-  		my $string = pop_output();
-
-	  	if (length $string > 30) {
-   		 	$string =~ s/(.{1,10}).*(.{1,10})/$1 ... $2/;
-  		}
-
-  		trace "discard content of \\$control: $string" if DISCARD_CONTENT;
-
-	} else {
- 	
- 	 die "($_[CONTROL], $_[ARG], $_[EVENT])" if DISCARD_CONTENT;
-	
-	}
-
+sub discard_content {		
+  my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
+  trace "($_[CONTROL], $_[ARG], $_[EVENT])" if DISCARD_CONTENT;
+  if ($_[ARG] eq "0") { 
+    pop_output();
+    $control[TOP]->{"$_[CONTROL]1"} = 1;
+  } elsif ($_[EVENT] eq 'start') { 
+    push_output();
+    $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+  } elsif ($_[ARG] eq "1") { # see above
+    $cevent = 'start';
+    push_output();
+  } elsif ($_[EVENT] eq 'end') { # End of discard
+    my $string = pop_output();
+    if (length $string > 30) {
+      $string =~ s/(.{1,10}).*(.{1,10})/$1 ... $2/;
+    }
+    trace "discard content of \\$control: $string" if DISCARD_CONTENT;
+  } else {
+    die "($_[CONTROL], $_[ARG], $_[EVENT])" if DISCARD_CONTENT;
+  }
 }
 
-
-# Document meta-data collator. Whenever we hit an info group,
-# this sub is called. All it does is put all the text 'in-scope'
-# into the %info hash...
-
-sub do_on_info {
-
-	my $string;
-	
-	if ($_[EVENT] eq 'start') { 
- 		
- 		push_output();
-		$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-  
-	} else {
-		
-		$string = pop_output();
-		$info{"$_[CONTROL]$_[ARG]"} = $string;
-	
-	}
+sub do_on_info {		# 'info' content
+  #my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
+  my $string;
+  if ($_[EVENT] eq 'start') { 
+    push_output();
+    $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+  } else {
+    $string = pop_output();
+    $info{"$_[CONTROL]$_[ARG]"} = $string;
+  }
 }
-
-
-
-
 				# SYMBOLS
 # default mapping for symbols
 # char processed by the parser symbol() callback: - _ ~ : | { } * ' \\
@@ -639,16 +255,7 @@ $symbol{'tab'} = "\t";
 $symbol{'line'} = "\n";
 $symbol{'page'} = "\f";
 
-# Handler for symbols - prints the symbol corresponding
-# to our first argument...
-
-sub do_on_symbol {
-
-	output $symbol{$_[CONTROL]};
-	
-}
-
-
+sub do_on_symbol { output $symbol{$_[CONTROL]} }
 my %symbol_ctrl = map {		# install the do_on_symbol() routine
   if (/^[a-z]+$/) {
     $_ => \&do_on_symbol
@@ -657,25 +264,15 @@ my %symbol_ctrl = map {		# install the do_on_symbol() routine
   }
 } keys %symbol;
 
-
-
-
-
 ###########################################################################################
 my %char_props;			# control hash must be declarated before install_callback()
 # purpose: associate callbacks to controls
 # 1. an hash name that contains the controls
 # 2. a callback name
-
-# Sets the call back given as the second argument
-# as the %do_on_control for all controls currently
-# in %char_props. DON'T UNDERSTAND.
-
 sub install_callback {		# not a method!!!
-
   my($control, $callback) = ($_[1], $_[2]);
   no strict 'refs';
-  unless ( %char_props ) { # why I can't write %{$control}
+  unless (defined(%char_props)) { # why I can't write %{$control}
     die "'%$control' not defined";
   }
   for (keys %char_props) {
@@ -690,263 +287,139 @@ sub install_callback {		# not a method!!!
 #my %control_definition = ( # control => [default_value nassociated_callback]
 #			  'char_props' => qw(0 do_on_control),
 #			 );
-
-
-
-# Remove character formatting properties ... there are actually more
-# character formatting properties defined in the RTF spec, but
-# these seem to be the ones supported by this module...
-
 sub reset_char_props {
-
-	%char_props = map {
-	
-		$_ => 0
-	
-	} qw(b i ul sub super strike);
+  %char_props = map {
+    $_ => 0
+  } qw(b i ul sub super strike);
 }
-
-
 my $char_prop_change = 0;
 my %current_char_props = %char_props;
 use constant OUTPUT_CHAR_PROPS => 0;
-
-# Force a START or END event on our current character 
-# properties...  This is a method call.
-
 sub force_char_props {		# force a START/END event
-
-	# Obviously you're not allowed to do this in the fonttable
-	# or style sheet...
-	
-	return if $IN_STYLESHEET or $IN_FONTTBL;
-
-	trace "@_" if OUTPUT_CHAR_PROPS;
-
-	# [0] is our object 
-	$event = $_[1];		# END or START
+  return if $IN_STYLESHEET or $IN_FONTTBL;
+  trace "@_" if OUTPUT_CHAR_PROPS;
+  $event = $_[1];		# END or START
 				# close or open all activated char prorperties
-
-	push_output();
-
-	while (my($char_prop, $value) = each %char_props) {
-
-		next unless $value;
-
-		trace "$event active char props: $char_prop" if OUTPUT_CHAR_PROPS;
-
-		if (defined (my $action = $do_on_event{$char_prop})) {
-
-			($style, $event) = ($char_prop, $event);
-
- 			&$action;
-
-		}
-
-		$current_char_props{$char_prop} = $value;
-
-	}
-
-	$char_prop_change = 0;
-
-	pop_output();
-
+  push_output();
+  while (my($char_prop, $value) = each %char_props) {
+    next unless $value;
+    trace "$event active char props: $char_prop" if OUTPUT_CHAR_PROPS;
+    if (defined (my $action = $do_on_event{$char_prop})) {
+      ($style, $event) = ($char_prop, $event);
+      &$action;
+    }
+    $current_char_props{$char_prop} = $value;
+  }
+  $char_prop_change = 0;
+  pop_output();
 }
-
-
 use constant PROCESS_CHAR_PROPS => 0;
-
-# Only run outside of stylesheets and fonttables,
-# and only when the $char_prop_change flag is
-# set. 
-
 sub process_char_props {
-
-	return if $IN_STYLESHEET or $IN_FONTTBL;
-
-	return unless $char_prop_change;
-
-	# Add a new output block
-
-	push_output();
-
-	# Go through char_props (is the what we were, or what we're going to?!)
-	while (my($char_prop, $value) = each %char_props) {
-
-		# Get the current character property
-		my $prop = $current_char_props{$char_prop};
-
-		# Set it to an explicit 0 if not set
-		$prop = defined $prop ? $prop : 0;
-
-		trace "$char_prop $value" if PROCESS_CHAR_PROPS;
-
-		# If the values in %char_props and $current_char_props don't match..
-		if ($prop != $value) {
-
-			# See if we have an event...
-			if (defined (my $action = $do_on_event{$char_prop})) {
-
-				# Set event to start or end depending on if
-				# the $value is a literal 1. 
-				$event = $value == 1 ? 'start' : 'end';
-
-				($style, $event) = ($char_prop, $event);
-
-				# Fire the event
-				&$action;
-
-			}
-
-			# Set the $current_char_props to equal what was in %char_props
-			$current_char_props{$char_prop} = $value;
-
-		}
-
-		trace "$char_prop - $prop - $value" if PROCESS_CHAR_PROPS;
-
-	}
-
-	# Reset the flag
-	$char_prop_change = 0;
-
-	# Return whatever was on the stack
-	pop_output();
-
+  return if $IN_STYLESHEET or $IN_FONTTBL;
+  return unless $char_prop_change;
+  push_output();
+  while (my($char_prop, $value) = each %char_props) {
+    my $prop = $current_char_props{$char_prop};
+    $prop = defined $prop ? $prop : 0;
+    trace "$char_prop $value" if PROCESS_CHAR_PROPS;
+    if ($prop != $value) {
+      if (defined (my $action = $do_on_event{$char_prop})) {
+	$event = $value == 1 ? 'start' : 'end';
+	($style, $event) = ($char_prop, $event);
+	&$action;
+      }
+      $current_char_props{$char_prop} = $value;
+    }
+    trace "$char_prop - $prop - $value" if PROCESS_CHAR_PROPS;
+  }
+  $char_prop_change = 0;
+  pop_output();
 }
-
 use constant DO_ON_CHAR_PROP => 0;
-
-# Again, not called in a font or stylesheet, for obvious reasons.
-# Set the char_prop_change flag. If the argument is '0', we set
-# that character property to that - if the event is start, we set
-# it to one, otherwise we throw a warning.
-
 sub do_on_char_prop {		# associated callback
-
-	return if $IN_STYLESHEET or $IN_FONTTBL;
-
-	my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
-
-	trace "my(\$control, \$arg, \$cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);" if DO_ON_CHAR_PROP;
-
-	$char_prop_change = 1;
-
-	if (defined($_[ARG]) and $_[ARG] eq "0") {		# \b0 
-		
-		$char_props{$_[CONTROL]} = 0;
-
-	} elsif ($_[EVENT] eq 'start') { # eg. \b or \b1
-
-		$char_props{$_[CONTROL]} = 1; 
-
-	} else {			# 'end'
-
-		warn "statement not reachable";
-		$char_props{$_[CONTROL]} = 0;
-	
-	}
-
+  return if $IN_STYLESHEET or $IN_FONTTBL;
+  my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
+  trace "my(\$control, \$arg, \$cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);" if DO_ON_CHAR_PROP;
+  $char_prop_change = 1;
+  if (defined($_[ARG]) and $_[ARG] eq "0") {		# \b0 
+    $char_props{$_[CONTROL]} = 0;
+  } elsif ($_[EVENT] eq 'start') { # eg. \b or \b1
+    $char_props{$_[CONTROL]} = 1; 
+  } else {			# 'end'
+    warn "statement not reachable";
+    $char_props{$_[CONTROL]} = 0;
+  }
 }
-
-
-
-
-# LOOK MA! THIS BE IMPORTANT
 __PACKAGE__->reset_char_props();
 __PACKAGE__->install_callback('char_props', 'do_on_char_prop');
-
-
-
 ###########################################################################
 				# not more used!!!
-#use constant DO_ON_TOGGLE => 0;
-#sub do_on_toggle {		# associated callback
-##
-#
- # return if $IN_STYLESHEET or $IN_FONTTBL;
- # my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
- # trace "my(\$control, \$arg, \$cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);" if DO_ON_TOGGLE;
-#
- # if ($_[ARG] eq "0") {		# \b0, register an START event for this control
- #   $control[TOP]->{"$_[CONTROL]1"} = 1; # register a start event for this properties
- #   $cevent = 'end';
- # } elsif ($_[EVENT] eq 'start') { # \b or \b1
- #   $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
- # } else {			# $_[EVENT] eq 'end'
- #   if ($_[ARG] eq "1") {	
- #     $cevent = 'start';
- #   } else {			
- #   }
- # }
- # trace "(\$style, \$event, \$text) = ($control, $cevent, '')" if DO_ON_TOGGLE;
- # if (defined (my $action = $do_on_event{$control})) {
- #   ($style, $event, $text) = ($control, $cevent, '');
- #   &$action;
- # } 
-#}
-
-
+use constant DO_ON_TOGGLE => 0;
+sub do_on_toggle {		# associated callback
+  return if $IN_STYLESHEET or $IN_FONTTBL;
+  my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
+  trace "my(\$control, \$arg, \$cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);" if DO_ON_TOGGLE;
+
+  if ($_[ARG] eq "0") {		# \b0, register an START event for this control
+    $control[TOP]->{"$_[CONTROL]1"} = 1; # register a start event for this properties
+    $cevent = 'end';
+  } elsif ($_[EVENT] eq 'start') { # \b or \b1
+    $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+  } else {			# $_[EVENT] eq 'end'
+    if ($_[ARG] eq "1") {	
+      $cevent = 'start';
+    } else {			
+    }
+  }
+  trace "(\$style, \$event, \$text) = ($control, $cevent, '')" if DO_ON_TOGGLE;
+  if (defined (my $action = $do_on_event{$control})) {
+    ($style, $event, $text) = ($control, $cevent, '');
+    &$action;
+  } 
+}
 ###########################################################################
 				# FLAGS
 use constant DO_ON_FLAG => 0;
-
-# Simply sets that pargraph properties of said flag to 1
-
 sub do_on_flag {
-
   #my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
-	die if $_[ARG];			# no argument by definition
-	trace "$_[CONTROL]" if DO_ON_FLAG;
-	$par_props{$_[CONTROL]} = 1;
-
+  die if $_[ARG];			# no argument by definition
+  trace "$_[CONTROL]" if DO_ON_FLAG;
+  $par_props{$_[CONTROL]} = 1;
 }
 
 use vars qw/%charset/;
 my $bullet_item = 'b7'; # will be redefined in a next release!!!
 
-
 				# Try to find a "RTF/<application>/char_map" file
 				# possible values for the control word are: ansi, mac, pc, pca
 sub define_charset {
-
-	my $charset = $_[CONTROL];
-	eval {			
-		no strict 'refs';
-		*charset = \%{"$charset"};
-	};
-  
-	warn $@ if $@;
-
-	my @charset_data = $_[SELF]->charmap_reader('char_map');
-
-	my ($name, $char, $hexa);
-	my %char = map{
-		
-		s/^\s+//; 
-		next unless /\S/;
-		($name, $char) = split /\s+/; 
-		
-		if (!defined($hexa = $charset{$name})) {
-  			
-  			'undef' => undef;
-    
-		} else {
- 			
- 			$hexa => $char;
-    
-		}
-
-	} (@charset_data);
-		
-	%charset = %char;		# for a direct translation of hexadecimal values
-	warn $@ if $@;
-
+  my $charset = $_[CONTROL];
+  eval {			
+    no strict 'refs';
+    *charset = \%{"$charset"};
+  };
+  warn $@ if $@;
+
+  my $charset_file = $_[SELF]->application_dir() . "/char_map";
+  my $application = ref $_[SELF];
+  open CHAR_MAP, "$charset_file"
+    or die "unable to open the '$charset_file': $!";
+
+  my ($name, $char, $hexa);
+  my %char = map{
+    s/^\s+//; 
+    next unless /\S/;
+    ($name, $char) = split /\s+/; 
+    if (!defined($hexa = $charset{$name})) {
+      'undef' => undef;
+    } else {
+      $hexa => $char;
+    }
+  } (<CHAR_MAP>);
+  %charset = %char;		# for a direct translation of hexadecimal values
+  warn $@ if $@;
 }
 
-
-
-
 my %flag_ctrl =			
   (				
    'ql' => \&do_on_flag,
@@ -983,129 +456,498 @@ my %value_ctrl =
 my %pn = ();			# paragraph numbering 
 my $field_ref = '';		# identifier associated to a field
 #trace "define callback for $_[CONTROL]";
-				
-				
-				
-				
-# BEGIN API REDEFINITION
-
-#   Ok, so this is actually the place to start as far as concerns
-#	  working out how the hell^Wfuck this thing works. I'm moving
-#	  all the constants to the top, and adding API documentation
-#	  here so future readers will have less trouble.
-
-				
-use constant GROUP_START_TRACE => 0;
-use constant GROUP_END_TRACE => 0;
-use constant TEXT_TRACE => 0;
-use constant PARSE_START_END => 0;
-
-# Called when we first start actually parsing the document
-sub parse_start {
-	
-	my $self = shift;
-
-	# Place holders for non-printed data
-		
-		%info = ();
-		%fonttbl = ();
-		%colortbl = ();
-		%stylesheet = ();
-
-	# Add an initial element to our output stack
-		
-		push_output();
-
-	# If there's an event defined for the start of a document,
-	#   execute it now...
-		
-		if (defined (my $action = $do_on_event{'document'})) {
-		
-			# $event tells our action handler what's happening...
-			
-				$event = 'start';
-		
-			# Actually execute said action
-		
-				&$action;
-		
-		}
-
-	# Prints and clears the top element on the output stack
-	
-		flush_top_output();	
-
-	# Add another element to the output stack
-	
-		push_output();
-
-}
-
-# Called at the end of parsing
-sub parse_end {
-
-	my $self = shift;
-
-	# @output_stack+0 forces scalar context?
-	trace "parseEnd \@output_stack: ", @output_stack+0 if STACK_TRACE;
-
-	# Call the end of document even if it exists
-	if (defined (my $action = $do_on_event{'document'})) {
-		
-		($style, $event, $text) = ($cstylename, 'end', '');
-		&$action;
-	
-	} 
-	
-	# Print and clear the top element on the output stack
-	
-		flush_top_output();		# @output_stack == 2;
-
-}
+%do_on_control = 
+  (
+   %do_on_control,		
+   %flag_ctrl,
+   %value_ctrl,
+   %symbol_ctrl,
+   %destination_ctrl,
 
+   'plain' => sub {
+     #unless (@control) {       die "\@control stack is empty";     }
+     #output('plain');
+     reset_char_props();
+   },
+   'rtf' => sub { # rtfN, N is version number 
+     if ($_[EVENT] eq 'start') { 
+       push_output('nul');
+       $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+     } else {
+       pop_output();
+     }
+   },
+   'info' => sub {		# {\info {...}}
+     if ($_[EVENT] eq 'start') { 
+       push_output('nul');
+       $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+     } else {
+       pop_output();
+     }
+   },
+				# INFO GROUP
+   # Other informations:
+   # {\printim\yr1997\mo11\dy3\hr11\min5}
+   # {\version3}{\edmins1}{\nofpages3}{\nofwords1278}{\nofchars7287}
+   # {\*\company SONOVISION-ITEP}{\vern57443}
+   'title' => \&do_on_info,	# destination
+   'author' => \&do_on_info,	# destination
+   'revtim' => \&do_on_info,	# destination
+   'creatim' => \&do_on_info,	# destination, {\creatim\yr1996\mo9\dy18\hr9\min17}
+   'yr' => sub { output "$_[ARG]-" }, # value
+   'mo' => sub { output "$_[ARG]-" }, # value
+   'dy' => sub { output "$_[ARG]-" }, # value
+   'hr' => sub { output "$_[ARG]-" }, # value
+   'min' => sub { output "$_[ARG]" }, # value
 
+				# binary data
+   'bin' => sub { $_[SELF]->read_bin($_[ARG]) }, # value
 
+				# Color table - destination
+   'colortbl' => \&discard_content,
+				# Font table - destination
+   'fonttbl' => sub {
+     #trace "$#control $_[CONTROL] $_[ARG] $_[EVENT]";
+     if ($_[EVENT] eq 'start') { 
+       $IN_FONTTBL = 1 ;
+       push_output('nul');
+       $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+     } else {
+       $IN_FONTTBL = 0 ;
+       pop_output();
+     }
+   },
+				# file table - destination
+   'filetbl' => sub {
+     #trace "$#control $_[CONTROL] $_[ARG] $_[EVENT]";
+     if ($_[EVENT] eq 'start') { 
+       push_output('nul');
+       $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+     } else {
+       pop_output();
+     }
+   },
+
+   'f', sub {			
+     #my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
+     # perhaps interesting to provide a contextual
+     # definition of this kind of control words
+     # eg. in fonttbl call 'fonttbl:f', outside call 'f'
+     use constant FONTTBL_TRACE => 0; # if you want to see the fonttbl of the document
+     if ($IN_FONTTBL) {
+       if ($_[EVENT] eq 'start') {
+	 push_output();
+	 $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+       } else {
+	 my $fontname = pop_output;
+	 my $fontdef = "$_[CONTROL]$_[ARG]";
+	 if ($fontname =~ s/\s*;$//) {
+	   trace "$fontdef => $fontname" if FONTTBL_TRACE;
+	   $fonttbl{$fontdef} = $fontname;
+	 } else {
+	   warn "can't analyze $fontname";
+	 }
+       }
+       return;
+     } elsif ($IN_STYLESHEET) {	# eg. \f1 => Normal;
+       return if $styledef;	# if you have already encountered an \sn
+       $styledef = "$_[CONTROL]$_[ARG]";
+       if ($_[EVENT] eq 'start') {
+	 #trace "start $_[CONTROL]$_[ARG]" if STYLESHEET;
+	 push_output();
+	 $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+       } else {
+	 my $stylename = pop_output;
+	 #trace "end\n $_[CONTROL]" if STYLESHEET;
+	 if ($stylename =~ s/\s*;$//) {
+	   trace "$styledef => $stylename" if STYLESHEET_TRACE;
+	   $stylesheet{$styledef} = $stylename;
+	 } else {
+	   warn "can't analyze '$stylename' ($styledef; event: $_[EVENT])";
+	 }
+       }
+       $styledef = '';
+       return;
+     }
+     return if $styledef;	# if you have already encountered an \sn
+     $styledef = "$_[CONTROL]$_[ARG]";
+     $stylename = $stylesheet{"$styledef"};
+     trace "$styledef => $stylename" if STYLESHEET_TRACE;
+     return unless $stylename;
+
+     if ($cstylename ne $stylename) { # notify a style changing
+       if (defined (my $action = $do_on_event{'style_change'})) {
+	 ($style, $newstyle) = ($cstylename, $stylename);
+	 &$action;
+       } 
+     }
+     $cstylename = $stylename;
+     $par_props{'stylename'} = $cstylename; # the current style 
+   },
+				# 
+				# Style processing
+				# 
+   'stylesheet' => sub {
+     trace "stylesheet $#control $_[CONTROL] $_[ARG] $_[EVENT]" if STYLESHEET_TRACE;
+     if ($_[EVENT] eq 'start') { 
+       $IN_STYLESHEET = 1 ;
+       push_output('nul');
+       $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+     } else {
+       $IN_STYLESHEET = 0;
+       pop_output;
+     }
+   },
+   's', sub {
+     my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
+     $styledef = "$_[CONTROL]$_[ARG]";
+
+     if ($IN_STYLESHEET) {
+       if ($_[EVENT] eq 'start') {
+	 push_output();
+	 $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+       } else {
+	 my $stylename = pop_output;
+	 warn "empty stylename" and return if $stylename eq '';
+	 if ($stylename =~ s/\s*;$//) {
+	   trace "$styledef => $stylename|" if STYLESHEET_TRACE;
+	   $stylesheet{$styledef} = $stylename;
+	   $styledef = '';
+	 } else {
+	   warn "can't analyze style name: '$stylename'";
+	 }
+       }
+       return;
+     }
+
+     $stylename = $stylesheet{"$styledef"};
+     if ($cstylename ne $stylename) {
+       if (defined (my $action = $do_on_event{'style_change'})) {
+	 ($style, $newstyle) = ($cstylename, $stylename);
+	 &$action;
+       } 
+     }
+     $cstylename = $stylename;
+     $par_props{'stylename'} = $cstylename; # the current style 
+     trace "$styledef => $stylename" if STYLESHEET_TRACE;
+   },
+				# a very minimal table processing
+   'trowd' => sub {		# row start
+     use constant TABLE_TRACE => 0;
+     #print STDERR "=>Beginning of ROW\n";
+     unless ($IN_TABLE) {
+       $IN_TABLE = 1;
+       if (defined (my $action = $do_on_event{'table'})) {
+	 $event = 'start';
+	 trace "table $event $text\n" if TABLE_TRACE;
+	 &$action;
+       } 
+
+       push_output();		# table content
+       push_output();		# row  sequence
+       push_output();		# cell sequence
+       push_output();		# cell content
+     }
+   },
+   'intbl' => sub {
+     $par_props{'intbl'} = 1;
+     unless ($IN_TABLE) {
+       warn "ouverture en catastrophe" if TABLE_TRACE;
+       $IN_TABLE = 1;
+       if (defined (my $action = $do_on_event{'table'})) {
+	 $event = 'start';
+	 trace "table $event $text\n" if TABLE_TRACE;
+	 &$action;
+       } 
+
+       push_output();
+       push_output();
+       push_output();
+       push_output();
+     }
+   },
+   'row' => sub {		# row end
+     $text = pop_output;
+     $text = pop_output . $text;
+     if (defined (my $action = $do_on_event{'cell'})) {
+       $event = 'end';
+       trace "row $event $text\n" if TABLE_TRACE;
+       &$action;
+     } 
+     $text = pop_output;
+     if (defined (my $action = $do_on_event{'row'})) {
+       $event = 'end';
+       trace "row $event $text\n" if TABLE_TRACE;
+       &$action;
+     } 
+     push_output();
+     push_output();
+     push_output();
+   },
+   'cell' => sub {		# end of cell
+     trace "process cell content: $text\n" if TABLE_TRACE;
+     $text = pop_output;
+     if (defined (my $action = $do_on_event{'par'})) {
+       ($style, $event,) = ('par', 'end',);
+       &$action;
+     } else {
+       warn "$text";;
+     }
+     $text = pop_output;
+     if (defined (my $action = $do_on_event{'cell'})) {
+       $event = 'end';
+       trace "cell $event $text\n" if TABLE_TRACE;
+       &$action;
+     } 
+ 				# prepare next cell
+     push_output();
+     push_output();
+     trace "\@output_stack in table: ", @output_stack+0 if STACK_TRACE;
+   },
+   'par' => sub {		# END OF PARAGRAPH
+     #my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
+     trace "($_[CONTROL], $_[ARG], $_[EVENT])" if STYLE_TRACE;
+     if ($IN_TABLE and not $par_props{'intbl'}) { # End of Table
+       $IN_TABLE = 0;
+       my $next_text = pop_output; # next paragraph content
+       
+       $text = pop_output;
+       $text = pop_output . "$text";
+       if (defined (my $action = $do_on_event{'cell'})) { # end of cell
+	 $event = 'end';
+	 trace "cell $event $text\n" if TABLE_TRACE;
+	 &$action;
+       } 
+       $text = pop_output;
+       if (defined (my $action = $do_on_event{'row'})) { # end of row
+	 $event = 'end';
+	 trace "row $event $text\n" if TABLE_TRACE;
+	 &$action;
+       } 
+       $text = pop_output;
+       if (defined (my $action = $do_on_event{'table'})) { # end of table
+	 $event = 'end';
+	 trace "table $event $text\n" if TABLE_TRACE;
+	 &$action;
+       } 
+       push_output();	       
+       trace "end of table ($next_text)\n" if TABLE_TRACE;
+       output($next_text);
+     } else {
+       #push_output();	
+     }
+				# paragraph style
+     if (defined($cstylename) and $cstylename ne '') { # end of previous style
+       $style = $cstylename;
+     } else {
+       $cstylename = $style = 'par'; # no better solution
+     }
+     $par_props{'stylename'} = $cstylename; # the current style 
+
+     if ($par_props{intbl}) {	# paragraph in tbl
+       trace "process cell content: $text\n" if TABLE_TRACE;
+       if (defined (my $action = $do_on_event{$style})) {
+	 ($style, $event, $text) = ($style, 'end', pop_output);
+	 &$action;
+       } elsif (defined ($action = $do_on_event{'par'})) {
+	 #($style, $event, $text) = ('par', 'end', pop_output);
+	 ($style, $event, $text) = ($style, 'end', pop_output);
+	 &$action;
+       } else {
+	 warn;
+       }
+       push_output(); 
+     #} elsif (defined (my $action = $do_on_event{'par_styles'})) {
+     } elsif (defined (my $action = $do_on_event{$style})) {
+       ($style, $event, $text) = ($style, 'end', pop_output);
+       &$action;
+       flush_top_output();
+       push_output(); 
+     } elsif (defined ($action = $do_on_event{'par'})) {
+       #($style, $event, $text) = ('par', 'end', pop_output);
+       ($style, $event, $text) = ($style, 'end', pop_output);
+       &$action;
+       flush_top_output();
+       push_output(); 
+     } else {
+       trace "no definition for '$style' in %do_on_event\n" if STYLE_TRACE;
+       flush_top_output();
+       push_output(); 
+     }
+				# redefine this!!!
+     $cli = $par_props{'li'};
+     $styledef = '';		
+     $par_props{'bullet'} = $par_props{'number'} = $par_props{'tab'} = 0; # 
+   },
+				# Resets to default paragraph properties
+				# Stop inheritence of paragraph properties
+   'pard' => sub {		
+				# !!!-> reset_par_props()
+     foreach (qw(qj qc ql qr intbl li)) {
+       $par_props{$_} = 0;
+     }
+     foreach (qw(list_item)) {
+       $par_props{$_} = '';
+     }
+   },
+				# ####################
+				# Fields and Bookmarks
+#    'field' => sub {  		# for a future version
+#      use constant FIELD_TRACE => 0;
+#      if ($_[EVENT] eq 'start') {
+#        push_output();
+#        $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+#        $field_ref = '';
+#      } else {
+#        #trace "$_[CONTROL] content: ", pop_output();
+#        if (defined (my $action = $do_on_event{'field'})) {
+# 	 ($style, $event, $text) = ($style, 'end', pop_output);
+# 	 &$action($field_ref);
+#        } 
+#      }
+#   },
+
+   # don't uncomment!!!
+#   'fldrslt' => sub { 
+#     return;
+#     if ($_[EVENT] eq 'start') {
+#       push_output();
+#       $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+#     } else {
+#       #trace "$_[CONTROL] content: ", pop_output();
+#       pop_output();
+#     }
+#   },
+   # uncomment!!!
+   # eg: {\*\fldinst {\i0  REF version \\* MERGEFORMAT }}
+#   '*fldinst' => sub {		# Destination
+#     my $string = $_[EVENT];
+#     trace "$_[CONTROL] content: $string" if FIELD_TRACE;
+#     $string =~ /\b(REF|PAGEREF)\s+(_\w\w\w\d+)/i;
+#     $field_ref = $2;
+#     # PerlBug???; $_[CONTROL] == $1 - very strange
+#     trace "$_[CONTROL] content: $string -> $2" if FIELD_TRACE;
+#     trace "$_[1] content: $string -> $2" if FIELD_TRACE;
+#     if (defined (my $action = $do_on_event{'field'})) {
+#       ($style, $event, $text) = ($style, 'start', '');
+#       &$action($field_ref);
+#     } 
+#   },
+#				# Bookmarks
+#   '*bkmkstart' => sub {		# destination
+#     my $string = $_[EVENT];
+#     if (defined (my $action = $do_on_event{'bookmark'})) {
+#       $string =~ /(_\w\w\w\d+)/;	# !!!
+#       trace "$_[CONTROL] content: $string -> $1" if TRACE;
+#       ($style, $event, $text) = ($style, 'start', $1);
+#       &$action;
+#     } 
+#   },
+#   '*bkmkend' => sub {		# destination
+#     my $string = $_[EVENT];
+#     if (defined (my $action = $do_on_event{'bookmark'})) {
+#       $string =~ /(_\w\w\w\d+)/;	# !!!
+#       ($style, $event, $text) = ($style, 'end', $1);
+#       &$action;
+#     }
+#   },
+				# ###########################
+   'pn' => sub {  		# Turn on PARAGRAPH NUMBERING
+     #trace "($_[CONTROL], $_[ARG], $_[EVENT])" if TRACE;
+     if ($_[EVENT] eq 'start') {
+       %pn = ();
+       $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+     } else {
+       # I don't like this!!! redesign the parser???
+       trace("Level: $pn{level} - Type: $pn{type} - Bullet: $pn{bullet}") if LIST_TRACE;
+       $par_props{list_item} = \%pn;
+     }
+   },
+   'pnlvl' => sub {		# Paragraph level $_[ARG] is a level from 1 to 9
+     $pn{level} = $_[ARG];
+   },
+   'pnlvlbody' => sub {		# Paragraph level 10
+     $pn{level} = 10;
+   },
+   'pnlvlblt' => sub {		# Paragraph level 11, processs the 'pntxtb' group
+     $pn{level} = 11;		# bullet
+   },
+  'pntxtb' => sub {
+     if ($_[EVENT] eq 'start') { 
+       push_output();
+       $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+     } else {
+       $pn{'bullet'} = pop_output();
+     }
+  },
+  'pntxta' => sub {
+     if ($_[EVENT] eq 'start') { 
+       push_output();
+       $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+     } else {
+       pop_output();
+     }
+  },
+				# Numbering Types
+   'pncard' => sub {		# Cardinal numbering: One, Two, Three
+     $pn{type} = $_[CONTROL];
+   },
+   'pndec' => sub {		# Decimal numbering: 1, 2, 3
+     $pn{type} = $_[CONTROL];
+   },
+   'pnucltr' => sub {		# Uppercase alphabetic numbering
+     $pn{type} = $_[CONTROL];
+   },
+   'pnlcltr' => sub {		# Lowercase alphabetic numbering
+     $pn{type} = $_[CONTROL];
+   },
+   'pnucrm' => sub {		# Uppercase roman numbering
+     $pn{type} = $_[CONTROL];
+   },
+   'pnlcrm' => sub {		# Lowercase roman numbering
+     $pn{type} = $_[CONTROL];
+   },
+  'pntext' => sub {		# ignore text content
+     if ($_[EVENT] eq 'start') { 
+       push_output();
+       $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
+     } else {
+       pop_output();
+     }
+   },
+   #'tab' => sub { $par_props{'tab'} = 1 }, # special char
+
+   'li' => sub {		# line indent - value
+     use constant LI_TRACE => 0;
+     my $indent = $_[ARG];
+     $indent =~ s/^-//;
+     trace "line indent: $_[ARG] -> $indent" if LI_TRACE;
+     $par_props{'li'} = $indent;
+   },
+  );
+###########################################################################
+				# Parser callback definitions
+use constant GROUP_START_TRACE => 0;
 sub group_start {		# on {
-
   my $self = shift;
-  
   trace "" if GROUP_START_TRACE;
-  
-  # Take a copy of the parent block's paragraph properties
-  	push @par_props_stack, { %par_props };
-
-  # Take a copy of the parent block's character properties
-  	push @char_props_stack, { %char_props };
-
-  # Aha! More accurately, controls we've opened, so we can close them in group_end()
-  	push @control, {};		# hash of controls
-
-
+  push @par_props_stack, { %par_props };
+  push @char_props_stack, { %char_props };
+  push @control, {};		# hash of controls
 }
-
+use constant GROUP_END_TRACE => 0;
 sub group_end {			# on }
 				# par properties
-  
-  # Retrieve parent block's paragraph properties
-  	%par_props = %{ pop @par_props_stack };
-  
-  # And use it to set the current stylename
-  	$cstylename = $par_props{'stylename'}; # the current style 
+  %par_props = %{ pop @par_props_stack };
+  $cstylename = $par_props{'stylename'}; # the current style 
 
 				# Char properties
 				# process control like \b0
-  
-  # Grab the character properties of our parent
-  	%char_props = %{ pop @char_props_stack }; 
-  
-  # Fire off the 'char props have changed' event
-  	$char_prop_change = 1;
-	output process_char_props();
-
-  # Always a /really/ /really/ bad sign :-(
-  	no strict qw/refs/;
+  %char_props = %{ pop @char_props_stack }; 
+  $char_prop_change = 1;
+  output process_char_props();
 
-  # Send an end thingy to each control we're closing
+  no strict qw/refs/;
   foreach my $control (keys %{pop @control}) { # End Events!
     $control =~ /([^\d]+)(\d+)?/; # eg: b0, b1
     trace "($#control): $1-$2" if GROUP_END_TRACE;
@@ -1113,19 +955,12 @@ sub group_end {			# on }
     &{"RTF::Action::$1"}($_[SELF], $1, $2, 'end'); 
   }
 }
-
-# Just dump text
+use constant TEXT_TRACE => 0;
 sub text { 
-
   trace "$_[1]" if TEXT_TRACE;
   output($_[1]);
-
 }
-
-# If we have an equiv, print it, otherwise, print the original
-
-sub char {		
-
+sub char {			
   if (defined(my $char = $charset{$_[1]}))  {
     #print STDERR "$_[1] => $char\n";
     output "$char";
@@ -1133,873 +968,42 @@ sub char {
     output "$_[1]"; 
   }
 }
-
 sub symbol {			# symbols: \ - _ ~ : | { } * \'
-
   if (defined(my $sym = $symbol{$_[1]}))  {
     output "$sym";
   } else {
     output "$_[1]";		# as it
   }
 }
+use constant PARSE_START_END => 0;
+sub parse_start {
+  my $self = shift;
 
+  # some initializations
+  %info = ();
+  %fonttbl = ();
+  %colortbl = ();
+  %stylesheet = ();
 
-
-
-
-sub debug {
-
-	my $function = shift;
-	
-	print STDERR "[RTF::Control::$function]" . (join '|', @_ ) , "\n";
-
+  push_output();
+  if (defined (my $action = $do_on_event{'document'})) {
+    $event = 'start';
+    &$action;
+  }
+  flush_top_output();	
+  push_output();
+}
+sub parse_end {
+  my $self = shift;
+  my $action = '';
+  trace "parseEnd \@output_stack: ", @output_stack+0 if STACK_TRACE;
+
+  if (defined ($action = $do_on_event{'document'})) {
+    ($style, $event, $text) = ($cstylename, 'end', '');
+    &$action;
+  } 
+  flush_top_output();		# @output_stack == 2;
 }
-
-
-
-
-
-
-
-
-%do_on_control = 
-  (
-   %do_on_control,		
-   %flag_ctrl,
-   %value_ctrl,
-   %symbol_ctrl,
-   %destination_ctrl,
-
-	# Resets character formatting in scope... Note how we don't
-	# check for start and end events? My guess is this is because
-	# the original author is a BAD BAD MAN, and because running
-	# reset_char_props() when \plain goes out of scope doesn't
-	# cause any side effects. Something to experiment with when
-	# I have a regression test suite...
-	###########################################################
-
-	'plain' => sub {
-	
-		reset_char_props();
-	
-	},
-
-	###########################################################
-   
-	# The only thing puzzling me here is why we're doing a null
-	# call to push_output. This (and other subroutines below)
-	# are ripe for a bit of refactoring - they all do the same
-	# thing!
-	###########################################################
-   
-	'rtf' => sub { # rtfN, N is version number 
-
-		if ($_[EVENT] eq 'start') { 
-			
-			push_output('nul');
-			$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-
-		} else {
-
-			# There may actually be content at this point!
-			flush_top_output();
-
-			# The buffer should be empty at this point.
-			# Make it so :-) This should use an RTF::Tokenizer
-			# method before I release this as production.
-			# TODO...
-
-			$_[SELF]->{_TOKENIZER}->{_BUFFER} = '';
-			$_[SELF]->{_TOKENIZER}->{_FILEHANDLE} = '';
-			
-		}
-
-	},
-   
-	###########################################################   
-   
-
-   
-   	# Info group. The &do_on_info sub is trivial, and merely puts
-   	# the rest of the text in a destination into %info, with the
-   	# key being the field (like 'title'). creatim is kinda clever
-   	# then in that it turns the rest of those fields into one
-   	# long text string.
-   	#
-   	# Other information we could grab:
-   	# {\printim\yr1997\mo11\dy3\hr11\min5}
-	# {\version3}{\edmins1}{\nofpages3}{\nofwords1278}{\nofchars7287}
-	# {\*\company SONOVISION-ITEP}{\vern57443}
-	###########################################################
-
-	'info' => sub {		# {\info {...}}
-	
-		if ($_[EVENT] eq 'start') { 
-
-			# Stops us collecting any text we don't want
-
-			push_output('nul');
-			$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-
-		} else {
-			
-			pop_output();
-
-		}
-	
-	},
-	   
-   'title' => \&do_on_info,		# destination
-   'author' => \&do_on_info,	# destination
-   'revtim' => \&do_on_info,	# destination
-   'creatim' => \&do_on_info,	# destination, {\creatim\yr1996\mo9\dy18\hr9\min17}
-   'yr' => sub { output "$_[ARG]-" }, # value
-   'mo' => sub { output "$_[ARG]-" }, # value
-   'dy' => sub { output "$_[ARG]-" }, # value
-   'hr' => sub { output "$_[ARG]-" }, # value
-   'min' => sub { output "$_[ARG]" }, # value
-
-	###########################################################
-
-	# Read binary data - only, this function has been removed
-	# from RTF::Parser.pm. Ooops. Add it back in and PUT IN 
-	# A TEST.
-	###########################################################
-
-   'bin' => sub { $_[SELF]->read_bin($_[ARG]) }, # value
-
-	# \ulnone should be treated as if it were \ul0...
-	###########################################################
-	
-	 'ulnone' => sub {
-		
-		$_[SELF]->do_on_char_prop( 'ul', '0', 'start' );
-		
-		},
-
-	# Clearly we're not interested in the colour table....
-	###########################################################
-
-   'colortbl' => \&discard_content,
-
-	# The start of the font-table. There's a global(ish) flag
-	# $IN_FONTTBL that influences how other parts of the module
-	# work. The main thing we do is turn this flag on when we
-	# get to this point. The 'push_output('nul')' also turns
-	# off any output while we're in the font table.
-	###########################################################
-		
-	'fonttbl' => sub {
-
-		if ($_[EVENT] eq 'start') { 
-			
-			# Set the global flag
-			$IN_FONTTBL = 1;
-			
-			# Turn off output
-			push_output('nul');
-			
-			# Remember that this event has fired, and close it
-			# when we go out of scope.
-			$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-
-		} else {
-			
-			$IN_FONTTBL = 0 ;
-			pop_output();
-		
-		}
-	
-	},
-	
-	###########################################################
-
-	# We seem to not want anything to do with the filetable
-	# either - I guess the reason we define a control for it
-	# (because otherwise it'd get skipped as an unknow destination
-	# I think) is so that subclassers can handle it if they
-	# want.
-	###########################################################
-	
-	'filetbl' => sub {
-
-		#trace "$#control $_[CONTROL] $_[ARG] $_[EVENT]";
-		if ($_[EVENT] eq 'start') { 
-
-			push_output('nul');
-			$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-     
-		} else {
-       
-			pop_output();
-
-		}
-		
-	},
-
-	###########################################################
-	
-
-	# A font control - highly context-dependant control word ... Can be used
-	# to introduce a font definition when we're in the font-table, to specify
-	# which font a style uses in the style-table, or to change the font we're
-	# currently using when used as a paragraph/character property.
-	###########################################################
-
-	'f' => sub {			
-
-		use constant FONTTBL_TRACE => 0; # if you want to see the fonttbl of the document
-
-		# We're in the middle of the font-table, so this is a font definition.
-		# We're only really interested in what happens when we pass *out* of 
-		# scope, because at that point we'll have grabbed the font-name. I'd
-		# like to add panose support at some point.
-
-		if ($IN_FONTTBL) {
-			
-			if ($_[EVENT] eq 'start') {
-
-				# Add a new element to the output stack that we can
-				# snarf back in a minute when we hit the group close
-				
-				push_output();
-				
-				# Say we're open
-				
-				$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-  
-			} else {
-
-				# Grab the element from the output stack, which'll be
-				# our fontname
-
-				my $fontname = pop_output;
-				
-				# This will be something like 'f1'
-				
-				my $fontdef = "$_[CONTROL]$_[ARG]";
-
-				# Remove the trailing semi-colon and any space
-
-				if ($fontname =~ s/\s*;$//) {
-					
-					trace "$fontdef => $fontname" if FONTTBL_TRACE;
-					
-					# Set the fontdef and the fontname in the font-table hash
-					
-					$fonttbl{$fontdef} = $fontname;
-
-				} else {
-
-					warn "can't analyze $fontname";
-
-				}
-  
-  			}
-  			
-  			return;
-  			
-  		# We're in the style sheet. This part doesn't make much sense
-  		# just yet, will come back to it. Looks like \f is being used
-  		# to recognise when a style definition is finished?! Bizarre.
-
-		} elsif ($IN_STYLESHEET) {	# eg. \f1 => Normal;
-
-			return if $styledef;	# if you have already encountered an \sn
-			$styledef = "$_[CONTROL]$_[ARG]";
-
-			if ($_[EVENT] eq 'start') {
-				
-				#trace "start $_[CONTROL]$_[ARG]" if STYLESHEET;
-				push_output();
-				$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-
-			} else {
-
-				my $stylename = pop_output;
-				#trace "end\n $_[CONTROL]" if STYLESHEET;
-
-				if ($stylename =~ s/\s*;$//) {
-				
-					trace "$styledef => $stylename" if STYLESHEET_TRACE;
-					$stylesheet{$styledef} = $stylename;
-
-				} else {
-
-					warn "can't analyze '$stylename' ($styledef; event: $_[EVENT])";
-
-				}
-			
-			}
-  
-  			$styledef = '';
-  			return;
-
-		}
-
-		return if $styledef;	# if you have already encountered an \sn
-		
-		# This doesn't make a great deal of sense
-		$styledef = "$_[CONTROL]$_[ARG]";
-		$stylename = $stylesheet{"$styledef"};
-		trace "$styledef => $stylename" if STYLESHEET_TRACE;
-
-		return unless $stylename;
-
-		if ($cstylename ne $stylename) { # notify a style changing
-		
-			if (defined (my $action = $do_on_event{'style_change'})) {
-
-				($style, $newstyle) = ($cstylename, $stylename);
-				&$action;
-			
-			} 
-
-		}
-		
-		$cstylename = $stylename;
-		$par_props{'stylename'} = $cstylename; # the current style 
-	
-	},
-   
-	###########################################################   
-   
-	# Stylesheet - like font-table above, we set the flag, and
-	# make sure we don't grab any unwanted text...
-
-	'stylesheet' => sub {
-		
-		trace "stylesheet $#control $_[CONTROL] $_[ARG] $_[EVENT]" if STYLESHEET_TRACE;
-		
-		if ($_[EVENT] eq 'start') { 
-			
-			$IN_STYLESHEET = 1 ;
-			push_output('nul');
-			$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-		
-		} else {
-			
-			$IN_STYLESHEET = 0;
-			pop_output;
-		
-		}
-	},
-   
-	###########################################################   
-
-	# Stylesheet definition
-	###########################################################   
-   
-	's' => sub {
-
-		my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);
-		
-		$styledef = "$_[CONTROL]$_[ARG]";
-
-		# This looks pretty much identical to \f - only, looking at it,
-		# it probably doesn't work. My head hurts.
-
-		if ($IN_STYLESHEET) {
-
-			if ($_[EVENT] eq 'start') {
-				
-				push_output();
-				$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-	
-			} else {
-				
-				my $stylename = pop_output;
-				warn "empty stylename" and return if $stylename eq '';
-
-				if ($stylename =~ s/\s*;$//) {
-				
-					trace "$styledef => $stylename|" if STYLESHEET_TRACE;
-					$stylesheet{$styledef} = $stylename;
-					$styledef = '';
-				
-				} else {
-	
-					warn "can't analyze style name: '$stylename'";
-	
-				}
-		
-			}
-   
-   			return;
-	
-		}
-
-		$stylename = $stylesheet{"$styledef"};
- 
-		if ($cstylename ne $stylename) {
-   
-   			if (defined (my $action = $do_on_event{'style_change'})) {
-
-				($style, $newstyle) = ($cstylename, $stylename);
-				
-				&$action;
-   			
-   			} 
- 		
- 		}
- 
- 		$cstylename = $stylename;
- 		$par_props{'stylename'} = $cstylename; # the current style 
- 		trace "$styledef => $stylename" if STYLESHEET_TRACE;
-
-	},
-   
-	###########################################################   
-   
-   
-	# Tells us we're starting a row...
-	###########################################################   
-
-	'trowd' => sub {		
-
-		use constant TABLE_TRACE => 0;
-		
-		#print STDERR "=>Beginning of ROW\n";
-
-		# If we're not in a table...
-		
-		unless ($IN_TABLE) {
-
-			# Set the flag to say we now are
-
-			$IN_TABLE = 1;
-		
-			# Fire off a table even if we have one
-			
-			if (defined (my $action = $do_on_event{'table'})) {
-			
-				$event = 'start';
-				trace "table $event $text\n" if TABLE_TRACE;
-				&$action;
- 			
- 			} 
-
-			# Add lots of output holders for various things...
-			
-			push_output();		# table content
-			push_output();		# row  sequence
-			push_output();		# cell sequence
-			push_output();		# cell content
-		
-		}
-	
-	},
-
-	# Perhaps the control that opens a table? Never the less,
-	# an exact clone of the function above!
-	###########################################################   
-   
-   
-	'intbl' => sub {
-
-		$par_props{'intbl'} = 1;
-
-		unless ($IN_TABLE) {
-			
-			warn "ouverture en catastrophe" if TABLE_TRACE;
-			$IN_TABLE = 1;
-
-			if (defined (my $action = $do_on_event{'table'})) {
-
-				$event = 'start';
-				trace "table $event $text\n" if TABLE_TRACE;
-				&$action;
-
-			} 
-
-			push_output();
-			push_output();
-			push_output();
-			push_output();
-
-		}
-	
-	},
-
-	# The end of a row
-	###########################################################   
-
-
-	'row' => sub {		# row end
-		
-		# Grab the cell and the 'cell sequence'
-		
-		$text = pop_output;
-		$text = pop_output . $text;
-
-		# Fire off the 'end cell' handler if we have one
-		
-		if (defined (my $action = $do_on_event{'cell'})) {
-			
-			$event = 'end';
-			trace "row $event $text\n" if TABLE_TRACE;
-			&$action;
-
-		} 
-
-		# Grab any row text
-
-		$text = pop_output;
-
-		# Fire off the end-row event
-
-		if (defined (my $action = $do_on_event{'row'})) {
-
-			$event = 'end';
-			trace "row $event $text\n" if TABLE_TRACE;
-			&$action;
-		} 
-
-		# Prep the next row
-
-		push_output();
-		push_output();
-		push_output();
-
-	},
-   
-	###########################################################   
-
-	# End of a cell
-	###########################################################   
-   
-   
-	'cell' => sub {		# end of cell
-
-		trace "process cell content: $text\n" if TABLE_TRACE;
-		$text = pop_output;
-  
-  		# Fire the paragraph handler
-  
-		if (defined (my $action = $do_on_event{'par'})) {
-			
-			($style, $event,) = ('par', 'end',);
-			&$action;
-
-		} else {
-		
-			warn "$text";;
-
-		}
-  
-		$text = pop_output;
-
-		# Fire the end-cell handler
-
-		if (defined (my $action = $do_on_event{'cell'})) {
-			
-			$event = 'end';
-			trace "cell $event $text\n" if TABLE_TRACE;
-			&$action;
-
-		} 
-			# prepare next cell
-		push_output();
-		push_output();
-		trace "\@output_stack in table: ", @output_stack+0 if STACK_TRACE;
-
-	},
-   
-	###########################################################   
-   
-
-	# And thus the paragraph ends
-	###########################################################   
-   
-	'par' => sub {		# END OF PARAGRAPH
-
-		trace "($_[CONTROL], $_[ARG], $_[EVENT])" if STYLE_TRACE;
-  
-  		# Close a table. Add to $text, and call even handlers
-  		# for cell, row, and table, in order. 
-  
-		if ($IN_TABLE and not $par_props{'intbl'}) { # End of Table
-
-			$IN_TABLE = 0;
-			my $next_text = pop_output; # next paragraph content
-    
-			$text = pop_output;
-			$text = pop_output . "$text";
-    
-			if (defined (my $action = $do_on_event{'cell'})) { # end of cell
-			
-				$event = 'end';
-				trace "cell $event $text\n" if TABLE_TRACE;
-				&$action;
-    		
-    		} 
-    
- 			$text = pop_output;
- 
- 			if (defined (my $action = $do_on_event{'row'})) { # end of row
-
-				$event = 'end';
-				trace "row $event $text\n" if TABLE_TRACE;
-				&$action;
-			
-			} 
-
-			$text = pop_output;
-
-			if (defined (my $action = $do_on_event{'table'})) { # end of table
-
-				$event = 'end';
-				trace "table $event $text\n" if TABLE_TRACE;
-				&$action;
-
-			}
-			 
-			push_output();	       
-			trace "end of table ($next_text)\n" if TABLE_TRACE;
-			output($next_text);
-
-		} else {
-			
-			#push_output();	
-		
-		}
-		
-			# paragraph style
-		if (defined($cstylename) and $cstylename ne '') { # end of previous style
-			
-			$style = $cstylename;
-
-		} else {
-		
-			$cstylename = $style = 'par'; # no better solution
-		
-		}
-
-		$par_props{'stylename'} = $cstylename; # the current style 
-
-		if ($par_props{intbl}) {	# paragraph in tbl
-			
-			trace "process cell content: $text\n" if TABLE_TRACE;
-
-			if (defined (my $action = $do_on_event{$style})) {
-
-				($style, $event, $text) = ($style, 'end', pop_output);
-				&$action;
-
-			} elsif (defined ($action = $do_on_event{'par'})) {
-
-				#($style, $event, $text) = ('par', 'end', pop_output);
-				($style, $event, $text) = ($style, 'end', pop_output);
-				&$action;
-
-			} else {
-
-				warn;
-			
-			}
-			
-			push_output();
-			 
-  		#} elsif (defined (my $action = $do_on_event{'par_styles'})) {
-  		} elsif (defined (my $action = $do_on_event{$style})) {
-    		
-    		($style, $event, $text) = ($style, 'end', pop_output);
-    		&$action;
-    		flush_top_output();
-    		push_output();
-    		 
-		} elsif (defined ($action = $do_on_event{'par'})) {
-			
-			#($style, $event, $text) = ('par', 'end', pop_output);
-			($style, $event, $text) = ($style, 'end', pop_output);
-			&$action;
-			flush_top_output();
-			push_output(); 
-  
-  		} else {
-			
-			trace "no definition for '$style' in %do_on_event\n" if STYLE_TRACE;
-			flush_top_output();
-			push_output(); 
-  
-		}
-			# redefine this!!!
-		$cli = $par_props{'li'};
-		$styledef = '';		
-		$par_props{'bullet'} = $par_props{'number'} = $par_props{'tab'} = 0; # 
-
-	},
-				# Resets to default paragraph properties
-				# Stop inheritence of paragraph properties
-   
-   
-	'pard' => sub {		
-		
-		# !!!-> reset_par_props()
-		foreach (qw(qj qc ql qr intbl li)) {
-
-			$par_props{$_} = 0;
-		
-		}
-		
-		foreach (qw(list_item)) {
-			
-			$par_props{$_} = '';
-   
-		}
-
-	},
-
-				# ###########################
-
-	'pn' => sub {  		# Turn on PARAGRAPH NUMBERING
-		
-		#trace "($_[CONTROL], $_[ARG], $_[EVENT])" if TRACE;
-
-		if ($_[EVENT] eq 'start') {
-			
-			%pn = ();
-			$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-   
-		} else {
-
-			# I don't like this!!! redesign the parser???
- 			trace("Level: $pn{level} - Type: $pn{type} - Bullet: $pn{bullet}") if LIST_TRACE;
-			$par_props{list_item} = \%pn;
-		
-		}
-	
-	},
-	
-
-	'pnlvl' => sub {		# Paragraph level $_[ARG] is a level from 1 to 9
-		
-		$pn{level} = $_[ARG];
-
-	},
-
-	'pnlvlbody' => sub {		# Paragraph level 10
-	
-		$pn{level} = 10;	
-		
-	},
- 
-	'pnlvlblt' => sub {		# Paragraph level 11, processs the 'pntxtb' group
-		
-		$pn{level} = 11;		# bullet
-	
-	},
-	
-	'pntxtb' => sub {
-
-		if ($_[EVENT] eq 'start') { 
-		
-			push_output();
-			$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-		
-		} else {
-
-			$pn{'bullet'} = pop_output();
-		
-		}
-	
-	},
-	
-	'pntxta' => sub {
-	
-		if ($_[EVENT] eq 'start') { 
-		
-			push_output();
-			$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-
-		} else {
-			
-			pop_output();
-
-		}
-	
-	},
-				# Numbering Types
- 	'pncard' => sub {		# Cardinal numbering: One, Two, Three
- 		$pn{type} = $_[CONTROL];
-	},
- 	
- 	'pndec' => sub {		# Decimal numbering: 1, 2, 3
-   		$pn{type} = $_[CONTROL];
- 	},
- 
- 	'pnucltr' => sub {		# Uppercase alphabetic numbering
-	 	$pn{type} = $_[CONTROL];
-	 },
-	 
- 	'pnlcltr' => sub {		# Lowercase alphabetic numbering
-   		$pn{type} = $_[CONTROL];
- 	},
- 	
- 	'pnucrm' => sub {		# Uppercase roman numbering
-   		$pn{type} = $_[CONTROL];
- 	},
- 	
- 	'pnlcrm' => sub {		# Lowercase roman numbering
-   		$pn{type} = $_[CONTROL];
- 	},
-
-
-	'pntext' => sub {		# ignore text content
-		
-		if ($_[EVENT] eq 'start') { 
-		
-			push_output();
-			$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1;
-		
-		} else {
-	
-			pop_output();
-		
-		}
-		
-	},
- #'tab' => sub { $par_props{'tab'} = 1 }, # special char
-
-	'li' => sub {		# line indent - value
-
-		use constant LI_TRACE => 0;
-		my $indent = $_[ARG];
-		$indent =~ s/^-//;
-		trace "line indent: $_[ARG] -> $indent" if LI_TRACE;
-		$par_props{'li'} = $indent;
-	
-	},
-);
-###########################################################################
-		
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 use vars qw(%not_processed);
 END {
   if (@control) {
@@ -1,49 +0,0 @@
-package RTF::HTML::Converter::ansi;
-
-my @data = (<DATA>);
-chomp(@data);
-
-sub data {
-
-	return @data;
-
-}
-
-1;
-
-__DATA__
-00 ` 
-01 &acute;
-02 ^
-03 ~
-04 &shy;
-05 &shy;
-06 &deg;
-07 &uml;
-08 &middot;
-20 --
-30 _
-82 ,
-83 f
-84 ,,
-85 ...
-86 +
-87 ++
-88 ^
-89 0/00
-8a S
-8b <
-8c OE
-91 `
-92 '
-93 ``
-94 ''
-95 &middot;
-96 -
-97 --
-98 ~
-99 [tm]
-9a s
-9b >
-9c oe
-9f Y
@@ -1,197 +0,0 @@
-package RTF::HTML::Converter::charmap;
-
-my @data = (<DATA>);
-chomp(@data);
-
-sub data {
-
-	return @data;
-
-}
-
-1;
-
-__DATA__
-exclam		!
-quotedbl	"
-numbersign	#
-dollar		$
-percent		%
-ampersand	&amp;
-quoteright	'
-parenleft	(
-parenright	)
-asterisk	*
-plus		+
-comma		,
-hyphen		-
-period		.
-slash		/
-zero		0
-one		1
-two		2
-three		3
-four		4
-five		5
-six		6
-seven		7
-eight		8
-nine		9
-colon		:
-semicolon	;
-less		&lt;
-equal		=
-greater		&gt;
-question	?
-at		@
-bracketleft	[
-backslash	\
-bracketright	]
-asciicircum	^
-underscore	_
-quoteleft	`
-braceleft	{
-bar		|
-braceright	}
-asciitilde	~
-OE		OE
-acute		'
-angleleft	[
-angleright	&gt;
-approxequal	~
-arrowboth	&lt;-&gt; 
-arrowdblboth	&lt;=&gt; 
-arrowdblleft	&lt;=
-arrowdblright	=&gt;
-arrowleft	&lt;-
-arrowright	-&gt;
-bullet		*    
-cent		&#162;
-circumflex	^
-copyright	&#169;
-copyrightsans	&#169;
-dagger		+    
-degree		&#176;
-delta		d    
-divide		&#247;
-dotlessi	i    
-ellipsis	...
-emdash		--   
-endash		-    
-fi		fi   
-fl		fl   
-fraction	/
-grave		`
-greaterequal	&gt;=
-guillemotleft	&#171;
-guillemotright	&#187;
-guilsinglleft	&lt;
-guilsinglright	&gt;
-lessequal	&lt;=
-logicalnot	&#172;
-mathasterisk	*
-mathequal	=
-mathminus	-
-mathnumbersign	#
-mathplus	+
-mathtilde	~
-minus		-
-mu		&#181;
-multiply	&#215;
-nobrkhyphen	-
-nobrkspace	&#160;
-notequal	!=
-oe		oe
-onehalf		&#189;
-onequarter	&#188;
-periodcentered	.
-plusminus	&#177;
-quotedblbase	,,
-quotedblleft	"
-quotedblright	"
-quotesinglbase	,
-registered	&#174;
-registersans	&#174;
-threequarters	&#190;
-tilde		~
-trademark	[tm]
-AE		&AElig;
-Aacute      &Aacute;
-Acircumflex &Acirc;
-Agrave      &Agrave;
-Aring       &Aring;
-Atilde		&#195;
-Adieresis	&Auml;
-Ccedilla	&Ccedil;
-Eth		&#208;
-Eacute	&Eacute;
-Ecircumflex	&Ecirc;
-Egrave	&Egrave;
-Edieresis	&Euml;
-Iacute	&Iacute;
-Icircumflex	&Icirc;
-Igrave	&Igrave;
-Idieresis	&Iuml;
-Ntilde	&Ntilde;
-Oacute	&Oacute;
-Ocircumflex	&Ocirc;
-Ograve	&Ograve;
-Oslash	&Oslash;
-Otilde	&#213;
-Odieresis	&Ouml;
-Thorn	&#222;
-Uacute	&Uacute;
-Ucircumflex	&Ucirc;
-Ugrave	&Ugrave;
-Udieresis	&Uuml;
-Yacute	&#221;
-ae		&aelig;
-aacute	&aacute;
-acircumflex	&acirc;
-agrave	&agrave;
-aring	&aring;
-atilde	&atilde;
-adieresis	&auml;
-ccedilla	&ccedil;
-eacute	&eacute;
-ecircumflex	&ecirc;
-egrave	&egrave;
-eth	&#240;
-edieresis	&euml;
-iacute	&iacute;
-icircumflex	&icirc;
-igrave	&igrave;
-idieresis	&iuml;
-ntilde	&ntilde;
-oacute	&oacute;
-ocircumflex	&ocirc;
-ograve	&ograve;
-oslash	&oslash;
-otilde	&otilde;
-odieresis	&ouml;
-germandbls	&szlig;
-thorn	&#254;
-uacute	&uacute;
-ucircumflex	&ucirc;
-ugrave	&ugrave;
-udieresis	&uuml;
-yacute	&yacute;
-ydieresis	&yuml;
-newline	<br>
-ordfeminine     &#170;
-ordmasculine    &#186;
-questiondown    &#191;
-exclamdown      &#161;
-section         &#167;
-onesuperior     &#185;
-twosuperior     &#178;
-threesuperior   &#179;
-sterling        &#163;
-currency        &#164;
-yen             &#165;
-brokenbar       &#166;
-dieresis        &#168;
-opthyphen       &#173;
-macron          &#175;
-paragraph       &#182;
-cedilla         &#184;
@@ -3,9 +3,6 @@ use strict;
 package RTF::HTML::Converter;
 
 use RTF::Control;
-use RTF::HTML::Converter::ansi;
-use RTF::HTML::Converter::charmap;
-
 @RTF::HTML::Converter::ISA = qw(RTF::Control);
 
 use constant TRACE => 0;
@@ -14,87 +11,6 @@ use constant SHOW_STYLE_NOT_PROCESSED => 1;
 use constant SHOW_STYLE => 0;	# insert style name in the output
 use constant SHOW_RTF_LINE_NUMBER => 0;
 
-use constant RTF_DEBUG => 0;
-
-
-
-=head1 NAME
-
-RTF::HTML::Converter - Perl extension for converting RTF into HTML
-
-=head1 DESCRIPTION
-
-Perl extension for converting RTF into HTML
-
-=head1 SYNOPSIS
-
-	use strict;
-	use RTF::HTML::Converter;
-	
-	my $object = RTF::HTML::Converter->new(
-	
-		output => \*STDOUT
-	
-	);
-
-	$object->parse_stream( \*RTF_FILE );
-	
-OR
-
-	use strict;
-	use RTF::HTML::Converter;
-	
-	my $object = RTF::HTML::Converter->new(
-	
-		output => \$string
-	
-	);
-
-	$object->parse_string( $rtf_data );
-
-=head1 METHODS
-
-=head2 new()
-
-Constructor method. Currently takes one named parameter, C<output>,
-which can either be a reference to a filehandle, or a reference to
-a string. This is where our HTML will end up.
-
-=head2 parse_stream()
-
-Read RTF in from a filehandle, and start processing it. Pass me
-a reference to a filehandle.
-
-=head2 parse_string()
-
-Read RTF in from a string, and start processing it. Pass me a string.
-
-=head1 JUST SO YOU KNOW
-
-You can mix-and-match your output and input methods - nothing to stop
-you outputting to a string when you've read from a filehandle...
-
-=head1 AUTHOR
-
-Peter Sergeant C<rtf.parser@clueball.com>, originally by Philippe Verdret
-
-=head1 COPYRIGHT
-
-Copyright 2004 B<Pete Sergeant>.
-
-This program is free software; you can redistribute it and/or modify it under
-the same terms as Perl itself.
-
-=head1 CREDITS
-
-This work was carried out under a grant generously provided by The Perl Foundation -
-give them money!
-
-
-=cut
-
-
-
 # Symbol exported by the RTF::Ouptut module:
 # %info: informations of the {\info ...}
 # %par_props: paragraph properties
@@ -119,8 +35,6 @@ my $CURRENT_LI = 0;		# current list indent
 my @LIST_STACK = ();		# stack of opened lists
 my %LI_LEVEL = ();		# li -> list level
 
-my %charmap_defaults = map({ sprintf("%02x", $_) => "&#$_;" } (0..255));
-
 my %PAR_ALIGN = qw(
 		 qc CENTER
 		 ql LEFT
@@ -378,9 +292,6 @@ use constant GEN_TAGS_WARNS => 1;
 my @element_stack = ();		
 my %open_element = ();
 sub gen_tags {			# manage a minimal context for tag outputs
-
-	debug( 'gen_tags', @_ ) if RTF_DEBUG > 5;
-
   die "bad argument number"  unless (@_ >= 2);
   my ($eve, $tag, $att)  = @_;
 
@@ -427,13 +338,15 @@ $do_on_control{'ansi'} =	# callback redefinition
   sub {
     # RTF: \'<hex value>
     # HTML: &#<dec value>;
-    
-    my @charmap_data = $_[SELF]->charmap_reader( $_[CONTROL] );
+    my $charset = $_[CONTROL];
+    my $charset_file = $_[SELF]->application_dir() . "/$charset";
+    open CHAR_MAP, "$charset_file"
+      or die "unable to open the '$charset_file': $!";
 
     my %charset = (		# general rule
-		   %charmap_defaults,
+		   map({ sprintf("%02x", $_) => "&#$_;" } (0..255)),
 				# and some specific defs
-		   map({ s/^\s+//; split /\s+/ } @charmap_data)
+		   map({ s/^\s+//; split /\s+/ } (<CHAR_MAP>))
 		  );
     *char = sub { 
       my $char_props;
@@ -447,7 +360,6 @@ $do_on_control{'ansi'} =	# callback redefinition
     } 
   };
 
-
 				# symbol processing
 				# RTF: \~
 				# named chars
@@ -457,11 +369,7 @@ $symbol{'tab'} = ' '; #'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
 $symbol{'ldblquote'} = '&laquo;';
 $symbol{'rdblquote'} = '&raquo;';
 $symbol{'line'} = '<br>';
-sub symbol {	
-
-		debug( 'symbol', @_ ) if RTF_DEBUG > 5;
-
-		
+sub symbol {			
   my $char_props;
   if ($START_NEW_PARA) {	
     $char_props = $_[SELF]->force_char_props('start');
@@ -478,10 +386,6 @@ sub symbol {
 				# Text
 				# certainly do the same thing with the char() method
 sub text {			# parser callback redefinition
-
-	debug( 'text', @_ ) if RTF_DEBUG > 5;
-
-
   my $text = $_[1];
   my $char_props = '';
   if ($START_NEW_PARA) {	
@@ -500,13 +404,5 @@ sub text {			# parser callback redefinition
   }
 }
 
-sub debug {
-
-	my $function = shift;
-	
-	print STDERR "[RTF::HTML::Converter::$function]" . (join '|', @_ ) , "\n";
-
-}
-
 1;
 __END__
@@ -0,0 +1,35 @@
+00 ` 
+01 &acute;
+02 ^
+03 ~
+04 &shy;
+05 &shy;
+06 &deg;
+07 &uml;
+08 &middot;
+20 --
+30 _
+82 ,
+83 f
+84 ,,
+85 ...
+86 +
+87 ++
+88 ^
+89 0/00
+8a S
+8b <
+8c OE
+91 `
+92 '
+93 ``
+94 ''
+95 &middot;
+96 -
+97 --
+98 ~
+99 [tm]
+9a s
+9b >
+9c oe
+9f Y
@@ -0,0 +1,183 @@
+exclam		!
+quotedbl	"
+numbersign	#
+dollar		$
+percent		%
+ampersand	&amp;
+quoteright	'
+parenleft	(
+parenright	)
+asterisk	*
+plus		+
+comma		,
+hyphen		-
+period		.
+slash		/
+zero		0
+one		1
+two		2
+three		3
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		&lt;
+equal		=
+greater		&gt;
+question	?
+at		@
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	`
+braceleft	{
+bar		|
+braceright	}
+asciitilde	~
+OE		OE
+acute		'
+angleleft	[
+angleright	&gt;
+approxequal	~
+arrowboth	&lt;-&gt; 
+arrowdblboth	&lt;=&gt; 
+arrowdblleft	&lt;=
+arrowdblright	=&gt;
+arrowleft	&lt;-
+arrowright	-&gt;
+bullet		*    
+cent		&#162;
+circumflex	^
+copyright	&#169;
+copyrightsans	&#169;
+dagger		+    
+degree		&#176;
+delta		d    
+divide		&#247;
+dotlessi	i    
+ellipsis	...
+emdash		--   
+endash		-    
+fi		fi   
+fl		fl   
+fraction	/
+grave		`
+greaterequal	&gt;=
+guillemotleft	&#171;
+guillemotright	&#187;
+guilsinglleft	&lt;
+guilsinglright	&gt;
+lessequal	&lt;=
+logicalnot	&#172;
+mathasterisk	*
+mathequal	=
+mathminus	-
+mathnumbersign	#
+mathplus	+
+mathtilde	~
+minus		-
+mu		&#181;
+multiply	&#215;
+nobrkhyphen	-
+nobrkspace	&#160;
+notequal	!=
+oe		oe
+onehalf		&#189;
+onequarter	&#188;
+periodcentered	.
+plusminus	&#177;
+quotedblbase	,,
+quotedblleft	"
+quotedblright	"
+quotesinglbase	,
+registered	&#174;
+registersans	&#174;
+threequarters	&#190;
+tilde		~
+trademark	[tm]
+AE		&AElig;
+Aacute      &Aacute;
+Acircumflex &Acirc;
+Agrave      &Agrave;
+Aring       &Aring;
+Atilde		&#195;
+Adieresis	&Auml;
+Ccedilla	&Ccedil;
+Eth		&#208;
+Eacute	&Eacute;
+Ecircumflex	&Ecirc;
+Egrave	&Egrave;
+Edieresis	&Euml;
+Iacute	&Iacute;
+Icircumflex	&Icirc;
+Igrave	&Igrave;
+Idieresis	&Iuml;
+Ntilde	&Ntilde;
+Oacute	&Oacute;
+Ocircumflex	&Ocirc;
+Ograve	&Ograve;
+Oslash	&Oslash;
+Otilde	&#213;
+Odieresis	&Ouml;
+Thorn	&#222;
+Uacute	&Uacute;
+Ucircumflex	&Ucirc;
+Ugrave	&Ugrave;
+Udieresis	&Uuml;
+Yacute	&#221;
+ae		&aelig;
+aacute	&aacute;
+acircumflex	&acirc;
+agrave	&agrave;
+aring	&aring;
+atilde	&atilde;
+adieresis	&auml;
+ccedilla	&ccedil;
+eacute	&eacute;
+ecircumflex	&ecirc;
+egrave	&egrave;
+eth	&#240;
+edieresis	&euml;
+iacute	&iacute;
+icircumflex	&icirc;
+igrave	&igrave;
+idieresis	&iuml;
+ntilde	&ntilde;
+oacute	&oacute;
+ocircumflex	&ocirc;
+ograve	&ograve;
+oslash	&oslash;
+otilde	&otilde;
+odieresis	&ouml;
+germandbls	&szlig;
+thorn	&#254;
+uacute	&uacute;
+ucircumflex	&ucirc;
+ugrave	&ugrave;
+udieresis	&uuml;
+yacute	&yacute;
+ydieresis	&yuml;
+newline	<br>
+ordfeminine     &#170;
+ordmasculine    &#186;
+questiondown    &#191;
+exclamdown      &#161;
+section         &#167;
+onesuperior     &#185;
+twosuperior     &#178;
+threesuperior   &#179;
+sterling        &#163;
+currency        &#164;
+yen             &#165;
+brokenbar       &#166;
+dieresis        &#168;
+opthyphen       &#173;
+macron          &#175;
+paragraph       &#182;
+cedilla         &#184;
@@ -1,638 +1,317 @@
-
-# This is a beta release. A lot of this code is hacked to be backwards
-# compatible. You have been warned.
-
-=head1 NAME
-
-RTF::Parser - An event-driven RTF Parser
-
-=head1 DESCRIPTION
-
-An event-driven RTF Parser
-
-=head1 PUBLIC SERVICE ANNOUNCEMENT
-
-This is the third and final (I hope) beta release of RTF::Parser before I
-release a 'production' version (hopefully around Feb 1st 04). I took over
-RTF::Parser from Phillipe Verdret, in a state where it had no documentation.
-I've been working since then on refactoring parts of it, writing tests and
-documentation, but this is still a work in progress. Please bear with me,
-ignore the gaping ommission of tests and documentation for RTF::Control,
-and send me bug reports and suggestions.
-
-=head1 IMPORTANT HINTS
-
-RTF parsing is non-trivial. The inner workings of these modules are somewhat
-scary. You should go and read the 'Introduction' document included with this
-distribution before going any further - it explains how this distribution fits
-together, and is B<vital> reading.
-
-If you just want to convert RTF to HTML or text, from inside your own script,
-jump straight to the docs for L<RTF::HTML::Converter> or L<RTF::TEXT::Converter>
-respectively.
-
-=head1 SUBCLASSING RTF::PARSER
-
-When you subclass RTF::Parser, you'll want to do two things. You'll firstly
-want to overwrite the methods below described as the API. This describes what
-we do when we have tokens that aren't control words (except 'symbols' - see below).
-
-Then you'll want to create a hash that maps control words to code references
-that you want executed. They'll get passed a copy of the RTF::Parser object,
-the name of the control word (say, 'b'), any arguments passed with the control
-word, and then 'start'.
-
-=head2 An example...
-
-The following code removes bold tags from RTF documents, and then spits back
-out RTF.
-
-  {
-  
-    # Create our subclass
-      
-      package UnboldRTF;
-
-    # We'll be doing lots of printing without newlines, so don't buffer output
-
-      $|++;
-
-    # Subclassing magic...
-    
-      use RTF::Parser;
-      @UnboldRTF::ISA = ( 'RTF::Parser' );
-                        
-    # Redefine the API nicely
-        
-      sub parse_start { print STDERR "Starting...\n"; }
-      sub group_start { print '{' }
-      sub group_end   { print '}' }
-      sub text        { print "\n" . $_[1] }
-      sub char        { print "\\\'$_[1]" }
-      sub symbol      { print "\\$_[1]" }
-      sub parse_end   { print STDERR "All done...\n"; }
-
-  }
-
-  my %do_on_control = (
-
-	# What to do when we see any control we don't have
-	#   a specific action for... In this case, we print it.
-
-    '__DEFAULT__' => sub {
-
-      my ( $self, $type, $arg ) = @_;
-      $arg = "\n" unless defined $arg;
-      print "\\$type$arg";
-
-     },
-     
-   # When we come across a bold tag, we just ignore it.
-     
-     'b' => sub {},
-
-  );
-
-  # Grab STDIN...
-
-    my $data = join '', (<>);
-
-  # Create an instance of the class we created above
-
-    my $parser = UnboldRTF->new();
-
-  # Prime the object with our control handlers...
- 
-    $parser->control_definition( \%do_on_control );
-  
-  # Don't skip undefined destinations...
-  
-    $parser->dont_skip_destinations(1);
-
-  # Start the parsing!
-
-    $parser->parse_string( $data );
-
-=head1 METHODS
-
-=cut
+# Sonovision-Itep, Philippe Verdret 1998-1999
+# An event-driven RTF parser
 
 require 5.004;
+use strict;
 package RTF::Parser;
-use vars qw($VERSION);
 
-use strict;
-use Carp;
-use RTF::Tokenizer 1.01;
+$RTF::Parser::VERSION = "1.07";
 use RTF::Config;
+use File::Basename;
 
-$VERSION = '1.09';
-my $DEBUG = 0;
-
-# Debugging stuff I'm leaving in in case someone is using it..,
-	use constant PARSER_TRACE => 0;
-	
-	sub backtrace { 
-  		Carp::confess;			
-	}
-
-	$SIG{'INT'} = \&backtrace if PARSER_TRACE;
-	$SIG{__DIE__} = \&backtrace if PARSER_TRACE;
-
-
-=head2 new
-
-Creates a new RTF::Parser object. Doesn't accept any arguments.
-
-=cut
-
-sub new {
-
-	# Get the real class name
-	my $proto = shift;
-	my $class = ref( $proto ) || $proto;
-	
-	my $self = {};
-	
-	$self->{_RTF_CONTROL_USED}++ if $INC{'RTF/Control.pm'};
-
-	$self->{_DONT_SKIP_DESTINATIONS} = 0;
-	
-	bless $self, $class;
-
-	return $self;
-
+use constant PARSER_TRACE => 0;
+sub backtrace { 
+  require Carp;
+  Carp::confess;			
 }
+$SIG{'INT'} = \&backtrace if PARSER_TRACE;
+$SIG{__DIE__} = \&backtrace if PARSER_TRACE;
+ 
+# Parser::Generic
+sub parse_stream {
+  my $self = shift;
+  my $stream = shift;
+  my $reader = shift;		# eg: parse_stream(\*FH, \&read)
+  my $buffer = '';
 
-# For backwards compatability, we import RTF::Control's %do_on_control
-# if we've loaded RTF::Control (which would suggest we're being subclassed
-# by RTF::Control). This isn't nice or pretty, but it doesn't break things.
-# I'd do this in new() but there's no guarentee it'll be set by then...
-
-sub _install_do_on_control {
-
-	my $self = shift;
-	
-	return if $self->{_DO_ON_CONTROL};
-	
-	if ( $self->{_RTF_CONTROL_USED} ) {
-	
-		$self->{_DO_ON_CONTROL} = \%RTF::Control::do_on_control;
-	
+  unless (defined $stream) {
+    die "file not defined";
+  }
+  $self->{Filename} = '';
+  local(*F) = $stream;
+  unless (fileno F) {
+    $self->{Filename} = $stream;     # Assume $stream is a filename
+    open(F, $stream) or die "Can't open '$stream' ($!)";
+  }
+  binmode(F);
+  $self->{Filehandle} = \*F;
+  $self->{Eof} = 0;
+  $self->{Buffer} = \$buffer;
+  $self->{If_data_needed} = ref $reader eq 'SUB' ? 
+    $reader :
+      sub {			# The default reader
+	if ($buffer .= <F>) {
+	  1;
 	} else {
-	
-		$self->{_DO_ON_CONTROL} = {};
-	
+	  $self->{Eof} = 1;
+	  0;
 	}
-
+      };
+  local *if_data_needed = $self->{If_data_needed};
+				# Now parse the stream
+  $self->if_data_needed() or die "unexpected end of data";
+  $self->parse();
+  close(F) if $self->{Filename} ne '';
+  $self;
 }
-
-=head2 parse_stream( \*FH )
-
-This function used to accept a second parameter - a function specifying how
-the filehandle should be read. This is deprecated, because I could find no
-examples of people using it, nor could I see why people might want to use it.
-
-Pass this function a reference to a filehandle (or, now, a filename! yay) to
-begin reading and processing.
-
-=cut
-
-sub parse_stream {
-
-	my $self = shift;
-	my $stream = shift;
-	my $reader = shift;
-	
-	$self->_install_do_on_control();
-	
-	die("parse_stream no longer accepts a reader") if $reader;
-
-	# Put an appropriately primed RTF::Tokenizer object into our object
-	$self->{_TOKENIZER} = RTF::Tokenizer->new( file => $stream ); 
-
-	$self->_parse();
-	
-	return $self;
-
-}
-
-=head2 parse_string( $string )
-
-Pass this function a string to begin reading and processing.
-
-=cut
-
 sub parse_string {
- 
-	my $self = shift;
-	my $string = shift;
-
-	$self->_install_do_on_control();
-
-	# Put an appropriately primed RTF::Tokenizer object into our object
-	$self->{_TOKENIZER} = RTF::Tokenizer->new( string => $string ); 
-
-	$self->_parse();
-	
-	return $self;
-
+  my $self = shift;
+  my $buffer = $_[0];
+  $self->{Filehandle} = '';
+  $self->{Filename} = '';
+  $self->{Eof} = 0;
+  $self->{If_data_needed} = sub { 0 };
+  local *if_data_needed = $self->{If_data_needed};
+  $self->{Buffer} = \$buffer;
+  $self->parse();
+  $self;
 }
-
-=head2 control_definition
-
-The code that's executed when we trigger a control event is kept
-in a hash. We're holding this somewhere in our object. Earlier 
-versions would make the assumption we're being subclassed by
-RTF::Control, which isn't something I want to assume. If you are
-using RTF::Control, you don't need to worry about this, because
-we're grabbing %RTF::Control::do_on_control, and using that.
-
-Otherwise, you pass this method a reference to a hash where the keys
-are control words, and the values are coderefs that you want executed.
-This sets all the callbacks... The arguments passed to your coderefs
-are: $self, control word itself (like, say, 'par'), any parameter the
-control word had, and then 'start'.
-
-If you don't pass it a reference, you get back the reference of the
-current control hash we're holding.
-
-=cut
-
-sub control_definition {
-
-	my $self = shift;
-
-	if (@_) {
-    
-    	if (ref $_[0] eq 'HASH') {
-    	
-      		$self->{_DO_ON_CONTROL} = shift;
-      		
-    	} else {
-
-      		die "argument of control_definition() method must be an HASHREF";
-
- 		}
-  
-  	} else {
-    			
-    	return $self->{_DO_ON_CONTROL};
-  
-  	}
-
+sub new {
+  my $receiver = shift;		# or something like this
+  my $class = (ref $receiver or $receiver);
+  my $self = bless {
+		    Buffer => '', # internal buffer
+		    Eof => 0,	# 1 if EOF, not used
+		    EOR => '',	# end of record regex
+		    Filename => '', # filename
+		    Filehandle => '',	#
+		    Line => 0,	# not used
+		   }, $class;
+  $self;
 }
 
-=head2 rtf_control_emulation
-
-If you pass it a boolean argument, it'll set whether or not it thinks RTF::Control
-has been loaded. If you don't pass it an argument, it'll return what it thinks...
-
-=cut
-
-sub rtf_control_emulation {
-
-	my $self = shift;
-	my $bool = shift;
-	
-	if ( defined $bool ) {
-
-		$self->{_RTF_CONTROL_USED} = $bool;
-	
-	} else {
-	
-		return $self->{_RTF_CONTROL_USED};
-	
-	}
+sub line { $_[1] ? $_[0]->{Line} = $_[1] : $_[0]->{Line} } 
+sub filename { $_[1] ? $_[0]->{Filename} = $_[1] : $_[0]->{Filename} } 
+sub buffer { $_[1] ? $_[0]->{Buffer} = $_[1] : $_[0]->{Buffer} } 
+sub eof { $_[1] ? $_[0]->{Eof} = $_[1] : $_[0]->{Eof} } 
+sub eor { $_[1] ? $_[0]->{EOR} = $_[1] : $_[0]->{EOR} } 
 
+sub error {			# not used
+  my($self, $message) = @_;
+  my $atline = $.;
+  my $infile = $self->{Filename};
 }
-
-=head2 dont_skip_destinations
-
-The RTF spec says that we skip any destinations that we don't have an explicit
-handler for. You could well not want this. Accepts a boolean argument, true
-to process destinations, 0 to skip the ones we don't understand.
-
-=cut
-
-sub dont_skip_destinations {
-
-	my $self = shift;
-	my $bool = shift;
-
-	$self->{_DONT_SKIP_DESTINATIONS} = $bool;
-
+#################################################################################
+# interface must change if you want to write: $self->$1($1, $2);
+# $self->$control($control, $arg, 'start');
+# I'll certainly redefine this in a next release
+my $DO_ON_CONTROL = \%RTF::Control::do_on_control; # default
+sub control_definition {
+  my $self = shift;
+  if (@_) {
+    if (ref $_[0]) {
+      $DO_ON_CONTROL = shift;
+    } else {
+      die "argument of control_definition() method must be an HASHREF";
+    }
+  } else {
+    $DO_ON_CONTROL;
+  }
 }
-
-
-# This is how he decided to call control actions. Leaving
-#   it to do the right thing at the moment... Users of the
-#	module don't need to know our dirty little secret...
-
-{
-	package RTF::Action;		
- 	use RTF::Config;
-
-	use vars qw($AUTOLOAD);
-	
-	my $default;
-	
-	# The original RTF::Parser allowed $LOGFILE to be set
-	# that made RTF::Config do fun things. We're allowing it
-	# to, but wrapping it up a bit more carefully...
-	if ( $LOG_FILE ) {
-	
-		$default = sub { $RTF::Control::not_processed{$_[1]}++ }
-	
-	}
-      		
-  	my $sub;
-
-	sub AUTOLOAD {
-    
-    	my $self = $_[0];
-    
-    	$AUTOLOAD =~ s/^.*:://;	
-    	    
-    	no strict 'refs';
-    	
-    	if (defined ($sub = $self->{_DO_ON_CONTROL}->{$AUTOLOAD})) {
-     
-     		# Yuck, empty if. But we're just going to leave it for a while
-     
-			} else {
-			
-				if ( $default ) {
-			
-					$sub = $default 
-			
-				} elsif ( $self->{_DO_ON_CONTROL}->{'__DEFAULT__'} ) {
-
-					$sub = $self->{_DO_ON_CONTROL}->{'__DEFAULT__'};
-			
-				} else {
-			
-					$sub = sub {};
-			
-				}
-    
-    	}
-    	
-    	# I don't understand why he's using goto here...
-    	*$AUTOLOAD = $sub; 
-    	goto &$sub; 
-  
+{ package RTF::Action;		
+  use RTF::Config;
+
+  use vars qw($AUTOLOAD);
+  my $default = $LOG_FILE ?	# or define a __DEFAULT__ action in %do_on_control
+    sub { $RTF::Control::not_processed{$_[1]}++ } : 
+      sub {};
+  my $sub;
+
+  sub AUTOLOAD {
+    #my $self = $_[0];
+    #print STDERR "definition of the '$AUTOLOAD' sub\n";
+
+    $AUTOLOAD =~ s/^.*:://;	
+    no strict 'refs';
+    if (defined ($sub = $DO_ON_CONTROL->{"$AUTOLOAD"})) {
+      # Generate on the fly a new method and call it
+      #*{"$AUTOLOAD"} = $sub; &{"$AUTOLOAD"}(@_); 
+      # in the OOP style: *{"$AUTOLOAD"} = $sub; $self->$AUTOLOAD(@_);
+      #goto &{*{"$AUTOLOAD"} = $sub}; 
+    } else {
+      #goto &{*{"$AUTOLOAD"} = $default};	
+      $sub = $default;
+    }
+    *$AUTOLOAD = $sub; 
+    goto &$sub; 
   }
-  
 }
-
-
-
-=head1 API
-
-These are some methods that you're going to want to over-ride if you
-subclass this modules. In general though, people seem to want to subclass
-RTF::Control, which subclasses this module.
-
-=head2 parse_start
-
-Called before we start parsing...
-
-=head2 parse_end
-
-Called when we're finished parsing
-
-=head2 group_start
-
-Called when we encounter an opening {
-
-=head2 group_end
-
-Called when we encounter a closing }
-
-=head2 text
-
-Called when we encounter plain-text. Is given the text as its
-first argument
-
-=head2 char
-
-Called when we encounter a hex-escaped character. The hex characters
-are passed as the first argument.
-
-=head2 symbol
-
-Called when we come across a control character. This is interesting, because,
-I'd have treated these as control words, so, I'm using Philippe's list as control
-words that'll trigger this for you. These are C<-_~:|{}*'\>. This needs to be
-tested.
-
-=head2 bitmap
-
-Called when we come across a command that's talking about a linked bitmap
-file. You're given the file name.
-
-=head2 binary
-
-Called when we have binary data. You get passed it.
-
-=cut
-
+sub DESTROY {}
+#################################################################################
+				# parser's API
 sub parse_start {}
 sub parse_end {}
 sub group_start {}
 sub group_end {}
 sub text {}
 sub char {}
-sub symbol {} # -_~:|{}*'\ 
-sub bitmap {} # \{bm(?:[clr]|cwd)
+sub symbol {}
+sub bitmap {}
 sub binary {}			
 
-# This is the big, bad parse routine that isn't called directly.
-# We loop around RTF::Tokenizer, making event calls when we need to.
-
-	sub _parse {
-	
-		# Read in our object
- 			my $self = shift;
- 			
- 		# Execute any pre-parse subroutines
- 			$self->parse_start();
- 			
- 		# Loop until we find the EOF
- 			while (1) {
- 			
- 				# Read in our initial token
- 					my ( $token_type, $token_argument, $token_parameter)
- 						= $self->{_TOKENIZER}->get_token();
- 						
- 				# Control words
- 					if ( $token_type eq 'control' ) {
- 				
- 						# We have a special handler for control words
- 							$self->_control( $token_argument, $token_parameter );
- 				
- 				# Plain text
- 					} elsif ( $token_type eq 'text' ) {
- 					
- 						# Send it to the text() routine
- 							$self->text( $token_argument );
- 				
- 				# Groups
- 					} elsif ( $token_type eq 'group' ) {
- 				
- 						# Call the appropriate handler
- 							$token_argument ?
- 								$self->group_start :
- 								$self->group_end;	
- 				
- 				# EOF
- 					} else {
- 			
- 						last;	
- 					
- 					}	
-	
- 			}
- 			
- 		# All done
- 			$self->parse_end();
- 			$self;
- 	
-	}
-	
-# Control word handler (yeuch)
-#	purl, be RTF barbie is <reply>Control words are *HARD*!
-	sub _control {
-	
-		my $self = shift;
-		my $type = shift;
-		my $arg  = shift;
-	
-		#  standard, control_symbols, hex
-		
-		# Funky destination
-			if ( $type eq '*' ) {
-	
-				# We might actually want to process it...
-				if ( $self->{_DONT_SKIP_DESTINATIONS} ) {
+#################################################################################
+				# Parser
+# RTF Specification
+# The delimiter marks the end of the RTF control word, and can
+# be one of the following:
+# 1. a space. In this case, the space is part of the control word
+# 2. a digit or an hyphen, ...
+# 3. any character other than a letter or a digit
+# 
+my $CONTROL_WORD = '[a-z]{1,32}'; # or '[a-z]+';
+my $CONTROL_ARG = '(?:\d+|-\d+)'; # argument of control words, or: '-?\d+';
+my $END_OF_CONTROL = '(?:[ ]|(?=[^a-z0-9]))'; 
+my $CONTROL_SYMBOLS = q![-_~:|{}*\'\\\\]!; # Symbols (Special characters)
+my $DESTINATION = '[*]';	
+				# Another possibility: (?:[^\\\\{}]+|\\\\.)+
+				# the following accepts the null string:
+my $DESTINATION_CONTENT = '[^\\\\{}]*(?:\\\\.[^\\\\{}]*)*'; 
+my $HEXA = q![0-9abcdef][0-9abcdef]!;
+my $PLAINTEXT = '[^{}\\\\\n\r]+'; 
+my $BITMAP_START = '\\\\{bm(?:[clr]|cwd) '; # Ex.: \{bmcwd 
+my $BITMAP_END = q!\\\\}!;
+my $BITMAP_FILE = '(?:[^\\\\{}]+|\\\\[^{}])+'; 
+
+sub parse {
+  my $self = shift;
+  my $buffer = $self->{Buffer};
+  my $guard = 0;
+
+  unless ($self->{EOR}) {       # auto-determination
+				# or if call from parse_file() 
+				# read one line and use /\cM$/
+    $self->{EOR} = ($$buffer =~ /\cM/ ? q!\r\n! : q!\n!);
+  }
 
-					$self->_control_execute( '*' );
-				
-				} else {
-	
-				# Grab the next token
- 					my ( $token_type, $token_argument, $token_parameter)
- 						= $self->{_TOKENIZER}->get_token();
- 				
- 				# Basic sanity check
- 					croak('Malformed RTF - \* not followed by a control...')
- 						unless $token_type eq 'control';
- 						
- 				# Do we have a handler for it?
-					if ( defined $self->{_DO_ON_CONTROL}->{$token_argument} ) {
-						$self->_control_execute( $token_argument, $token_parameter )
-					} else {
-						$self->_skip_group();
-						$self->group_end();
-					}
-				}
-						
-		# Binary data
-			} elsif ( $type eq 'bin' ) {
-			
-				# Grab the next token
- 					my ( $token_type, $token_argument, $token_parameter)
- 						= $self->{_TOKENIZER}->get_token();
- 				 
- 				# Basic sanity check
- 					croak('Malformed RTF - \bin not followed by text...')
- 						unless $token_type eq 'text';
- 						
- 				# Send it to the handler
- 					$self->binary( $token_argument );		
- 		
- 		# Implement a bitmap handler here
- 		
- 		# Control symbols
- 			} elsif ( $type =~ m/[-_~:|{}*\\]/ ) {
- 			
- 				# Send it to the handler
- 					$self->symbol( $type );					
-			
-		# Entity
-			} elsif ( $type eq "'" ) {
-			
-				# Entity handler
-					$self->char( $arg );
-		
-		# Some other control type - give it to the control executer
-			} else {
-			
-				# Pass it to our default executer
-					$self->_control_execute( $type, $arg )
-			
-			}
-	
-	
-	}
-	
-# Control word executer (this is nasty)
-	sub _control_execute {
-	
-	
-		my $self = shift;
-		my $type = shift;
-		my $arg  = shift;
-	
-		no strict 'refs';		
-    	&{"RTF::Action::$type"}($self, $type, $arg, 'start');
-	
+  $self->parse_start();		# Action before parsing
+  while (1) {
+    $$buffer =~ s/^\\($CONTROL_WORD)($CONTROL_ARG)?$END_OF_CONTROL//o and do {
+      my ($control, $arg) = ($1, $2);
+      no strict 'refs';		
+      &{"RTF::Action::$control"}($self, $control, $arg, 'start');
+      next;
+    };
+    $$buffer =~ s/^($PLAINTEXT)//o and do {
+      $self->text($1);
+      next;
+    };
+    $$buffer =~ s/^\{\\$DESTINATION\\(($CONTROL_WORD)($CONTROL_ARG)?)$END_OF_CONTROL//o and do { 
+      # RTF Specification: "discard all text up to and including the closing brace"
+      # Example:  {\*\controlWord ... }
+      # '\*' is an escaping mechanism
+
+      if (defined $DO_ON_CONTROL->{$2}) { # if it's a registered control then don't skip
+	$$buffer = "\{\\$1" . $$buffer;
+      } else {			# skip!
+	my $level = 1;
+	my($control, $arg) = ($2, $3);
+	my $content = "\{\\*\\$1";
+	$self->{Start} = $.;		# could be used by the error() method
+	while (1) {
+	  $$buffer =~ s/^\{// and do {
+	    $content .= "\{";
+	    ++$level;
+	    next;
+	  };
+	  $$buffer =~ s/^\}// and do { # 
+	    $content .= "\}";
+	    --$level > 0 ? next : last;
+	  };
+	  $$buffer =~ s/^($DESTINATION_CONTENT)//o and do {
+	    if ($1 ne '') {
+	      $content .= $1;
+	      next;
+	    }
+	  };
+	  if ($$buffer eq '') {
+	    $self->if_data_needed() 
+	      or die "unexpected end of data: unable to find end of destination"; 
+	  } else {
+	    die "unable to analyze '$$buffer' in destination";
+	  }
 	}
-
-# Skip a group
-	sub _skip_group {
-	
-		my $self = shift;
-	
-		my $level_counter = 1;
-		
-		while ( $level_counter ) {
-		
-			# Get a token
-				my ( $token_type, $token_argument, $token_parameter)
- 					= $self->{_TOKENIZER}->get_token();
-		
-			# Make sure we can't loop forever
-				last if $token_type eq 'eof';
-				
-			# We're in business if it's a group
-				if ($token_type eq 'group') {
-				
-					$token_argument ?
-						$level_counter++ :
-						$level_counter-- ;
-				
-				}
-		
-		}
-	
+	no strict 'refs';		
+	&{"RTF::Action::*$control"}($self, '*' . "$control", $arg, $content);
+      }
+      next;
+    };
+    $$buffer =~ s/^\{(?!\\[*])// and do { # can't be a destination
+      $self->group_start();
+      next;
+    };
+    $$buffer =~ s/^\}// and do {		# 
+      $self->group_end();
+      next;
+    };
+    $$buffer =~ s/^$BITMAP_START//o and do { # bitmap filename
+      my $filename;
+      do {
+	$$buffer =~ s/^($BITMAP_FILE)//o;
+	$filename .= $1;
+	
+	if ($$buffer eq '') {
+	  $self->if_data_needed()  or die "unexpected end of data"; 
 	}
 
+      } until ($$buffer =~ s/^$BITMAP_END//o);
+      $self->bitmap($filename);
+      next;
+    };
+    $$buffer =~ s/^\\\'($HEXA)//o and do {
+      $self->char($1);	
+      next;
+    };
+    $$buffer =~ s/^\\($CONTROL_SYMBOLS)//o and do {
+      $self->symbol($1);
+      next;
+    };
+    $$buffer =~ s/^$self->{EOR}$//o;     # End of line
+    $self->if_data_needed() and next;
+    # can't goes there, except one time at EOF
+    last if $guard++ > 0;	
+  }
+				# could be in parse_end()
+  if ($$buffer ne '') {  
+    my $data = substr($$buffer, 0, 100);
+    die "unanalized data: '$data ...' at line $. file $self->{Filename}\n";  
+  }
+				# 
+  $self->parse_end();		# Action after
+  $self;
+}
+sub read {			# by line
+  my $self = $_[0];
+  my $FH = $self->{Filehandle};
+  if (${$self->{Buffer}} .= <$FH>) {
+    1;
+  } else {
+    $self->{Eof} = 1;
+    0;
+  }
+}
+use constant READ_BIN => 0;
+sub read_bin {
+  my $self = shift;
+  my $length = shift;
+  print STDERR "need to read $length chars\n" if READ_BIN;
+  my $bufref = $self->{Buffer};
+  my $fh = $self->{Filehandle};
+  my $binary = $$bufref . $self->{Strimmed};
+  my $toread = $length - length($binary);
+  print STDERR "data to read: $toread\n" if READ_BIN;
+  if ($toread > 0) {
+    my $n = CORE::read($fh, $binary, $toread, length($binary));
+    print STDERR "binary data: $n chars\n" if READ_BIN;
+    unless ($toread == $n) {
+      die "unable to read binary data\n";
+    }
+  } else {
+    $binary = substr($$bufref, 0, $length);
+    substr($$bufref, 0, $length) = '';
+  }
+  $self->binary($binary);	# and call the binary() method
+}
 1;
+__END__
 
-=head1 AUTHOR
-
-Peter Sergeant C<rtf.parser@clueball.com>, originally by Philippe Verdret
-
-=head1 COPYRIGHT
-
-Copyright 2004 B<Pete Sergeant>.
-
-This program is free software; you can redistribute it and/or modify it under
-the same terms as Perl itself.
-
-=head1 CREDITS
 
-This work was carried out under a grant generously provided by The Perl Foundation -
-give them money!
@@ -1,49 +0,0 @@
-package RTF::TEXT::Converter::ansi;
-
-my @data = (<DATA>);
-chomp(@data);
-
-sub data {
-
-	return @data;
-
-}
-
-1;
-
-__DATA__
-00 ` 
-01 &acute;
-02 ^
-03 ~
-04 &shy;
-05 &shy;
-06 &deg;
-07 &uml;
-08 &middot;
-20 --
-30 _
-82 ,
-83 f
-84 ,,
-85 ...
-86 +
-87 ++
-88 ^
-89 0/00
-8a S
-8b <
-8c OE
-91 `
-92 '
-93 ``
-94 ''
-95 &middot;
-96 -
-97 --
-98 ~
-99 [tm]
-9a s
-9b >
-9c oe
-9f Y
@@ -1,197 +0,0 @@
-package RTF::TEXT::Converter::charmap;
-
-my @data = (<DATA>);
-chomp(@data);
-
-sub data {
-
-	return @data;
-
-}
-
-1;
-
-__DATA__
-exclam		!
-quotedbl	"
-numbersign	#
-dollar		$
-percent		%
-ampersand	&amp;
-quoteright	'
-parenleft	(
-parenright	)
-asterisk	*
-plus		+
-comma		,
-hyphen		-
-period		.
-slash		/
-zero		0
-one		1
-two		2
-three		3
-four		4
-five		5
-six		6
-seven		7
-eight		8
-nine		9
-colon		:
-semicolon	;
-less		&lt;
-equal		=
-greater		&gt;
-question	?
-at		@
-bracketleft	[
-backslash	\
-bracketright	]
-asciicircum	^
-underscore	_
-quoteleft	`
-braceleft	{
-bar		|
-braceright	}
-asciitilde	~
-OE		OE
-acute		'
-angleleft	[
-angleright	&gt;
-approxequal	~
-arrowboth	&lt;-&gt; 
-arrowdblboth	&lt;=&gt; 
-arrowdblleft	&lt;=
-arrowdblright	=&gt;
-arrowleft	&lt;-
-arrowright	-&gt;
-bullet		*    
-cent		&#162;
-circumflex	^
-copyright	&#169;
-copyrightsans	&#169;
-dagger		+    
-degree		&#176;
-delta		d    
-divide		&#247;
-dotlessi	i    
-ellipsis	...
-emdash		--   
-endash		-    
-fi		fi   
-fl		fl   
-fraction	/
-grave		`
-greaterequal	&gt;=
-guillemotleft	&#171;
-guillemotright	&#187;
-guilsinglleft	&lt;
-guilsinglright	&gt;
-lessequal	&lt;=
-logicalnot	&#172;
-mathasterisk	*
-mathequal	=
-mathminus	-
-mathnumbersign	#
-mathplus	+
-mathtilde	~
-minus		-
-mu		&#181;
-multiply	&#215;
-nobrkhyphen	-
-nobrkspace	&#160;
-notequal	!=
-oe		oe
-onehalf		&#189;
-onequarter	&#188;
-periodcentered	.
-plusminus	&#177;
-quotedblbase	,,
-quotedblleft	"
-quotedblright	"
-quotesinglbase	,
-registered	&#174;
-registersans	&#174;
-threequarters	&#190;
-tilde		~
-trademark	[tm]
-AE		&AElig;
-Aacute      &Aacute;
-Acircumflex &Acirc;
-Agrave      &Agrave;
-Aring       &Aring;
-Atilde		&#195;
-Adieresis	&Auml;
-Ccedilla	&Ccedil;
-Eth		&#208;
-Eacute	&Eacute;
-Ecircumflex	&Ecirc;
-Egrave	&Egrave;
-Edieresis	&Euml;
-Iacute	&Iacute;
-Icircumflex	&Icirc;
-Igrave	&Igrave;
-Idieresis	&Iuml;
-Ntilde	&Ntilde;
-Oacute	&Oacute;
-Ocircumflex	&Ocirc;
-Ograve	&Ograve;
-Oslash	&Oslash;
-Otilde	&#213;
-Odieresis	&Ouml;
-Thorn	&#222;
-Uacute	&Uacute;
-Ucircumflex	&Ucirc;
-Ugrave	&Ugrave;
-Udieresis	&Uuml;
-Yacute	&#221;
-ae		&aelig;
-aacute	&aacute;
-acircumflex	&acirc;
-agrave	&agrave;
-aring	&aring;
-atilde	&atilde;
-adieresis	&auml;
-ccedilla	&ccedil;
-eacute	&eacute;
-ecircumflex	&ecirc;
-egrave	&egrave;
-eth	&#240;
-edieresis	&euml;
-iacute	&iacute;
-icircumflex	&icirc;
-igrave	&igrave;
-idieresis	&iuml;
-ntilde	&ntilde;
-oacute	&oacute;
-ocircumflex	&ocirc;
-ograve	&ograve;
-oslash	&oslash;
-otilde	&otilde;
-odieresis	&ouml;
-germandbls	&szlig;
-thorn	&#254;
-uacute	&uacute;
-ucircumflex	&ucirc;
-ugrave	&ugrave;
-udieresis	&uuml;
-yacute	&yacute;
-ydieresis	&yuml;
-newline	<br>
-ordfeminine     &#170;
-ordmasculine    &#186;
-questiondown    &#191;
-exclamdown      &#161;
-section         &#167;
-onesuperior     &#185;
-twosuperior     &#178;
-threesuperior   &#179;
-sterling        &#163;
-currency        &#164;
-yen             &#165;
-brokenbar       &#166;
-dieresis        &#168;
-opthyphen       &#173;
-macron          &#175;
-paragraph       &#182;
-cedilla         &#184;
@@ -3,95 +3,12 @@ use strict;
 package RTF::TEXT::Converter;
 
 use RTF::Control;
-use RTF::TEXT::Converter::ansi;
-use RTF::TEXT::Converter::charmap;
-
 @RTF::TEXT::Converter::ISA = qw(RTF::Control);
 
 use constant TRACE => 0;
 use constant LIST_TRACE => 0;
 use constant SHOW_RTF_LINE_NUMBER => 0;
 
-
-
-=head1 NAME
-
-RTF::TEXT::Converter - Perl extension for converting RTF into text
-
-=head1 DESCRIPTION
-
-Perl extension for converting RTF into text
-
-=head1 SYNOPSIS
-
-	use strict;
-	use RTF::TEXT::Converter;
-	
-	my $object = RTF::TEXT::Converter->new(
-	
-		output => \*STDOUT
-	
-	);
-
-	$object->parse_stream( \*RTF_FILE );
-	
-OR
-
-	use strict;
-	use RTF::TEXT::Converter;
-	
-	my $object = RTF::TEXT::Converter->new(
-	
-		output => \$string
-	
-	);
-
-	$object->parse_string( $rtf_data );
-
-=head1 METHODS
-
-=head2 new()
-
-Constructor method. Currently takes one named parameter, C<output>,
-which can either be a reference to a filehandle, or a reference to
-a string. This is where our text output will end up.
-
-=head2 parse_stream()
-
-Read RTF in from a filehandle, and start processing it. Pass me
-a reference to a filehandle.
-
-=head2 parse_string()
-
-Read RTF in from a string, and start processing it. Pass me a string.
-
-=head1 JUST SO YOU KNOW
-
-You can mix-and-match your output and input methods - nothing to stop
-you outputting to a string when you've read from a filehandle...
-
-=head1 AUTHOR
-
-Peter Sergeant C<rtf.parser@clueball.com>, originally by Philippe Verdret
-
-=head1 COPYRIGHT
-
-Copyright 2004 B<Pete Sergeant>.
-
-This program is free software; you can redistribute it and/or modify it under
-the same terms as Perl itself.
-
-=head1 CREDITS
-
-This work was carried out under a grant generously provided by The Perl Foundation -
-give them money!
-
-
-=cut
-
-
-
-
 # Symbol exported by the RTF::Ouptut module:
 # %info: informations of the {\info ...}
 # %par_props: paragraph properties
@@ -106,8 +23,6 @@ give them money!
 ###########################################################################
 my $N = "\n"; # Pretty-printing
 
-my %charmap_defaults = map({ sprintf("%02x", $_) => chr($_) } (0..255));
-
 				# you can split on sentences here if you want!!!
 				# some output parameters
 %do_on_event = 
@@ -136,7 +51,7 @@ my %charmap_defaults = map({ sprintf("%02x", $_) => chr($_) } (0..255));
    },
    'par' => sub {		# Default rule: if no entry for a paragraph style
 				# Paragraph styles
-     #return output($text) unless $text =~ /\S/;
+     return output($text) unless $text =~ /\S/;
      output "$text$N";
    },
   );
@@ -149,57 +64,34 @@ my %charmap_defaults = map({ sprintf("%02x", $_) => chr($_) } (0..255));
 # - method redefinition (could be the purist's solution)
 # - $Control::do_on_control{control_word} = sub {}; 
 # - when %do_on_control is exported write:
-
-
-# OK, so a little rewrite has gone on here. I don't like opening 'ansi'
-# and 'char_map' files, so I've wrapped them in RTF::TEXT::ansi.pm, and
-# so on. This makes it an awful lot cleaner, but falls back as
-# appropriate
-
-
 $do_on_control{'ansi'} =	# callcack redefinition
   sub {
-
-    my @charmap_data = $_[SELF]->charmap_reader( $_[CONTROL] );
-
-    # Create the charset hash...
-		my %charset = (
-
-		# Defaults...
-			%charmap_defaults,
-		
-		# Specifics from our charset file...
-			map({ s/^\s+//; split /\s+/ } @charmap_data )
-
-		);
-
-	# Over-ride &char to return our character mapping
-		local($^W);
-		*char = sub { 
-			output $charset{$_[1]}
-		} 
- 
- };
+    # RTF: \'<hex value>
+    # HTML: &#<dec value>;
+    my $charset = $_[CONTROL];
+    my $charset_file = $_[SELF]->application_dir(__FILE__) . "/$charset";
+    open CHAR_MAP, "$charset_file"
+      or die "unable to open the '$charset_file': $!";
+
+    my %charset = (		# general rule
+		   map({ sprintf("%02x", $_) => "&#$_;" } (0..255)),
+				# and some specific defs
+		   map({ s/^\s+//; split /\s+/ } (<CHAR_MAP>))
+		  );
+    *char = sub { 
+      output $charset{$_[1]}
+    } 
+  };
 
 				# symbol processing
 				# RTF: \~
 				# named chars
 				# RTF: \ldblquote, \rdblquote
-$symbol{'~'} = ' ';
-$symbol{'tab'} = "\t";
+$symbol{'~'} = '&nbsp;';
+$symbol{'tab'} = ' ';
 $symbol{'ldblquote'} = '"';
 $symbol{'rdblquote'} = '"';
 $symbol{'line'} = "\n";
-$symbol{'_'} = '-';
-
-# If we get called from a non-ansi document, then we've not redefined
-# char() to something sensible, so we put a nice definition here...
-sub char {
-
-	output $charmap_defaults{ $_[1] }
-
-}
-
 sub symbol {			
   if (defined(my $sym = $symbol{$_[1]}))  {
     output $sym;
@@ -0,0 +1,35 @@
+00 ` 
+01 &acute;
+02 ^
+03 ~
+04 &shy;
+05 &shy;
+06 &deg;
+07 &uml;
+08 &middot;
+20 --
+30 _
+82 ,
+83 f
+84 ,,
+85 ...
+86 +
+87 ++
+88 ^
+89 0/00
+8a S
+8b <
+8c OE
+91 `
+92 '
+93 ``
+94 ''
+95 &middot;
+96 -
+97 --
+98 ~
+99 [tm]
+9a s
+9b >
+9c oe
+9f Y
@@ -0,0 +1,183 @@
+exclam		!
+quotedbl	"
+numbersign	#
+dollar		$
+percent		%
+ampersand	&amp;
+quoteright	'
+parenleft	(
+parenright	)
+asterisk	*
+plus		+
+comma		,
+hyphen		-
+period		.
+slash		/
+zero		0
+one		1
+two		2
+three		3
+four		4
+five		5
+six		6
+seven		7
+eight		8
+nine		9
+colon		:
+semicolon	;
+less		&lt;
+equal		=
+greater		&gt;
+question	?
+at		@
+bracketleft	[
+backslash	\
+bracketright	]
+asciicircum	^
+underscore	_
+quoteleft	`
+braceleft	{
+bar		|
+braceright	}
+asciitilde	~
+OE		OE
+acute		'
+angleleft	[
+angleright	&gt;
+approxequal	~
+arrowboth	&lt;-&gt; 
+arrowdblboth	&lt;=&gt; 
+arrowdblleft	&lt;=
+arrowdblright	=&gt;
+arrowleft	&lt;-
+arrowright	-&gt;
+bullet		*    
+cent		&#162;
+circumflex	^
+copyright	&#169;
+copyrightsans	&#169;
+dagger		+    
+degree		&#176;
+delta		d    
+divide		&#247;
+dotlessi	i    
+ellipsis	...
+emdash		--   
+endash		-    
+fi		fi   
+fl		fl   
+fraction	/
+grave		`
+greaterequal	&gt;=
+guillemotleft	&#171;
+guillemotright	&#187;
+guilsinglleft	&lt;
+guilsinglright	&gt;
+lessequal	&lt;=
+logicalnot	&#172;
+mathasterisk	*
+mathequal	=
+mathminus	-
+mathnumbersign	#
+mathplus	+
+mathtilde	~
+minus		-
+mu		&#181;
+multiply	&#215;
+nobrkhyphen	-
+nobrkspace	&#160;
+notequal	!=
+oe		oe
+onehalf		&#189;
+onequarter	&#188;
+periodcentered	.
+plusminus	&#177;
+quotedblbase	,,
+quotedblleft	"
+quotedblright	"
+quotesinglbase	,
+registered	&#174;
+registersans	&#174;
+threequarters	&#190;
+tilde		~
+trademark	[tm]
+AE		&AElig;
+Aacute      &Aacute;
+Acircumflex &Acirc;
+Agrave      &Agrave;
+Aring       &Aring;
+Atilde		&#195;
+Adieresis	&Auml;
+Ccedilla	&Ccedil;
+Eth		&#208;
+Eacute	&Eacute;
+Ecircumflex	&Ecirc;
+Egrave	&Egrave;
+Edieresis	&Euml;
+Iacute	&Iacute;
+Icircumflex	&Icirc;
+Igrave	&Igrave;
+Idieresis	&Iuml;
+Ntilde	&Ntilde;
+Oacute	&Oacute;
+Ocircumflex	&Ocirc;
+Ograve	&Ograve;
+Oslash	&Oslash;
+Otilde	&#213;
+Odieresis	&Ouml;
+Thorn	&#222;
+Uacute	&Uacute;
+Ucircumflex	&Ucirc;
+Ugrave	&Ugrave;
+Udieresis	&Uuml;
+Yacute	&#221;
+ae		&aelig;
+aacute	&aacute;
+acircumflex	&acirc;
+agrave	&agrave;
+aring	&aring;
+atilde	&atilde;
+adieresis	&auml;
+ccedilla	&ccedil;
+eacute	&eacute;
+ecircumflex	&ecirc;
+egrave	&egrave;
+eth	&#240;
+edieresis	&euml;
+iacute	&iacute;
+icircumflex	&icirc;
+igrave	&igrave;
+idieresis	&iuml;
+ntilde	&ntilde;
+oacute	&oacute;
+ocircumflex	&ocirc;
+ograve	&ograve;
+oslash	&oslash;
+otilde	&otilde;
+odieresis	&ouml;
+germandbls	&szlig;
+thorn	&#254;
+uacute	&uacute;
+ucircumflex	&ucirc;
+ugrave	&ugrave;
+udieresis	&uuml;
+yacute	&yacute;
+ydieresis	&yuml;
+newline	<br>
+ordfeminine     &#170;
+ordmasculine    &#186;
+questiondown    &#191;
+exclamdown      &#161;
+section         &#167;
+onesuperior     &#185;
+twosuperior     &#178;
+threesuperior   &#179;
+sterling        &#163;
+currency        &#164;
+yen             &#165;
+brokenbar       &#166;
+dieresis        &#168;
+opthyphen       &#173;
+macron          &#175;
+paragraph       &#182;
+cedilla         &#184;
@@ -0,0 +1,66 @@
+#!/usr/local/bin/perl 
+# Sonovision-Itep, Verdret 1995-1999
+
+require 5.004;
+use strict;
+
+my $VERSION = "1.07";
+
+use Getopt::Long;
+use File::Basename;
+
+use vars qw/$BASENAME $DIRNAME/;
+BEGIN {
+  ($BASENAME, $DIRNAME) = fileparse($0); 
+}
+use lib "$DIRNAME/lib";
+
+my $usage = "usage: 
+ -h                    print this help
+ -l log_file RTF_file  process RTF_file and generate a log file
+ -V                    print version number
+";
+my $help = "";
+
+use vars qw($EOM $trace);
+$trace = 0;
+$EOM = "\n";			# end of message
+
+use RTF::Config;
+
+die "$usage" unless @ARGV;
+use vars qw($trace $opt_d $opt_h $opt_t $opt_v $opt_V);
+{ local $SIG{__WARN__} = sub {};
+  GetOptions('h',		# Help
+	     't=s',		# name of the target document
+	     'r=s',		# name of the report file
+	     'd',		# debugging mode
+	     'v',		# verbose
+	     'V',		# print version number
+	     'l=s' => \$LOG_FILE, # -l logfile
+	    ) or die "$usage$EOM";
+}
+
+if ($opt_h) {
+  print STDOUT "$help\n";
+  exit 0;
+}
+if ($opt_V) {
+  print STDOUT "$VERSION\n";
+  exit 0;
+}
+if ($opt_d) {
+  $| = 1;
+  $EOM = "";
+}
+
+select(STDOUT);
+
+require RTF::HTML::Converter;
+my $self = new RTF::HTML::Converter(Output => \*STDOUT);	# actually the default
+
+foreach my $filename (@ARGV) {
+  $self->parse_stream($filename);
+}
+
+1;
@@ -0,0 +1,66 @@
+#!/usr/local/bin/perl
+# Sonovision-Itep, Verdret 1995-1999
+
+require 5.004;
+use strict;
+
+my $VERSION = "1.03";
+
+use Getopt::Long;
+use File::Basename;
+
+use vars qw/$BASENAME $DIRNAME/;
+BEGIN {
+  ($BASENAME, $DIRNAME) = fileparse($0); 
+}
+use lib "$DIRNAME/lib";
+
+my $usage = "usage: 
+ -h                    print this help
+ -l log_file RTF_file  process RTF_file and generate a log file
+ -V                    print version number
+";
+my $help = "";
+
+use vars qw($EOM $trace);
+$trace = 0;
+$EOM = "\n";			# end of message
+
+use RTF::Config;
+
+die "$usage" unless @ARGV;
+use vars qw($trace $opt_d $opt_h $opt_t $opt_v $opt_V);
+{ local $SIG{__WARN__} = sub {};
+  GetOptions('h',		# Help
+	     't=s',		# name of the target document
+	     'r=s',		# name of the report file
+	     'd',		# debugging mode
+	     'v',		# verbose
+	     'V',		# print version number
+	     'l=s' => \$LOG_FILE, # -l logfile
+	    ) or die "$usage$EOM";
+}
+
+if ($opt_h) {
+  print STDOUT "$help\n";
+  exit 0;
+}
+if ($opt_V) {
+  print STDOUT "$VERSION\n";
+  exit 0;
+}
+if ($opt_d) {
+  $| = 1;
+  $EOM = "";
+}
+
+select(STDOUT);
+
+require RTF::TEXT::Converter;
+my $self = new RTF::TEXT::Converter(Output => \*STDOUT);	# actually the default
+
+foreach my $filename (@ARGV) {
+  $self->parse_stream($filename);
+}
+
+1;
@@ -1,20 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use RTF::Parser;
-use Test::More tests => 2;
-
-my $object = RTF::Parser->new();
-
-isa_ok( $object, 'RTF::Parser' );
-
-package RTF::SubClassTest;
-@RTF::SubClassTest::ISA = ( 'RTF::Parser' );
-
-package main;
-
-# Check we can be subclassed
-
-my $sub_object = RTF::SubClassTest->new();
-
-isa_ok( $sub_object, 'RTF::SubClassTest' );
\ No newline at end of file
@@ -1,127 +0,0 @@
-#!/usr/bin/perl
-
-# Tests for the RTF::Parser API...
-
-	use strict;
-	use RTF::Parser;
-	use Test::More tests => 22;
-
-# Create a testing subclass...
-
-  {
-      
-      package RTFTest;
-
-    # We'll be doing lots of printing without newlines, so don't buffer output
-
-      $|++;
-
-    # Subclassing magic...
-    
-      @RTFTest::ISA = ( 'RTF::Parser' );
-                        
-    # Redefine the API in a test-friendly way
-        
-      sub parse_start { my $self = shift; push (@{ $self->{_TEST_BUFFER} }, 'parse_start'); }
-      sub group_start { my $self = shift; push (@{ $self->{_TEST_BUFFER} }, 'group_start'); }
-      sub group_end   { my $self = shift; push (@{ $self->{_TEST_BUFFER} }, 'group_end'); }
-      sub text        { my $self = shift; push (@{ $self->{_TEST_BUFFER} }, "text" );  }
-      sub char        { my $self = shift; push (@{ $self->{_TEST_BUFFER} }, 'char');  }
-      sub symbol      { my $self = shift; push (@{ $self->{_TEST_BUFFER} }, 'symbol');  }
-      sub parse_end   { my $self = shift; push (@{ $self->{_TEST_BUFFER} }, 'parse_end');  }
-
-  }
-
-  my %do_on_control = (
-
-        # What to do when we see any control we don't have
-        #   a specific action for...
-        
-    '__DEFAULT__' => sub {
-
-     },
-     
-   # Special bold handler
-     
-     'b' => sub {
-     	my $self = shift;
-     	my $type = shift;
-     	my $arg = shift;
-     	push (@{ $self->{_TEST_BUFFER} }, "[$type][$arg]" );
-     },
-
-  );
-
-  # Grab DATA...
-
-    my $data = join '', (<DATA>);
-
-  # Create an instance of the class we created above
-
-    my $parser = RTFTest->new();
-    $parser->{_TEST_BUFFER} = [];
-
-  # Prime the object with our control handlers...
- 
-    $parser->control_definition( \%do_on_control );
-  
-  # Don't skip undefined destinations...
-  
-    $parser->dont_skip_destinations(1);
-
-  # Start the parsing!
-
-    $parser->parse_string( $data );
-    
-  # Check our test buffer
-	
-	my @actions = @{ content() };
-		
-	foreach my $buffer ( @{ $parser->{_TEST_BUFFER} } ) {
-	
-		my $control = shift( @actions );
-				
-		is( $buffer, $control, "$buffer found" );
-	
-	}
-
-
-
-	sub content {
-
-	return [
-
-		'parse_start',
-		'group_start',
-		'group_start',
-		'group_start',
-		'text',
-		'group_end',
-		'group_end',
-		'group_start',
-		'text',
-		'char',
-		'text',
-		'text',
-		'char',
-		'text',
-		'text',
-		'group_end',
-		'symbol',
-		'[b][1]',
-		'text',
-		'[b][0]',
-		'group_end',
-		'parse_end',
-	
-	];
-
-	}
-
-__END__
-{\rtf1\ansi\deff0{\fonttbl{\f0 Times New Roman;}}
-{\pard\sb300\li900
-  Toc toc Il a ferm\'e9 la porte\line
-  Les lys du jardin sont fl\'e9tris\line
-  Quel est donc ce mort qu'on emporte
-  \par}\_\b1 Tell me it's so :-)\b0}
@@ -1,16 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use Test::More tests => 1;
-use RTF::Parser;
-
-{
-	local( $^W );
-	*RTF::Parser::text = sub { my $self = shift; $self->{_TEST_BUFF} = shift; };
-}
-
-my $parser = RTF::Parser->new( );
-
-$parser->parse_string( 'asdf' );
-
-is( $parser->{_TEST_BUFF}, "asdf", 'Data read from string' );
\ No newline at end of file
@@ -1,26 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use Test::More tests => 1;
-use RTF::Parser;
-
-SKIP: {
-	eval { require IO::Scalar };
-	skip "IO::Scalar not installed", 1 if $@;
-
-	my $string = "asdf\n";
-
-	my $fh = new IO::Scalar \$string;
-
-{
-	local( $^W );
-	*RTF::Parser::text = sub { my $self = shift; $self->{_TEST_BUFF} = shift; };
-}
-
-	my $parser = RTF::Parser->new( );
-
-	$parser->parse_stream( $fh );
-
-	is( $parser->{_TEST_BUFF}, "asdf", 'Data read from stream' );
-
-}
\ No newline at end of file
@@ -1,22 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use RTF::Parser;
-use Test::More tests => 2;
-
-my $object = RTF::Parser->new();
-
-ok( !($object->control_definition), "No control definitions installed yet");
-
-my $cds = {
-
-	b => sub { return 'la' },
-	ansi => sub { return 'ta' },
-
-};
-
-
-$object->control_definition( $cds );
-
-ok( eq_hash( ($object->control_definition), $cds), "Control definitions returned correctly");
-
@@ -1,26 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use RTF::Parser;
-use Test::More tests => 2;
-
-# First we check that destinations are skipped
-
-my $parser = RTF::Parser->new();
-
-{
-	local( $^W );
-	*RTF::Parser::text = sub { my $self = shift; $self->{_TEST_BUFF} = shift; };
-}
-
-$parser->parse_string( '{\rtf{\*\asdf Quick Brown}}' );
-
-ok( !$parser->{_TEST_BUFF}, "No text recorded" );
-
-# And then that they are
-
-$parser = RTF::Parser->new();
-$parser->dont_skip_destinations( 1 );
-$parser->parse_string( '{\rtf{\*\asdf Quick Brown}}' );
-
-is( $parser->{_TEST_BUFF}, "Quick Brown", "Text recorded" );
\ No newline at end of file
@@ -1,12 +0,0 @@
-#!/usr/bin/perl
-
-# We're checking that RTF::Control's new method gives us
-#	back an RTF::Control object...
-
-use strict;
-use RTF::Control;
-use Test::More tests => 1;
-
-my $object = RTF::Control->new();
-
-isa_ok( $object, 'RTF::Control' );
\ No newline at end of file
@@ -1,54 +0,0 @@
-#!/usr/bin/perl
-
-# RTF::Parser's first unit-test! Yay :-)
-#
-# We're checking that our replacement _configure statment will work
-#   in the same way that the original did.
-
-use strict;
-use RTF::Control;
-use Test::More tests => 6;
-
-{
-
-	package RTF::TESTSET::ConfigureTests;
-	use strict;
-	use vars qw( $top_output );
-	
-	@RTF::TESTSET::ConfigureTests::ISA = ('Exporter', 'RTF::Control');
-	@RTF::TESTSET::ConfigureTests::EXPORT = qw( $top_output );
-
-	
-	$top_output = '123';
-
-	# Redefine the set_top_output_to function that would
-	#   normally be called.
-	sub set_top_output_to {
-
-		my $self = shift;
-		$top_output = shift;
-	}
-
-}
-
-my $object = RTF::TESTSET::ConfigureTests->new();
-
-# Check that $top_output is accessible and our default value
-is( $RTF::TESTSET::ConfigureTests::top_output, '123', 'We can check $top_output');
-
-# Try the different config styles...
-$object->_configure( -output => 'answer1' );
-is( $RTF::TESTSET::ConfigureTests::top_output, 'answer1', '-output worked');
-
-$object->_configure( -Output => 'answer2' );
-is( $RTF::TESTSET::ConfigureTests::top_output, 'answer2', '-Output worked');
-
-$object->_configure( output => 'answer3' );
-is( $RTF::TESTSET::ConfigureTests::top_output, 'answer3', 'output worked');
-
-$object->_configure( Output => 'answer4' );
-is( $RTF::TESTSET::ConfigureTests::top_output, 'answer4', 'Output worked');
-
-# Just checking...
-$object->_configure( -atput => 'answer5' );
-is( $RTF::TESTSET::ConfigureTests::top_output, 'answer4', "-atput didn't work (correct behaviour)");
\ No newline at end of file
@@ -1,18 +0,0 @@
-#!/usr/bin/perl
-
-# We're checking that application_dir returns sensibly.
-
-use strict;
-use RTF::Control;
-
-use RTF::TEXT::Converter;
-
-use Test::More tests => 1;
-
-
-{ 
-
-	my $object = RTF::Control->new( -confdir => 'asdfasdf' );
-	is( $object->application_dir, 'asdfasdf', '-confdir to set application_dir works' );
-
-}
@@ -1,33 +0,0 @@
-#!/usr/bin/perl
-
-# We're checking that application_dir returns sensibly.
-
-use strict;
-use RTF::TEXT::Converter;
-use RTF::HTML::Converter;
-
-use Test::More tests => 8;
-
-my $text_object = RTF::TEXT::Converter->new( output => \*STDOUT );
-my $html_object = RTF::HTML::Converter->new( output => \*STDOUT );
-
-
-# Test TEXT...
-{
-	my @char_map_data = $text_object->charmap_reader('char_map' );
-	is( $char_map_data[0], 'exclam		!', "Module charmap, first result correct" );
-	is( $char_map_data[1], 'quotedbl	"', "Module charmap, second result correct" );	
-	my @ansi_data = $text_object->charmap_reader('ansi' );
-	is( $ansi_data[0], '00 ` ', "Module ansi, first result correct" );
-	is( $ansi_data[1], '01 &acute;', "Module ansi, second result correct" );	
-}
-
-# Test HTML...
-{
-	my @char_map_data = $html_object->charmap_reader('char_map' );
-	is( $char_map_data[0], 'exclam		!', "Module charmap, first result correct" );
-	is( $char_map_data[1], 'quotedbl	"', "Module charmap, second result correct" );	
-	my @ansi_data = $html_object->charmap_reader('ansi' );
-	is( $ansi_data[0], '00 ` ', "Module ansi, first result correct" );
-	is( $ansi_data[1], '01 &acute;', "Module ansi, second result correct" );	
-}
\ No newline at end of file
diff --git a/var/tmp/source/SARGIE/RTF-Parser-1.09/RTF-Parser-1.09/t/02_control_05_strip_dead_content.t b/var/tmp/source/SARGIE/RTF-Parser-1.09/RTF-Parser-1.09/t/02_control_05_strip_dead_content.t
deleted file mode 100644
index 22ce4d18..00000000
Binary files a/var/tmp/source/SARGIE/RTF-Parser-1.09/RTF-Parser-1.09/t/02_control_05_strip_dead_content.t and /dev/null differ
@@ -1,26 +0,0 @@
-#!/usr/bin/perl
-
-# \ulnone should be treated as \ul0
-# So we're going to throw out a character property
-# event as if it *were* \ul0... We'll test for this
-# by looking for a<\u>b
-
-use strict;
-use Test::More tests => 1;
-use RTF::HTML::Converter;
- 
-my $string;
-      
-my $object = RTF::HTML::Converter->new(
-        
-	output => \$string
-        
-        );
-
-$object->parse_string( q!{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fswiss\fcharset0 Arial;}}
-\viewkind4\uc1\pard\ul\f0\fs20 a\ulnone b\par
-}!);
-
-ok( ( $string =~ m!a</u>b! ), '\ulnone treated like \ul0' );
-
-
@@ -1,19 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use Test::More tests => 8;
-
-use RTF::HTML::Converter::ansi;
-use RTF::TEXT::Converter::ansi;
-use RTF::HTML::Converter::charmap;
-use RTF::TEXT::Converter::charmap;
-
-ok( (scalar RTF::HTML::Converter::ansi::data) > 1, "RTF::HTML::Converter::ansi returns more than one entry");
-ok( (scalar RTF::TEXT::Converter::ansi::data) > 1, "RTF::TEXT::Converter::ansi returns more than one entry");
-ok( (scalar RTF::HTML::Converter::charmap::data) > 1, "RTF::HTML::Converter::charmap returns more than one entry");
-ok( (scalar RTF::TEXT::Converter::charmap::data) > 1, "RTF::TEXT::Converter::charmap returns more than one entry");
-
-ok( (scalar RTF::HTML::Converter::ansi::data) > 1, "RTF::HTML::Converter::ansi returns more than one entry a second time");
-ok( (scalar RTF::TEXT::Converter::ansi::data) > 1, "RTF::TEXT::Converter::ansi returns more than one entry a second time");
-ok( (scalar RTF::HTML::Converter::charmap::data) > 1, "RTF::HTML::Converter::charmap returns more than one entry a second time");
-ok( (scalar RTF::TEXT::Converter::charmap::data) > 1, "RTF::TEXT::Converter::charmap returns more than one entry a second time");
\ No newline at end of file
@@ -1,17 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use RTF::TEXT::Converter;
-use Test::More tests => 1;
-
-my $data = join '', (<DATA>);
-my $output;
-my $object = RTF::TEXT::Converter->new( output => \$output );
-$object->parse_string( $data );
-
-ok( ( $output =~ m/abc... def/ ), "ANSI file read properly, used as appropriate" );
-
-__DATA__
-{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fswiss\fcharset0 Arial;}}
-\viewkind4\uc1\pard\ul\f0\fs20 abc\'85 def
-}
@@ -1,73 +0,0 @@
-use RTF::HTML::Converter;
-my $result;
-my $self = new RTF::HTML::Converter(Output => \$result);	
-
-my @RTF_Documents = split (/\n/, <<'DATA');
-{} # Ok!
-{\par} # Ok!
-{string\par} # Ok!
-{\b bold \i Bold Italic \i0 Bold again} # Ok!
-{\b bold {\i Bold Italic }Bold again} # Ok!
-{\b bold \i Bold Italic \plain\b Bold again} # Ok!
-DATA
-
-my @HTML_Documents = (<<'D1;',<<'D2;',<<'D3;',<<'D4;',<<'D5;', <<'D6;');
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
-<html>
-<body>
- </body>
-</html>
-D1;
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
-<html>
-<body>
- </body>
-</html>
-D2;
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
-<html>
-<body>
-
-<p>string</p>
- </body>
-</html>
-D3;
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
-<html>
-<body>
-<b>bold <i>Bold Italic </i>Bold again</b> </body>
-</html>
-D4;
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
-<html>
-<body>
-<b>bold <i>Bold Italic </i>Bold again</b> </body>
-</html>
-D5;
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
-<html>
-<body>
-<b>bold <i>Bold Italic </i>Bold again</b> </body>
-</html>
-D6;
-
-print "1..", @RTF_Documents+0, "\n";
-my $test = 0;
-foreach (@RTF_Documents) {
-  $test++;
-  s/\#.*//;
-  $result = '';
-  $self->parse_string($_);
-  if ($result eq $HTML_Documents[$test-1]) {
-    print "ok $test\n";
-  } else {
-    print STDERR "$_\n";
-    print STDERR $HTML_Documents[$test-1], "\n";
-    print STDERR "$result\n";
-  }
-}
-
-__DATA__
-
-
-
@@ -0,0 +1,73 @@
+use RTF::HTML::Converter;
+my $result;
+my $self = new RTF::HTML::Converter(Output => \$result);	
+
+my @RTF_Documents = split (/\n/, <<'DATA');
+{} # Ok!
+{\par} # Ok!
+{string\par} # Ok!
+{\b bold \i Bold Italic \i0 Bold again} # Ok!
+{\b bold {\i Bold Italic }Bold again} # Ok!
+{\b bold \i Bold Italic \plain\b Bold again} # Ok!
+DATA
+
+my @HTML_Documents = (<<'D1;',<<'D2;',<<'D3;',<<'D4;',<<'D5;', <<'D6;');
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
+<html>
+<body>
+ </body>
+</html>
+D1;
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
+<html>
+<body>
+ </body>
+</html>
+D2;
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
+<html>
+<body>
+
+<p>string</p>
+ </body>
+</html>
+D3;
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
+<html>
+<body>
+<b>bold <i>Bold Italic </i>Bold again</b> </body>
+</html>
+D4;
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
+<html>
+<body>
+<b>bold <i>Bold Italic </i>Bold again</b> </body>
+</html>
+D5;
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" []>
+<html>
+<body>
+<b>bold <i>Bold Italic </i>Bold again</b> </body>
+</html>
+D6;
+
+print "1..", @RTF_Documents+0, "\n";
+my $test = 0;
+foreach (@RTF_Documents) {
+  $test++;
+  s/\#.*//;
+  $result = '';
+  $self->parse_string($_);
+  if ($result eq $HTML_Documents[$test-1]) {
+    print "ok $test\n";
+  } else {
+    print STDERR "$_\n";
+    print STDERR $HTML_Documents[$test-1], "\n";
+    print STDERR "$result\n";
+  }
+}
+
+__DATA__
+
+
+